From c05948f0a1d7b46caa4dc096536d457c3c999df3 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Mon, 2 Jan 2023 20:43:35 -0600 Subject: [PATCH 01/42] Rename button/index.js to .jsx --- .../src/button/{index.js => index.tsx} | 52 +++++--- packages/components/src/button/types.ts | 120 ++++++++++++++++++ 2 files changed, 153 insertions(+), 19 deletions(-) rename packages/components/src/button/{index.js => index.tsx} (72%) create mode 100644 packages/components/src/button/types.ts diff --git a/packages/components/src/button/index.js b/packages/components/src/button/index.tsx similarity index 72% rename from packages/components/src/button/index.js rename to packages/components/src/button/index.tsx index 1b0fd57a441a91..f7e8666ae1f4f7 100644 --- a/packages/components/src/button/index.js +++ b/packages/components/src/button/index.tsx @@ -1,8 +1,8 @@ -// @ts-nocheck /** * External dependencies */ import classnames from 'classnames'; +import type { ForwardedRef, HTMLProps, ReactNode } from 'react'; /** * WordPress dependencies @@ -17,8 +17,10 @@ import { useInstanceId } from '@wordpress/compose'; import Tooltip from '../tooltip'; import Icon from '../icon'; import { VisuallyHidden } from '../visually-hidden'; +import type { WordPressComponentProps } from '../ui/context'; +import type { ButtonProps, DeprecatedButtonProps, DisabledEvents, TagName } from './types'; -const disabledEventsOnDisabledButton = [ 'onMouseDown', 'onClick' ]; +const disabledEventsOnDisabledButton: Array< keyof DisabledEvents > = [ 'onMouseDown', 'onClick' ]; function useDeprecatedProps( { isDefault, @@ -28,7 +30,7 @@ function useDeprecatedProps( { isLink, variant, ...otherProps -} ) { +}: WordPressComponentProps< ButtonProps & DeprecatedButtonProps, TagName > ) { let computedVariant = variant; if ( isPrimary ) { @@ -63,7 +65,10 @@ function useDeprecatedProps( { }; } -export function Button( props, ref ) { +export function UnforwardedButton( + props: WordPressComponentProps< ButtonProps, TagName >, + ref: ForwardedRef< any > +) { const { href, target, @@ -93,6 +98,7 @@ export function Button( props, ref ) { ); const hasChildren = + Array.isArray( children ) && children?.[ 0 ] && children[ 0 ] !== null && // Tooltip should not considered as a child @@ -113,8 +119,7 @@ export function Button( props, ref ) { const trulyDisabled = disabled && ! isFocusable; const Tag = href !== undefined && ! trulyDisabled ? 'a' : 'button'; - const tagProps = - Tag === 'a' + const tagProps: HTMLProps< TagName > = Tag === 'a' ? { href, target } : { type: 'button', @@ -145,24 +150,32 @@ export function Button( props, ref ) { // There's a label and... ( !! label && // The children are empty and... - ! children?.length && + ( ! Array.isArray( children ) || ! children?.length ) && // The tooltip is not explicitly disabled. false !== showTooltip ) ); - const descriptionId = describedBy ? instanceId : null; + const descriptionId = describedBy ? instanceId : undefined; const describedById = additionalProps[ 'aria-describedby' ] || descriptionId; + const tagElementProps = { + ...tagProps, + ...additionalProps, + className: classes, + 'aria-label': additionalProps[ 'aria-label' ] || label, + 'aria-describedby': describedById, + ref: ref, + } + + const TagElement = ( { children, ...otherProps }: { children: ReactNode } & typeof tagElementProps ) => { + return Tag === 'a' + ? { children } + : + } + const element = ( - + { icon && iconPosition === 'left' && ( ) } @@ -171,7 +184,7 @@ export function Button( props, ref ) { ) } { children } - + ); if ( ! shouldShowTooltip ) { @@ -190,7 +203,7 @@ export function Button( props, ref ) { return ( <> @@ -205,4 +218,5 @@ export function Button( props, ref ) { ); } -export default forwardRef( Button ); +export const Button = forwardRef( UnforwardedButton ); +export default Button; diff --git a/packages/components/src/button/types.ts b/packages/components/src/button/types.ts new file mode 100644 index 00000000000000..d98e7e3ffc20db --- /dev/null +++ b/packages/components/src/button/types.ts @@ -0,0 +1,120 @@ +/** + * External dependencies + */ +import type { KeyboardEvent, MouseEvent, ReactNode } from 'react'; + +/** + * Internal dependencies + */ +import type { Props as IconProps } from '../icon'; + +export type ButtonProps = { + /** + * Whether the button is disabled. + * If `true`, this will force a `button` element to be rendered. + */ + disabled?: boolean; + /** + * If provided, renders `a` instead of `button`. + */ + href?: string; + /** + * Specifies the button's style. + * The accepted values are: + * `'primary'` (the primary button styles), + * `'secondary'` (the default button styles), + * `'tertiary'` (the text-based button styles), and + * `'link'` (the link button styles). + */ + variant: 'primary' | 'secondary' | 'tertiary' | 'link'; + /** + * Renders a red text-based button style to indicate destructive behavior. + */ + isDestructive?: boolean; + /** + * Decreases the size of the button. + */ + isSmall?: boolean; + /** + * Renders a pressed button style. + */ + isPressed?: boolean; + /** + * Indicates activity while a action is being performed. + */ + isBusy?: boolean; + /** + * The button's children. + */ + children?: ReactNode; + /** + * The accessible description for the button. + */ + describedBy?: string; + /** + * Whether the button is focused. + */ + focus?: boolean; + /** + * If provided with `href`, sets the `target` attribute to the `a`. + */ + target?: string; + /** + * If provided, renders an Icon component inside the button. + */ + icon?: IconProps< unknown >[ 'icon' ]; + /** + * If provided with `icon`, sets the icon size. + * Please refer to the Icon component for more details regarding + * the default value of its `size` prop. + */ + iconSize?: IconProps< unknown > [ 'size' ] + /** + * If provided with `icon`, sets the position of icon relative to the `text`. + * + * @default 'left' + */ + iconPosition?: 'left' | 'right'; + /** + * If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them. + */ + text?: string; + /** + * If provided, renders a Tooltip component for the button. + */ + showTooltip?: boolean; + /** + * If provided with `showTooltip`, sets the position of the tooltip. + * Please refer to the Tooltip component for more details regarding the defaults. + */ + tooltipPosition?: string; + /** + * If provided with `showTooltip`, appends the Shortcut label to the tooltip content. + * If an `Object` is provided, it should contain `display` and `ariaLabel` keys. + */ + shortcut?: string | Object; + /** + * Sets the `aria-label` of the component, if none is provided. + * Sets the Tooltip content if `showTooltip` is provided. + */ + label?: string; + /** + * Whether this is focusable. + */ + __experimentalIsFocusable?: boolean; +} + +export type DeprecatedButtonProps = { + isDefault?: boolean; + isPrimary?: boolean; + isSecondary?: boolean; + isTertiary?: boolean; + isLink?: boolean; +} + +export type DisabledEvents = { + onMouseDown: MouseEvent; + onClick: KeyboardEvent; +}; + +export type TagName = 'a' | 'button'; From 5b57ef6a68f8855fecce9ddd432b2c007663f7fe Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Wed, 4 Jan 2023 22:08:35 -0600 Subject: [PATCH 02/42] Possible approach to the prop types --- packages/components/src/button/index.tsx | 44 ++++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index f7e8666ae1f4f7..3cb6371b06a1e8 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -18,9 +18,17 @@ import Tooltip from '../tooltip'; import Icon from '../icon'; import { VisuallyHidden } from '../visually-hidden'; import type { WordPressComponentProps } from '../ui/context'; -import type { ButtonProps, DeprecatedButtonProps, DisabledEvents, TagName } from './types'; - -const disabledEventsOnDisabledButton: Array< keyof DisabledEvents > = [ 'onMouseDown', 'onClick' ]; +import type { + ButtonProps, + DeprecatedButtonProps, + DisabledEvents, + TagName, +} from './types'; + +const disabledEventsOnDisabledButton: Array< keyof DisabledEvents > = [ + 'onMouseDown', + 'onClick', +]; function useDeprecatedProps( { isDefault, @@ -119,7 +127,8 @@ export function UnforwardedButton( const trulyDisabled = disabled && ! isFocusable; const Tag = href !== undefined && ! trulyDisabled ? 'a' : 'button'; - const tagProps: HTMLProps< TagName > = Tag === 'a' + const tagProps: HTMLProps< TagName > = + Tag === 'a' ? { href, target } : { type: 'button', @@ -166,13 +175,22 @@ export function UnforwardedButton( 'aria-label': additionalProps[ 'aria-label' ] || label, 'aria-describedby': describedById, ref: ref, - } + }; - const TagElement = ( { children, ...otherProps }: { children: ReactNode } & typeof tagElementProps ) => { - return Tag === 'a' - ? { children } - : - } + const TagElement = ( { + children: tagChildren, + ...otherProps + }: { children: ReactNode } & typeof tagElementProps ) => { + return Tag === 'a' ? ( + ) }> + { tagChildren } + + ) : ( + + ); + }; const element = ( @@ -203,7 +221,11 @@ export function UnforwardedButton( return ( <> From 718959ceed41f93e8a008d316f8f7fed910e2ffa Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Mon, 9 Jan 2023 17:08:24 -0600 Subject: [PATCH 03/42] Simplify the tag container --- packages/components/src/button/README.md | 6 +++ .../button/{deprecated.js => deprecated.tsx} | 26 +++++++++++-- packages/components/src/button/index.tsx | 38 ++++++++++--------- packages/components/src/button/types.ts | 25 ++++++++---- 4 files changed, 66 insertions(+), 29 deletions(-) rename packages/components/src/button/{deprecated.js => deprecated.tsx} (50%) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index b8b3a7f3111d2b..3efaccee73b72b 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -177,6 +177,12 @@ Whether the button is focused. - Type: `Boolean` - Required: No +#### `onMouseDown`: ( event: MouseEvent< HTMLElement > ) => void;` + +Called when the mouse is down. + +- Required: No + #### target If provided with `href`, sets the `target` attribute to the `a`. diff --git a/packages/components/src/button/deprecated.js b/packages/components/src/button/deprecated.tsx similarity index 50% rename from packages/components/src/button/deprecated.js rename to packages/components/src/button/deprecated.tsx index 5f18e0e5eb1648..8a5a2fa917ebd8 100644 --- a/packages/components/src/button/deprecated.js +++ b/packages/components/src/button/deprecated.tsx @@ -1,4 +1,8 @@ -// @ts-nocheck +/** + * External dependencies + */ +import type { ForwardedRef } from 'react'; + /** * WordPress dependencies */ @@ -8,9 +12,23 @@ import { forwardRef } from '@wordpress/element'; /** * Internal dependencies */ -import Button from '../button'; +import Button from '.'; +import type { ButtonProps, DeprecatedIconButtonProps, TagName } from './types'; +import type { WordPressComponentProps } from '../ui/context'; -function IconButton( { labelPosition, size, tooltip, label, ...props }, ref ) { +function UnforwardedIconButton( + { + labelPosition, + size, + tooltip, + label, + ...props + }: WordPressComponentProps< + ButtonProps & DeprecatedIconButtonProps, + TagName + >, + ref: ForwardedRef< any > +) { deprecated( 'wp.components.IconButton', { since: '5.4', alternative: 'wp.components.Button', @@ -29,4 +47,4 @@ function IconButton( { labelPosition, size, tooltip, label, ...props }, ref ) { ); } -export default forwardRef( IconButton ); +export default forwardRef( UnforwardedIconButton ); diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index 3cb6371b06a1e8..f9b6f0a67c314d 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -2,7 +2,12 @@ * External dependencies */ import classnames from 'classnames'; -import type { ForwardedRef, HTMLProps, ReactNode } from 'react'; +import type { + ForwardedRef, + HTMLProps, + MouseEvent, + ReactNode, +} from 'react'; /** * WordPress dependencies @@ -21,11 +26,11 @@ import type { WordPressComponentProps } from '../ui/context'; import type { ButtonProps, DeprecatedButtonProps, - DisabledEvents, + DisabledEvent, TagName, } from './types'; -const disabledEventsOnDisabledButton: Array< keyof DisabledEvents > = [ +const disabledEventsOnDisabledButton: Array< DisabledEvent > = [ 'onMouseDown', 'onClick', ]; @@ -142,9 +147,13 @@ export function UnforwardedButton( tagProps[ 'aria-disabled' ] = true; for ( const disabledEvent of disabledEventsOnDisabledButton ) { - additionalProps[ disabledEvent ] = ( event ) => { - event.stopPropagation(); - event.preventDefault(); + additionalProps[ disabledEvent ] = ( + event: MouseEvent< HTMLElement > + ) => { + if ( event ) { + event.stopPropagation(); + event.preventDefault(); + } }; } } @@ -174,21 +183,16 @@ export function UnforwardedButton( className: classes, 'aria-label': additionalProps[ 'aria-label' ] || label, 'aria-describedby': describedById, - ref: ref, + ref, }; - const TagElement = ( { - children: tagChildren, - ...otherProps - }: { children: ReactNode } & typeof tagElementProps ) => { + const TagElement = ( tagProps: { children: ReactNode } & typeof tagElementProps ) => { return Tag === 'a' ? ( - ) }> - { tagChildren } - + ) } /> ) : ( - + ) } + /> ); }; diff --git a/packages/components/src/button/types.ts b/packages/components/src/button/types.ts index d98e7e3ffc20db..ea297bfa65fb9f 100644 --- a/packages/components/src/button/types.ts +++ b/packages/components/src/button/types.ts @@ -1,7 +1,7 @@ /** * External dependencies */ -import type { KeyboardEvent, MouseEvent, ReactNode } from 'react'; +import type { MouseEventHandler, ReactNode } from 'react'; /** * Internal dependencies @@ -26,7 +26,7 @@ export type ButtonProps = { * `'tertiary'` (the text-based button styles), and * `'link'` (the link button styles). */ - variant: 'primary' | 'secondary' | 'tertiary' | 'link'; + variant?: 'primary' | 'secondary' | 'tertiary' | 'link'; /** * Renders a red text-based button style to indicate destructive behavior. */ @@ -68,13 +68,17 @@ export type ButtonProps = { * Please refer to the Icon component for more details regarding * the default value of its `size` prop. */ - iconSize?: IconProps< unknown > [ 'size' ] + iconSize?: IconProps< unknown >[ 'size' ]; /** * If provided with `icon`, sets the position of icon relative to the `text`. * * @default 'left' */ iconPosition?: 'left' | 'right'; + /** + * Called when the mouse is down. + */ + onMouseDown?: MouseEventHandler< HTMLElement >; /** * If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them. */ @@ -102,7 +106,7 @@ export type ButtonProps = { * Whether this is focusable. */ __experimentalIsFocusable?: boolean; -} +}; export type DeprecatedButtonProps = { isDefault?: boolean; @@ -110,11 +114,16 @@ export type DeprecatedButtonProps = { isSecondary?: boolean; isTertiary?: boolean; isLink?: boolean; -} +}; -export type DisabledEvents = { - onMouseDown: MouseEvent; - onClick: KeyboardEvent; +export type DeprecatedIconButtonProps = { + labelPosition: ButtonProps[ 'tooltipPosition' ]; + size: ButtonProps[ 'iconSize' ]; + showTooltip?: boolean; + label: ButtonProps[ 'label' ]; + tooltip: ButtonProps[ 'label' ]; }; +export type DisabledEvent = 'onMouseDown' | 'onClick'; + export type TagName = 'a' | 'button'; From d8cae0c54eb80113966b93fd743ced5474ba1f21 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Mon, 9 Jan 2023 17:18:55 -0600 Subject: [PATCH 04/42] Allow passing childrent to TagElement --- packages/components/src/button/index.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index f9b6f0a67c314d..6126617d142bec 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -186,18 +186,22 @@ export function UnforwardedButton( ref, }; - const TagElement = ( tagProps: { children: ReactNode } & typeof tagElementProps ) => { + const TagElement = ( { children }: { children: ReactNode } ) => { return Tag === 'a' ? ( - ) } /> + ) } > + { children } + ) : ( ) } - /> + { ...( tagElementProps as WordPressComponentProps< {}, 'button' > ) } + > + { children } + ); }; const element = ( - + { icon && iconPosition === 'left' && ( ) } From d007837768b59eb6f1edfb7dd44c3647e15584dc Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Mon, 9 Jan 2023 23:12:38 -0600 Subject: [PATCH 05/42] Fix the type of onKeyDown --- .../border-box-control-linked-button/component.tsx | 6 +++++- .../border-control/border-control-dropdown/component.tsx | 2 +- packages/components/src/button/types.ts | 6 +----- packages/components/src/date-time/date/index.tsx | 3 ++- packages/components/src/dropdown/stories/index.tsx | 2 +- packages/components/src/form-token-field/token.tsx | 2 +- packages/components/src/tab-panel/index.tsx | 2 +- packages/components/src/tab-panel/types.ts | 3 ++- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx b/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx index c4001369f8e015..d02342c921cef9 100644 --- a/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx +++ b/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx @@ -14,6 +14,7 @@ import { contextConnect, WordPressComponentProps } from '../../ui/context'; import { useBorderBoxControlLinkedButton } from './hook'; import type { LinkedButtonProps } from '../types'; +import type { ButtonProps, TagName } from '../../button/types'; const BorderBoxControlLinkedButton = ( props: WordPressComponentProps< LinkedButtonProps, 'div' >, @@ -27,7 +28,10 @@ const BorderBoxControlLinkedButton = ( ), diff --git a/packages/components/src/form-token-field/token.tsx b/packages/components/src/form-token-field/token.tsx index 9d2c522037d8e9..e5633aa3b75cf0 100644 --- a/packages/components/src/form-token-field/token.tsx +++ b/packages/components/src/form-token-field/token.tsx @@ -73,7 +73,7 @@ export default function Token( { ; -} +}; -export const Default = Template.bind( {} ); +export const Default: ComponentStory< typeof Button > = Template.bind( {} ); Default.args = { children: 'Code is poetry', }; -export const Primary = Template.bind( {} ); +export const Primary: ComponentStory< typeof Button > = Template.bind( {} ); Primary.args = { ...Default.args, variant: 'primary', }; -export const Secondary = Template.bind( {} ); +export const Secondary: ComponentStory< typeof Button > = Template.bind( {} ); Secondary.args = { ...Default.args, variant: 'secondary', }; -export const Tertiary = Template.bind( {} ); +export const Tertiary: ComponentStory< typeof Button > = Template.bind( {} ); Tertiary.args = { ...Default.args, variant: 'tertiary', }; -export const Link = Template.bind( {} ); +export const Link: ComponentStory< typeof Button > = Template.bind( {} ); Link.args = { ...Default.args, variant: 'link', }; -export const IsDestructive = Template.bind( {} ); +export const IsDestructive: ComponentStory< typeof Button > = Template.bind( + {} +); IsDestructive.args = { ...Default.args, isDestructive: true, }; -export const Icon = Template.bind( {} ); +export const Icon: ComponentStory< typeof Button > = Template.bind( {} ); Icon.args = { label: 'Code is poetry', icon: 'wordpress', }; -export const groupedIcons = () => { - const GroupContainer = ( { children } ) => ( +export const groupedIcons: ComponentStory< typeof Button > = () => { + const GroupContainer = ( { children }: { children: ReactNode } ) => (
{ children }
); From 9e6cc7dab06a061f8d713d11b60453a17f5516c4 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Mon, 9 Jan 2023 23:48:08 -0600 Subject: [PATCH 09/42] Alphabetize types.ts types --- packages/components/src/button/README.md | 6 -- packages/components/src/button/deprecated.tsx | 2 +- .../components/src/button/stories/index.tsx | 2 +- packages/components/src/button/types.ts | 94 +++++++++---------- 4 files changed, 49 insertions(+), 55 deletions(-) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index 3efaccee73b72b..b8b3a7f3111d2b 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -177,12 +177,6 @@ Whether the button is focused. - Type: `Boolean` - Required: No -#### `onMouseDown`: ( event: MouseEvent< HTMLElement > ) => void;` - -Called when the mouse is down. - -- Required: No - #### target If provided with `href`, sets the `target` attribute to the `a`. diff --git a/packages/components/src/button/deprecated.tsx b/packages/components/src/button/deprecated.tsx index 8a5a2fa917ebd8..36e6b15c909a29 100644 --- a/packages/components/src/button/deprecated.tsx +++ b/packages/components/src/button/deprecated.tsx @@ -18,10 +18,10 @@ import type { WordPressComponentProps } from '../ui/context'; function UnforwardedIconButton( { + label, labelPosition, size, tooltip, - label, ...props }: WordPressComponentProps< ButtonProps & DeprecatedIconButtonProps, diff --git a/packages/components/src/button/stories/index.tsx b/packages/components/src/button/stories/index.tsx index 16bf5a9d641831..ffaf361d5874aa 100644 --- a/packages/components/src/button/stories/index.tsx +++ b/packages/components/src/button/stories/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { ReactNode } from 'react'; /** * WordPress dependencies @@ -19,7 +20,6 @@ import { */ import './style.css'; import Button from '..'; -import type { ReactNode } from 'react'; const meta: ComponentMeta< typeof Button > = { title: 'Components/Button', diff --git a/packages/components/src/button/types.ts b/packages/components/src/button/types.ts index 03d0f2db891527..4693650170ad5e 100644 --- a/packages/components/src/button/types.ts +++ b/packages/components/src/button/types.ts @@ -9,95 +9,95 @@ import type { ReactNode } from 'react'; import type { Props as IconProps } from '../icon'; export type ButtonProps = { + /** + * The button's children. + */ + children?: ReactNode; + /** + * The accessible description for the button. + */ + describedBy?: string; /** * Whether the button is disabled. * If `true`, this will force a `button` element to be rendered. */ disabled?: boolean; /** - * If provided, renders `a` instead of `button`. + * Whether the button is focused. */ - href?: string; + focus?: boolean; /** - * Specifies the button's style. - * The accepted values are: - * `'primary'` (the primary button styles), - * `'secondary'` (the default button styles), - * `'tertiary'` (the text-based button styles), and - * `'link'` (the link button styles). + * If provided, renders `a` instead of `button`. */ - variant?: 'primary' | 'secondary' | 'tertiary' | 'link'; + href?: string; /** - * Renders a red text-based button style to indicate destructive behavior. + * If provided, renders an Icon component inside the button. */ - isDestructive?: boolean; + icon?: IconProps< unknown >[ 'icon' ]; /** - * Decreases the size of the button. + * If provided with `icon`, sets the position of icon relative to the `text`. + * + * @default 'left' */ - isSmall?: boolean; + iconPosition?: 'left' | 'right'; /** - * Renders a pressed button style. + * If provided with `icon`, sets the icon size. + * Please refer to the Icon component for more details regarding + * the default value of its `size` prop. */ - isPressed?: boolean; + iconSize?: IconProps< unknown >[ 'size' ]; /** * Indicates activity while a action is being performed. */ isBusy?: boolean; /** - * The button's children. + * Renders a red text-based button style to indicate destructive behavior. */ - children?: ReactNode; + isDestructive?: boolean; /** - * The accessible description for the button. + * Renders a pressed button style. */ - describedBy?: string; + isPressed?: boolean; /** - * Whether the button is focused. + * Decreases the size of the button. */ - focus?: boolean; + isSmall?: boolean; /** - * If provided with `href`, sets the `target` attribute to the `a`. + * Sets the `aria-label` of the component, if none is provided. + * Sets the Tooltip content if `showTooltip` is provided. */ - target?: string; + label?: string; /** - * If provided, renders an Icon component inside the button. + * If provided with `showTooltip`, appends the Shortcut label to the tooltip content. + * If an `Object` is provided, it should contain `display` and `ariaLabel` keys. */ - icon?: IconProps< unknown >[ 'icon' ]; + shortcut?: string | Object; /** - * If provided with `icon`, sets the icon size. - * Please refer to the Icon component for more details regarding - * the default value of its `size` prop. + * If provided, renders a Tooltip component for the button. */ - iconSize?: IconProps< unknown >[ 'size' ]; + showTooltip?: boolean; /** - * If provided with `icon`, sets the position of icon relative to the `text`. - * - * @default 'left' + * If provided with `href`, sets the `target` attribute to the `a`. */ - iconPosition?: 'left' | 'right'; + target?: string; /** * If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them. */ text?: string; - /** - * If provided, renders a Tooltip component for the button. - */ - showTooltip?: boolean; /** * If provided with `showTooltip`, sets the position of the tooltip. * Please refer to the Tooltip component for more details regarding the defaults. */ tooltipPosition?: string; /** - * If provided with `showTooltip`, appends the Shortcut label to the tooltip content. - * If an `Object` is provided, it should contain `display` and `ariaLabel` keys. - */ - shortcut?: string | Object; - /** - * Sets the `aria-label` of the component, if none is provided. - * Sets the Tooltip content if `showTooltip` is provided. + * Specifies the button's style. + * The accepted values are: + * primary' (the primary button styles) + * 'secondary' (the default button styles) + * 'tertiary' (the text-based button styles) + * 'link' (the link button styles) */ - label?: string; + variant?: 'primary' | 'secondary' | 'tertiary' | 'link'; /** * Whether this is focusable. */ @@ -106,16 +106,16 @@ export type ButtonProps = { export type DeprecatedButtonProps = { isDefault?: boolean; + isLink?: boolean; isPrimary?: boolean; isSecondary?: boolean; isTertiary?: boolean; - isLink?: boolean; }; export type DeprecatedIconButtonProps = { labelPosition: ButtonProps[ 'tooltipPosition' ]; - size: ButtonProps[ 'iconSize' ]; showTooltip?: boolean; + size: ButtonProps[ 'iconSize' ]; label: ButtonProps[ 'label' ]; tooltip: ButtonProps[ 'label' ]; }; From 9298bd7d52f2494eccc22bce780cd8a9648018dc Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Tue, 10 Jan 2023 00:04:06 -0600 Subject: [PATCH 10/42] Refactor TagElement to element --- packages/components/src/button/index.tsx | 49 ++++++++++-------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index a375d103bf2bab..726d3c7c84ea02 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import type { ForwardedRef, HTMLProps, MouseEvent, ReactNode } from 'react'; +import type { ForwardedRef, HTMLProps, MouseEvent } from 'react'; /** * WordPress dependencies @@ -170,7 +170,7 @@ export function UnforwardedButton( const describedById = additionalProps[ 'aria-describedby' ] || descriptionId; - const tagElementProps = { + const elementProps = { ...tagProps, ...additionalProps, className: classes, @@ -179,31 +179,8 @@ export function UnforwardedButton( ref, }; - const TagElement = ( { - children: tagChildren, - }: { - children: ReactNode; - } ) => { - return Tag === 'a' ? ( - ) } - > - { tagChildren } - - ) : ( - ) } - > - { tagChildren } - - ); - }; - - const element = ( - + const elementChildren = ( + <> { icon && iconPosition === 'left' && ( ) } @@ -212,9 +189,25 @@ export function UnforwardedButton( ) } { children } - + ); + const element = + Tag === 'a' ? ( + ) }> + { elementChildren } + + ) : ( + + ); + if ( ! shouldShowTooltip ) { return ( <> From 7314d0aabec95da90ab26e60a708a34274f249c2 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Tue, 10 Jan 2023 00:16:59 -0600 Subject: [PATCH 11/42] Alphabetize an import --- .../border-box-control-linked-button/component.tsx | 6 +----- packages/components/src/tab-panel/types.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx b/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx index d02342c921cef9..cc7d3239289156 100644 --- a/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx +++ b/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx @@ -14,7 +14,6 @@ import { contextConnect, WordPressComponentProps } from '../../ui/context'; import { useBorderBoxControlLinkedButton } from './hook'; import type { LinkedButtonProps } from '../types'; -import type { ButtonProps, TagName } from '../../button/types'; const BorderBoxControlLinkedButton = ( props: WordPressComponentProps< LinkedButtonProps, 'div' >, @@ -28,10 +27,7 @@ const BorderBoxControlLinkedButton = ( - ); - if ( ! shouldShowTooltip ) { return ( <> From 67efafe95aa288f4ad1905e541968a9658fbd89b Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 14:44:21 -0600 Subject: [PATCH 13/42] Use the [] array type syntax --- packages/components/src/button/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index e6230445a90f18..922f0a57a324a5 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -25,7 +25,7 @@ import type { TagName, } from './types'; -const disabledEventsOnDisabledButton: Array< DisabledEvent > = [ +const disabledEventsOnDisabledButton: DisabledEvent[] = [ 'onMouseDown', 'onClick', ]; From bbc7cd4ebf05bb07fb8c3c28bee7b3a2bf1e3cf5 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 15:12:39 -0600 Subject: [PATCH 14/42] Improve the typing of hasChildren --- packages/components/src/button/index.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index 922f0a57a324a5..85a848f2f2fb02 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -106,11 +106,13 @@ export function UnforwardedButton( ); const hasChildren = - Array.isArray( children ) && - children?.[ 0 ] && - children[ 0 ] !== null && - // Tooltip should not considered as a child - children?.[ 0 ]?.props?.className !== 'components-tooltip'; + ( 'string' === typeof children && !! children ) || ( + Array.isArray( children ) && + children?.[ 0 ] && + children[ 0 ] !== null && + // Tooltip should not considered as a child + children?.[ 0 ]?.props?.className !== 'components-tooltip' + ); const classes = classnames( 'components-button', className, { 'is-secondary': variant === 'secondary', From 0f7a2422c28de4a340b689349df04c5414d0554f Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 15:21:41 -0600 Subject: [PATCH 15/42] Fix the typing of chilren.length --- packages/components/src/button/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index 85a848f2f2fb02..e6cfc9b948ccaa 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import type { ForwardedRef, HTMLProps, MouseEvent } from 'react'; +import type { ForwardedRef, HTMLProps, MouseEvent, ReactElement } from 'react'; /** * WordPress dependencies @@ -163,7 +163,7 @@ export function UnforwardedButton( // There's a label and... ( !! label && // The children are empty and... - ( ! Array.isArray( children ) || ! children?.length ) && + ! ( children as string | ReactElement[] )?.length && // The tooltip is not explicitly disabled. false !== showTooltip ) ); @@ -209,7 +209,7 @@ export function UnforwardedButton( <> Date: Sun, 15 Jan 2023 15:22:25 -0600 Subject: [PATCH 16/42] Revert "Revert changes to element, this will fail type checking" This reverts commit 0b616c785677c407879b6b0f7708409b6ca3dbaf. --- packages/components/src/button/index.tsx | 38 +++++++++++++++++------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index e6cfc9b948ccaa..e15d99f2fb6d3a 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -172,15 +172,17 @@ export function UnforwardedButton( const describedById = additionalProps[ 'aria-describedby' ] || descriptionId; - const element = ( - + const elementProps = { + ...tagProps, + ...additionalProps, + className: classes, + 'aria-label': additionalProps[ 'aria-label' ] || label, + 'aria-describedby': describedById, + ref, + }; + + const elementChildren = ( + <> { icon && iconPosition === 'left' && ( ) } @@ -189,9 +191,25 @@ export function UnforwardedButton( ) } { children } - + ); + const element = + Tag === 'a' ? ( + ) }> + { elementChildren } + + ) : ( + + ); + if ( ! shouldShowTooltip ) { return ( <> From dadbb4bb958d2e638ba7bc1fa5ff8a4f6d042816 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 15:24:46 -0600 Subject: [PATCH 17/42] Pass the generic of WordPressComponentProps a second argument --- packages/components/src/button/index.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index e15d99f2fb6d3a..8257526eaa5084 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -106,13 +106,12 @@ export function UnforwardedButton( ); const hasChildren = - ( 'string' === typeof children && !! children ) || ( - Array.isArray( children ) && + ( 'string' === typeof children && !! children ) || + ( Array.isArray( children ) && children?.[ 0 ] && children[ 0 ] !== null && // Tooltip should not considered as a child - children?.[ 0 ]?.props?.className !== 'components-tooltip' - ); + children?.[ 0 ]?.props?.className !== 'components-tooltip' ); const classes = classnames( 'components-button', className, { 'is-secondary': variant === 'secondary', @@ -196,13 +195,18 @@ export function UnforwardedButton( const element = Tag === 'a' ? ( - ) }> + ) } + > { elementChildren } ) : ( ; +const Template: ComponentStory< typeof Button > = ( props ) => { + return ; }; export const Default: ComponentStory< typeof Button > = Template.bind( {} ); @@ -176,7 +173,7 @@ Icon.args = { icon: 'wordpress', }; -export const groupedIcons: ComponentStory< typeof Button > = () => { +export const GroupedIcons: ComponentStory< typeof Button > = () => { const GroupContainer = ( { children }: { children: ReactNode } ) => (
{ children }
); From e702dd475b9c8eba500f9fd2eea58c03bc7f728d Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 16:06:08 -0600 Subject: [PATCH 19/42] Use React.MousEvent --- packages/components/src/tab-panel/types.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/components/src/tab-panel/types.ts b/packages/components/src/tab-panel/types.ts index 7901599afb0e6c..5a5b883a51a308 100644 --- a/packages/components/src/tab-panel/types.ts +++ b/packages/components/src/tab-panel/types.ts @@ -1,12 +1,11 @@ /** * External dependencies */ -import type { ReactNode } from 'react'; +import type { MouseEvent, ReactNode } from 'react'; /** * Internal dependencies */ -import type { Button } from '../button'; import type { IconType } from '../icon'; type Tab< IconProps = unknown > = { @@ -35,7 +34,7 @@ type Tab< IconProps = unknown > = { export type TabButtonProps< IconProps = unknown > = { children: ReactNode; label?: string; - onClick: Parameters< typeof Button >[ 0 ][ 'onClick' ]; + onClick: ( event: MouseEvent ) => void; selected: boolean; showTooltip?: boolean; tabId: string; From 0badec81e00ec56afe71a48f5275b66821efc9f6 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 16:47:13 -0600 Subject: [PATCH 20/42] Update README.md with types from types.ts --- packages/components/src/button/README.md | 61 +++++++++++------------- packages/components/src/button/types.ts | 4 +- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index b8b3a7f3111d2b..363bbb5230d4c0 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -121,67 +121,71 @@ The presence of a `href` prop determines whether an `anchor` element is rendered Props not included in this set will be applied to the `a` or `button` element. -#### disabled +#### `children`: `ReactNode` + +The button's children. + +- Required: No + +#### `disabled`: `boolean` Whether the button is disabled. If `true`, this will force a `button` element to be rendered. -- Type: `Boolean` - Required: No -#### href +#### `describedBy`: `string` + +An accessible description for the button. + +- Required: No + +#### `href`: `string` If provided, renders `a` instead of `button`. -- Type: `String` - Required: No -#### variant +#### `variant`: `string` Specifies the button's style. The accepted values are `'primary'` (the primary button styles), `'secondary'` (the default button styles), `'tertiary'` (the text-based button styles), and `'link'` (the link button styles). -- Type: `String` - Required: No -#### isDestructive +#### `isDestructive`: `boolean` Renders a red text-based button style to indicate destructive behavior. -- Type: `Boolean` - Required: No -#### isSmall +#### `isSmall`: `boolean` Decreases the size of the button. - Type: `Boolean` - Required: No -#### isPressed +#### `isPressed`: `boolean` Renders a pressed button style. -- Type: `Boolean` - Required: No -#### isBusy +#### `isBusy`: `boolean` Indicates activity while a action is being performed. -- Type: `Boolean` - Required: No -#### focus +#### `focus`: `boolean` Whether the button is focused. -- Type: `Boolean` - Required: No -#### target +#### `target`: `string` If provided with `href`, sets the `target` attribute to the `a`. -- Type: `String` - Required: No #### className @@ -191,61 +195,54 @@ An optional additional class name to apply to the rendered button. - Type: `String` - Required: No -#### icon +#### `icon`: `IconProps< unknown >[ 'icon' ]` If provided, renders an [Icon](/packages/components/src/icon/README.md) component inside the button. -- Type: `String|Function|WPComponent|null` - Required: No -#### iconSize +#### `iconSize`: `IconProps< unknown >[ 'size' ]` If provided with `icon`, sets the icon size. Please refer to the [Icon](/packages/components/src/icon/README.md) component for more details regarding the default value of its `size` prop. -- Type: `Number` - Required: No -#### iconPosition +#### `iconPosition`: `'left' | 'right'` If provided with `icon`, sets the position of icon relative to the `text`. Available options are `left|right`. -- Type: `string` - Required: No - Default: `left` -#### text +#### `text`: `string` If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them. -- Type: `String` - Required: No -#### showTooltip +#### `showTooltip`: `boolean` If provided, renders a [Tooltip](/packages/components/src/tooltip/README.md) component for the button. -- Type: `Boolean` - Required: No -#### tooltipPosition +#### `tooltipPosition`: `string` If provided with`showTooltip`, sets the position of the tooltip. Please refer to the [Tooltip](/packages/components/src/tooltip/README.md) component for more details regarding the defaults. - Type: `String` - Require: No -#### shortcut +#### `shortcut`: `string | object` If provided with `showTooltip`, appends the Shortcut label to the tooltip content. If an `Object` is provided, it should contain `display` and `ariaLabel` keys. -- Type: `String|Object` - Required: No -#### label +#### `label`: `string` Sets the `aria-label` of the component, if none is provided. Sets the Tooltip content if `showTooltip` is provided. -- Type: `String` - Required: No ## Related components diff --git a/packages/components/src/button/types.ts b/packages/components/src/button/types.ts index 4693650170ad5e..aaf32c2972d8b4 100644 --- a/packages/components/src/button/types.ts +++ b/packages/components/src/button/types.ts @@ -14,7 +14,7 @@ export type ButtonProps = { */ children?: ReactNode; /** - * The accessible description for the button. + * An accessible description for the button. */ describedBy?: string; /** @@ -92,7 +92,7 @@ export type ButtonProps = { /** * Specifies the button's style. * The accepted values are: - * primary' (the primary button styles) + * 'primary' (the primary button styles) * 'secondary' (the default button styles) * 'tertiary' (the text-based button styles) * 'link' (the link button styles) From b9a3b506e8a854ddbd3145c8e3dc42fd9fb421fd Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 16:51:51 -0600 Subject: [PATCH 21/42] Fix the type of shortcut --- packages/components/src/button/README.md | 4 ++-- packages/components/src/button/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index 363bbb5230d4c0..154c7e92518d21 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -233,9 +233,9 @@ If provided with`showTooltip`, sets the position of the tooltip. Please refer to - Type: `String` - Require: No -#### `shortcut`: `string | object` +#### `shortcut`: `string | { display: string; ariaLabel: string; }` -If provided with `showTooltip`, appends the Shortcut label to the tooltip content. If an `Object` is provided, it should contain `display` and `ariaLabel` keys. +If provided with `showTooltip`, appends the Shortcut label to the tooltip content. If an object is provided, it should contain `display` and `ariaLabel` keys. - Required: No diff --git a/packages/components/src/button/types.ts b/packages/components/src/button/types.ts index aaf32c2972d8b4..961db58ae95272 100644 --- a/packages/components/src/button/types.ts +++ b/packages/components/src/button/types.ts @@ -69,9 +69,9 @@ export type ButtonProps = { label?: string; /** * If provided with `showTooltip`, appends the Shortcut label to the tooltip content. - * If an `Object` is provided, it should contain `display` and `ariaLabel` keys. + * If an object is provided, it should contain `display` and `ariaLabel` keys. */ - shortcut?: string | Object; + shortcut?: string | { display: string; ariaLabel: string }; /** * If provided, renders a Tooltip component for the button. */ From 57866b7881c5e59e5b211863ca2168a63ef0c808 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 16:54:14 -0600 Subject: [PATCH 22/42] Remove unnecessary Type annotations --- packages/components/src/button/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index 154c7e92518d21..600c4cebcfc773 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -161,7 +161,6 @@ Renders a red text-based button style to indicate destructive behavior. Decreases the size of the button. -- Type: `Boolean` - Required: No #### `isPressed`: `boolean` @@ -188,11 +187,10 @@ If provided with `href`, sets the `target` attribute to the `a`. - Required: No -#### className +#### `className`: `string` An optional additional class name to apply to the rendered button. -- Type: `String` - Required: No #### `icon`: `IconProps< unknown >[ 'icon' ]` @@ -230,8 +228,7 @@ If provided, renders a [Tooltip](/packages/components/src/tooltip/README.md) com If provided with`showTooltip`, sets the position of the tooltip. Please refer to the [Tooltip](/packages/components/src/tooltip/README.md) component for more details regarding the defaults. -- Type: `String` -- Require: No +- Required: No #### `shortcut`: `string | { display: string; ariaLabel: string; }` From d8dcaee2f4a20d6eb629065fb9f097c7f05a81ec Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 17:00:02 -0600 Subject: [PATCH 23/42] In README.md, alphabetize the props --- packages/components/src/button/README.md | 76 ++++++++++++------------ 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index 600c4cebcfc773..74dd70f1105995 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -127,9 +127,9 @@ The button's children. - Required: No -#### `disabled`: `boolean` +#### `className`: `string` -Whether the button is disabled. If `true`, this will force a `button` element to be rendered. +An optional additional class name to apply to the rendered button. - Required: No @@ -139,82 +139,76 @@ An accessible description for the button. - Required: No -#### `href`: `string` - -If provided, renders `a` instead of `button`. - -- Required: No - -#### `variant`: `string` +#### `disabled`: `boolean` -Specifies the button's style. The accepted values are `'primary'` (the primary button styles), `'secondary'` (the default button styles), `'tertiary'` (the text-based button styles), and `'link'` (the link button styles). +Whether the button is disabled. If `true`, this will force a `button` element to be rendered. - Required: No -#### `isDestructive`: `boolean` +#### `focus`: `boolean` -Renders a red text-based button style to indicate destructive behavior. +Whether the button is focused. - Required: No -#### `isSmall`: `boolean` +#### `href`: `string` -Decreases the size of the button. +If provided, renders `a` instead of `button`. - Required: No -#### `isPressed`: `boolean` +#### `icon`: `IconProps< unknown >[ 'icon' ]` -Renders a pressed button style. +If provided, renders an [Icon](/packages/components/src/icon/README.md) component inside the button. - Required: No -#### `isBusy`: `boolean` +#### `iconPosition`: `'left' | 'right'` -Indicates activity while a action is being performed. +If provided with `icon`, sets the position of icon relative to the `text`. Available options are `left|right`. - Required: No +- Default: `left` -#### `focus`: `boolean` +#### `iconSize`: `IconProps< unknown >[ 'size' ]` -Whether the button is focused. +If provided with `icon`, sets the icon size. Please refer to the [Icon](/packages/components/src/icon/README.md) component for more details regarding the default value of its `size` prop. - Required: No -#### `target`: `string` +#### `isBusy`: `boolean` -If provided with `href`, sets the `target` attribute to the `a`. +Indicates activity while a action is being performed. - Required: No -#### `className`: `string` +#### `isDestructive`: `boolean` -An optional additional class name to apply to the rendered button. +Renders a red text-based button style to indicate destructive behavior. - Required: No -#### `icon`: `IconProps< unknown >[ 'icon' ]` +#### `isPressed`: `boolean` -If provided, renders an [Icon](/packages/components/src/icon/README.md) component inside the button. +Renders a pressed button style. - Required: No -#### `iconSize`: `IconProps< unknown >[ 'size' ]` +#### `isSmall`: `boolean` -If provided with `icon`, sets the icon size. Please refer to the [Icon](/packages/components/src/icon/README.md) component for more details regarding the default value of its `size` prop. +Decreases the size of the button. - Required: No -#### `iconPosition`: `'left' | 'right'` +#### `label`: `string` -If provided with `icon`, sets the position of icon relative to the `text`. Available options are `left|right`. +Sets the `aria-label` of the component, if none is provided. Sets the Tooltip content if `showTooltip` is provided. - Required: No -- Default: `left` -#### `text`: `string` +#### `shortcut`: `string | { display: string; ariaLabel: string; }` -If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them. +If provided with `showTooltip`, appends the Shortcut label to the tooltip content. If an object is provided, it should contain `display` and `ariaLabel` keys. - Required: No @@ -224,24 +218,28 @@ If provided, renders a [Tooltip](/packages/components/src/tooltip/README.md) com - Required: No -#### `tooltipPosition`: `string` +#### `target`: `string` -If provided with`showTooltip`, sets the position of the tooltip. Please refer to the [Tooltip](/packages/components/src/tooltip/README.md) component for more details regarding the defaults. +If provided with `href`, sets the `target` attribute to the `a`. - Required: No -#### `shortcut`: `string | { display: string; ariaLabel: string; }` +#### `text`: `string` -If provided with `showTooltip`, appends the Shortcut label to the tooltip content. If an object is provided, it should contain `display` and `ariaLabel` keys. +If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them. - Required: No -#### `label`: `string` +#### `tooltipPosition`: `string` -Sets the `aria-label` of the component, if none is provided. Sets the Tooltip content if `showTooltip` is provided. +If provided with`showTooltip`, sets the position of the tooltip. Please refer to the [Tooltip](/packages/components/src/tooltip/README.md) component for more details regarding the defaults. - Required: No +#### `variant`: `'primary' | 'secondary' | 'tertiary' | 'link'` + +Specifies the button's style. The accepted values are `'primary'` (the primary button styles), `'secondary'` (the default button styles), `'tertiary'` (the text-based button styles), and `'link'` (the link button styles). + ## Related components - To group buttons together, use the [ButtonGroup](/packages/components/src/button-group/README.md) component. From 5e270a1c65665309a90ecd1cb992e0b071efc2c4 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 17:03:48 -0600 Subject: [PATCH 24/42] Add a Required annotation to the variant prop --- packages/components/src/button/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/components/src/button/README.md b/packages/components/src/button/README.md index 74dd70f1105995..465d56b574b195 100644 --- a/packages/components/src/button/README.md +++ b/packages/components/src/button/README.md @@ -240,6 +240,8 @@ If provided with`showTooltip`, sets the position of the tooltip. Please refer to Specifies the button's style. The accepted values are `'primary'` (the primary button styles), `'secondary'` (the default button styles), `'tertiary'` (the text-based button styles), and `'link'` (the link button styles). +- Required: No + ## Related components - To group buttons together, use the [ButtonGroup](/packages/components/src/button-group/README.md) component. From 8ce49375b970ccc660b7ecae6b72980f039890ad Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 17:19:15 -0600 Subject: [PATCH 25/42] Add a JS DocBlock to Button --- packages/components/src/button/index.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index 8257526eaa5084..7665b103dd3161 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -250,5 +250,20 @@ export function UnforwardedButton( ); } +/** + * Lets users take actions and make choices with a single click or tap. + * + * ```jsx + * import { Button } from '@wordpress/components'; + * const Mybutton = () => ( + * + * ); + * ``` + */ export const Button = forwardRef( UnforwardedButton ); export default Button; From fd4144a5857a9a7e60b1310e33e5e3e01d54157d Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sun, 15 Jan 2023 17:57:27 -0600 Subject: [PATCH 26/42] Add a CHANGELOG entry --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8fd6fe51c38ab8..070e03cd9908d7 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -14,6 +14,7 @@ - `SandBox`: Convert to TypeScript ([#46478](https://github.com/WordPress/gutenberg/pull/46478)). - `ResponsiveWrapper`: Convert to TypeScript ([#46480](https://github.com/WordPress/gutenberg/pull/46480)). - `ItemGroup`: migrate Storybook to controls, refactor to TypeScript ([46945](https://github.com/WordPress/gutenberg/pull/46945)). +- `Button`: Convert to TypeScript ([#46997](https://github.com/WordPress/gutenberg/pull/46997)). ### Bug Fix From 916f9ac45ae0d40b844bc58884828e9077601d40 Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sat, 21 Jan 2023 15:05:30 -0600 Subject: [PATCH 27/42] Commit Lena's suggestion: Update packages/components/src/button/types.ts Co-authored-by: Lena Morita --- packages/components/src/button/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/button/types.ts b/packages/components/src/button/types.ts index 961db58ae95272..b66d85d11961e9 100644 --- a/packages/components/src/button/types.ts +++ b/packages/components/src/button/types.ts @@ -88,7 +88,7 @@ export type ButtonProps = { * If provided with `showTooltip`, sets the position of the tooltip. * Please refer to the Tooltip component for more details regarding the defaults. */ - tooltipPosition?: string; + tooltipPosition?: PopoverProps[ 'position' ]; /** * Specifies the button's style. * The accepted values are: From 3632a42bc8eef7f6167a24bc2d2330881f35ad5c Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sat, 21 Jan 2023 15:06:25 -0600 Subject: [PATCH 28/42] Commit Lena's suggestion: Update packages/components/src/button/deprecated.tsx Co-authored-by: Lena Morita --- packages/components/src/button/deprecated.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/components/src/button/deprecated.tsx b/packages/components/src/button/deprecated.tsx index 36e6b15c909a29..7acd6da33a298c 100644 --- a/packages/components/src/button/deprecated.tsx +++ b/packages/components/src/button/deprecated.tsx @@ -23,10 +23,8 @@ function UnforwardedIconButton( size, tooltip, ...props - }: WordPressComponentProps< - ButtonProps & DeprecatedIconButtonProps, - TagName - >, + }: React.ComponentPropsWithoutRef< typeof Button > & + DeprecatedIconButtonProps, ref: ForwardedRef< any > ) { deprecated( 'wp.components.IconButton', { From 309db5cf29dc7dd2cc9291841223c53936a8443d Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sat, 21 Jan 2023 15:06:53 -0600 Subject: [PATCH 29/42] Commit Lena's suggestion: Update packages/components/src/button/index.tsx Co-authored-by: Lena Morita --- packages/components/src/button/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index 7665b103dd3161..4ad82fb607a1ff 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -25,10 +25,10 @@ import type { TagName, } from './types'; -const disabledEventsOnDisabledButton: DisabledEvent[] = [ +const disabledEventsOnDisabledButton = [ 'onMouseDown', 'onClick', -]; +] as const; function useDeprecatedProps( { isDefault, From 31cbdab15c013bae56a08cedbc132439a1eb6b8d Mon Sep 17 00:00:00 2001 From: Ryan Kienstra Date: Sat, 21 Jan 2023 22:17:20 -0600 Subject: [PATCH 30/42] Apply Lena's suggestion to change 'div' to 'button' Also, correct some typing errors. --- .../border-box-control-linked-button/component.tsx | 4 ++-- .../border-box-control-linked-button/hook.ts | 2 +- packages/components/src/button/deprecated.tsx | 3 +-- packages/components/src/button/index.tsx | 12 ++---------- packages/components/src/button/types.ts | 1 + 5 files changed, 7 insertions(+), 15 deletions(-) diff --git a/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx b/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx index cc7d3239289156..d5fe6a9eb1f761 100644 --- a/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx +++ b/packages/components/src/border-box-control/border-box-control-linked-button/component.tsx @@ -16,7 +16,7 @@ import { useBorderBoxControlLinkedButton } from './hook'; import type { LinkedButtonProps } from '../types'; const BorderBoxControlLinkedButton = ( - props: WordPressComponentProps< LinkedButtonProps, 'div' >, + props: WordPressComponentProps< LinkedButtonProps, 'button' >, forwardedRef: React.ForwardedRef< any > ) => { const { className, isLinked, ...buttonProps } = @@ -27,7 +27,7 @@ const BorderBoxControlLinkedButton = ( diff --git a/packages/components/src/button/test/index.tsx b/packages/components/src/button/test/index.tsx index 18f59621e55d1c..ca06c6ff469bb5 100644 --- a/packages/components/src/button/test/index.tsx +++ b/packages/components/src/button/test/index.tsx @@ -126,7 +126,7 @@ describe( 'Button', () => { } ); it( 'should not pass the prop target into the element', () => { - render(