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

Don't hardcode CSS units #32482

Merged
merged 6 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
/**
* WordPress dependencies
*/
import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
import { Platform } from '@wordpress/element';
import {
__experimentalUnitControl as UnitControl,
__experimentalUseCustomUnits as useCustomUnits,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

const isWeb = Platform.OS === 'web';

const CSS_UNITS = [
{
value: 'px',
label: isWeb ? 'px' : __( 'Pixels (px)' ),
default: '2',
},
{
value: 'em',
label: isWeb ? 'em' : __( 'Relative to parent font size (em)' ),
default: '.2',
},
{
value: 'rem',
label: isWeb ? 'rem' : __( 'Relative to root font size (rem)' ),
default: '.2',
},
];
/**
* Internal dependencies
*/
import useSetting from '../../components/use-setting';

/**
* Control for letter-spacing.
Expand All @@ -34,12 +21,16 @@ const CSS_UNITS = [
* @return {WPElement} Letter-spacing control.
*/
export default function LetterSpacingControl( { value, onChange } ) {
const units = useCustomUnits( {
availableUnits: useSetting( 'layout.units' ) || [ 'px', 'em', 'rem' ],
Copy link
Contributor

Choose a reason for hiding this comment

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

in which situation the fallback is necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

If for some reason value can't be retrieved from a theme.json file then the fallback will be used. It's a "better safe than sorry" fallback to make sure nothing breaks.

Copy link
Contributor

Choose a reason for hiding this comment

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

It feels we should have a system that provide defaults in the block-editor package for all settings instead of repeating the same code over and over in all places.

Copy link
Contributor

Choose a reason for hiding this comment

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

@nosolosw @jorgefilipecosta how defauts for the block-editor are provided now? (I mean in the frontend without the core theme.json)

Copy link
Member

Choose a reason for hiding this comment

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

To make sure I follow: do you mean what happens in the editor when a theme doesn't provide a theme.json? In the specific case of layout.units we don't provide a fallback. We do for some things like spacing.units. We pre-populate the block editor store with defaults, but we also don't do that for __experimentalFeatures.

Adding the fallback in the useSetting hook sounds like something we should explore.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine if the defaults are duplicated between client and server, if there's a valid reason for it. The endpoint for settings is good to get the settings that are not "defaults" but for the defaults, I don't see the issue for mobile.

Copy link
Member

Choose a reason for hiding this comment

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

How do you feel passing defaults as initialization to the block editor?

The fact that we have them in multiple places (client defaults for the store, useSetting, server, etc) has been problematic in the past and this issue is also a good demonstration of that.

Copy link
Contributor

Choose a reason for hiding this comment

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

How do you feel passing defaults as initialization to the block editor?

I think the editor should have defaults bundled, and not require passing settings to work properly.

Copy link
Contributor

Choose a reason for hiding this comment

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

the reason is simple, the block-editor package is independent and it's really not great to force its users to pass a complex settings object to get sane defaults.

Copy link
Member

Choose a reason for hiding this comment

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

I've prepared #32702 that adds a default value for __experimentalFeatures in the @wordpress/block-editor package. It ports the existing defaults set by the core theme.json.

defaultValues: { px: '2', em: '.2', rem: '.2' },
} );
return (
<UnitControl
label={ __( 'Letter-spacing' ) }
value={ value }
__unstableInputWidth="60px"
units={ CSS_UNITS }
units={ units }
onChange={ onChange }
/>
);
Expand Down
17 changes: 13 additions & 4 deletions packages/block-editor/src/hooks/border-radius.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
/**
* WordPress dependencies
*/
import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
import {
__experimentalUnitControl as UnitControl,
__experimentalUseCustomUnits as useCustomUnits,
parseUnit,
} from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { CSS_UNITS, parseUnit } from './border';
import { cleanEmptyObject } from './utils';
import useSetting from '../components/use-setting';

const MIN_BORDER_RADIUS_VALUE = 0;

Expand All @@ -28,7 +32,8 @@ export function BorderRadiusEdit( props ) {

// Step value is maintained in state so step is appropriate for current unit
// even when current radius value is undefined.
const initialStep = parseUnit( style?.border?.radius ) === 'px' ? 1 : 0.25;
const initialStep =
parseUnit( style?.border?.radius )[ 1 ] === 'px' ? 1 : 0.25;
const [ step, setStep ] = useState( initialStep );

const onUnitChange = ( newUnit ) => {
Expand All @@ -51,6 +56,10 @@ export function BorderRadiusEdit( props ) {
setAttributes( { style: newStyle } );
};

const units = useCustomUnits( {
availableUnits: useSetting( 'layout.units' ) || [ 'px', 'em', 'rem' ],
} );

return (
<UnitControl
value={ style?.border?.radius }
Expand All @@ -59,7 +68,7 @@ export function BorderRadiusEdit( props ) {
onChange={ onChange }
onUnitChange={ onUnitChange }
step={ step }
units={ CSS_UNITS }
units={ units }
/>
);
}
17 changes: 13 additions & 4 deletions packages/block-editor/src/hooks/border-width.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
/**
* WordPress dependencies
*/
import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
import {
__experimentalUnitControl as UnitControl,
__experimentalUseCustomUnits as useCustomUnits,
parseUnit,
} from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { CSS_UNITS, parseUnit } from './border';
import { cleanEmptyObject } from './utils';
import useSetting from '../components/use-setting';

const MIN_BORDER_WIDTH = 0;

Expand All @@ -28,7 +32,8 @@ export const BorderWidthEdit = ( props ) => {

// Step value is maintained in state so step is appropriate for current unit
// even when current radius value is undefined.
const initialStep = parseUnit( style?.border?.width ) === 'px' ? 1 : 0.25;
const initialStep =
parseUnit( style?.border?.width )[ 1 ] === 'px' ? 1 : 0.25;
const [ step, setStep ] = useState( initialStep );

const onUnitChange = ( newUnit ) => {
Expand All @@ -51,6 +56,10 @@ export const BorderWidthEdit = ( props ) => {
setAttributes( { style: newStyle } );
};

const units = useCustomUnits( {
availableUnits: useSetting( 'layout.units' ) || [ 'px', 'em', 'rem' ],
} );

return (
<UnitControl
value={ style?.border?.width }
Expand All @@ -59,7 +68,7 @@ export const BorderWidthEdit = ( props ) => {
onChange={ onChange }
onUnitChange={ onUnitChange }
step={ step }
units={ CSS_UNITS }
units={ units }
/>
);
};
37 changes: 0 additions & 37 deletions packages/block-editor/src/hooks/border.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,7 @@ import { BorderRadiusEdit } from './border-radius';
import { BorderStyleEdit } from './border-style';
import { BorderWidthEdit } from './border-width';

const isWeb = Platform.OS === 'web';

export const BORDER_SUPPORT_KEY = '__experimentalBorder';
export const CSS_UNITS = [
{
value: 'px',
label: isWeb ? 'px' : __( 'Pixels (px)' ),
default: '',
a11yLabel: __( 'Pixels (px)' ),
},
{
value: 'em',
label: isWeb ? 'em' : __( 'Relative to parent font size (em)' ),
default: '',
a11yLabel: __( 'Relative to parent font size (em)' ),
},
{
value: 'rem',
label: isWeb ? 'rem' : __( 'Relative to root font size (rem)' ),
default: '',
a11yLabel: __( 'Relative to root font size (rem)' ),
},
];

/**
* Parses a CSS unit from a border CSS value.
*
* @param {string} cssValue CSS value to parse e.g. `10px` or `1.5em`.
* @return {string} CSS unit from provided value or default 'px'.
*/
export function parseUnit( cssValue ) {
const value = String( cssValue ).trim();
const unitMatch = value.match( /[\d.\-\+]*\s*(.*)/ )[ 1 ];
const unit = unitMatch !== undefined ? unitMatch.toLowerCase() : '';
const currentUnit = CSS_UNITS.find( ( item ) => item.value === unit );

return currentUnit?.value || 'px';
}

export function BorderPanel( props ) {
const isDisabled = useIsBorderDisabled( props );
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export { Truncate as __experimentalTruncate } from './truncate';
export {
default as __experimentalUnitControl,
useCustomUnits as __experimentalUseCustomUnits,
parseUnit,
aristath marked this conversation as resolved.
Show resolved Hide resolved
} from './unit-control';
export { default as VisuallyHidden } from './visually-hidden';
export { VStack as __experimentalVStack } from './v-stack';
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/unit-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,5 @@ function UnitControl(

const ForwardedUnitControl = forwardRef( UnitControl );

export { useCustomUnits } from './utils';
export { parseUnit, useCustomUnits } from './utils';
export default ForwardedUnitControl;