From 7c96b7c9dfa9ade7c9d9552dd19ee2c323cf7e0d Mon Sep 17 00:00:00 2001 From: Maxime Cloutier Date: Tue, 12 Sep 2023 14:39:52 -0600 Subject: [PATCH 1/8] Make ActionList filtering opt-in --- .../src/components/ActionList/ActionList.tsx | 28 ++++---- .../FilterActionsProvider.tsx | 19 ++++++ .../components/FilterActionsProvider/index.ts | 1 + polaris-react/src/components/Page/Page.tsx | 4 +- .../Page/components/Header/Header.tsx | 64 ++++++++++--------- 5 files changed, 74 insertions(+), 42 deletions(-) create mode 100644 polaris-react/src/components/FilterActionsProvider/FilterActionsProvider.tsx create mode 100644 polaris-react/src/components/FilterActionsProvider/index.ts diff --git a/polaris-react/src/components/ActionList/ActionList.tsx b/polaris-react/src/components/ActionList/ActionList.tsx index 5ea8a908d46..8a70e87e5c5 100644 --- a/polaris-react/src/components/ActionList/ActionList.tsx +++ b/polaris-react/src/components/ActionList/ActionList.tsx @@ -1,4 +1,4 @@ -import React, {useMemo, useRef, useState} from 'react'; +import React, {useContext, useMemo, useRef, useState} from 'react'; import type {ActionListItemDescriptor, ActionListSection} from '../../types'; import {Key} from '../../types'; @@ -6,12 +6,13 @@ import { wrapFocusNextFocusableMenuItem, wrapFocusPreviousFocusableMenuItem, } from '../../utilities/focus'; +import {useI18n} from '../../utilities/i18n'; import {Box} from '../Box'; import {KeypressListener} from '../KeypressListener'; -import {useI18n} from '../../utilities/i18n'; +import {FilterActionsContext} from '../FilterActionsProvider'; -import {SearchField, Item, Section} from './components'; import type {ItemProps} from './components'; +import {Item, SearchField, Section} from './components'; export interface ActionListProps { /** Collection of actions for list */ @@ -20,6 +21,8 @@ export interface ActionListProps { sections?: readonly ActionListSection[]; /** Defines a specific role attribute for each action in the list */ actionRole?: 'menuitem' | string; + /** Allow users to filter items in the list. Will only show if more than 8 items in the list. The item content of every items must be a string for this to work */ + hasFiltering?: boolean; /** Callback when any item is clicked or keypressed */ onActionAnyItem?: ActionListItemDescriptor['onAction']; } @@ -30,10 +33,11 @@ export function ActionList({ items, sections = [], actionRole, + hasFiltering, onActionAnyItem, }: ActionListProps) { const i18n = useI18n(); - + const filterActions = useContext(FilterActionsContext); let finalSections: readonly ActionListSection[] = []; const actionListRef = useRef(null); const [searchText, setSeachText] = useState(''); @@ -116,12 +120,6 @@ export function ActionList({ ) : null; - const totalActions = - finalSections?.reduce( - (acc: number, section) => acc + section.items.length, - 0, - ) || 0; - const totalFilteredActions = useMemo(() => { const totalSectionItems = filteredSections?.reduce( @@ -132,11 +130,17 @@ export function ActionList({ return totalSectionItems; }, [filteredSections]); - const showSearch = totalActions >= 8; + const totalActions = + finalSections?.reduce( + (acc: number, section) => acc + section.items.length, + 0, + ) || 0; + + const hasSearch = totalActions >= 8; return ( <> - {showSearch && isFilterable && ( + {(hasFiltering || filterActions) && hasSearch && isFilterable && ( 0 ? '0' : '2'}> (false); + +type FilterActionsProviderProps = PropsWithChildren<{ + filterActions: boolean; +}>; + +export function FilterActionsProvider({ + children, + filterActions, +}: FilterActionsProviderProps) { + return ( + + {children} + + ); +} diff --git a/polaris-react/src/components/FilterActionsProvider/index.ts b/polaris-react/src/components/FilterActionsProvider/index.ts new file mode 100644 index 00000000000..d5f2b313195 --- /dev/null +++ b/polaris-react/src/components/FilterActionsProvider/index.ts @@ -0,0 +1 @@ +export * from './FilterActionsProvider'; diff --git a/polaris-react/src/components/Page/Page.tsx b/polaris-react/src/components/Page/Page.tsx index 71d7e62c13b..f5a552faf6f 100644 --- a/polaris-react/src/components/Page/Page.tsx +++ b/polaris-react/src/components/Page/Page.tsx @@ -48,7 +48,9 @@ export function Page({ divider && hasHeaderContent && styles.divider, ); - const headerMarkup = hasHeaderContent ?
: null; + const headerMarkup = hasHeaderContent ? ( +
+ ) : null; return (
diff --git a/polaris-react/src/components/Page/components/Header/Header.tsx b/polaris-react/src/components/Page/components/Header/Header.tsx index 720c7941bea..ffba84660e0 100644 --- a/polaris-react/src/components/Page/components/Header/Header.tsx +++ b/polaris-react/src/components/Page/components/Header/Header.tsx @@ -29,6 +29,7 @@ import {isReactElement} from '../../../../utilities/is-react-element'; import {Box} from '../../../Box'; import {HorizontalStack} from '../../../HorizontalStack'; import {useFeatures} from '../../../../utilities/features'; +import {FilterActionsProvider} from '../../../FilterActionsProvider'; import {Title} from './components'; import type {TitleProps} from './components'; @@ -49,6 +50,8 @@ interface PrimaryAction export interface HeaderProps extends TitleProps { /** Visually hide the title */ titleHidden?: boolean; + /** Enables filtering action list items */ + filterActions?: boolean; /** Primary page-level action */ primaryAction?: PrimaryAction | React.ReactNode; /** Page-level pagination */ @@ -79,6 +82,7 @@ export function Header({ titleHidden = false, primaryAction, pagination, + filterActions, additionalNavigation, backAction, secondaryActions = [], @@ -229,35 +233,37 @@ export function Header({ visuallyHidden={titleHidden} >
- -
- {slot1} - {slot2} - -
- ( -
{children}
- )} - > - {slot3} - {slot4} -
-
-
-
-
- -
- {slot5} - -
{slot6}
-
-
-
+ + +
+ {slot1} + {slot2} + +
+ ( +
{children}
+ )} + > + {slot3} + {slot4} +
+
+
+
+
+ +
+ {slot5} + +
{slot6}
+
+
+
+
); From fd8f5c53fbb4e53e1072b0fadf0fc5363acad635 Mon Sep 17 00:00:00 2001 From: Maxime Cloutier Date: Thu, 14 Sep 2023 11:08:13 -0600 Subject: [PATCH 2/8] Add tests --- .../ActionList/tests/ActionList.test.tsx | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/polaris-react/src/components/ActionList/tests/ActionList.test.tsx b/polaris-react/src/components/ActionList/tests/ActionList.test.tsx index ed10230353e..fe817e6fbd4 100644 --- a/polaris-react/src/components/ActionList/tests/ActionList.test.tsx +++ b/polaris-react/src/components/ActionList/tests/ActionList.test.tsx @@ -240,6 +240,7 @@ describe('', () => { it('does not render search with 7 or less items', () => { const actionList = mountWithApp( ', () => { it('renders search with 8 or more items', () => { const actionList = mountWithApp( ', () => { expect(actionList).toContainReactComponentTimes(SearchField, 1); }); - it('renders search with 10 or more items or section items', () => { + it('does not renders search with 8 and no hasFiltering', () => { + const actionList = mountWithApp( + , + ); + + expect(actionList).not.toContainReactComponentTimes(SearchField, 1); + }); + + it('renders search with 8 or more items or section items', () => { const actionList = mountWithApp( ', () => { const actionList = mountWithApp( Date: Thu, 14 Sep 2023 11:42:06 -0600 Subject: [PATCH 3/8] Add changeset --- .changeset/lazy-hornets-train.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lazy-hornets-train.md diff --git a/.changeset/lazy-hornets-train.md b/.changeset/lazy-hornets-train.md new file mode 100644 index 00000000000..2e51275c8aa --- /dev/null +++ b/.changeset/lazy-hornets-train.md @@ -0,0 +1,5 @@ +--- +'@shopify/polaris': patch +--- + +Make ActionList filtering opt-in From fb39852403758b6bb438a7adbe72cc151d854533 Mon Sep 17 00:00:00 2001 From: Maxime Cloutier Date: Thu, 14 Sep 2023 12:16:13 -0600 Subject: [PATCH 4/8] Update .changeset/lazy-hornets-train.md Co-authored-by: Kyle Durand --- .changeset/lazy-hornets-train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lazy-hornets-train.md b/.changeset/lazy-hornets-train.md index 2e51275c8aa..3c88f820b06 100644 --- a/.changeset/lazy-hornets-train.md +++ b/.changeset/lazy-hornets-train.md @@ -2,4 +2,4 @@ '@shopify/polaris': patch --- -Make ActionList filtering opt-in +Added `allowFiltering` prop on `ActionList`, and `filterActions` prop on Page Header From 5e3bd32b24fb372365b12d810aee3e5ec60aa5a6 Mon Sep 17 00:00:00 2001 From: Maxime Cloutier Date: Thu, 14 Sep 2023 12:16:20 -0600 Subject: [PATCH 5/8] Update .changeset/lazy-hornets-train.md Co-authored-by: Kyle Durand --- .changeset/lazy-hornets-train.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lazy-hornets-train.md b/.changeset/lazy-hornets-train.md index 3c88f820b06..f2103c69573 100644 --- a/.changeset/lazy-hornets-train.md +++ b/.changeset/lazy-hornets-train.md @@ -1,5 +1,5 @@ --- -'@shopify/polaris': patch +'@shopify/polaris': minor --- Added `allowFiltering` prop on `ActionList`, and `filterActions` prop on Page Header From 9d9116c94d5c5c6d51f68400c13fca6c58f9eb01 Mon Sep 17 00:00:00 2001 From: Maxime Cloutier Date: Thu, 14 Sep 2023 12:16:27 -0600 Subject: [PATCH 6/8] Update polaris-react/src/components/ActionList/ActionList.tsx Co-authored-by: Kyle Durand --- polaris-react/src/components/ActionList/ActionList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polaris-react/src/components/ActionList/ActionList.tsx b/polaris-react/src/components/ActionList/ActionList.tsx index 8a70e87e5c5..4143c4b2152 100644 --- a/polaris-react/src/components/ActionList/ActionList.tsx +++ b/polaris-react/src/components/ActionList/ActionList.tsx @@ -22,7 +22,7 @@ export interface ActionListProps { /** Defines a specific role attribute for each action in the list */ actionRole?: 'menuitem' | string; /** Allow users to filter items in the list. Will only show if more than 8 items in the list. The item content of every items must be a string for this to work */ - hasFiltering?: boolean; + allowFiltering?: boolean; /** Callback when any item is clicked or keypressed */ onActionAnyItem?: ActionListItemDescriptor['onAction']; } From c5ad6391397b22942e99d6d86215a3d22df2471e Mon Sep 17 00:00:00 2001 From: Maxime Cloutier Date: Thu, 14 Sep 2023 12:22:06 -0600 Subject: [PATCH 7/8] PR fixes --- .../src/components/ActionList/ActionList.stories.tsx | 1 + polaris-react/src/components/ActionList/ActionList.tsx | 4 ++-- .../components/ActionList/tests/ActionList.test.tsx | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/polaris-react/src/components/ActionList/ActionList.stories.tsx b/polaris-react/src/components/ActionList/ActionList.stories.tsx index c8c59bff71d..27aed5951dc 100644 --- a/polaris-react/src/components/ActionList/ActionList.stories.tsx +++ b/polaris-react/src/components/ActionList/ActionList.stories.tsx @@ -390,6 +390,7 @@ export function WithFiltering() {
({ content: `Item #${index + 1}`, }))} diff --git a/polaris-react/src/components/ActionList/ActionList.tsx b/polaris-react/src/components/ActionList/ActionList.tsx index 4143c4b2152..1b67cfded55 100644 --- a/polaris-react/src/components/ActionList/ActionList.tsx +++ b/polaris-react/src/components/ActionList/ActionList.tsx @@ -33,7 +33,7 @@ export function ActionList({ items, sections = [], actionRole, - hasFiltering, + allowFiltering, onActionAnyItem, }: ActionListProps) { const i18n = useI18n(); @@ -140,7 +140,7 @@ export function ActionList({ return ( <> - {(hasFiltering || filterActions) && hasSearch && isFilterable && ( + {(allowFiltering || filterActions) && hasSearch && isFilterable && ( 0 ? '0' : '2'}> ', () => { it('does not render search with 7 or less items', () => { const actionList = mountWithApp( ', () => { it('renders search with 8 or more items', () => { const actionList = mountWithApp( ', () => { expect(actionList).toContainReactComponentTimes(SearchField, 1); }); - it('does not renders search with 8 and no hasFiltering', () => { + it('does not renders search with 8 and no allowFiltering', () => { const actionList = mountWithApp( ', () => { const actionList = mountWithApp( ', () => { const actionList = mountWithApp( Date: Fri, 15 Sep 2023 10:10:49 -0600 Subject: [PATCH 8/8] PR fixes --- polaris-react/src/components/ActionList/ActionList.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/polaris-react/src/components/ActionList/ActionList.tsx b/polaris-react/src/components/ActionList/ActionList.tsx index 1b67cfded55..cfb20301610 100644 --- a/polaris-react/src/components/ActionList/ActionList.tsx +++ b/polaris-react/src/components/ActionList/ActionList.tsx @@ -27,6 +27,8 @@ export interface ActionListProps { onActionAnyItem?: ActionListItemDescriptor['onAction']; } +const FILTER_ACTIONS_THRESHOLD = 8; + export type ActionListItemProps = ItemProps; export function ActionList({ @@ -136,11 +138,11 @@ export function ActionList({ 0, ) || 0; - const hasSearch = totalActions >= 8; + const hasManyActions = totalActions >= FILTER_ACTIONS_THRESHOLD; return ( <> - {(allowFiltering || filterActions) && hasSearch && isFilterable && ( + {(allowFiltering || filterActions) && hasManyActions && isFilterable && ( 0 ? '0' : '2'}>