From cfd4163d4f9fbbcc3f260c8a6c86617fe68f9a5a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 21 Apr 2023 13:13:59 +1000 Subject: [PATCH 01/10] Allow passing popover props for palette popovers --- .../components/src/palette-edit/index.tsx | 39 +++++++++++++++++-- packages/components/src/palette-edit/types.ts | 8 +++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/components/src/palette-edit/index.tsx b/packages/components/src/palette-edit/index.tsx index bd9818d5d8db2..6f472a95b905b 100644 --- a/packages/components/src/palette-edit/index.tsx +++ b/packages/components/src/palette-edit/index.tsx @@ -6,7 +6,13 @@ import { paramCase as kebabCase } from 'change-case'; /** * WordPress dependencies */ -import { useState, useRef, useEffect, useCallback } from '@wordpress/element'; +import { + useState, + useRef, + useEffect, + useCallback, + useMemo, +} from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { lineSolid, moreVertical, plus } from '@wordpress/icons'; import { @@ -106,13 +112,20 @@ function ColorPickerPopover< T extends Color | Gradient >( { isGradient, element, onChange, + popoverProps: receivedPopoverProps, onClose = () => {}, }: ColorPickerPopoverProps< T > ) { + const popoverProps: ColorPickerPopoverProps< T >[ 'popoverProps' ] = { + shift: true, + offset: 20, + placement: 'left-start', + ...receivedPopoverProps, + }; + return ( { ! isGradient && ( @@ -154,17 +167,31 @@ function Option< T extends Color | Gradient >( { onStartEditing, onRemove, onStopEditing, + popoverProps: receivedPopoverProps, slugPrefix, isGradient, }: OptionProps< T > ) { const focusOutsideProps = useFocusOutside( onStopEditing ); const value = isGradient ? element.gradient : element.color; + // Use internal state instead of a ref to make sure that the component + // re-renders when the popover's anchor updates. + const [ popoverAnchor, setPopoverAnchor ] = useState( null ); + const popoverProps = useMemo( + () => ( { + ...receivedPopoverProps, + // Use the custom palette color item as the popover anchor. + anchor: popoverAnchor, + } ), + [ popoverAnchor, receivedPopoverProps ] + ); + return ( ( { isGradient={ isGradient } onChange={ onChange } element={ element } + popoverProps={ popoverProps } /> ) } @@ -244,6 +272,7 @@ function PaletteEditListView< T extends Color | Gradient >( { canOnlyChangeValues, slugPrefix, isGradient, + popoverProps, }: PaletteEditListViewProps< T > ) { // When unmounting the component if there are empty elements (the user did not complete the insertion) clean them. const elementsReference = useRef< typeof elements >(); @@ -317,6 +346,7 @@ function PaletteEditListView< T extends Color | Gradient >( { } } } slugPrefix={ slugPrefix } + popoverProps={ popoverProps } /> ) ) } @@ -356,6 +386,7 @@ export function PaletteEdit( { canOnlyChangeValues, canReset, slugPrefix = '', + popoverProps, }: PaletteEditProps ) { const isGradient = !! gradients; const elements = isGradient ? gradients : colors; @@ -541,6 +572,7 @@ export function PaletteEdit( { setEditingElement={ setEditingElement } slugPrefix={ slugPrefix } isGradient={ isGradient } + popoverProps={ popoverProps } /> ) } { ! isEditing && editingElement !== null && ( @@ -568,6 +600,7 @@ export function PaletteEdit( { ); } } element={ elements[ editingElement ?? -1 ] } + popoverProps={ popoverProps } /> ) } { ! isEditing && diff --git a/packages/components/src/palette-edit/types.ts b/packages/components/src/palette-edit/types.ts index 5513b94553778..56bff3a57dab6 100644 --- a/packages/components/src/palette-edit/types.ts +++ b/packages/components/src/palette-edit/types.ts @@ -7,6 +7,7 @@ import type { Key, MouseEventHandler } from 'react'; * Internal dependencies */ import type { HeadingSize } from '../heading/types'; +import type { PopoverProps } from '../popover/types'; export type Color = { color: string; @@ -85,7 +86,9 @@ type PaletteEditGradients = { }; export type PaletteEditProps = BasePaletteEdit & - ( PaletteEditColors | PaletteEditGradients ); + ( PaletteEditColors | PaletteEditGradients ) & { + popoverProps?: Omit< PopoverProps, 'children' >; + }; type EditingElement = number | null; @@ -94,6 +97,7 @@ export type ColorPickerPopoverProps< T extends Color | Gradient > = { onChange: ( newElement: T ) => void; isGradient?: T extends Gradient ? true : false; onClose?: () => void; + popoverProps?: Omit< PopoverProps, 'children' >; }; export type NameInputProps = { @@ -112,6 +116,7 @@ export type OptionProps< T extends Color | Gradient > = { onRemove: MouseEventHandler< HTMLButtonElement >; onStartEditing: () => void; onStopEditing: () => void; + popoverProps?: Omit< PopoverProps, 'children' >; slugPrefix: string; }; @@ -121,6 +126,7 @@ export type PaletteEditListViewProps< T extends Color | Gradient > = { isGradient: T extends Gradient ? true : false; canOnlyChangeValues: PaletteEditProps[ 'canOnlyChangeValues' ]; editingElement?: EditingElement; + popoverProps?: Omit< PopoverProps, 'children' >; setEditingElement: ( newEditingElement?: EditingElement ) => void; slugPrefix: string; }; From cd394fffdda4ef3a5674f87a56191eb5420c71e8 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 21 Apr 2023 13:14:27 +1000 Subject: [PATCH 02/10] Leverage popover props to modify palette popovers on mobile --- .../components/global-styles/color-palette-panel.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/edit-site/src/components/global-styles/color-palette-panel.js b/packages/edit-site/src/components/global-styles/color-palette-panel.js index 7bf422b878e01..e81b35772e2df 100644 --- a/packages/edit-site/src/components/global-styles/color-palette-panel.js +++ b/packages/edit-site/src/components/global-styles/color-palette-panel.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { useViewportMatch } from '@wordpress/compose'; import { __experimentalPaletteEdit as PaletteEdit, __experimentalVStack as VStack, @@ -43,6 +44,15 @@ export default function ColorPalettePanel( { name } ) { 'color.defaultPalette', name ); + + const isMobileViewport = useViewportMatch( 'small', '<' ); + const popoverProps = isMobileViewport + ? { + placement: 'bottom-start', + offset: 8, + } + : undefined; + return ( ) } { !! defaultColors && @@ -68,6 +79,7 @@ export default function ColorPalettePanel( { name } ) { onChange={ setDefaultColors } paletteLabel={ __( 'Default' ) } paletteLabelHeadingLevel={ 3 } + popoverProps={ popoverProps } /> ) } ); From b554e20dce4a8adf951828185d55c59cdba08862 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 24 Apr 2023 10:39:50 +1000 Subject: [PATCH 03/10] Add changelog --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 260c50887297d..c7ac55f89cf79 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -40,6 +40,7 @@ - `Modal`: Updated spacing / dimensions of `isFullScreen` ([#49894](https://github.com/WordPress/gutenberg/pull/49894)). - `SlotFill`: Added util for creating private SlotFills and supporting Symbol keys ([#49819](https://github.com/WordPress/gutenberg/pull/49819)). - `IconType`: Export for external use ([#49649](https://github.com/WordPress/gutenberg/pull/49649)). +- `PaletteEdit`: Allow custom position for color popovers ([#49975](https://github.com/WordPress/gutenberg/pull/49975)). ### Bug Fix From 384bf31cbebe607b556cfef3413b831b635d4b05 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:10:52 +1000 Subject: [PATCH 04/10] Tweak PaletteEdit storybook default args for popover position --- packages/components/src/palette-edit/stories/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/src/palette-edit/stories/index.tsx b/packages/components/src/palette-edit/stories/index.tsx index 5fd0d45592a82..5739964fbb276 100644 --- a/packages/components/src/palette-edit/stories/index.tsx +++ b/packages/components/src/palette-edit/stories/index.tsx @@ -59,6 +59,10 @@ Default.args = { ], paletteLabel: 'Colors', emptyMessage: 'Colors are empty', + popoverProps: { + placement: 'bottom-start', + offset: 8, + }, }; export const Gradients = Template.bind( {} ); From c70716b8bfd7dfeec6d8a1121437ffd47671e0a0 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:20:25 +1000 Subject: [PATCH 05/10] Improve changelog description --- packages/components/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c7ac55f89cf79..060344af3eede 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -40,7 +40,7 @@ - `Modal`: Updated spacing / dimensions of `isFullScreen` ([#49894](https://github.com/WordPress/gutenberg/pull/49894)). - `SlotFill`: Added util for creating private SlotFills and supporting Symbol keys ([#49819](https://github.com/WordPress/gutenberg/pull/49819)). - `IconType`: Export for external use ([#49649](https://github.com/WordPress/gutenberg/pull/49649)). -- `PaletteEdit`: Allow custom position for color popovers ([#49975](https://github.com/WordPress/gutenberg/pull/49975)). +- `PaletteEdit`: Allow custom popover configuration ([#49975](https://github.com/WordPress/gutenberg/pull/49975)). ### Bug Fix From 31f2f9426505c242d21482822791bc73b704daa4 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 2 May 2023 11:26:34 +1000 Subject: [PATCH 06/10] Clean up types --- packages/components/src/palette-edit/types.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/components/src/palette-edit/types.ts b/packages/components/src/palette-edit/types.ts index 56bff3a57dab6..db45d2fb07487 100644 --- a/packages/components/src/palette-edit/types.ts +++ b/packages/components/src/palette-edit/types.ts @@ -59,6 +59,10 @@ export type BasePaletteEdit = { * @default '' */ slugPrefix?: string; + /** + * Props to pass through to the underlying Popover component. + */ + popoverProps?: Omit< PopoverProps, 'children' >; }; type PaletteEditColors = { @@ -86,9 +90,7 @@ type PaletteEditGradients = { }; export type PaletteEditProps = BasePaletteEdit & - ( PaletteEditColors | PaletteEditGradients ) & { - popoverProps?: Omit< PopoverProps, 'children' >; - }; + ( PaletteEditColors | PaletteEditGradients ); type EditingElement = number | null; @@ -97,7 +99,7 @@ export type ColorPickerPopoverProps< T extends Color | Gradient > = { onChange: ( newElement: T ) => void; isGradient?: T extends Gradient ? true : false; onClose?: () => void; - popoverProps?: Omit< PopoverProps, 'children' >; + popoverProps?: PaletteEditProps[ 'popoverProps' ]; }; export type NameInputProps = { @@ -116,7 +118,7 @@ export type OptionProps< T extends Color | Gradient > = { onRemove: MouseEventHandler< HTMLButtonElement >; onStartEditing: () => void; onStopEditing: () => void; - popoverProps?: Omit< PopoverProps, 'children' >; + popoverProps?: PaletteEditProps[ 'popoverProps' ]; slugPrefix: string; }; @@ -126,7 +128,7 @@ export type PaletteEditListViewProps< T extends Color | Gradient > = { isGradient: T extends Gradient ? true : false; canOnlyChangeValues: PaletteEditProps[ 'canOnlyChangeValues' ]; editingElement?: EditingElement; - popoverProps?: Omit< PopoverProps, 'children' >; + popoverProps?: PaletteEditProps[ 'popoverProps' ]; setEditingElement: ( newEditingElement?: EditingElement ) => void; slugPrefix: string; }; From 2b5b2ecb8333112f98ba76ecdacf7931dc088f43 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 2 May 2023 11:47:33 +1000 Subject: [PATCH 07/10] Prevent color palette panel recreating popoverProps --- .../src/components/global-styles/color-palette-panel.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/color-palette-panel.js b/packages/edit-site/src/components/global-styles/color-palette-panel.js index e81b35772e2df..185a46fdba476 100644 --- a/packages/edit-site/src/components/global-styles/color-palette-panel.js +++ b/packages/edit-site/src/components/global-styles/color-palette-panel.js @@ -15,6 +15,7 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { unlock } from '../../private-apis'; const { useGlobalSetting } = unlock( blockEditorPrivateApis ); +const mobilePopoverProps = { placement: 'bottom-start', offset: 8 }; export default function ColorPalettePanel( { name } ) { const [ themeColors, setThemeColors ] = useGlobalSetting( @@ -46,12 +47,7 @@ export default function ColorPalettePanel( { name } ) { ); const isMobileViewport = useViewportMatch( 'small', '<' ); - const popoverProps = isMobileViewport - ? { - placement: 'bottom-start', - offset: 8, - } - : undefined; + const popoverProps = isMobileViewport ? mobilePopoverProps : undefined; return ( Date: Tue, 2 May 2023 12:42:51 +1000 Subject: [PATCH 08/10] Make memoization consistent and merge classnames --- .../components/src/palette-edit/index.tsx | 27 +++++++++++-------- packages/components/src/palette-edit/types.ts | 6 ++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/components/src/palette-edit/index.tsx b/packages/components/src/palette-edit/index.tsx index 6f472a95b905b..9061222567103 100644 --- a/packages/components/src/palette-edit/index.tsx +++ b/packages/components/src/palette-edit/index.tsx @@ -1,6 +1,7 @@ /** * External dependencies */ +import classnames from 'classnames'; import { paramCase as kebabCase } from 'change-case'; /** @@ -115,19 +116,23 @@ function ColorPickerPopover< T extends Color | Gradient >( { popoverProps: receivedPopoverProps, onClose = () => {}, }: ColorPickerPopoverProps< T > ) { - const popoverProps: ColorPickerPopoverProps< T >[ 'popoverProps' ] = { - shift: true, - offset: 20, - placement: 'left-start', - ...receivedPopoverProps, - }; + const popoverProps: ColorPickerPopoverProps< T >[ 'popoverProps' ] = + useMemo( + () => ( { + shift: true, + offset: 20, + placement: 'left-start', + ...receivedPopoverProps, + className: classnames( + 'components-palette-edit__popover', + receivedPopoverProps?.className + ), + } ), + [ receivedPopoverProps ] + ); return ( - + { ! isGradient && ( ; + popoverProps?: Omit< + WordPressComponentProps< PopoverProps, 'div', false >, + 'children' + >; }; type PaletteEditColors = { From 1f6490cada282538962bd760d2943d93e2b9ce45 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 4 May 2023 10:41:53 +1000 Subject: [PATCH 09/10] Tweak popoverProps type --- packages/components/src/palette-edit/types.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/components/src/palette-edit/types.ts b/packages/components/src/palette-edit/types.ts index 9925070a300e5..1cc0611628c2f 100644 --- a/packages/components/src/palette-edit/types.ts +++ b/packages/components/src/palette-edit/types.ts @@ -6,9 +6,8 @@ import type { Key, MouseEventHandler } from 'react'; /** * Internal dependencies */ +import type Popover from '../popover'; import type { HeadingSize } from '../heading/types'; -import type { PopoverProps } from '../popover/types'; -import type { WordPressComponentProps } from '../ui/context'; export type Color = { color: string; @@ -64,7 +63,7 @@ export type BasePaletteEdit = { * Props to pass through to the underlying Popover component. */ popoverProps?: Omit< - WordPressComponentProps< PopoverProps, 'div', false >, + React.ComponentPropsWithoutRef< typeof Popover >, 'children' >; }; From fd815ed63c41d5b586b440cda0e0190ec7e78b9f Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 4 May 2023 11:01:32 +1000 Subject: [PATCH 10/10] Fix changelog --- packages/components/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 060344af3eede..babf4e9c84f50 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -19,6 +19,7 @@ ### Enhancements - `Modal`: Add css class to children container ([#50099](https://github.com/WordPress/gutenberg/pull/50099)). +- `PaletteEdit`: Allow custom popover configuration ([#49975](https://github.com/WordPress/gutenberg/pull/49975)). ## 23.9.0 (2023-04-26) @@ -40,7 +41,6 @@ - `Modal`: Updated spacing / dimensions of `isFullScreen` ([#49894](https://github.com/WordPress/gutenberg/pull/49894)). - `SlotFill`: Added util for creating private SlotFills and supporting Symbol keys ([#49819](https://github.com/WordPress/gutenberg/pull/49819)). - `IconType`: Export for external use ([#49649](https://github.com/WordPress/gutenberg/pull/49649)). -- `PaletteEdit`: Allow custom popover configuration ([#49975](https://github.com/WordPress/gutenberg/pull/49975)). ### Bug Fix