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

FontSizePicker: Use components instead of helper functions #44891

Merged
merged 30 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dc4b183
FontSizePicker: Use components instead of helper functions
noisysocks Oct 12, 2022
bbf17a3
Remove duplicate dependency header
noisysocks Oct 12, 2022
450d63b
Reuse types from FontSizePickerProps where possible
noisysocks Oct 13, 2022
c50fa22
Rename 'number' to 'parsedValue'
noisysocks Oct 13, 2022
f882797
Use constants for defaultOption and customOption
noisysocks Oct 13, 2022
b108a6e
Don't show 'Custom' option in select when custom sizes are disabled
noisysocks Oct 13, 2022
4cdf21c
Swap label and aria-label
noisysocks Oct 13, 2022
c76c8e6
Use slug in select if name is an empty string
noisysocks Oct 13, 2022
c5e4fae
Add test that checks all the t-shirt labels
noisysocks Oct 13, 2022
6b26dc2
Merge remote-tracking branch 'origin/trunk' into update/simplify-font…
noisysocks Oct 25, 2022
97e572a
Make filenames match component names
noisysocks Oct 25, 2022
1de7d4e
Make DEFAULT_OPTION logic more explicit
noisysocks Oct 25, 2022
10bf17e
Restore headerHint logic to how it was
noisysocks Oct 25, 2022
8f87273
Use expect().toHaveContent
noisysocks Oct 25, 2022
299d680
Rewrite FontSizePicker unit tests to use userEvent and be more compre…
noisysocks Oct 26, 2022
b0314d2
Use header label's aria-label
noisysocks Oct 28, 2022
c2b4da6
Put back the Gigantosaurus 🦖
noisysocks Oct 28, 2022
d6c4d65
Update changelog
noisysocks Oct 28, 2022
9b9fc00
Merge branch 'trunk' into update/font-size-picker-unit-tests
noisysocks Oct 28, 2022
a939507
Remove editorialising comment
noisysocks Oct 31, 2022
22c9ab3
Use getByLabelText( 'Custom Size' ) to select slider
noisysocks Oct 31, 2022
8a0fc89
Remove redundant test
noisysocks Oct 31, 2022
1673ba3
Add tests for non-px font sizes
noisysocks Nov 1, 2022
ab89dde
Assert length of options/radios
noisysocks Nov 1, 2022
4032f0f
Assert number of calls to onChange
noisysocks Nov 1, 2022
41006fc
Merge branch 'update/font-size-picker-unit-tests' into update/simplif…
noisysocks Nov 1, 2022
591288b
Can un-comment this failing assertion now
noisysocks Nov 1, 2022
3af78ec
Update CHANGELOG.md
noisysocks Nov 1, 2022
bdef23a
Merge branch 'trunk' into update/simplify-font-size-picker
noisysocks Nov 1, 2022
639db98
Fix regression when value=""
noisysocks Nov 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
- `TextControl`: Set Storybook control types on `help`, `label` and `type` ([#45405](https://github.com/WordPress/gutenberg/pull/45405)).
- `Autocomplete`: use Popover's new `placement` prop instead of legacy `position` prop ([#44396](https://github.com/WordPress/gutenberg/pull/44396/)).
- `FontSizePicker`: Add more comprehensive tests ([#45298](https://github.com/WordPress/gutenberg/pull/45298)).
- `FontSizePicker`: Refactor to use components instead of helper functions ([#44891](https://github.com/WordPress/gutenberg/pull/44891)).

## 21.3.0 (2022-10-19)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import CustomSelectControl from '../custom-select-control';
import { parseQuantityAndUnitFromRawValue } from '../unit-control';
import type {
FontSizePickerSelectProps,
FontSizePickerSelectOption,
} from './types';

const DEFAULT_OPTION: FontSizePickerSelectOption = {
key: 'default',
name: __( 'Default' ),
value: undefined,
};

const CUSTOM_OPTION: FontSizePickerSelectOption = {
key: 'custom',
name: __( 'Custom' ),
};

const FontSizePickerSelect = ( props: FontSizePickerSelectProps ) => {
const {
fontSizes,
value,
disableCustomFontSizes,
size,
onChange,
onSelectCustom,
} = props;

const options: FontSizePickerSelectOption[] = [
DEFAULT_OPTION,
...fontSizes.map( ( fontSize ) => {
const [ quantity ] = parseQuantityAndUnitFromRawValue(
fontSize.size
);
return {
key: fontSize.slug,
name: fontSize.name || fontSize.slug,
value: fontSize.size,
__experimentalHint:
quantity !== undefined ? String( quantity ) : undefined,
};
} ),
...( disableCustomFontSizes ? [] : [ CUSTOM_OPTION ] ),
];

const selectedOption = value
? options.find( ( option ) => option.value === value ) ?? CUSTOM_OPTION
: DEFAULT_OPTION;

return (
<CustomSelectControl
__nextUnconstrainedWidth
className="components-font-size-picker__select"
label={ __( 'Font size' ) }
hideLabelFromVision
describedBy={ sprintf(
// translators: %s: Currently selected font size.
__( 'Currently selected font size: %s' ),
selectedOption.name
) }
options={ options }
value={ selectedOption }
onChange={ ( {
selectedItem,
}: {
selectedItem: FontSizePickerSelectOption;
} ) => {
if ( selectedItem === CUSTOM_OPTION ) {
onSelectCustom();
} else {
onChange( selectedItem.value );
}
} }
size={ size }
/>
);
};

export default FontSizePickerSelect;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
ToggleGroupControl,
ToggleGroupControlOption,
} from '../toggle-group-control';
import type { FontSizePickerToggleGroupProps } from './types';

/**
* In case we have at most five font sizes, show a `T-shirt size` alias as a
* label of the font size. The label assumes that the font sizes are ordered
* accordingly - from smallest to largest.
*/
const FONT_SIZES_ALIASES = [
/* translators: S stands for 'small' and is a size label. */
__( 'S' ),
/* translators: M stands for 'medium' and is a size label. */
__( 'M' ),
/* translators: L stands for 'large' and is a size label. */
__( 'L' ),
/* translators: XL stands for 'extra large' and is a size label. */
__( 'XL' ),
/* translators: XXL stands for 'extra extra large' and is a size label. */
__( 'XXL' ),
];

const FontSizePickerToggleGroup = ( props: FontSizePickerToggleGroupProps ) => {
const { fontSizes, value, __nextHasNoMarginBottom, size, onChange } = props;
return (
<ToggleGroupControl
__nextHasNoMarginBottom={ __nextHasNoMarginBottom }
label={ __( 'Font size' ) }
hideLabelFromVision
value={ value }
onChange={ onChange }
isBlock
size={ size }
>
{ fontSizes.map( ( fontSize, index ) => (
<ToggleGroupControlOption
key={ fontSize.slug }
value={ fontSize.size }
label={ FONT_SIZES_ALIASES[ index ] }
aria-label={ fontSize.name || FONT_SIZES_ALIASES[ index ] }
showTooltip
/>
) ) }
</ToggleGroupControl>
);
};

export default FontSizePickerToggleGroup;
140 changes: 45 additions & 95 deletions packages/components/src/font-size-picker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { ForwardedRef } from 'react';
* WordPress dependencies
*/
import deprecated from '@wordpress/deprecated';
import { __, sprintf } from '@wordpress/i18n';
import { __ } from '@wordpress/i18n';
import { settings } from '@wordpress/icons';
import { useState, useMemo, forwardRef } from '@wordpress/element';

Expand All @@ -22,24 +22,10 @@ import {
parseQuantityAndUnitFromRawValue,
useCustomUnits,
} from '../unit-control';
import CustomSelectControl from '../custom-select-control';
import { VisuallyHidden } from '../visually-hidden';
import {
ToggleGroupControl,
ToggleGroupControlOption,
} from '../toggle-group-control';
import {
getFontSizeOptions,
getSelectedOption,
isSimpleCssValue,
CUSTOM_FONT_SIZE,
} from './utils';
import { isSimpleCssValue } from './utils';
import { HStack } from '../h-stack';
import type {
FontSizePickerProps,
FontSizeSelectOption,
FontSizeToggleGroupOption,
} from './types';
import type { FontSizePickerProps } from './types';
import {
Container,
HeaderHint,
Expand All @@ -48,6 +34,8 @@ import {
ResetButton,
} from './styles';
import { Spacer } from '../spacer';
import FontSizePickerSelect from './font-size-picker-select';
import FontSizePickerToggleGroup from './font-size-picker-toggle-group';

const UnforwardedFontSizePicker = (
props: FontSizePickerProps,
Expand All @@ -65,6 +53,7 @@ const UnforwardedFontSizePicker = (
withSlider = false,
withReset = true,
} = props;

if ( ! __nextHasNoMarginBottom ) {
deprecated( 'Bottom margin styles for wp.components.FontSizePicker', {
since: '6.1',
Expand All @@ -77,28 +66,16 @@ const UnforwardedFontSizePicker = (
availableUnits: [ 'px', 'em', 'rem' ],
} );

/**
* The main font size UI displays a toggle group when the presets are less
* than six and a select control when they are more.
*/
const fontSizesContainComplexValues = fontSizes.some(
( { size: sizeArg } ) => ! isSimpleCssValue( sizeArg )
);
const shouldUseSelectControl = fontSizes.length > 5;
const options = useMemo(
() =>
getFontSizeOptions(
shouldUseSelectControl,
fontSizes,
disableCustomFontSizes
),
[ shouldUseSelectControl, fontSizes, disableCustomFontSizes ]
const selectedFontSize = fontSizes.find(
( fontSize ) => fontSize.size === value
ciampo marked this conversation as resolved.
Show resolved Hide resolved
);
const selectedOption = getSelectedOption( fontSizes, value );
const isCustomValue = selectedOption.slug === CUSTOM_FONT_SIZE;
const isCustomValue = !! value && ! selectedFontSize;

const [ showCustomValueControl, setShowCustomValueControl ] = useState(
! disableCustomFontSizes && isCustomValue
);

const headerHint = useMemo( () => {
if ( showCustomValueControl ) {
return `(${ __( 'Custom' ) })`;
Expand All @@ -113,49 +90,48 @@ const UnforwardedFontSizePicker = (
`(${ value })`
);
}

if ( shouldUseSelectControl ) {
return (
selectedOption?.size !== undefined &&
isSimpleCssValue( selectedOption?.size ) &&
`(${ selectedOption?.size })`
selectedFontSize?.size !== undefined &&
isSimpleCssValue( selectedFontSize?.size ) &&
`(${ selectedFontSize?.size })`
);
}

if ( ! selectedFontSize ) {
return __( 'Default' );
}

// Calculate the `hint` for toggle group control.
let hint = selectedOption?.name || selectedOption.slug;
let hint = selectedFontSize.name || selectedFontSize.slug;
const fontSizesContainComplexValues = fontSizes.some(
( fontSize ) => ! isSimpleCssValue( fontSize.size )
);
if (
! fontSizesContainComplexValues &&
typeof selectedOption.size === 'string'
typeof selectedFontSize.size === 'string'
) {
const [ , unit ] = parseQuantityAndUnitFromRawValue(
selectedOption.size,
selectedFontSize.size,
units
);
hint += `(${ unit })`;
}
return hint;
}, [
showCustomValueControl,
selectedOption?.name,
selectedOption?.size,
value,
isCustomValue,
selectedFontSize,
value,
shouldUseSelectControl,
fontSizesContainComplexValues,
fontSizes,
] );

if ( ! options ) {
if ( fontSizes.length === 0 && disableCustomFontSizes ) {
return null;
}

// This is used for select control only. We need to add support
// for ToggleGroupControl.
const currentFontSizeSR = sprintf(
// translators: %s: Currently selected font size.
__( 'Currently selected font size: %s' ),
selectedOption.name
);

// If neither the value or first font size is a string, then FontSizePicker
// operates in a legacy "unitless" mode where UnitControl can only be used
// to select px values and onChange() is always called with number values.
Expand Down Expand Up @@ -210,43 +186,31 @@ const UnforwardedFontSizePicker = (
{ !! fontSizes.length &&
shouldUseSelectControl &&
! showCustomValueControl && (
<CustomSelectControl
__nextUnconstrainedWidth
className="components-font-size-picker__select"
label={ __( 'Font size' ) }
hideLabelFromVision
describedBy={ currentFontSizeSR }
options={ options as FontSizeSelectOption[] }
value={ ( options as FontSizeSelectOption[] ).find(
( option ) => option.key === selectedOption.slug
) }
onChange={ ( {
selectedItem,
}: {
selectedItem: FontSizeSelectOption;
} ) => {
if ( selectedItem.size === undefined ) {
<FontSizePickerSelect
fontSizes={ fontSizes }
value={ value }
disableCustomFontSizes={ disableCustomFontSizes }
size={ size }
onChange={ ( newValue ) => {
if ( newValue === undefined ) {
onChange?.( undefined );
} else {
onChange?.(
hasUnits
? selectedItem.size
: Number( selectedItem.size )
hasUnits ? newValue : Number( newValue )
);
}
if ( selectedItem.key === CUSTOM_FONT_SIZE ) {
setShowCustomValueControl( true );
}
} }
size={ size }
onSelectCustom={ () =>
setShowCustomValueControl( true )
}
/>
) }
{ ! shouldUseSelectControl && ! showCustomValueControl && (
<ToggleGroupControl
__nextHasNoMarginBottom={ __nextHasNoMarginBottom }
label={ __( 'Font size' ) }
hideLabelFromVision
<FontSizePickerToggleGroup
fontSizes={ fontSizes }
value={ value }
__nextHasNoMarginBottom={ __nextHasNoMarginBottom }
size={ size }
onChange={ ( newValue ) => {
if ( newValue === undefined ) {
onChange?.( undefined );
Expand All @@ -256,21 +220,7 @@ const UnforwardedFontSizePicker = (
);
}
} }
isBlock
size={ size }
>
{ ( options as FontSizeToggleGroupOption[] ).map(
( option ) => (
<ToggleGroupControlOption
key={ option.key }
value={ option.value }
label={ option.label }
aria-label={ option.name }
showTooltip={ true }
/>
)
) }
</ToggleGroupControl>
/>
) }
{ ! disableCustomFontSizes && showCustomValueControl && (
<Flex className="components-font-size-picker__custom-size-control">
Expand Down
Loading