diff --git a/packages/block-editor/src/components/border-radius-control/all-input-control.js b/packages/block-editor/src/components/border-radius-control/all-input-control.js index 31ad2aa30df9f..27256f03547f0 100644 --- a/packages/block-editor/src/components/border-radius-control/all-input-control.js +++ b/packages/block-editor/src/components/border-radius-control/all-input-control.js @@ -61,6 +61,7 @@ export default function AllInputControl( { onChange={ handleOnChange } onUnitChange={ handleOnUnitChange } placeholder={ allPlaceholder } + size={ '__unstable-large' } /> ); } diff --git a/packages/block-editor/src/components/border-radius-control/index.js b/packages/block-editor/src/components/border-radius-control/index.js index 9c2e96ba99b93..8754d39ac570f 100644 --- a/packages/block-editor/src/components/border-radius-control/index.js +++ b/packages/block-editor/src/components/border-radius-control/index.js @@ -113,6 +113,7 @@ export default function BorderRadiusControl( { onChange, values } ) { withInputField={ false } onChange={ handleSliderChange } step={ step } + __nextHasNoMarginBottom /> ) : ( diff --git a/packages/block-editor/src/components/border-radius-control/input-controls.js b/packages/block-editor/src/components/border-radius-control/input-controls.js index aa32c68c1a472..b33b79a482435 100644 --- a/packages/block-editor/src/components/border-radius-control/input-controls.js +++ b/packages/block-editor/src/components/border-radius-control/input-controls.js @@ -80,6 +80,7 @@ export default function BoxInputControls( { onUnitChange={ createHandleOnUnitChange( corner ) } + size={ '__unstable-large' } /> diff --git a/packages/block-editor/src/components/border-radius-control/style.scss b/packages/block-editor/src/components/border-radius-control/style.scss index 7e4f220709924..c94dfbbd0a8fd 100644 --- a/packages/block-editor/src/components/border-radius-control/style.scss +++ b/packages/block-editor/src/components/border-radius-control/style.scss @@ -10,24 +10,21 @@ justify-content: space-between; align-items: flex-start; - > .components-unit-control-wrapper { - width: 110px; + .components-border-radius-control__unit-control { + width: calc((100% - #{$grid-unit-20}) / 2); margin-bottom: 0; - margin-right: #{ $grid-unit-15 }; + margin-right: $grid-unit-20; flex-shrink: 0; } - .components-range-control { + .components-border-radius-control__range-control { flex: 1; - margin-bottom: 0; - - .components-base-control__field { - margin-bottom: 0; - height: 30px; - } + margin-right: $grid-unit-15; - .components-range-control__wrapper { - margin-right: 10px; + > div { + height: 40px; + display: flex; + align-items: center; } } @@ -37,22 +34,16 @@ } .components-border-radius-control__input-controls-wrapper { - display: flex; - width: 70%; - flex-wrap: wrap; - - .components-border-radius-control__tooltip-wrapper { - width: calc(50% - #{ $grid-unit-10 }); - margin-bottom: $grid-unit-10; - margin-right: $grid-unit-10; - } + display: grid; + gap: $grid-unit-20; + grid-template-columns: repeat(2, minmax(0, 1fr)); + margin-right: $grid-unit-15; } - .component-border-radius-control__linked-button.has-icon { + .component-border-radius-control__linked-button { display: flex; justify-content: center; - margin-left: 2px; - margin-top: 3px; + margin-top: $grid-unit-10; svg { margin-right: 0; diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index ffaf5d4615783..11ee3e95f4d66 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -272,6 +272,7 @@ export function BorderPanel( props ) { onChange={ onBorderChange } popoverOffset={ 40 } popoverPlacement="left-start" + size="__unstable-large" value={ hydratedBorder } __experimentalHasMultipleOrigins={ true } __experimentalIsRenderedInSidebar={ true } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index abebbf294e609..b33944fb43115 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -14,10 +14,12 @@ - `BoxControl` & `CustomSelectControl`: Add `onMouseOver` and `onMouseOut` callback props to allow handling of these events by parent components ([#44955](https://github.com/WordPress/gutenberg/pull/44955)) -## Enhancements +### Enhancements - `FontSizePicker`: Improved slider design when `withSlider` is set ([#44598](https://github.com/WordPress/gutenberg/pull/44598)). - `ToggleControl`: Improved types for the `help` prop, covering the dynamic render function option, and enabled the dynamic `help` behavior only for a controlled component ([#45279](https://github.com/WordPress/gutenberg/pull/45279)). +- `BorderControl` & `BorderBoxControl`: Replace `__next36pxDefaultSize` with "default" and "large" size variants ([#41860](https://github.com/WordPress/gutenberg/pull/41860)). +- `UnitControl`: Remove outer wrapper to normalize className placement ([#41860](https://github.com/WordPress/gutenberg/pull/41860)). ### Bug Fix @@ -30,6 +32,7 @@ ### Internal +- `BorderBoxControl`: Convert stories to TypeScript and use Controls ([#45002](https://github.com/WordPress/gutenberg/pull/45002)). - `Disabled`: add a note in the docs about the lack of polyfill for the `inert` attribute ([#45272](https://github.com/WordPress/gutenberg/pull/45272)) - `Snackbar`: updated to satisfy `react/exhaustive-deps` eslint rule ([#44934](https://github.com/WordPress/gutenberg/pull/44934)) - `AnglePickerControl`: Set Storybook Label control type to 'text' ([#45122](https://github.com/WordPress/gutenberg/pull/45122)). diff --git a/packages/components/src/border-box-control/border-box-control-linked-button/hook.ts b/packages/components/src/border-box-control/border-box-control-linked-button/hook.ts index 58c2089888409..043c101b05f5a 100644 --- a/packages/components/src/border-box-control/border-box-control-linked-button/hook.ts +++ b/packages/components/src/border-box-control/border-box-control-linked-button/hook.ts @@ -17,18 +17,15 @@ export function useBorderBoxControlLinkedButton( ) { const { className, - __next36pxDefaultSize = false, + size = 'default', ...otherProps } = useContextSystem( props, 'BorderBoxControlLinkedButton' ); // Generate class names. const cx = useCx(); const classes = useMemo( () => { - return cx( - styles.BorderBoxControlLinkedButton( __next36pxDefaultSize ), - className - ); - }, [ className, cx, __next36pxDefaultSize ] ); + return cx( styles.borderBoxControlLinkedButton( size ), className ); + }, [ className, cx, size ] ); return { ...otherProps, className: classes }; } 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 e0d44852bca58..b5b80c0aa6b50 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 @@ -31,10 +31,10 @@ const BorderBoxControlSplitControls = ( popoverPlacement, popoverOffset, rightAlignedClassName, + size = 'default', value, __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, - __next36pxDefaultSize, ...otherProps } = useBorderBoxControlSplitControls( props ); @@ -67,17 +67,14 @@ const BorderBoxControlSplitControls = ( isCompact: true, __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, - __next36pxDefaultSize, + size, }; const mergedRef = useMergeRefs( [ setPopoverAnchor, forwardedRef ] ); return ( - + ) { - const { className, ...otherProps } = useContextSystem( - props, - 'BorderBoxControlSplitControls' - ); + const { + className, + size = 'default', + ...otherProps + } = useContextSystem( props, 'BorderBoxControlSplitControls' ); // Generate class names. const cx = useCx(); - const rtlWatchResult = rtl.watch(); const classes = useMemo( () => { - return cx( styles.borderBoxControlSplitControls(), className ); - // rtlWatchResult is needed to refresh styles when the writing direction changes - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ cx, className, rtlWatchResult ] ); + return cx( styles.borderBoxControlSplitControls( size ), className ); + }, [ cx, className, size ] ); const centeredClassName = useMemo( () => { - return cx( styles.CenteredBorderControl, className ); + return cx( styles.centeredBorderControl, className ); }, [ cx, className ] ); const rightAlignedClassName = useMemo( () => { return cx( styles.rightBorderControl(), className ); - // rtlWatchResult is needed to refresh styles when the writing direction changes - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ cx, className, rtlWatchResult ] ); + }, [ cx, className ] ); return { ...otherProps, centeredClassName, className: classes, rightAlignedClassName, + size, }; } diff --git a/packages/components/src/border-box-control/border-box-control-visualizer/hook.ts b/packages/components/src/border-box-control/border-box-control-visualizer/hook.ts index 75fc6a7a36777..4e6e69e9d8452 100644 --- a/packages/components/src/border-box-control/border-box-control-visualizer/hook.ts +++ b/packages/components/src/border-box-control/border-box-control-visualizer/hook.ts @@ -8,7 +8,7 @@ import { useMemo } from '@wordpress/element'; */ import * as styles from '../styles'; import { useContextSystem, WordPressComponentProps } from '../../ui/context'; -import { useCx, rtl } from '../../utils'; +import { useCx } from '../../utils'; import type { VisualizerProps } from '../types'; @@ -18,21 +18,18 @@ export function useBorderBoxControlVisualizer( const { className, value, - __next36pxDefaultSize = false, + size = 'default', ...otherProps } = useContextSystem( props, 'BorderBoxControlVisualizer' ); // Generate class names. const cx = useCx(); - const rtlWatchResult = rtl.watch(); const classes = useMemo( () => { return cx( - styles.borderBoxControlVisualizer( value, __next36pxDefaultSize ), + styles.borderBoxControlVisualizer( value, size ), className ); - // rtlWatchResult is needed to refresh styles when the writing direction changes - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ cx, className, value, __next36pxDefaultSize, rtlWatchResult ] ); + }, [ cx, className, value, size ] ); return { ...otherProps, className: classes, value }; } 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 c895c1b853de1..86492a4f4136a 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 @@ -138,6 +138,14 @@ Works in conjunctions with `popoverPlacement` and allows leaving a space between - Required: No +### `size`: `string` + +Size of the control. + +- Required: No +- Default: `default` +- Allowed values: `default`, `__unstable-large` + ### `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 195d968eca22b..4918abafebfce 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 @@ -11,7 +11,6 @@ import { useMergeRefs } from '@wordpress/compose'; import BorderBoxControlLinkedButton from '../border-box-control-linked-button'; import BorderBoxControlSplitControls from '../border-box-control-split-controls'; import { BorderControl } from '../../border-control'; -import { HStack } from '../../h-stack'; import { StyledLabel } from '../../base-control/styles/base-control-styles'; import { View } from '../../view'; import { VisuallyHidden } from '../../visually-hidden'; @@ -38,8 +37,8 @@ const BorderLabel = ( props: LabelProps ) => { ); }; -const BorderBoxControl = ( - props: WordPressComponentProps< BorderBoxControlProps, 'div' >, +const UnconnectedBorderBoxControl = ( + props: WordPressComponentProps< BorderBoxControlProps, 'div', false >, forwardedRef: React.ForwardedRef< any > ) => { const { @@ -59,11 +58,12 @@ const BorderBoxControl = ( onSplitChange, popoverPlacement, popoverOffset, + size = 'default', splitValue, toggleLinked, + wrapperClassName, __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, - __next36pxDefaultSize = false, ...otherProps } = useBorderBoxControl( props ); @@ -96,7 +96,7 @@ const BorderBoxControl = ( label={ label } hideLabelFromVision={ hideLabelFromVision } /> - + { isLinked ? ( ) : ( ) } - + ); }; -const ConnectedBorderBoxControl = contextConnect( - BorderBoxControl, +/** + * The `BorderBoxControl` effectively has two view states. The first, a "linked" + * view, allows configuration of a flat border via a single `BorderControl`. + * The second, a "split" view, contains a `BorderControl` for each side + * as well as a visualizer for the currently selected borders. Each view also + * contains a button to toggle between the two. + * + * When switching from the "split" view to "linked", if the individual side + * borders are not consistent, the "linked" view will display any border + * properties selections that are consistent while showing a mixed state for + * those that aren't. For example, if all borders had the same color and style + * but different widths, then the border dropdown in the "linked" view's + * `BorderControl` would show that consistent color and style but the "linked" + * view's width input would show "Mixed" placeholder text. + * + * ```jsx + * import { __experimentalBorderBoxControl as BorderBoxControl } from '@wordpress/components'; + * import { __ } from '@wordpress/i18n'; + * + * const colors = [ + * { name: 'Blue 20', color: '#72aee6' }, + * // ... + * ]; + * + * const MyBorderBoxControl = () => { + * const defaultBorder = { + * color: '#72aee6', + * style: 'dashed', + * width: '1px', + * }; + * const [ borders, setBorders ] = useState( { + * top: defaultBorder, + * right: defaultBorder, + * bottom: defaultBorder, + * left: defaultBorder, + * } ); + * const onChange = ( newBorders ) => setBorders( newBorders ); + * + * return ( + * + * ); + * }; + * ``` + */ +export const BorderBoxControl = contextConnect( + UnconnectedBorderBoxControl, 'BorderBoxControl' ); -export default ConnectedBorderBoxControl; +export default BorderBoxControl; diff --git a/packages/components/src/border-box-control/border-box-control/hook.ts b/packages/components/src/border-box-control/border-box-control/hook.ts index 7a4add756ed2d..fed695d182b42 100644 --- a/packages/components/src/border-box-control/border-box-control/hook.ts +++ b/packages/components/src/border-box-control/border-box-control/hook.ts @@ -100,11 +100,15 @@ export function useBorderBoxControl( const cx = useCx(); const classes = useMemo( () => { - return cx( styles.BorderBoxControl, className ); + return cx( styles.borderBoxControl, className ); }, [ cx, className ] ); const linkedControlClassName = useMemo( () => { - return cx( styles.LinkedBorderControl ); + return cx( styles.linkedBorderControl() ); + }, [ cx ] ); + + const wrapperClassName = useMemo( () => { + return cx( styles.wrapper ); }, [ cx ] ); return { @@ -119,5 +123,6 @@ export function useBorderBoxControl( toggleLinked, linkedValue, splitValue, + wrapperClassName, }; } diff --git a/packages/components/src/border-box-control/stories/index.js b/packages/components/src/border-box-control/stories/index.js deleted file mode 100644 index 469d6d4d3407f..0000000000000 --- a/packages/components/src/border-box-control/stories/index.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * External dependencies - */ -import styled from '@emotion/styled'; - -/** - * WordPress dependencies - */ -import { useEffect, useState } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import Button from '../../button'; -import Popover from '../../popover'; -import { BorderBoxControl } from '../'; -import { Provider as SlotFillProvider } from '../../slot-fill'; - -// Available border colors. -const colors = [ - { name: 'Gray 0', color: '#f6f7f7' }, - { name: 'Gray 5', color: '#dcdcde' }, - { name: 'Gray 20', color: '#a7aaad' }, - { name: 'Gray 70', color: '#3c434a' }, - { name: 'Gray 100', color: '#101517' }, - { name: 'Blue 20', color: '#72aee6' }, - { name: 'Blue 40', color: '#3582c4' }, - { name: 'Blue 70', color: '#0a4b78' }, - { name: 'Red 40', color: '#e65054' }, - { name: 'Red 70', color: '#8a2424' }, - { name: 'Green 10', color: '#68de7c' }, - { name: 'Green 40', color: '#00a32a' }, - { name: 'Green 60', color: '#007017' }, - { name: 'Yellow 10', color: '#f2d675' }, - { name: 'Yellow 40', color: '#bd8600' }, -]; - -export default { - title: 'Components (Experimental)/BorderBoxControl', - component: BorderBoxControl, - parameters: { - knobs: { disable: false }, - }, -}; - -const _default = ( props ) => { - const { defaultBorder } = props; - const [ borders, setBorders ] = useState( defaultBorder ); - - useEffect( () => setBorders( defaultBorder ), [ defaultBorder ] ); - - return ( - - - setBorders( newBorders ) } - value={ borders } - { ...props } - /> - - - - The BorderBoxControl is intended to be used within a component - that will provide reset controls. The button below is only for - convenience. - - - - - ); -}; - -export const Default = _default.bind( {} ); -Default.args = { - disableCustomColors: false, - enableAlpha: true, - enableStyle: true, - defaultBorder: { - color: '#72aee6', - style: 'dashed', - width: '1px', - }, - __next36pxDefaultSize: false, - popoverPlacement: 'right-start', -}; - -const WrapperView = styled.div` - max-width: 280px; - padding: 16px; -`; - -const Separator = styled.hr` - margin-top: 100px; - border-color: #ddd; - border-style: solid; - border-bottom: none; -`; - -const HelpText = styled.p` - color: #aaa; - font-size: 0.9em; -`; diff --git a/packages/components/src/border-box-control/stories/index.tsx b/packages/components/src/border-box-control/stories/index.tsx new file mode 100644 index 0000000000000..b391c2f00f592 --- /dev/null +++ b/packages/components/src/border-box-control/stories/index.tsx @@ -0,0 +1,90 @@ +/** + * External dependencies + */ +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { ComponentProps } from 'react'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Button from '../../button'; +import Popover from '../../popover'; +import { BorderBoxControl } from '../'; +import { Provider as SlotFillProvider } from '../../slot-fill'; + +const meta: ComponentMeta< typeof BorderBoxControl > = { + title: 'Components (Experimental)/BorderBoxControl', + component: BorderBoxControl, + argTypes: { + onChange: { action: 'onChange' }, + value: { control: { type: null } }, + }, + parameters: { + controls: { expanded: true }, + docs: { source: { state: 'open' } }, + }, +}; +export default meta; + +// Available border colors. +const colors = [ + { name: 'Blue 20', color: '#72aee6' }, + { name: 'Blue 40', color: '#3582c4' }, + { name: 'Red 40', color: '#e65054' }, + { name: 'Red 70', color: '#8a2424' }, + { name: 'Yellow 10', color: '#f2d675' }, + { name: 'Yellow 40', color: '#bd8600' }, +]; + +const Template: ComponentStory< typeof BorderBoxControl > = ( props ) => { + const { onChange, ...otherProps } = props; + const [ borders, setBorders ] = useState< typeof props[ 'value' ] >(); + + const onChangeMerged: ComponentProps< + typeof BorderBoxControl + >[ 'onChange' ] = ( newBorders ) => { + setBorders( newBorders ); + onChange( newBorders ); + }; + + return ( + + +
+

+ The BorderBoxControl is intended to be used within a component + that will provide reset controls. The button below is only for + convenience. +

+ + { /* @ts-expect-error Ignore until Popover.Slot is converted to TS */ } + +
+ ); +}; +export const Default = Template.bind( {} ); +Default.args = { + colors, + label: 'Borders', +}; diff --git a/packages/components/src/border-box-control/styles.ts b/packages/components/src/border-box-control/styles.ts index e5bb4ce638acd..3fba981080a51 100644 --- a/packages/components/src/border-box-control/styles.ts +++ b/packages/components/src/border-box-control/styles.ts @@ -7,29 +7,33 @@ import { css } from '@emotion/react'; * Internal dependencies */ import { COLORS, CONFIG, rtl } from '../utils'; -import { space } from '../ui/utils/space'; import type { Border } from '../border-control/types'; import type { Borders } from './types'; -export const BorderBoxControl = css``; +export const borderBoxControl = css``; -export const LinkedBorderControl = css` +export const linkedBorderControl = () => css` flex: 1; + ${ rtl( { marginRight: '24px' } )() } `; -export const BorderBoxControlLinkedButton = ( - __next36pxDefaultSize?: boolean +export const wrapper = css` + position: relative; +`; + +export const borderBoxControlLinkedButton = ( + size?: 'default' | '__unstable-large' ) => { return css` - flex: 0; - flex-basis: 24px; + position: absolute; + top: ${ size === '__unstable-large' ? '8px' : '3px' }; + ${ rtl( { right: 0 } )() } line-height: 0; - margin-top: ${ __next36pxDefaultSize ? '6px' : '3px' }; `; }; -const BorderBoxStyleWithFallback = ( border?: Border ) => { +const borderBoxStyleWithFallback = ( border?: Border ) => { const { color = COLORS.gray[ 200 ], style = 'solid', @@ -46,36 +50,38 @@ const BorderBoxStyleWithFallback = ( border?: Border ) => { export const borderBoxControlVisualizer = ( borders?: Borders, - __next36pxDefaultSize?: boolean + size?: 'default' | '__unstable-large' ) => { return css` position: absolute; - top: ${ __next36pxDefaultSize ? '18px' : '15px' }; - right: 30px; - bottom: ${ __next36pxDefaultSize ? '18px' : '15px' }; - left: 30px; - border-top: ${ BorderBoxStyleWithFallback( borders?.top ) }; - border-bottom: ${ BorderBoxStyleWithFallback( borders?.bottom ) }; + top: ${ size === '__unstable-large' ? '20px' : '15px' }; + right: ${ size === '__unstable-large' ? '39px' : '29px' }; + bottom: ${ size === '__unstable-large' ? '20px' : '15px' }; + left: ${ size === '__unstable-large' ? '39px' : '29px' }; + border-top: ${ borderBoxStyleWithFallback( borders?.top ) }; + border-bottom: ${ borderBoxStyleWithFallback( borders?.bottom ) }; ${ rtl( { - borderLeft: BorderBoxStyleWithFallback( borders?.left ), + borderLeft: borderBoxStyleWithFallback( borders?.left ), } )() } ${ rtl( { - borderRight: BorderBoxStyleWithFallback( borders?.right ), + borderRight: borderBoxStyleWithFallback( borders?.right ), } )() } `; }; -export const borderBoxControlSplitControls = () => css` +export const borderBoxControlSplitControls = ( + size?: 'default' | '__unstable-large' +) => css` position: relative; flex: 1; - ${ rtl( { marginRight: space( 3 ) }, { marginLeft: space( 3 ) } )() } + width: ${ size === '__unstable-large' ? undefined : '80%' }; `; -export const CenteredBorderControl = css` +export const centeredBorderControl = css` grid-column: span 2; margin: 0 auto; `; export const rightBorderControl = () => css` - ${ rtl( { marginLeft: 'auto' }, { marginRight: 'auto' } )() } + ${ rtl( { marginLeft: 'auto' } )() } `; diff --git a/packages/components/src/border-box-control/types.ts b/packages/components/src/border-box-control/types.ts index d852a5bd1e40a..8e88e0b958c56 100644 --- a/packages/components/src/border-box-control/types.ts +++ b/packages/components/src/border-box-control/types.ts @@ -44,12 +44,11 @@ export type BorderBoxControlProps = ColorProps & */ value: AnyBorder; /** - * Start opting into the larger default height that will become the - * default size in a future version. + * Size of the control. * - * @default false + * @default 'default' */ - __next36pxDefaultSize?: boolean; + size?: 'default' | '__unstable-large'; }; export type LinkedButtonProps = { @@ -66,12 +65,11 @@ export type LinkedButtonProps = { */ onClick: () => void; /** - * Start opting into the larger default height that will become the - * default size in a future version. + * Size of the control. * - * @default false + * @default 'default' */ - __next36pxDefaultSize?: boolean; + size?: 'default' | '__unstable-large'; }; export type VisualizerProps = { @@ -82,12 +80,11 @@ export type VisualizerProps = { */ value?: Borders; /** - * Start opting into the larger default height that will become the - * default size in a future version. + * Size of the control. * - * @default false + * @default 'default' */ - __next36pxDefaultSize?: boolean; + size?: 'default' | '__unstable-large'; }; export type SplitControlsProps = ColorProps & { @@ -116,10 +113,9 @@ export type SplitControlsProps = ColorProps & { */ value?: Borders; /** - * Start opting into the larger default height that will become the - * default size in a future version. + * Size of the control. * - * @default false + * @default 'default' */ - __next36pxDefaultSize?: boolean; + size?: 'default' | '__unstable-large'; }; 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 bcf90b71a59db..a50ad72150054 100644 --- a/packages/components/src/border-control/border-control-dropdown/hook.ts +++ b/packages/components/src/border-control/border-control-dropdown/hook.ts @@ -22,7 +22,7 @@ export function useBorderControlDropdown( colors, onChange, previousStyleSelection, - __next36pxDefaultSize, + size = 'default', ...otherProps } = useContextSystem( props, 'BorderControlDropdown' ); @@ -53,18 +53,16 @@ export function useBorderControlDropdown( // Generate class names. const cx = useCx(); const classes = useMemo( () => { - return cx( styles.borderControlDropdown(), className ); - }, [ className, cx ] ); + return cx( styles.borderControlDropdown( size ), className ); + }, [ className, cx, size ] ); const indicatorClassName = useMemo( () => { return cx( styles.borderColorIndicator ); }, [ cx ] ); const indicatorWrapperClassName = useMemo( () => { - return cx( - styles.colorIndicatorWrapper( border, __next36pxDefaultSize ) - ); - }, [ border, cx, __next36pxDefaultSize ] ); + return cx( styles.colorIndicatorWrapper( border, size ) ); + }, [ border, cx, size ] ); 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 718ec3d703908..83bf939b97961 100644 --- a/packages/components/src/border-control/border-control/README.md +++ b/packages/components/src/border-control/border-control/README.md @@ -135,6 +135,14 @@ dropdown. The header includes a label for the color picker and a close button. - Required: No +### `size`: `string` + +Size of the control. + +- Required: No +- Default: `default` +- Allowed values: `default`, `__unstable-large` + ### `value`: `Object` An object representing a border or `undefined`. Used to set the current border diff --git a/packages/components/src/border-control/border-control/component.tsx b/packages/components/src/border-control/border-control/component.tsx index cae27c1eefa4b..bf0beb8508546 100644 --- a/packages/components/src/border-control/border-control/component.tsx +++ b/packages/components/src/border-control/border-control/component.tsx @@ -53,6 +53,7 @@ const UnconnectedBorderControl = ( __unstablePopoverProps, previousStyleSelection, showDropdownHeader, + size = 'default', sliderClassName, value: border, widthUnit, @@ -60,7 +61,6 @@ const UnconnectedBorderControl = ( withSlider, __experimentalHasMultipleOrigins, __experimentalIsRenderedInSidebar, - __next36pxDefaultSize, ...otherProps } = useBorderControl( props ); @@ -70,7 +70,7 @@ const UnconnectedBorderControl = ( label={ label } hideLabelFromVision={ hideLabelFromVision } /> - + } label={ __( 'Border width' ) } @@ -100,6 +100,7 @@ const UnconnectedBorderControl = ( placeholder={ placeholder } disableUnits={ disableUnits } __unstableInputWidth={ inputWidth } + size={ size } /> { withSlider && ( { const widthStyle = !! wrapperWidth && styles.wrapperWidth; - const heightStyle = styles.wrapperHeight( __next36pxDefaultSize ); + const heightStyle = styles.wrapperHeight( size ); return cx( styles.innerWrapper(), widthStyle, heightStyle ); - }, [ wrapperWidth, cx, __next36pxDefaultSize ] ); + }, [ wrapperWidth, cx, size ] ); const sliderClassName = useMemo( () => { return cx( styles.borderSlider() ); @@ -143,6 +147,6 @@ export function useBorderControl( value: border, widthUnit, widthValue, - __next36pxDefaultSize, + size, }; } diff --git a/packages/components/src/border-control/stories/index.tsx b/packages/components/src/border-control/stories/index.tsx index 59aa440591b7f..2735e3ea2717b 100644 --- a/packages/components/src/border-control/stories/index.tsx +++ b/packages/components/src/border-control/stories/index.tsx @@ -36,12 +36,12 @@ export default meta; // Available border colors. const colors = [ - { name: 'Blue', color: '#72aee6' }, - { name: 'Red', color: '#e65054' }, - { name: 'Yellow', color: '#f2d675' }, - { name: 'Blue', color: '#72aee6' }, - { name: 'Red', color: '#e65054' }, - { name: 'Yellow', color: '#f2d675' }, + { name: 'Blue 20', color: '#72aee6' }, + { name: 'Blue 40', color: '#3582c4' }, + { name: 'Red 40', color: '#e65054' }, + { name: 'Red 70', color: '#8a2424' }, + { name: 'Yellow 10', color: '#f2d675' }, + { name: 'Yellow 40', color: '#bd8600' }, ]; // Multiple origin colors. @@ -84,14 +84,12 @@ const Template: ComponentStory< typeof BorderControl > = ( { return ( -
- -
- { /* @ts-expect-error Ignore until Popover is converted to TS */ } + + { /* @ts-expect-error Ignore until Popover.Slot is converted to TS */ }
); diff --git a/packages/components/src/border-control/styles.ts b/packages/components/src/border-control/styles.ts index 3c49e53a350ee..b105e8b62bd7b 100644 --- a/packages/components/src/border-control/styles.ts +++ b/packages/components/src/border-control/styles.ts @@ -13,7 +13,7 @@ import { StyledLabel, } from '../base-control/styles/base-control-styles'; import { - Root as UnitControlWrapper, + ValueInput as UnitControlWrapper, UnitSelect, } from '../unit-control/styles/unit-control-styles'; @@ -56,26 +56,28 @@ export const wrapperWidth = css` } `; -/* - * When default control height is 36px the following should be removed. - * See: InputControl and __next36pxDefaultSize. - */ -export const wrapperHeight = ( __next36pxDefaultSize?: boolean ) => { +export const wrapperHeight = ( size?: 'default' | '__unstable-large' ) => { return css` - height: ${ __next36pxDefaultSize ? '36px' : '30px' }; + height: ${ size === '__unstable-large' ? '40px' : '30px' }; `; }; -export const borderControlDropdown = () => css` +export const borderControlDropdown = ( + size?: 'default' | '__unstable-large' +) => css` background: #fff; && > button { /* - * Override button component height and padding to fit within - * BorderControl regardless of size. + * Override button component styles to fit within BorderControl + * regardless of size. */ - height: 100%; - padding: ${ space( 0.75 ) }; + height: ${ size === '__unstable-large' ? '40px' : '30px' }; + width: ${ size === '__unstable-large' ? '40px' : '30px' }; + padding: 0; + display: flex; + align-items: center; + justify-content: center; ${ rtl( { borderRadius: `2px 0 0 2px` }, { borderRadius: `0 2px 2px 0` } @@ -106,7 +108,7 @@ export const colorIndicatorBorder = ( border?: Border ) => { export const colorIndicatorWrapper = ( border?: Border, - __next36pxDefaultSize?: boolean + size?: 'default' | '__unstable-large' ) => { const { style } = border || {}; @@ -114,9 +116,9 @@ export const colorIndicatorWrapper = ( border-radius: 9999px; border: 2px solid transparent; ${ style ? colorIndicatorBorder( border ) : undefined } - width: ${ __next36pxDefaultSize ? '28px' : '22px' }; - height: ${ __next36pxDefaultSize ? '28px' : '22px' }; - padding: ${ __next36pxDefaultSize ? '2px' : '1px' }; + width: ${ size === '__unstable-large' ? '24px' : '22px' }; + height: ${ size === '__unstable-large' ? '24px' : '22px' }; + padding: ${ size === '__unstable-large' ? '2px' : '1px' }; /* * ColorIndicator @@ -125,13 +127,8 @@ export const colorIndicatorWrapper = ( * over the active state of the border control dropdown's toggle button. */ & > span { - ${ ! __next36pxDefaultSize - ? css` - /* Dimensions fit in 30px overall control height. */ - height: 16px; - width: 16px; - ` - : '' } + height: ${ space( 4 ) }; + width: ${ space( 4 ) }; background: linear-gradient( -45deg, transparent 48%, diff --git a/packages/components/src/border-control/types.ts b/packages/components/src/border-control/types.ts index 9725d90a7f62a..7710fb4705493 100644 --- a/packages/components/src/border-control/types.ts +++ b/packages/components/src/border-control/types.ts @@ -123,12 +123,11 @@ export type BorderControlProps = ColorProps & */ withSlider?: boolean; /** - * Start opting into the larger default height that will become the - * default size in a future version. + * Size of the control. * - * @default false + * @default 'default' */ - __next36pxDefaultSize?: boolean; + size?: 'default' | '__unstable-large'; }; export type DropdownProps = ColorProps & { @@ -165,12 +164,11 @@ export type DropdownProps = ColorProps & { */ showDropdownHeader?: boolean; /** - * Start opting into the larger default height that will become the - * default size in a future version. + * Size of the control. * - * @default false + * @default 'default' */ - __next36pxDefaultSize?: boolean; + size?: 'default' | '__unstable-large'; }; export type StylePickerProps = LabelProps & { diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index 83e6fe500faa1..5f932fd5e0fff 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -38,6 +38,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` -webkit-justify-content: space-between; justify-content: space-between; height: 100%; + box-sizing: border-box; position: relative; border-radius: 2px; padding-top: 0; @@ -309,6 +310,7 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` -webkit-justify-content: space-between; justify-content: space-between; height: 100%; + box-sizing: border-box; position: relative; border-radius: 2px; padding-top: 0; @@ -590,6 +592,7 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] -webkit-justify-content: space-between; justify-content: space-between; height: 100%; + box-sizing: border-box; position: relative; border-radius: 2px; padding-top: 0; @@ -883,6 +886,7 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] -webkit-justify-content: space-between; justify-content: space-between; height: 100%; + box-sizing: border-box; position: relative; border-radius: 2px; padding-top: 0; diff --git a/packages/components/src/font-size-picker/types.ts b/packages/components/src/font-size-picker/types.ts index 2c824125bb7e1..e61988b6d4fbf 100644 --- a/packages/components/src/font-size-picker/types.ts +++ b/packages/components/src/font-size-picker/types.ts @@ -58,7 +58,7 @@ export type FontSizePickerProps = { /** * Size of the control. * - * @default default + * @default 'default' */ size?: 'default' | '__unstable-large'; }; diff --git a/packages/components/src/input-control/styles/input-control-styles.tsx b/packages/components/src/input-control/styles/input-control-styles.tsx index b35efb42378ea..1be98530d1fa4 100644 --- a/packages/components/src/input-control/styles/input-control-styles.tsx +++ b/packages/components/src/input-control/styles/input-control-styles.tsx @@ -34,6 +34,7 @@ const rootFocusedStyles = ( { isFocused }: RootProps ) => { }; export const Root = styled( Flex )< RootProps >` + box-sizing: border-box; position: relative; border-radius: 2px; padding-top: 0; diff --git a/packages/components/src/unit-control/index.tsx b/packages/components/src/unit-control/index.tsx index a3416d3005e27..c4baaf64568da 100644 --- a/packages/components/src/unit-control/index.tsx +++ b/packages/components/src/unit-control/index.tsx @@ -23,7 +23,7 @@ import { __ } from '@wordpress/i18n'; */ import type { WordPressComponentProps } from '../ui/context'; import * as inputControlActionTypes from '../input-control/reducer/actions'; -import { Root, ValueInput } from './styles/unit-control-styles'; +import { ValueInput } from './styles/unit-control-styles'; import UnitSelectControl from './unit-select-control'; import { CSS_UNITS, @@ -58,7 +58,6 @@ function UnforwardedUnitControl( onChange: onChangeProp, onUnitChange, size = 'default', - style, unit: unitProp, units: unitsProp = CSS_UNITS, value: valueProp, @@ -105,7 +104,13 @@ function UnforwardedUnitControl( // Stores parsed value for hand-off in state reducer. const refParsedQuantity = useRef< number | undefined >( undefined ); - const classes = classnames( 'components-unit-control', className ); + const classes = classnames( + 'components-unit-control', + // This class is added for legacy purposes to maintain it on the outer + // wrapper. See: https://github.com/WordPress/gutenberg/pull/45139 + 'components-unit-control-wrapper', + className + ); const handleOnQuantityChange = ( nextQuantityValue: number | string | undefined, @@ -177,7 +182,7 @@ function UnforwardedUnitControl( : undefined; const changeProps = { event, data }; - // The `onChange` callback already gets called, no need to call it explicitely. + // The `onChange` callback already gets called, no need to call it explicitly. onUnitChange?.( validParsedUnit, changeProps ); setUnit( validParsedUnit ); @@ -258,27 +263,25 @@ function UnforwardedUnitControl( } return ( - - - + ); } diff --git a/packages/components/src/unit-control/styles/unit-control-styles.ts b/packages/components/src/unit-control/styles/unit-control-styles.ts index 51532e6ea75c5..9cf51b2d3bbda 100644 --- a/packages/components/src/unit-control/styles/unit-control-styles.ts +++ b/packages/components/src/unit-control/styles/unit-control-styles.ts @@ -18,16 +18,6 @@ type SelectProps = { selectSize: SelectSize; }; -export const Root = styled.div` - box-sizing: border-box; - position: relative; - - /* Target the InputControl's backdrop and make focus styles smoother. */ - &&& ${ BackdropUI } { - transition: box-shadow 0.1s linear; - } -`; - // TODO: Resolve need to use &&& to increase specificity // https://github.com/WordPress/gutenberg/issues/18483 @@ -37,6 +27,10 @@ export const ValueInput = styled( NumberControl )` display: block; width: 100%; } + + ${ BackdropUI } { + transition: box-shadow 0.1s linear; + } } `; diff --git a/packages/edit-site/src/components/global-styles/border-panel.js b/packages/edit-site/src/components/global-styles/border-panel.js index ec6c9a4ecc12b..420561207b872 100644 --- a/packages/edit-site/src/components/global-styles/border-panel.js +++ b/packages/edit-site/src/components/global-styles/border-panel.js @@ -186,6 +186,7 @@ export default function BorderPanel( { name } ) { value={ border } __experimentalHasMultipleOrigins={ true } __experimentalIsRenderedInSidebar={ true } + size={ '__unstable-large' } /> ) }