Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BorderControl: Replace style picker with ToggleGroupControl #57562

Merged
merged 5 commits into from Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -142,6 +142,7 @@ const BorderControlDropdown = (
enableStyle,
indicatorClassName,
indicatorWrapperClassName,
isStyleSettable,
onReset,
onColorChange,
onStyleChange,
Expand Down Expand Up @@ -218,7 +219,7 @@ const BorderControlDropdown = (
clearable={ false }
enableAlpha={ enableAlpha }
/>
{ enableStyle && (
{ enableStyle && isStyleSettable && (
<BorderControlStylePicker
label={ __( 'Style' ) }
value={ style }
Expand Down
Expand Up @@ -7,84 +7,49 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import Button from '../../button';
import { StyledLabel } from '../../base-control/styles/base-control-styles';
import { View } from '../../view';
import { Flex } from '../../flex';
import { VisuallyHidden } from '../../visually-hidden';
import type { WordPressComponentProps } from '../../context';
import { contextConnect } from '../../context';
import { useBorderControlStylePicker } from './hook';

import type { LabelProps, StylePickerProps } from '../types';
import type { StylePickerProps } from '../types';
import {
ToggleGroupControl,
ToggleGroupControlOptionIcon,
} from '../../toggle-group-control';

const BORDER_STYLES = [
{ label: __( 'Solid' ), icon: lineSolid, value: 'solid' },
{ label: __( 'Dashed' ), icon: lineDashed, value: 'dashed' },
{ label: __( 'Dotted' ), icon: lineDotted, value: 'dotted' },
];

const Label = ( props: LabelProps ) => {
const { label, hideLabelFromVision } = props;

if ( ! label ) {
return null;
}

return hideLabelFromVision ? (
<VisuallyHidden as="label">{ label }</VisuallyHidden>
) : (
<StyledLabel>{ label }</StyledLabel>
);
};

const BorderControlStylePicker = (
props: WordPressComponentProps< StylePickerProps, 'div' >,
function UnconnectedBorderControlStylePicker(
{ onChange, ...restProps }: StylePickerProps,
forwardedRef: React.ForwardedRef< any >
) => {
const {
buttonClassName,
hideLabelFromVision,
label,
onChange,
value,
...otherProps
} = useBorderControlStylePicker( props );

) {
return (
<View { ...otherProps } ref={ forwardedRef }>
<Label
label={ label }
hideLabelFromVision={ hideLabelFromVision }
/>
<Flex justify="flex-start" gap={ 1 }>
{ BORDER_STYLES.map( ( borderStyle ) => (
<Button
key={ borderStyle.value }
className={ buttonClassName }
icon={ borderStyle.icon }
size="small"
isPressed={ borderStyle.value === value }
onClick={ () =>
onChange(
borderStyle.value === value
? undefined
: borderStyle.value
)
}
aria-label={ borderStyle.label }
label={ borderStyle.label }
showTooltip={ true }
/>
) ) }
</Flex>
</View>
<ToggleGroupControl
__nextHasNoMarginBottom
__next40pxDefaultSize
ref={ forwardedRef }
isDeselectable
onChange={ ( value ) => {
onChange?.( value as string | undefined );
} }
{ ...restProps }
>
{ BORDER_STYLES.map( ( borderStyle ) => (
<ToggleGroupControlOptionIcon
key={ borderStyle.value }
value={ borderStyle.value }
icon={ borderStyle.icon }
label={ borderStyle.label }
/>
) ) }
</ToggleGroupControl>
);
};
}

const ConnectedBorderControlStylePicker = contextConnect(
BorderControlStylePicker,
const BorderControlStylePicker = contextConnect(
UnconnectedBorderControlStylePicker,
'BorderControlStylePicker'
);

export default ConnectedBorderControlStylePicker;
export default BorderControlStylePicker;

This file was deleted.

Expand Up @@ -46,6 +46,7 @@ const UnconnectedBorderControl = (
hideLabelFromVision,
innerWrapperClassName,
inputWidth,
isStyleSettable,
label,
onBorderChange,
onSliderChange,
Expand Down Expand Up @@ -80,6 +81,7 @@ const UnconnectedBorderControl = (
disableCustomColors={ disableCustomColors }
enableAlpha={ enableAlpha }
enableStyle={ enableStyle }
isStyleSettable={ isStyleSettable }
onChange={ onBorderChange }
previousStyleSelection={ previousStyleSelection }
showDropdownHeader={ showDropdownHeader }
Expand Down
27 changes: 14 additions & 13 deletions packages/components/src/border-control/border-control/hook.ts
Expand Up @@ -14,16 +14,12 @@ import { useCx } from '../../utils/hooks/use-cx';

import type { Border, BorderControlProps } from '../types';

const sanitizeBorder = ( border?: Border ) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored the logic of this sanitizeBorder function so it can be reused to determine the isStyleSettable boolean. I renamed it and inverted the logic to isValidBorder for better readability within the file.

const hasNoWidth = border?.width === undefined || border.width === '';
const hasNoColor = border?.color === undefined;

// If width and color are undefined, unset any style selection as well.
if ( hasNoWidth && hasNoColor ) {
return undefined;
}

return border;
// If either width or color are defined, the border is considered valid
// and a border style can be set as well.
const isValidBorder = ( border?: Border ) => {
const hasWidth = border?.width !== undefined && border.width !== '';
const hasColor = border?.color !== undefined;
return hasWidth || hasColor;
};

export function useBorderControl(
Expand Down Expand Up @@ -53,12 +49,16 @@ export function useBorderControl(
const [ colorSelection, setColorSelection ] = useState< string >();
const [ styleSelection, setStyleSelection ] = useState< string >();

const isStyleSettable = shouldSanitizeBorder
? isValidBorder( border )
: true;

const onBorderChange = useCallback(
( newBorder?: Border ) => {
if ( shouldSanitizeBorder ) {
return onChange( sanitizeBorder( newBorder ) );
if ( shouldSanitizeBorder && ! isValidBorder( newBorder ) ) {
onChange( undefined );
return;
}

onChange( newBorder );
},
[ onChange, shouldSanitizeBorder ]
Expand Down Expand Up @@ -147,6 +147,7 @@ export function useBorderControl(
enableStyle,
innerWrapperClassName,
inputWidth: wrapperWidth,
isStyleSettable,
onBorderChange,
onSliderChange,
onWidthChange,
Expand Down
15 changes: 0 additions & 15 deletions packages/components/src/border-control/styles.ts
Expand Up @@ -165,21 +165,6 @@ export const resetButton = css`
}
`;

export const borderControlStylePicker = css`
${ StyledLabel } {
${ labelStyles }
}
`;

export const borderStyleButton = css`
&&&&& {
min-width: 32px;
width: 32px;
height: 32px;
padding: 4px;
}
`;

export const borderSlider = () => css`
flex: 1 1 60%;
${ rtl( { marginRight: space( 3 ) } )() }
Expand Down
10 changes: 9 additions & 1 deletion packages/components/src/border-control/types.ts
Expand Up @@ -8,6 +8,7 @@ import type { CSSProperties } from 'react';
*/
import type { ColorPaletteProps } from '../color-palette/types';
import type { PopoverProps } from '../popover/types';
import type { ToggleGroupControlProps } from '../toggle-group-control/types';

export type Border = {
color?: CSSProperties[ 'borderColor' ];
Expand Down Expand Up @@ -109,6 +110,10 @@ export type DropdownProps = ColorProps &
* values for its popover controls.
*/
border?: Border;
/**
* Whether a border style can be set, based on the border sanitization settings.
*/
isStyleSettable: boolean;
Comment on lines +119 to +122
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an addition to an internal subcomponent prop — will not affect public-facing types.

/**
* An internal prop used to control the visibility of the dropdown.
*/
Expand All @@ -131,7 +136,10 @@ export type DropdownProps = ColorProps &
showDropdownHeader?: boolean;
};

export type StylePickerProps = LabelProps & {
export type StylePickerProps = Omit<
ToggleGroupControlProps,
'value' | 'onChange' | 'children'
> & {
/**
* A callback function invoked when a border style is selected or cleared.
*/
Expand Down