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 and tellthemachines committed Jun 27, 2023
1 parent bd97387 commit a7c4b8f
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)).

### Bug Fix
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 };

0 comments on commit a7c4b8f

Please sign in to comment.