diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 40278503108838..b6d13f24455cf8 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Update `BorderControl` and `BorderBoxControl` to allow the passing of custom class names to popovers ([#39753](https://github.com/WordPress/gutenberg/pull/39753)). + ### Internal - `BaseControl`: Convert to TypeScript ([#39468](https://github.com/WordPress/gutenberg/pull/39468)). diff --git a/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx b/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx index 41e2b2b3c33463..f1e7e26c37f0fa 100644 --- a/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx +++ b/packages/components/src/border-box-control/border-box-control-split-controls/component.tsx @@ -25,6 +25,7 @@ const BorderBoxControlSplitControls = ( enableAlpha, enableStyle, onChange, + popoverClassNames, value, __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, @@ -49,6 +50,7 @@ const BorderBoxControlSplitControls = ( hideLabelFromVision={ true } label={ __( 'Top border' ) } onChange={ ( newBorder ) => onChange( newBorder, 'top' ) } + popoverContentClassName={ popoverClassNames?.top } value={ value?.top } { ...sharedBorderControlProps } /> @@ -56,6 +58,7 @@ const BorderBoxControlSplitControls = ( hideLabelFromVision={ true } label={ __( 'Left border' ) } onChange={ ( newBorder ) => onChange( newBorder, 'left' ) } + popoverContentClassName={ popoverClassNames?.left } value={ value?.left } { ...sharedBorderControlProps } /> @@ -63,6 +66,7 @@ const BorderBoxControlSplitControls = ( hideLabelFromVision={ true } label={ __( 'Right border' ) } onChange={ ( newBorder ) => onChange( newBorder, 'right' ) } + popoverContentClassName={ popoverClassNames?.right } value={ value?.right } { ...sharedBorderControlProps } /> @@ -71,6 +75,7 @@ const BorderBoxControlSplitControls = ( hideLabelFromVision={ true } label={ __( 'Bottom border' ) } onChange={ ( newBorder ) => onChange( newBorder, 'bottom' ) } + popoverContentClassName={ popoverClassNames?.bottom } value={ value?.bottom } { ...sharedBorderControlProps } /> diff --git a/packages/components/src/border-box-control/border-box-control/README.md b/packages/components/src/border-box-control/border-box-control/README.md index 0706d0e20f63d0..1d27bae1531137 100644 --- a/packages/components/src/border-box-control/border-box-control/README.md +++ b/packages/components/src/border-box-control/border-box-control/README.md @@ -116,6 +116,26 @@ _Note: The will be `undefined` if a user clears all borders._ - Required: Yes +### `popoverClassNames`: `Object` + +An object defining CSS classnames for all the inner `BorderControl` popover +content. + +Example: +```js +{ + linked: 'linked-border-popover-content', + top: 'top-border-popover-content', + right: 'right-border-popover-content', + bottom: 'bottom-border-popover-content', + left: 'left-border-popover-content', +} +``` + +By default, popovers are displayed relative to the button that initiated the popover. By supplying classnames for each individual popover, it is possible to add styling rules to align the popover positions to an unrelated design element, for example, the sidebar inspector in the block editor. + +- Required: No + ### `value`: `Object` An object representing the current border configuration. diff --git a/packages/components/src/border-box-control/border-box-control/component.tsx b/packages/components/src/border-box-control/border-box-control/component.tsx index 05018cf80fe76c..976fdf90c798b1 100644 --- a/packages/components/src/border-box-control/border-box-control/component.tsx +++ b/packages/components/src/border-box-control/border-box-control/component.tsx @@ -51,6 +51,7 @@ const BorderBoxControl = ( linkedValue, onLinkedChange, onSplitChange, + popoverClassNames, splitValue, toggleLinked, __experimentalHasMultipleOrigins, @@ -76,6 +77,7 @@ const BorderBoxControl = ( placeholder={ hasMixedBorders ? __( 'Mixed' ) : undefined } + popoverContentClassName={ popoverClassNames?.linked } shouldSanitizeBorder={ false } // This component will handle that. value={ linkedValue } withSlider={ true } @@ -94,6 +96,7 @@ const BorderBoxControl = ( enableAlpha={ enableAlpha } enableStyle={ enableStyle } onChange={ onSplitChange } + popoverClassNames={ popoverClassNames } value={ splitValue } __experimentalHasMultipleOrigins={ __experimentalHasMultipleOrigins diff --git a/packages/components/src/border-box-control/types.ts b/packages/components/src/border-box-control/types.ts index c07f197c3f65f6..2a87c708f506f1 100644 --- a/packages/components/src/border-box-control/types.ts +++ b/packages/components/src/border-box-control/types.ts @@ -14,6 +14,14 @@ export type AnyBorder = Border | Borders | undefined; export type BorderProp = keyof Border; export type BorderSide = keyof Borders; +export type PopoverClassNames = { + linked?: string; + top?: string; + right?: string; + bottom?: string; + left?: string; +}; + export type BorderBoxControlProps = ColorProps & LabelProps & { /** @@ -26,6 +34,11 @@ export type BorderBoxControlProps = ColorProps & * individual side borders, or `undefined`. */ onChange: ( value: AnyBorder ) => void; + /** + * An object defining CSS classnames for all the inner `BorderControl` + * popover content. + */ + popoverClassNames?: PopoverClassNames; /** * An object representing the current border configuration. * @@ -71,6 +84,11 @@ export type SplitControlsProps = ColorProps & { * changed. */ onChange: ( value: Border | undefined, side: BorderSide ) => void; + /** + * An object defining CSS classnames for the split side `BorderControl`s' + * popover content. + */ + popoverClassNames?: PopoverClassNames; /** * An object representing the current border configuration. It contains * properties for each side, with each side an object reflecting the border diff --git a/packages/components/src/border-control/border-control-dropdown/hook.ts b/packages/components/src/border-control/border-control-dropdown/hook.ts index 4bdbdc7ded5c41..789dd7870cca50 100644 --- a/packages/components/src/border-control/border-control-dropdown/hook.ts +++ b/packages/components/src/border-control/border-control-dropdown/hook.ts @@ -20,6 +20,7 @@ export function useBorderControlDropdown( border, className, colors, + contentClassName, onChange, previousStyleSelection, ...otherProps @@ -64,8 +65,8 @@ export function useBorderControlDropdown( }, [ border, cx ] ); const popoverClassName = useMemo( () => { - return cx( styles.borderControlPopover ); - }, [ cx ] ); + return cx( styles.borderControlPopover, contentClassName ); + }, [ cx, contentClassName ] ); const popoverControlsClassName = useMemo( () => { return cx( styles.borderControlPopoverControls ); diff --git a/packages/components/src/border-control/border-control/README.md b/packages/components/src/border-control/border-control/README.md index 8c5991c68a0091..9300a697e0b3cf 100644 --- a/packages/components/src/border-control/border-control/README.md +++ b/packages/components/src/border-control/border-control/README.md @@ -107,6 +107,13 @@ _Note: the value may be `undefined` if a user clears all border properties._ - Required: Yes +### `popoverContentClassName`: `string` + +A custom CSS class name to be assigned to the `BorderControl`'s dropdown +popover content. + +- Required: No + ### `shouldSanitizeBorder`: `boolean` If opted into, sanitizing the border means that if no width or color have been diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index d4025f2c3c92f7..cf170861ea6c85 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -43,6 +43,7 @@ const BorderControl = ( onSliderChange, onWidthChange, placeholder, + popoverContentClassName, previousStyleSelection, showDropdownHeader, sliderClassName, @@ -67,6 +68,7 @@ const BorderControl = ( div:first-of-type > ${ StyledLabel } { margin-bottom: 0; diff --git a/packages/components/src/border-control/types.ts b/packages/components/src/border-control/types.ts index 0873599ee09a27..0a5971819d91fb 100644 --- a/packages/components/src/border-control/types.ts +++ b/packages/components/src/border-control/types.ts @@ -80,6 +80,11 @@ export type BorderControlProps = ColorProps & * interaction that selects or clears, border color, style, or width. */ onChange: ( value?: Border ) => void; + /** + * A custom CSS class name to be assigned to the border control's + * dropdown popover content. + */ + popoverContentClassName?: string; /** * If opted into, sanitizing the border means that if no width or color * have been selected, the border style is also cleared and `undefined` @@ -118,6 +123,11 @@ export type DropdownProps = ColorProps & { * values for its popover controls. */ border?: Border; + /** + * A custom CSS class name to be assigned to the border control's + * dropdown popover content. + */ + contentClassName?: string; /** * This controls whether to render border style options. *