From 4c3dd2812bff289398577563a6b577cac985da60 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Thu, 4 Jan 2024 16:32:42 +0100 Subject: [PATCH 1/4] feat(Button): consume Penta tokens and update examples --- .../src/components/Button/Button.tsx | 30 ++-- .../Button/__tests__/Button.test.tsx | 25 ++- .../__snapshots__/Button.test.tsx.snap | 2 +- .../src/components/Button/examples/Button.md | 17 +++ .../Button/examples/ButtonAriaDisabled.tsx | 66 +++----- .../Button/examples/ButtonCallToAction.tsx | 18 +-- .../Button/examples/ButtonDisabled.tsx | 71 +++++---- .../Button/examples/ButtonLinks.tsx | 28 ++-- .../Button/examples/ButtonPlainNoPadding.tsx | 13 ++ .../Button/examples/ButtonProgress.tsx | 39 ++--- .../Button/examples/ButtonSmall.tsx | 16 +- .../Button/examples/ButtonStateful.tsx | 34 +++++ .../Button/examples/ButtonTypes.tsx | 10 +- .../Button/examples/ButtonVariations.tsx | 101 +++++++------ .../Button/examples/ButtonWithCount.tsx | 143 +++++++++--------- 15 files changed, 359 insertions(+), 254 deletions(-) create mode 100644 packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx create mode 100644 packages/react-core/src/components/Button/examples/ButtonStateful.tsx diff --git a/packages/react-core/src/components/Button/Button.tsx b/packages/react-core/src/components/Button/Button.tsx index d9b2ff8f8a5..13d2004b88f 100644 --- a/packages/react-core/src/components/Button/Button.tsx +++ b/packages/react-core/src/components/Button/Button.tsx @@ -13,7 +13,8 @@ export enum ButtonVariant { warning = 'warning', link = 'link', plain = 'plain', - control = 'control' + control = 'control', + stateful = 'stateful' } export enum ButtonType { @@ -28,6 +29,12 @@ export enum ButtonSize { lg = 'lg' } +export enum ButtonState { + read = 'read', + unread = 'unread', + attention = 'attention' +} + export interface BadgeCountObject { /** Adds styling to the badge to indicate it has been read */ isRead?: boolean; @@ -44,8 +51,8 @@ export interface ButtonProps extends Omit, 'r className?: string; /** Sets the base component to render. defaults to button */ component?: React.ElementType | React.ComponentType; - /** Adds active styling to button. */ - isActive?: boolean; + /** Adds clicked styling to button. */ + isClicked?: boolean; /** Adds block styling to button */ isBlock?: boolean; /** Adds disabled styling and disables the button using the disabled html attribute */ @@ -69,7 +76,11 @@ export interface ButtonProps extends Omit, 'r /** Sets button type */ type?: 'button' | 'submit' | 'reset'; /** Adds button variant styles */ - variant?: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'warning' | 'link' | 'plain' | 'control'; + variant?: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'warning' | 'link' | 'plain' | 'control' | 'stateful'; + /** Sets state of the stateful button variant. Default is "unread" */ + state?: 'read' | 'unread' | 'attention'; + /** Applies no padding on a plain button variant. Use when plain button is placed inline with text */ + noPadding?: boolean; /** Sets position of the icon. Note: "left" and "right" are deprecated. Use "start" and "end" instead */ iconPosition?: 'start' | 'end' | 'left' | 'right'; /** Adds accessible text to the button. */ @@ -94,9 +105,7 @@ const ButtonBase: React.FunctionComponent = ({ children = null, className = '', component = 'button', - // TODO: Update eslint ignore when issue #9907 is resolved - // eslint-disable-next-line @typescript-eslint/no-unused-vars - isActive = false, + isClicked = false, isBlock = false, isDisabled = false, isAriaDisabled = false, @@ -110,6 +119,8 @@ const ButtonBase: React.FunctionComponent = ({ isInline = false, type = ButtonType.button, variant = ButtonVariant.primary, + state = ButtonState.unread, + noPadding = false, iconPosition = 'start', 'aria-label': ariaLabel = null, icon = null, @@ -157,12 +168,13 @@ const ButtonBase: React.FunctionComponent = ({ isBlock && styles.modifiers.block, isDisabled && styles.modifiers.disabled, isAriaDisabled && styles.modifiers.ariaDisabled, - // TODO: Update when issue #9907 is resolved - // isActive && styles.modifiers.active, + isClicked && styles.modifiers.clicked, isInline && variant === ButtonVariant.link && styles.modifiers.inline, isDanger && (variant === ButtonVariant.secondary || variant === ButtonVariant.link) && styles.modifiers.danger, isLoading !== null && variant !== ButtonVariant.plain && styles.modifiers.progress, isLoading && styles.modifiers.inProgress, + noPadding && variant === ButtonVariant.plain && styles.modifiers.noPadding, + variant === ButtonVariant.stateful && styles.modifiers[state], size === ButtonSize.sm && styles.modifiers.small, size === ButtonSize.lg && styles.modifiers.displayLg, className diff --git a/packages/react-core/src/components/Button/__tests__/Button.test.tsx b/packages/react-core/src/components/Button/__tests__/Button.test.tsx index 738821facff..ca895903c40 100644 --- a/packages/react-core/src/components/Button/__tests__/Button.test.tsx +++ b/packages/react-core/src/components/Button/__tests__/Button.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; -import { Button, ButtonVariant } from '../Button'; +import { Button, ButtonState, ButtonVariant } from '../Button'; Object.values(ButtonVariant).forEach((variant) => { if (variant !== 'primary') { @@ -55,10 +55,9 @@ test('Renders with class pf-m-block when isBlock = true', () => { expect(screen.getByRole('button')).toHaveClass('pf-m-block'); }); -// TODO: Reenable or remove with issue #9907 -xtest('Renders with class pf-m-active when isActive = true', () => { - render(); - expect(screen.getByRole('button')).toHaveClass('pf-m-active'); +xtest('Renders with class pf-m-clicked when isClicked = true', () => { + render(); + expect(screen.getByRole('button')).toHaveClass('pf-m-clicked'); }); test('Renders with class pf-m-disabled when isDisabled = true', () => { @@ -80,6 +79,22 @@ test('Does not disable button when isDisabled = true and component = a', () => { expect(screen.getByText('Disabled yet focusable button')).not.toHaveProperty('disabled'); }); +test('Renders with class pf-m-unread by default when variant = stateful', () => { + render(); + expect(screen.getByRole('button')).toHaveClass('pf-m-stateful', 'pf-m-unread'); +}); + +Object.values(ButtonState).forEach((state) => { + test(`Renders with class pf-m-${state} when state = ${state} and variant = stateful`, () => { + render( + + ); + expect(screen.getByRole('button')).toHaveClass('pf-m-stateful', `pf-m-${state}`); + }); +}); + test('Renders with class pf-m-danger when isDanger = true and variant = secondary', () => { render( - {' '} - {' '} - {' '} - {' '} - -
-
- {' '} - {' '} - {' '} - {' '} - -
-
- - + - {' '} - - - - + +
+ + + + + + + + + ); diff --git a/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx b/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx index 8413ca91fd4..3c3887a478e 100644 --- a/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx @@ -1,22 +1,20 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; export const ButtonCallToAction: React.FunctionComponent = () => ( - + {' '} + {' '} + {' '} - -
-
-
+ + ); diff --git a/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx b/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx index 3deb37bff32..70d13a24514 100644 --- a/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx @@ -1,39 +1,52 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; +import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; export const ButtonDisabled: React.FunctionComponent = () => ( - {' '} - {' '} - {' '} - {' '} - + + + + + + + +
+ + + + + +
- {' '} - {' '} - {' '} - {' '} - + + + +
); diff --git a/packages/react-core/src/components/Button/examples/ButtonLinks.tsx b/packages/react-core/src/components/Button/examples/ButtonLinks.tsx index 232be49f72a..5a6ec5a1ead 100644 --- a/packages/react-core/src/components/Button/examples/ButtonLinks.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonLinks.tsx @@ -1,19 +1,19 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; export const ButtonLinks: React.FunctionComponent = () => ( - - {' '} - {' '} - {' '} - - + + + + ); diff --git a/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx b/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx new file mode 100644 index 00000000000..1cf0d045bc0 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { Button } from '@patternfly/react-core'; +import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon'; + +export const ButtonStateful: React.FunctionComponent = () => ( +

+ This is an example of a button + + which is placed inline with text +

+); diff --git a/packages/react-core/src/components/Button/examples/ButtonProgress.tsx b/packages/react-core/src/components/Button/examples/ButtonProgress.tsx index 61642eb7e0d..39fb0ca3f47 100644 --- a/packages/react-core/src/components/Button/examples/ButtonProgress.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonProgress.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; interface LoadingPropsType { @@ -36,19 +36,24 @@ export const ButtonProgress: React.FunctionComponent = () => { uploadingProps.isLoading = isUploading; return ( - - {' '} - {' '} -
+ <> + + + +
{' '} -
+ + ); }; diff --git a/packages/react-core/src/components/Button/examples/ButtonSmall.tsx b/packages/react-core/src/components/Button/examples/ButtonSmall.tsx index b4a1d30c048..2fea0b9be89 100644 --- a/packages/react-core/src/components/Button/examples/ButtonSmall.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonSmall.tsx @@ -1,24 +1,22 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; export const ButtonSmall: React.FunctionComponent = () => ( - + {' '} + {' '} + {' '} + {' '} + -
-
-
+ ); diff --git a/packages/react-core/src/components/Button/examples/ButtonStateful.tsx b/packages/react-core/src/components/Button/examples/ButtonStateful.tsx new file mode 100644 index 00000000000..a702457c409 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonStateful.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Button, Flex } from '@patternfly/react-core'; +import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; + +export const ButtonStateful: React.FunctionComponent = () => ( + <> + +
+
+ Read +
+ +
+
+
+ Unread +
+ +
+
+
+ Attention +
+ +
+
+ +); diff --git a/packages/react-core/src/components/Button/examples/ButtonTypes.tsx b/packages/react-core/src/components/Button/examples/ButtonTypes.tsx index 7fd63e119b1..fb2fd288835 100644 --- a/packages/react-core/src/components/Button/examples/ButtonTypes.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonTypes.tsx @@ -1,8 +1,10 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; export const ButtonTypes: React.FunctionComponent = () => ( - - - + + + + + ); diff --git a/packages/react-core/src/components/Button/examples/ButtonVariations.tsx b/packages/react-core/src/components/Button/examples/ButtonVariations.tsx index e808916fd07..dd679cfd43a 100644 --- a/packages/react-core/src/components/Button/examples/ButtonVariations.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonVariations.tsx @@ -1,54 +1,69 @@ import React from 'react'; -import { Button } from '@patternfly/react-core'; +import { Button, Flex } from '@patternfly/react-core'; import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; import ExternalLinkSquareAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon'; import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; +import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; export const ButtonVariations: React.FunctionComponent = () => ( - - {' '} - {' '} - {' '} - {' '} - {' '} - + <> + + + + + + + +
+ + + + + + +
- {' '} - {' '} - {' '} - + + + +
-
- -
-
- {' '} - -
+ + + + + + ); diff --git a/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx b/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx index 766ae5b3041..644ef31dfd2 100644 --- a/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { BadgeCountObject, Button } from '@patternfly/react-core'; +import { BadgeCountObject, Button, Flex } from '@patternfly/react-core'; export const ButtonWithCount: React.FunctionComponent = () => { const badgeCountObjectNotRead: BadgeCountObject = { @@ -15,75 +15,82 @@ export const ButtonWithCount: React.FunctionComponent = () => { }; return ( - -

Unread:

- {' '} - {' '} - {' '} - {' '} - {' '} + <> +
Unread:
+ + + + + + +
-

Unread disabled:

- {' '} - {' '} - {' '} - {' '} - {' '} +
Unread disabled:
+ + + + + + +
-

Read:

- {' '} - {' '} - {' '} - {' '} - {' '} +
Read:
+ + + + + + +
-

Read disabled:

- {' '} - {' '} - {' '} - {' '} - {' '} -
-
+
Read disabled:
+ + + + + + + + ); }; From 27fd5443fe21d4ea197f274d5a8111665474f065 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Thu, 11 Jan 2024 09:49:29 +0100 Subject: [PATCH 2/4] fix (Button docs): add aria-label to pass a11y tests --- .../src/components/Button/examples/ButtonPlainNoPadding.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx b/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx index 1cf0d045bc0..d92fb5eaef5 100644 --- a/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx @@ -5,7 +5,7 @@ import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question- export const ButtonStateful: React.FunctionComponent = () => (

This is an example of a button - which is placed inline with text From d076af7acf9030af16432c9fc6876c244395d462 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 16 Jan 2024 10:26:03 +0100 Subject: [PATCH 3/4] fix(Button): rename noPadding to hasNoPadding --- packages/react-core/src/components/Button/Button.tsx | 6 +++--- .../react-core/src/components/Button/examples/Button.md | 2 +- ...ButtonPlainNoPadding.tsx => ButtonPlainHasNoPadding.tsx} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename packages/react-core/src/components/Button/examples/{ButtonPlainNoPadding.tsx => ButtonPlainHasNoPadding.tsx} (68%) diff --git a/packages/react-core/src/components/Button/Button.tsx b/packages/react-core/src/components/Button/Button.tsx index 13d2004b88f..886c67fcf48 100644 --- a/packages/react-core/src/components/Button/Button.tsx +++ b/packages/react-core/src/components/Button/Button.tsx @@ -80,7 +80,7 @@ export interface ButtonProps extends Omit, 'r /** Sets state of the stateful button variant. Default is "unread" */ state?: 'read' | 'unread' | 'attention'; /** Applies no padding on a plain button variant. Use when plain button is placed inline with text */ - noPadding?: boolean; + hasNoPadding?: boolean; /** Sets position of the icon. Note: "left" and "right" are deprecated. Use "start" and "end" instead */ iconPosition?: 'start' | 'end' | 'left' | 'right'; /** Adds accessible text to the button. */ @@ -120,7 +120,7 @@ const ButtonBase: React.FunctionComponent = ({ type = ButtonType.button, variant = ButtonVariant.primary, state = ButtonState.unread, - noPadding = false, + hasNoPadding = false, iconPosition = 'start', 'aria-label': ariaLabel = null, icon = null, @@ -173,7 +173,7 @@ const ButtonBase: React.FunctionComponent = ({ isDanger && (variant === ButtonVariant.secondary || variant === ButtonVariant.link) && styles.modifiers.danger, isLoading !== null && variant !== ButtonVariant.plain && styles.modifiers.progress, isLoading && styles.modifiers.inProgress, - noPadding && variant === ButtonVariant.plain && styles.modifiers.noPadding, + hasNoPadding && variant === ButtonVariant.plain && styles.modifiers.noPadding, variant === ButtonVariant.stateful && styles.modifiers[state], size === ButtonSize.sm && styles.modifiers.small, size === ButtonSize.lg && styles.modifiers.displayLg, diff --git a/packages/react-core/src/components/Button/examples/Button.md b/packages/react-core/src/components/Button/examples/Button.md index eafbbd4785c..fd9eade8ce4 100644 --- a/packages/react-core/src/components/Button/examples/Button.md +++ b/packages/react-core/src/components/Button/examples/Button.md @@ -115,7 +115,7 @@ Buttons can display a `count` in the form of a badge to indicate some value or n To display a plain/icon button inline with text, use `noPadding` prop in addition to `variant="plain"`. -```ts file="./ButtonPlainNoPadding.tsx" +```ts file="./ButtonPlainHasNoPadding.tsx" ``` ### Stateful diff --git a/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx b/packages/react-core/src/components/Button/examples/ButtonPlainHasNoPadding.tsx similarity index 68% rename from packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx rename to packages/react-core/src/components/Button/examples/ButtonPlainHasNoPadding.tsx index d92fb5eaef5..4c86ad06f25 100644 --- a/packages/react-core/src/components/Button/examples/ButtonPlainNoPadding.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonPlainHasNoPadding.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { Button } from '@patternfly/react-core'; import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon'; -export const ButtonStateful: React.FunctionComponent = () => ( +export const ButtonPlainHasNoPadding: React.FunctionComponent = () => (

This is an example of a button - which is placed inline with text From 8572a61bac748583e78b3b7319ad157c806f56c1 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 16 Jan 2024 10:26:18 +0100 Subject: [PATCH 4/4] docs(Button): update fragments --- .../Button/examples/ButtonDisabled.tsx | 4 +- .../Button/examples/ButtonStateful.tsx | 42 +++++++++---------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx b/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx index 70d13a24514..63d1339eee3 100644 --- a/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx @@ -5,7 +5,7 @@ import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-i import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; export const ButtonDisabled: React.FunctionComponent = () => ( - + <> - + ); diff --git a/packages/react-core/src/components/Button/examples/ButtonStateful.tsx b/packages/react-core/src/components/Button/examples/ButtonStateful.tsx index a702457c409..3444b2b7fc9 100644 --- a/packages/react-core/src/components/Button/examples/ButtonStateful.tsx +++ b/packages/react-core/src/components/Button/examples/ButtonStateful.tsx @@ -3,32 +3,30 @@ import { Button, Flex } from '@patternfly/react-core'; import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; export const ButtonStateful: React.FunctionComponent = () => ( - <> - + +

-
- Read -
- + Read
+ +
+
-
- Unread -
- + Unread
+ +
+
-
- Attention -
- + Attention
- - + +
+ );