Skip to content

Commit

Permalink
Button: Introduce size prop (#51842)
Browse files Browse the repository at this point in the history
* Revert "Button: Add opt-in prop for larger `isSmall` size (#51012)"

This reverts commit 19bcabf.

# Conflicts:
#	packages/components/CHANGELOG.md

* Add docs for `size` prop

Also fixes type duplicate prop name issues in NumberControl and FontSizePicker

* Add CSS

* Fixup

* Add TODO for deprecation

* Add test for back compat

* Fixup

* Add changelog

* Tweak description for "compact"

* Note that the `size` prop takes precedence

* Add test for prop priority

* Stop leaking `spinButtonSize` prop for styling
  • Loading branch information
mirka authored Jun 23, 2023
1 parent f3e1557 commit a3af2c7
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 60 deletions.
2 changes: 1 addition & 1 deletion packages/base-styles/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $icon-size: 24px;
$button-size: 36px;
$button-size-next-default-40px: 40px; // transitionary variable for next default button size
$button-size-small: 24px;
$button-size-small-next-default-32px: 32px; // transitionary variable for next small button size
$button-size-compact: 32px;
$header-height: 60px;
$panel-header-height: $grid-unit-60;
$nav-sidebar-width: 360px;
Expand Down
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- `SelectControl`: Added option to set hidden options. ([#51545](https://github.com/WordPress/gutenberg/pull/51545))
- `UnitControl`: Revamp support for changing unit by typing ([#39303](https://github.com/WordPress/gutenberg/pull/39303)).
- `Modal`: Update corner radius to be between buttons and the site view frame, in a 2-4-8 system. ([#51254](https://github.com/WordPress/gutenberg/pull/51254)).
- `Button`: Introduce `size` prop with `default`, `compact`, and `small` variants ([#51842](https://github.com/WordPress/gutenberg/pull/51842)).
- `ItemGroup`: Update button focus state styles to be inline with other button focus states in the editor. ([#51576](https://github.com/WordPress/gutenberg/pull/51576)).
- `ItemGroup`: Update button focus state styles to target `:focus-visible` rather than `:focus`. ([#51787](https://github.com/WordPress/gutenberg/pull/51787)).

Expand Down
15 changes: 15 additions & 0 deletions packages/components/src/button/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ Renders a pressed button style.

Decreases the size of the button.

Deprecated in favor of the `size` prop. If both props are defined, the `size` prop will take precedence.

- Required: No

#### `label`: `string`
Expand All @@ -218,6 +220,19 @@ If provided, renders a [Tooltip](/packages/components/src/tooltip/README.md) com

- Required: No

#### `size`: `'default'` | `'compact'` | `'small'`

The size of the button.

- `'default'`: For normal text-label buttons, unless it is a toggle button.
- `'compact'`: For toggle buttons, icon buttons, and buttons when used in context of either.
- `'small'`: For icon buttons associated with more advanced or auxiliary features.

If the deprecated `isSmall` prop is also defined, this prop will take precedence.

- Required: No
- Default: `'default'`

#### `target`: `string`

If provided with `href`, sets the `target` attribute to the `a`.
Expand Down
15 changes: 11 additions & 4 deletions packages/components/src/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,18 @@ function useDeprecatedProps( {
isSecondary,
isTertiary,
isLink,
isSmall,
size,
variant,
...otherProps
}: ButtonProps & DeprecatedButtonProps ): ButtonProps {
let computedSize = size;
let computedVariant = variant;

if ( isSmall ) {
computedSize ??= 'small';
}

if ( isPrimary ) {
computedVariant ??= 'primary';
}
Expand Down Expand Up @@ -66,6 +73,7 @@ function useDeprecatedProps( {

return {
...otherProps,
size: computedSize,
variant: computedVariant,
};
}
Expand All @@ -76,8 +84,6 @@ export function UnforwardedButton(
) {
const {
__next40pxDefaultSize,
__next32pxSmallSize,
isSmall,
isPressed,
isBusy,
isDestructive,
Expand All @@ -91,6 +97,7 @@ export function UnforwardedButton(
shortcut,
label,
children,
size = 'default',
text,
variant,
__experimentalIsFocusable: isFocusable,
Expand Down Expand Up @@ -118,10 +125,10 @@ export function UnforwardedButton(

const classes = classnames( 'components-button', className, {
'is-next-40px-default-size': __next40pxDefaultSize,
'is-next-32px-small-size': __next32pxSmallSize,
'is-secondary': variant === 'secondary',
'is-primary': variant === 'primary',
'is-small': isSmall,
'is-small': size === 'small',
'is-compact': size === 'compact',
'is-tertiary': variant === 'tertiary',
'is-pressed': isPressed,
'is-busy': isBusy,
Expand Down
25 changes: 13 additions & 12 deletions packages/components/src/button/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -257,25 +257,26 @@
/* stylelint-enable */
}
&.is-compact {
height: $button-size-compact;
&.has-icon:not(.has-text) {
padding: 0;
width: $button-size-compact;
min-width: $button-size-compact;
}
}

&.is-small {
height: $button-size-small-next-default-32px;
height: $button-size-small;
line-height: 22px;
padding: 0 8px;
font-size: 11px;

&.has-icon:not(.has-text) {
padding: 0;
width: $button-size-small-next-default-32px;
min-width: $button-size-small-next-default-32px;
}

&:not(.is-next-32px-small-size) {
height: $button-size-small;

&.has-icon:not(.has-text) {
width: $button-size-small;
min-width: $button-size-small;
}
width: $button-size-small;
min-width: $button-size-small;
}
}

Expand Down
13 changes: 13 additions & 0 deletions packages/components/src/button/test/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,19 @@ describe( 'Button', () => {
);
expect( console ).toHaveWarned();
} );

it( 'should not break when the legacy isSmall prop is passed', () => {
render( <Button isSmall /> );
expect( screen.getByRole( 'button' ) ).toHaveClass( 'is-small' );
} );

it( 'should prioritize the `size` prop over `isSmall`', () => {
render( <Button size="compact" isSmall /> );
expect( screen.getByRole( 'button' ) ).not.toHaveClass(
'is-small'
);
expect( screen.getByRole( 'button' ) ).toHaveClass( 'is-compact' );
} );
} );

describe( 'static typing', () => {
Expand Down
26 changes: 17 additions & 9 deletions packages/components/src/button/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ type BaseButtonProps = {
* @default false
*/
__next40pxDefaultSize?: boolean;
/**
* Start opting into the larger `isSmall` button size that will become the
* default small size in a future version.
*
* Only takes effect when the `isSmall` prop is `true`.
*
* @default false
*/
__next32pxSmallSize?: boolean;
/**
* The button's children.
*/
Expand Down Expand Up @@ -74,8 +65,13 @@ type BaseButtonProps = {
* Renders a pressed button style.
*/
isPressed?: boolean;
// TODO: Deprecate officially (add console warning and move to DeprecatedButtonProps).
/**
* Decreases the size of the button.
*
* Deprecated in favor of the `size` prop. If both props are defined, the `size` prop will take precedence.
*
* @deprecated Use the `'small'` value on the `size` prop instead.
*/
isSmall?: boolean;
/**
Expand All @@ -92,6 +88,18 @@ type BaseButtonProps = {
* If provided, renders a Tooltip component for the button.
*/
showTooltip?: boolean;
/**
* The size of the button.
*
* - `'default'`: For normal text-label buttons, unless it is a toggle button.
* - `'compact'`: For toggle buttons, icon buttons, and buttons when used in context of either.
* - `'small'`: For icon buttons associated with more advanced or auxiliary features.
*
* If the deprecated `isSmall` prop is also defined, this prop will take precedence.
*
* @default 'default'
*/
size?: 'default' | 'compact' | 'small';
/**
* If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them.
*/
Expand Down
14 changes: 9 additions & 5 deletions packages/components/src/font-size-picker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useState, useMemo, forwardRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import { Button } from '../button';
import RangeControl from '../range-control';
import { Flex, FlexItem } from '../flex';
import {
Expand All @@ -31,7 +32,6 @@ import {
HeaderLabel,
HeaderToggle,
Controls,
ResetButton,
} from './styles';
import { Spacer } from '../spacer';
import FontSizePickerSelect from './font-size-picker-select';
Expand Down Expand Up @@ -268,17 +268,21 @@ const UnforwardedFontSizePicker = (
) }
{ withReset && (
<FlexItem>
<ResetButton
<Button
disabled={ value === undefined }
onClick={ () => {
onChange?.( undefined );
} }
isSmall
variant="secondary"
size={ size }
__next40pxDefaultSize
size={
size !== '__unstable-large'
? 'small'
: 'default'
}
>
{ __( 'Reset' ) }
</ResetButton>
</Button>
</FlexItem>
) }
</Flex>
Expand Down
10 changes: 0 additions & 10 deletions packages/components/src/font-size-picker/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Button from '../button';
import { HStack } from '../h-stack';
import { space } from '../ui/utils/space';
import { COLORS } from '../utils';
import type { FontSizePickerProps } from './types';

export const Container = styled.fieldset`
border: 0;
Expand Down Expand Up @@ -44,12 +43,3 @@ export const Controls = styled.div< {
${ ( props ) =>
! props.__nextHasNoMarginBottom && `margin-bottom: ${ space( 6 ) };` }
`;

export const ResetButton = styled( Button )< {
size: FontSizePickerProps[ 'size' ];
} >`
&&& {
height: ${ ( props ) =>
props.size === '__unstable-large' ? '40px' : '30px' };
}
`;
9 changes: 6 additions & 3 deletions packages/components/src/number-control/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
*/
import { Input, SpinButton } from './styles/number-control-styles';
import { Input, SpinButton, styles } from './styles/number-control-styles';
import * as inputControlActionTypes from '../input-control/reducer/actions';
import { add, subtract, roundClamp } from '../utils/math';
import { ensureNumber, isValueEmpty } from '../utils/values';
import type { WordPressComponentProps } from '../ui/context/wordpress-component';
import type { NumberControlProps } from './types';
import { HStack } from '../h-stack';
import { Spacer } from '../spacer';
import { useCx } from '../utils';

const noop = () => {};

Expand Down Expand Up @@ -78,6 +79,8 @@ function UnforwardedNumberControl(

const autoComplete = typeProp === 'number' ? 'off' : undefined;
const classes = classNames( 'components-number-control', className );
const cx = useCx();
const spinButtonClasses = cx( size === 'small' && styles.smallSpinButtons );

const spinValue = (
value: string | number | undefined,
Expand Down Expand Up @@ -236,6 +239,7 @@ function UnforwardedNumberControl(
<Spacer marginBottom={ 0 } marginRight={ 2 }>
<HStack spacing={ 1 }>
<SpinButton
className={ spinButtonClasses }
icon={ plusIcon }
isSmall
aria-hidden="true"
Expand All @@ -244,9 +248,9 @@ function UnforwardedNumberControl(
onClick={ buildSpinButtonClickHandler(
'up'
) }
size={ size }
/>
<SpinButton
className={ spinButtonClasses }
icon={ resetIcon }
isSmall
aria-hidden="true"
Expand All @@ -255,7 +259,6 @@ function UnforwardedNumberControl(
onClick={ buildSpinButtonClickHandler(
'down'
) }
size={ size }
/>
</HStack>
</Spacer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import InputControl from '../../input-control';
import { COLORS } from '../../utils';
import Button from '../../button';
import { space } from '../../ui/utils/space';
import type { NumberControlProps } from '../types';

const htmlArrowStyles = ( { hideHTMLArrows }: { hideHTMLArrows: boolean } ) => {
if ( ! hideHTMLArrows ) {
Expand All @@ -35,23 +34,16 @@ export const Input = styled( InputControl )`
${ htmlArrowStyles };
`;

const spinButtonSizeStyles = ( {
size,
}: Pick< NumberControlProps, 'size' > ) => {
if ( size !== 'small' ) {
return ``;
}

return css`
width: ${ space( 5 ) };
min-width: ${ space( 5 ) };
height: ${ space( 5 ) };
`;
};

export const SpinButton = styled( Button )`
&&&&& {
color: ${ COLORS.ui.theme };
${ spinButtonSizeStyles }
}
`;

const smallSpinButtons = css`
width: ${ space( 5 ) };
min-width: ${ space( 5 ) };
height: ${ space( 5 ) };
`;

export const styles = { smallSpinButtons };

1 comment on commit a3af2c7

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in a3af2c7.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5360174107
📝 Reported issues:

Please sign in to comment.