From 812743d3ffb8b83c9e9192189a5898d40f24d768 Mon Sep 17 00:00:00 2001 From: louwie17 Date: Mon, 10 May 2021 11:40:49 -0300 Subject: [PATCH] Move experimental list components to experimental package (https://github.com/woocommerce/woocommerce-admin/pull/6950) * Move experimental list components to experimental package * Update changelogs * Fix lint errors * Fix lint error * Update css lint * Fix test * Update package lock --- .../client/task-list/task-item.tsx | 3 +- .../client/task-list/task-list.js | 9 +- plugins/woocommerce-admin/package-lock.json | 23 +- .../packages/components/CHANGELOG.md | 3 +- .../packages/components/src/index.js | 8 +- .../packages/components/src/list/index.js | 4 - .../components/src/list/test/index.js | 267 +---------------- .../packages/components/src/style.scss | 1 - .../packages/experimental/CHANGELOG.md | 3 +- .../packages/experimental/package.json | 6 +- .../collapsible-list/index.tsx | 0 .../collapsible-list/style.scss | 2 +- .../experimental-list-item.tsx | 17 +- .../experimental-list}/experimental-list.tsx | 2 +- .../src/experimental-list/style.scss | 158 ++++++++++ .../src/experimental-list/test/index.tsx | 269 ++++++++++++++++++ .../packages/experimental/src/index.js | 4 + .../packages/experimental/src/style.scss | 5 + plugins/woocommerce-admin/readme.txt | 1 + plugins/woocommerce-admin/src/Loader.php | 10 +- 20 files changed, 493 insertions(+), 302 deletions(-) rename plugins/woocommerce-admin/packages/{components/src/list => experimental/src/experimental-list}/collapsible-list/index.tsx (100%) rename plugins/woocommerce-admin/packages/{components/src/list => experimental/src/experimental-list}/collapsible-list/style.scss (68%) rename plugins/woocommerce-admin/packages/{components/src/list => experimental/src/experimental-list}/experimental-list-item.tsx (80%) rename plugins/woocommerce-admin/packages/{components/src/list => experimental/src/experimental-list}/experimental-list.tsx (97%) create mode 100644 plugins/woocommerce-admin/packages/experimental/src/experimental-list/style.scss create mode 100644 plugins/woocommerce-admin/packages/experimental/src/experimental-list/test/index.tsx create mode 100644 plugins/woocommerce-admin/packages/experimental/src/style.scss diff --git a/plugins/woocommerce-admin/client/task-list/task-item.tsx b/plugins/woocommerce-admin/client/task-list/task-item.tsx index 510c832eb53..7c2cb52bb1f 100644 --- a/plugins/woocommerce-admin/client/task-list/task-item.tsx +++ b/plugins/woocommerce-admin/client/task-list/task-item.tsx @@ -4,8 +4,7 @@ import { __ } from '@wordpress/i18n'; import { Icon, check } from '@wordpress/icons'; import { Button, Tooltip } from '@wordpress/components'; -import { Text } from '@woocommerce/experimental'; -import { __experimentalListItem as ListItem } from '@woocommerce/components'; +import { Text, ListItem } from '@woocommerce/experimental'; import NoticeOutline from 'gridicons/dist/notice-outline'; import classnames from 'classnames'; diff --git a/plugins/woocommerce-admin/client/task-list/task-list.js b/plugins/woocommerce-admin/client/task-list/task-list.js index 280ee078eaf..f2b845eb552 100644 --- a/plugins/woocommerce-admin/client/task-list/task-list.js +++ b/plugins/woocommerce-admin/client/task-list/task-list.js @@ -5,16 +5,11 @@ import { __, _n, sprintf } from '@wordpress/i18n'; import { useEffect, useRef } from '@wordpress/element'; import { Button, Card, CardBody, CardHeader } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { - EllipsisMenu, - Badge, - __experimentalList as List, - __experimentalCollapsibleList as CollapsibleList, -} from '@woocommerce/components'; +import { EllipsisMenu, Badge } from '@woocommerce/components'; import { updateQueryString } from '@woocommerce/navigation'; import { OPTIONS_STORE_NAME, ONBOARDING_STORE_NAME } from '@woocommerce/data'; import { recordEvent } from '@woocommerce/tracks'; -import { Text } from '@woocommerce/experimental'; +import { Text, List, CollapsibleList } from '@woocommerce/experimental'; /** * Internal dependencies diff --git a/plugins/woocommerce-admin/package-lock.json b/plugins/woocommerce-admin/package-lock.json index 3b570a632a2..ad5d0258126 100644 --- a/plugins/woocommerce-admin/package-lock.json +++ b/plugins/woocommerce-admin/package-lock.json @@ -10851,13 +10851,17 @@ "dev": true, "requires": { "@babel/runtime": "7.14.0", - "@wordpress/components": "10.2.0" + "@wordpress/components": "10.2.0", + "@wordpress/element": "2.19.0", + "@wordpress/keycodes": "2.18.0", + "classnames": "^2.3.1", + "react-transition-group": "4.4.1" }, "dependencies": { "@babel/runtime": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.17.tgz", - "integrity": "sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", + "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -10949,6 +10953,17 @@ "@babel/runtime": "7.14.0", "@wordpress/a11y": "2.15.2", "@wordpress/data": "4.26.1" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", + "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + } } }, "@woocommerce/number": { diff --git a/plugins/woocommerce-admin/packages/components/CHANGELOG.md b/plugins/woocommerce-admin/packages/components/CHANGELOG.md index 02c091ffd0b..664aa46a9fd 100644 --- a/plugins/woocommerce-admin/packages/components/CHANGELOG.md +++ b/plugins/woocommerce-admin/packages/components/CHANGELOG.md @@ -3,9 +3,8 @@ - SelectControl: automatically scroll to selected options when list is displayed. #6906 - SelectControl: no longer auto selects on rendering list. #6906 - Make `Search` accept synchronous `autocompleter.options`. #6884 -- Add new (experimental) collapsible list item to collapse list items. #6869 - SelectControl: fix display of multiple selections without inline tags. #6862 -- Add new (experimental) list, and add depreciation notice for the current list. #6787 +- Add depreciation notice for the current list. #6787 - Force `` form elements id to be unique. #6871 - Add `controlId` and `name` props to ``. #6871 - Minor styling tweaks and fixes to ``. #6871 diff --git a/plugins/woocommerce-admin/packages/components/src/index.js b/plugins/woocommerce-admin/packages/components/src/index.js index e9b28d41ab7..a7f3d4ca144 100644 --- a/plugins/woocommerce-admin/packages/components/src/index.js +++ b/plugins/woocommerce-admin/packages/components/src/index.js @@ -25,13 +25,7 @@ export { default as Gravatar } from './gravatar'; export { H, Section } from './section'; export { default as ImageUpload } from './image-upload'; export { default as Link } from './link'; -export { - default as List, - ExperimentalList as __experimentalList, - ExperimentalListItem as __experimentalListItem, - ExperimentalListItemCollapse as __experimentalListItemCollapse, - ExperimentalCollapsibleList as __experimentalCollapsibleList, -} from './list'; +export { default as List } from './list'; export { default as MenuItem } from './ellipsis-menu/menu-item'; export { default as MenuTitle } from './ellipsis-menu/menu-title'; export { default as OrderStatus } from './order-status'; diff --git a/plugins/woocommerce-admin/packages/components/src/list/index.js b/plugins/woocommerce-admin/packages/components/src/list/index.js index 3aa7ac69701..c621a72218d 100644 --- a/plugins/woocommerce-admin/packages/components/src/list/index.js +++ b/plugins/woocommerce-admin/packages/components/src/list/index.js @@ -112,7 +112,3 @@ List.propTypes = { }; export default List; - -export { ExperimentalListItem } from './experimental-list-item'; -export { ExperimentalList } from './experimental-list'; -export { ExperimentalCollapsibleList } from './collapsible-list'; diff --git a/plugins/woocommerce-admin/packages/components/src/list/test/index.js b/plugins/woocommerce-admin/packages/components/src/list/test/index.js index 85ebd96faeb..202851816dc 100644 --- a/plugins/woocommerce-admin/packages/components/src/list/test/index.js +++ b/plugins/woocommerce-admin/packages/components/src/list/test/index.js @@ -1,278 +1,15 @@ -jest.mock( '../list-item', () => ( { - __esModule: true, - ...jest.requireActual( '../list-item' ), - handleKeyDown: jest.fn(), -} ) ); - /** * External dependencies */ -import { - render, - screen, - waitForElementToBeRemoved, -} from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; /** * Internal dependencies */ -import List, { - ExperimentalList, - ExperimentalListItem, - ExperimentalCollapsibleList, -} from '../index'; -import { handleKeyDown } from '../list-item'; +import List from '../index'; describe( 'List', () => { - describe( 'Experimental List', () => { - it( 'should render the new List which defaults to a ul component if items are not passed in', () => { - const { container } = render( - -
Test
-
- ); - - expect( container.querySelector( 'ul' ) ).toBeInTheDocument(); - } ); - - it( 'should render children passed in', () => { - const { container } = render( - -
Test
-
- ); - - expect( container ).toHaveTextContent( 'Test' ); - } ); - - it( 'should allow overriding the list type, and passing in arbitrary element props', () => { - const { container } = render( - -
Test
-
- ); - - expect( container.querySelector( 'ol' ) ).toBeInTheDocument(); - } ); - - describe( 'ExperimentalListItem', () => { - it( 'should render children passed in', () => { - const { container } = render( - -
Test
-
- ); - - expect( container ).toHaveTextContent( 'Test' ); - } ); - - it( 'allows disabling the gutter styling', () => { - const { container } = render( - -
Test
-
- ); - - expect( - container.querySelector( '.has-gutters' ) - ).not.toBeInTheDocument(); - } ); - - it( 'should disable animations by default and for unsupported values', () => { - // disabled by default - const { container, rerender } = render( - -
Test
-
- ); - - expect( - container.querySelector( '.transitions-disabled' ) - ).toBeInTheDocument(); - - // invalid value - rerender( - -
Test
-
- ); - - expect( - container.querySelector( '.transitions-disabled' ) - ).toBeInTheDocument(); - } ); - - it( 'should not disable animations if you provide a valid animation value', () => { - const { container } = render( - -
Test
-
- ); - - expect( - container.querySelector( '.transitions-disabled' ) - ).not.toBeInTheDocument(); - } ); - - it( 'supports onClick on the list item, and handles keyboard events', () => { - const dummyOnClick = jest.fn(); - - const { container, queryByRole } = render( - -
Test
-
- ); - - const listItem = container.querySelector( - '.woocommerce-list__item' - ); - - userEvent.click( listItem ); - - // it doesn't actually matter what key you hit here while handleKeyDown is mocked. - userEvent.type( listItem, '{enter}' ); - - // TODO check that the button role was added. - expect( queryByRole( 'button' ) ).toBeInTheDocument(); - expect( handleKeyDown ).toHaveBeenCalled(); - expect( dummyOnClick ).toHaveBeenCalled(); - } ); - - it( 'includes correct ARIA roles and a11y attributes when the item has an action', () => { - const clickHandler = jest.fn(); - render( - -
Test
-
- ); - - const item = screen.getByRole( 'button' ); - expect( item ).toBeInTheDocument(); - expect( item ).toHaveAttribute( 'role', 'button' ); - expect( item ).toHaveAttribute( 'tabindex', '0' ); - } ); - } ); - - describe( 'ExperimentalListItemCollapse', () => { - it( 'should not render its children intially, but an extra list footer with show text', () => { - const { container } = render( - -
Test
-
- ); - - expect( container ).not.toHaveTextContent( 'Test' ); - expect( container ).toHaveTextContent( 'Show more items' ); - } ); - - it( 'should render list items when footer is clicked and trigger onExpand', () => { - const onExpand = jest.fn(); - const onCollapse = jest.fn(); - const { container } = render( - -
Test
-
Test 2
-
- ); - - const listItem = container.querySelector( - '.list-item-collapse' - ); - - userEvent.click( listItem ); - expect( container ).toHaveTextContent( 'Test' ); - expect( container ).toHaveTextContent( 'Test 2' ); - expect( container ).not.toHaveTextContent( 'Show more items' ); - expect( container ).toHaveTextContent( 'Show less' ); - expect( onExpand ).toHaveBeenCalled(); - expect( onCollapse ).not.toHaveBeenCalled(); - } ); - - it( 'should render minimum children if minChildrenToShow is set and show the rest on expand', () => { - const onExpand = jest.fn(); - const onCollapse = jest.fn(); - const { container } = render( - -
Test
-
Test 2
-
Test 3
-
Test 4
-
- ); - - expect( container ).toHaveTextContent( 'Test' ); - expect( container ).toHaveTextContent( 'Test 2' ); - expect( container ).not.toHaveTextContent( 'Test 3' ); - expect( container ).not.toHaveTextContent( 'Test 4' ); - const listItem = container.querySelector( - '.list-item-collapse' - ); - - userEvent.click( listItem ); - expect( container ).toHaveTextContent( 'Test' ); - expect( container ).toHaveTextContent( 'Test 2' ); - expect( container ).toHaveTextContent( 'Test 3' ); - expect( container ).toHaveTextContent( 'Test 4' ); - expect( container ).not.toHaveTextContent( 'Show more items' ); - expect( container ).toHaveTextContent( 'Show less' ); - expect( onExpand ).toHaveBeenCalled(); - expect( onCollapse ).not.toHaveBeenCalled(); - } ); - - it( 'should correctly toggle the list', async () => { - const onExpand = jest.fn(); - const onCollapse = jest.fn(); - const { container } = render( - -
Test
-
Test 2
-
- ); - - let listItem = container.querySelector( '.list-item-collapse' ); - - userEvent.click( listItem ); - expect( container ).toHaveTextContent( 'Test' ); - expect( container ).toHaveTextContent( 'Test 2' ); - expect( container ).not.toHaveTextContent( 'Show more items' ); - expect( container ).toHaveTextContent( 'Show less' ); - - listItem = container.querySelector( '.list-item-collapse' ); - - userEvent.click( listItem ); - await waitForElementToBeRemoved( - container.querySelector( '#test' ) - ); - expect( container ).not.toHaveTextContent( 'Test' ); - expect( container ).not.toHaveTextContent( 'Test 2' ); - expect( container ).toHaveTextContent( 'Show more items' ); - expect( container ).not.toHaveTextContent( 'Show less' ); - expect( onExpand ).toHaveBeenCalledTimes( 1 ); - expect( onCollapse ).toHaveBeenCalledTimes( 1 ); - } ); - } ); - } ); - describe( 'Legacy List', () => { it( 'should have aria roles for items', () => { const clickHandler = jest.fn(); diff --git a/plugins/woocommerce-admin/packages/components/src/style.scss b/plugins/woocommerce-admin/packages/components/src/style.scss index 08628d54d5a..af7df1e4600 100644 --- a/plugins/woocommerce-admin/packages/components/src/style.scss +++ b/plugins/woocommerce-admin/packages/components/src/style.scss @@ -18,7 +18,6 @@ @import 'gravatar/style.scss'; @import 'image-upload/style.scss'; @import 'list/style.scss'; -@import 'list/collapsible-list/style.scss'; @import 'order-status/style.scss'; @import 'pagination/style.scss'; @import 'pill/style.scss'; diff --git a/plugins/woocommerce-admin/packages/experimental/CHANGELOG.md b/plugins/woocommerce-admin/packages/experimental/CHANGELOG.md index c038734b446..425dc7473d0 100644 --- a/plugins/woocommerce-admin/packages/experimental/CHANGELOG.md +++ b/plugins/woocommerce-admin/packages/experimental/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased -- Export component ExperimentalList and ExperimentalListItem as List and ListItem. +- Add new (experimental) collapsible list item to collapse list items. #6869 +- Add new (experimental) list. #6787 # 1.0.0 diff --git a/plugins/woocommerce-admin/packages/experimental/package.json b/plugins/woocommerce-admin/packages/experimental/package.json index 79b0424ef0d..5790f96510d 100644 --- a/plugins/woocommerce-admin/packages/experimental/package.json +++ b/plugins/woocommerce-admin/packages/experimental/package.json @@ -22,7 +22,11 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "7.14.0", - "@wordpress/components": "10.2.0" + "@wordpress/components": "10.2.0", + "@wordpress/element": "2.19.0", + "@wordpress/keycodes": "2.18.0", + "classnames": "^2.3.1", + "react-transition-group": "4.4.1" }, "publishConfig": { "access": "public" diff --git a/plugins/woocommerce-admin/packages/components/src/list/collapsible-list/index.tsx b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/collapsible-list/index.tsx similarity index 100% rename from plugins/woocommerce-admin/packages/components/src/list/collapsible-list/index.tsx rename to plugins/woocommerce-admin/packages/experimental/src/experimental-list/collapsible-list/index.tsx diff --git a/plugins/woocommerce-admin/packages/components/src/list/collapsible-list/style.scss b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/collapsible-list/style.scss similarity index 68% rename from plugins/woocommerce-admin/packages/components/src/list/collapsible-list/style.scss rename to plugins/woocommerce-admin/packages/experimental/src/experimental-list/collapsible-list/style.scss index cf463cb594a..61a05a28ac6 100644 --- a/plugins/woocommerce-admin/packages/components/src/list/collapsible-list/style.scss +++ b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/collapsible-list/style.scss @@ -1,4 +1,4 @@ -.woocommerce-list__item.list-item-collapse { +.woocommerce-experimental-list__item.list-item-collapse { justify-content: space-between; p { diff --git a/plugins/woocommerce-admin/packages/components/src/list/experimental-list-item.tsx b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/experimental-list-item.tsx similarity index 80% rename from plugins/woocommerce-admin/packages/components/src/list/experimental-list-item.tsx rename to plugins/woocommerce-admin/packages/experimental/src/experimental-list/experimental-list-item.tsx index 3eb14dec1ab..3732c6975f8 100644 --- a/plugins/woocommerce-admin/packages/components/src/list/experimental-list-item.tsx +++ b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/experimental-list-item.tsx @@ -2,12 +2,19 @@ * External dependencies */ import { CSSTransition } from 'react-transition-group'; +import { ENTER } from '@wordpress/keycodes'; import classnames from 'classnames'; -/** - * Internal dependencies - */ -import { handleKeyDown } from './list-item'; +function handleKeyDown( + event: React.KeyboardEvent< HTMLElement >, + onClick?: + | React.MouseEventHandler< HTMLElement > + | React.KeyboardEventHandler< HTMLElement > +) { + if ( typeof onClick === 'function' && event.keyCode === ENTER ) { + ( onClick as React.KeyboardEventHandler< HTMLElement > )( event ); + } +} type CSSTransitionProps = { in: boolean; @@ -73,7 +80,7 @@ export const ExperimentalListItem: React.FC< ListItemProps > = ( { // spread role props first, in case it is desired to override them { ...roleProps } { ...otherProps } - className={ `woocommerce-list__item ${ tagClasses } ${ className }` } + className={ `woocommerce-experimental-list__item ${ tagClasses } ${ className }` } > { children } diff --git a/plugins/woocommerce-admin/packages/components/src/list/experimental-list.tsx b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/experimental-list.tsx similarity index 97% rename from plugins/woocommerce-admin/packages/components/src/list/experimental-list.tsx rename to plugins/woocommerce-admin/packages/experimental/src/experimental-list/experimental-list.tsx index 62512b80667..4c6945d6a25 100644 --- a/plugins/woocommerce-admin/packages/components/src/list/experimental-list.tsx +++ b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/experimental-list.tsx @@ -26,7 +26,7 @@ export const ExperimentalList: React.FC< ListProps > = ( { return ( { /* Wrapping all children in a CSS Transition means no invalid props are passed to children and that anything can be animated. */ } diff --git a/plugins/woocommerce-admin/packages/experimental/src/experimental-list/style.scss b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/style.scss new file mode 100644 index 00000000000..8a43e310041 --- /dev/null +++ b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/style.scss @@ -0,0 +1,158 @@ +.woocommerce-experimental-list { + margin: 0; + padding: 0; +} + +a.woocommerce-experimental-list__item { + color: inherit; +} + +.woocommerce-experimental-list__item { + display: flex; + align-items: center; + margin-bottom: 0; + text-decoration: none; + + &.has-gutters { + padding: $gap $gap-large; + } + + &.has-action { + cursor: pointer; + } + + &:focus { + box-shadow: inset 0 0 0 1px $studio-wordpress-blue, + inset 0 0 0 2px $studio-white; + } + + &:focus-visible { + box-shadow: none; + } + + // transitions + &:not(.transitions-disabled) { + &.woocommerce-list__item-enter { + opacity: 0; + max-height: 0; + transform: translateX(50%); + } + + &.woocommerce-list__item-enter-active { + opacity: 1; + max-height: 100vh; + transform: translateX(0%); + transition: opacity 500ms, transform 500ms, max-height 500ms; + } + + &.woocommerce-list__item-exit { + opacity: 1; + max-height: 100vh; + transform: translateX(0%); + } + + &.woocommerce-list__item-exit-active { + opacity: 0; + max-height: 0; + transform: translateX(50%); + transition: opacity 500ms, transform 500ms, max-height 500ms; + } + } + + > .woocommerce-list__item-inner { + text-decoration: none; + width: 100%; + display: flex; + align-items: center; + padding: $gap $gap-large; + + &:focus { + box-shadow: inset 0 0 0 1px $studio-wordpress-blue, + inset 0 0 0 2px $studio-white; + } + } + + .woocommerce-list__item-title { + color: $studio-gray-90; + } + + .woocommerce-list__item-content { + margin-top: $gap-smallest; + display: block; + font-size: 14px; + line-height: 20px; + color: #50575d; + } + + .woocommerce-list__item-before { + margin-right: 20px; + display: flex; + align-items: center; + } + + .woocommerce-list__item-after { + margin-left: $gap; + display: flex; + align-items: center; + margin-left: auto; + } + + $chevron-color: $gray-900; + $background-color: $white; + $background-color-hover: $gray-100; + $border-color: $gray-100; + $foreground-color: var(--wp-admin-theme-color); + $foreground-color-hover: var(--wp-admin-theme-color); + + background-color: $background-color; + + &:not(:first-child) { + border-top: 1px solid $border-color; + } + + &:hover { + background-color: $background-color-hover; + + .woocommerce-list__item-title { + color: $foreground-color-hover; + } + + .woocommerce-list__item-before > svg { + fill: $foreground-color-hover; + } + } + + .woocommerce-list__item-title { + color: $foreground-color; + } + + .woocommerce-list__item-before > svg { + fill: $foreground-color; + } + + .woocommerce-list__item-after > svg { + fill: $chevron-color; + } + + &.is-complete { + .woocommerce-task__icon { + background-color: var(--wp-admin-theme-color); + } + + .woocommerce-list__item-title { + color: $gray-700; + } + + .woocommerce-list__item-content { + display: none; + } + } +} + +.woocommerce-experimental-list__item-title { + color: $studio-gray-80; +} + +.woocommerce-experimental-list__item-content { + color: $studio-gray-50; +} diff --git a/plugins/woocommerce-admin/packages/experimental/src/experimental-list/test/index.tsx b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/test/index.tsx new file mode 100644 index 00000000000..8f6dcd71541 --- /dev/null +++ b/plugins/woocommerce-admin/packages/experimental/src/experimental-list/test/index.tsx @@ -0,0 +1,269 @@ +/** + * External dependencies + */ +import { + render, + screen, + waitForElementToBeRemoved, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +/** + * Internal dependencies + */ +import { ExperimentalList } from '../experimental-list'; +import { ExperimentalListItem } from '../experimental-list-item'; +import { ExperimentalCollapsibleList } from '../collapsible-list'; + +describe( 'Experimental List', () => { + it( 'should render the new List which defaults to a ul component if items are not passed in', () => { + const { container } = render( + +
Test
+
+ ); + + expect( container.querySelector( 'ul' ) ).toBeInTheDocument(); + } ); + + it( 'should render children passed in', () => { + const { container } = render( + +
Test
+
+ ); + + expect( container ).toHaveTextContent( 'Test' ); + } ); + + it( 'should allow overriding the list type, and passing in arbitrary element props', () => { + const { container } = render( + +
Test
+
+ ); + + expect( container.querySelector( 'ol' ) ).toBeInTheDocument(); + } ); + + describe( 'ExperimentalListItem', () => { + it( 'should render children passed in', () => { + const { container } = render( + +
Test
+
+ ); + + expect( container ).toHaveTextContent( 'Test' ); + } ); + + it( 'allows disabling the gutter styling', () => { + const { container } = render( + +
Test
+
+ ); + + expect( + container.querySelector( '.has-gutters' ) + ).not.toBeInTheDocument(); + } ); + + it( 'should disable animations by default and for unsupported values', () => { + // disabled by default + const { container, rerender } = render( + +
Test
+
+ ); + + expect( + container.querySelector( '.transitions-disabled' ) + ).toBeInTheDocument(); + + // invalid value + rerender( + +
Test
+
+ ); + + expect( + container.querySelector( '.transitions-disabled' ) + ).toBeInTheDocument(); + } ); + + it( 'should not disable animations if you provide a valid animation value', () => { + const { container } = render( + +
Test
+
+ ); + + expect( + container.querySelector( '.transitions-disabled' ) + ).not.toBeInTheDocument(); + } ); + + it( 'supports onClick on the list item, and handles keyboard events', () => { + const dummyOnClick = jest.fn(); + + const { container, queryByRole } = render( + +
Test
+
+ ); + + const listItem = container.querySelector( + '.woocommerce-experimental-list__item' + ); + + if ( listItem ) { + userEvent.click( listItem ); + + // it doesn't actually matter what key you hit here while handleKeyDown is mocked. + userEvent.type( listItem, '{enter}' ); + } + + // TODO check that the button role was added. + expect( queryByRole( 'button' ) ).toBeInTheDocument(); + expect( dummyOnClick ).toHaveBeenCalled(); + } ); + + it( 'includes correct ARIA roles and a11y attributes when the item has an action', () => { + const clickHandler = jest.fn(); + render( + +
Test
+
+ ); + + const item = screen.getByRole( 'button' ); + expect( item ).toBeInTheDocument(); + expect( item ).toHaveAttribute( 'role', 'button' ); + expect( item ).toHaveAttribute( 'tabindex', '0' ); + } ); + } ); + + describe( 'ExperimentalListItemCollapse', () => { + it( 'should not render its children intially, but an extra list footer with show text', () => { + const { container } = render( + +
Test
+
+ ); + + expect( container ).not.toHaveTextContent( 'Test' ); + expect( container ).toHaveTextContent( 'Show more items' ); + } ); + + it( 'should render list items when footer is clicked and trigger onExpand', () => { + const onExpand = jest.fn(); + const onCollapse = jest.fn(); + const { container } = render( + +
Test
+
Test 2
+
+ ); + + const listItem = container.querySelector( '.list-item-collapse' ); + + if ( listItem ) { + userEvent.click( listItem ); + } + expect( container ).toHaveTextContent( 'Test' ); + expect( container ).toHaveTextContent( 'Test 2' ); + expect( container ).not.toHaveTextContent( 'Show more items' ); + expect( container ).toHaveTextContent( 'Show less' ); + expect( onExpand ).toHaveBeenCalled(); + expect( onCollapse ).not.toHaveBeenCalled(); + } ); + + it( 'should render minimum children if minChildrenToShow is set and show the rest on expand', () => { + const onExpand = jest.fn(); + const onCollapse = jest.fn(); + const { container } = render( + +
Test
+
Test 2
+
Test 3
+
Test 4
+
+ ); + + expect( container ).toHaveTextContent( 'Test' ); + expect( container ).toHaveTextContent( 'Test 2' ); + expect( container ).not.toHaveTextContent( 'Test 3' ); + expect( container ).not.toHaveTextContent( 'Test 4' ); + const listItem = container.querySelector( '.list-item-collapse' ); + + if ( listItem ) { + userEvent.click( listItem ); + } + expect( container ).toHaveTextContent( 'Test' ); + expect( container ).toHaveTextContent( 'Test 2' ); + expect( container ).toHaveTextContent( 'Test 3' ); + expect( container ).toHaveTextContent( 'Test 4' ); + expect( container ).not.toHaveTextContent( 'Show more items' ); + expect( container ).toHaveTextContent( 'Show less' ); + expect( onExpand ).toHaveBeenCalled(); + expect( onCollapse ).not.toHaveBeenCalled(); + } ); + + it( 'should correctly toggle the list', async () => { + const onExpand = jest.fn(); + const onCollapse = jest.fn(); + const { container } = render( + +
Test
+
Test 2
+
+ ); + + let listItem = container.querySelector( '.list-item-collapse' ); + + if ( listItem ) { + userEvent.click( listItem ); + } + expect( container ).toHaveTextContent( 'Test' ); + expect( container ).toHaveTextContent( 'Test 2' ); + expect( container ).not.toHaveTextContent( 'Show more items' ); + expect( container ).toHaveTextContent( 'Show less' ); + + listItem = container.querySelector( '.list-item-collapse' ); + + if ( listItem ) { + userEvent.click( listItem ); + } + await waitForElementToBeRemoved( + container.querySelector( '#test' ) + ); + expect( container ).not.toHaveTextContent( 'Test' ); + expect( container ).not.toHaveTextContent( 'Test 2' ); + expect( container ).toHaveTextContent( 'Show more items' ); + expect( container ).not.toHaveTextContent( 'Show less' ); + expect( onExpand ).toHaveBeenCalledTimes( 1 ); + expect( onCollapse ).toHaveBeenCalledTimes( 1 ); + } ); + } ); +} ); diff --git a/plugins/woocommerce-admin/packages/experimental/src/index.js b/plugins/woocommerce-admin/packages/experimental/src/index.js index a16b3381c67..f28a774b503 100644 --- a/plugins/woocommerce-admin/packages/experimental/src/index.js +++ b/plugins/woocommerce-admin/packages/experimental/src/index.js @@ -32,3 +32,7 @@ export const NavigationItem = NavigationItemComponent || __experimentalNavigationItem; export const Text = TextComponent || __experimentalText; export const useSlot = useSlotHook || __experimentalUseSlot; + +export { ExperimentalListItem as ListItem } from './experimental-list/experimental-list-item'; +export { ExperimentalList as List } from './experimental-list/experimental-list'; +export { ExperimentalCollapsibleList as CollapsibleList } from './experimental-list/collapsible-list'; diff --git a/plugins/woocommerce-admin/packages/experimental/src/style.scss b/plugins/woocommerce-admin/packages/experimental/src/style.scss new file mode 100644 index 00000000000..1f4e0eb7ccf --- /dev/null +++ b/plugins/woocommerce-admin/packages/experimental/src/style.scss @@ -0,0 +1,5 @@ +/** + * Internal Dependencies + */ +@import 'experimental-list/style.scss'; +@import 'experimental-list/collapsible-list/style.scss'; diff --git a/plugins/woocommerce-admin/readme.txt b/plugins/woocommerce-admin/readme.txt index e7b55e83011..fff34b1bc67 100644 --- a/plugins/woocommerce-admin/readme.txt +++ b/plugins/woocommerce-admin/readme.txt @@ -137,6 +137,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt - Update: UI updates to Payment Task screen #6766 - Update: Adding setup required icon for non-configured payment methods #6811 - Update: Task list component with new Experimental Task list. #6849 +- Update: Experimental task list import to the experimental package. #6950 - Update: Redirect to WC Home after setting up a payment method #6891 - Update: Replace marketing extension - Google Listings and Ads. #6939 - Dev: Fix a bug where trying to load an asset registry causes a crash. #6951 diff --git a/plugins/woocommerce-admin/src/Loader.php b/plugins/woocommerce-admin/src/Loader.php index 722c5d4c617..53fad5030bd 100644 --- a/plugins/woocommerce-admin/src/Loader.php +++ b/plugins/woocommerce-admin/src/Loader.php @@ -431,6 +431,14 @@ class Loader { ); wp_style_add_data( 'wc-customer-effort-score', 'rtl', 'replace' ); + wp_register_style( + 'wc-experimental', + self::get_url( 'experimental/style', 'css' ), + array(), + $css_file_version + ); + wp_style_add_data( 'wc-experimental', 'rtl', 'replace' ); + wp_localize_script( WC_ADMIN_APP, 'wcAdminAssets', @@ -446,7 +454,7 @@ class Loader { wp_register_style( WC_ADMIN_APP, self::get_url( "app/style{$rtl}", 'css' ), - array( 'wc-components', 'wc-customer-effort-score', 'wp-components' ), + array( 'wc-components', 'wc-customer-effort-score', 'wp-components', 'wc-experimental' ), $css_file_version );