diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 80c9884c565712..d20fb5898eb3aa 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - Refine `ExternalLink` to be same size as the text, to appear more as a glyph than an icon. ([#37859](https://github.com/WordPress/gutenberg/pull/37859)) +- Updated `ToolsPanel` header icon to only show "plus" icon when all items are optional and all are currently hidden ([#38262](https://github.com/WordPress/gutenberg/pull/38262)) ### Bug Fix diff --git a/packages/components/src/tools-panel/stories/index.js b/packages/components/src/tools-panel/stories/index.js index f3afeb11904ee6..a27792da448abb 100644 --- a/packages/components/src/tools-panel/stories/index.js +++ b/packages/components/src/tools-panel/stories/index.js @@ -2,6 +2,7 @@ * External dependencies */ import styled from '@emotion/styled'; +import { boolean } from '@storybook/addon-knobs'; /** * WordPress dependencies @@ -23,6 +24,9 @@ import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; export default { title: 'Components (Experimental)/ToolsPanel', component: ToolsPanel, + parameters: { + knobs: { disable: false }, + }, }; export const _default = () => { @@ -138,19 +142,36 @@ export const WithNonToolsPanelItems = () => { export const WithOptionalItemsPlusIcon = () => { const [ height, setHeight ] = useState(); const [ width, setWidth ] = useState(); + const [ minWidth, setMinWidth ] = useState(); const resetAll = () => { setHeight( undefined ); setWidth( undefined ); + setMinWidth( undefined ); }; + const includeDefaultControls = boolean( 'includeDefaultControls', false ); + return ( + !! minWidth } + label="Minimum width" + onDeselect={ () => setMinWidth( undefined ) } + isShownByDefault={ includeDefaultControls } + > + setMinWidth( next ) } + /> + !! width } label="Width" diff --git a/packages/components/src/tools-panel/test/index.js b/packages/components/src/tools-panel/test/index.js index 81ec094b2453b3..d1d884d439fa43 100644 --- a/packages/components/src/tools-panel/test/index.js +++ b/packages/components/src/tools-panel/test/index.js @@ -942,6 +942,17 @@ describe( 'ToolsPanel', () => { } ); describe( 'panel header icon toggle', () => { + const defaultControls = { + attributes: { value: false }, + hasValue: jest.fn().mockImplementation( () => { + return !! defaultControls.attributes.value; + } ), + label: 'Default', + onDeselect: jest.fn(), + onSelect: jest.fn(), + isShownByDefault: true, + }; + const optionalControls = { attributes: { value: false }, hasValue: jest.fn().mockImplementation( () => { @@ -953,7 +964,26 @@ describe( 'ToolsPanel', () => { isShownByDefault: false, }; - it( 'should render appropriate icons for the dropdown menu', async () => { + it( 'should render appropriate icon for the dropdown menu where there are default controls', async () => { + render( + + +
Default control
+
+ +
Optional control
+
+
+ ); + + const optionsDisplayedIcon = screen.getByRole( 'button', { + name: 'View options', + } ); + + expect( optionsDisplayedIcon ).toBeInTheDocument(); + } ); + + it( 'should render appropriate icons for the dropdown menu where there are no default controls', async () => { render( diff --git a/packages/components/src/tools-panel/tools-panel/hook.ts b/packages/components/src/tools-panel/tools-panel/hook.ts index 851ed4ca0c5841..3ef134d00c85c4 100644 --- a/packages/components/src/tools-panel/tools-panel/hook.ts +++ b/packages/components/src/tools-panel/tools-panel/hook.ts @@ -48,6 +48,10 @@ const generateMenuItems = ( { return menuItems; }; +const isMenuItemTypeEmpty = ( + obj?: ToolsPanelMenuItems[ ToolsPanelMenuItemKey ] +) => obj && Object.keys( obj ).length === 0; + export function useToolsPanel( props: WordPressComponentProps< ToolsPanelProps, 'div' > ) { @@ -167,24 +171,24 @@ export function useToolsPanel( ] = useState( false ); useEffect( () => { - if ( menuItems.optional ) { - const optionalItems = Object.entries( menuItems.optional ); - const allControlsHidden = - optionalItems.length > 0 && - ! optionalItems.some( ( [ , isSelected ] ) => isSelected ); + if ( + isMenuItemTypeEmpty( menuItems?.default ) && + ! isMenuItemTypeEmpty( menuItems?.optional ) + ) { + const allControlsHidden = ! Object.entries( + menuItems.optional + ).some( ( [ , isSelected ] ) => isSelected ); setAreAllOptionalControlsHidden( allControlsHidden ); } - }, [ menuItems.optional, setAreAllOptionalControlsHidden ] ); + }, [ menuItems, setAreAllOptionalControlsHidden ] ); const cx = useCx(); const classes = useMemo( () => { - const hasDefaultMenuItems = - menuItems?.default && !! Object.keys( menuItems?.default ).length; const wrapperStyle = hasInnerWrapper && styles.ToolsPanelWithInnerWrapper( DEFAULT_COLUMNS ); const emptyStyle = - ! hasDefaultMenuItems && + isMenuItemTypeEmpty( menuItems?.default ) && areAllOptionalControlsHidden && styles.ToolsPanelHiddenInnerWrapper;