feat(ui): add loading state to Button and ButtonIcon components
Add optional `loading` prop to both Button and ButtonIcon components that displays a spinner and disables interaction while async operations are in progress. Implementation details: - Uses React Aria's ProgressBar with indeterminate state for spinner - Displays RiLoader4Line icon with smooth rotation animation - Wraps content in container with opacity transition when loading - Accessible via aria-label "Loading" on progress indicator - Component definitions updated with content, spinner class names and loading data attribute Documentation: - Added Loading examples to both Button and ButtonIcon docs showing interactive demos - Updated props tables with loading boolean prop - Created Storybook stories covering all variants, sizes, and with icons Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
buttonIconVariantsSnippet,
|
||||
buttonIconSizesSnippet,
|
||||
buttonIconDisabledSnippet,
|
||||
buttonIconLoadingSnippet,
|
||||
buttonIconResponsiveSnippet,
|
||||
buttonIconAsLinkSnippet,
|
||||
} from './button-icon.props';
|
||||
@@ -74,6 +75,18 @@ Here's a view when buttons are disabled.
|
||||
code={buttonIconDisabledSnippet}
|
||||
/>
|
||||
|
||||
### Loading
|
||||
|
||||
Here's a view when buttons are in a loading state.
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<ButtonIconSnippet story="Loading" />}
|
||||
code={buttonIconLoadingSnippet}
|
||||
/>
|
||||
|
||||
### Responsive
|
||||
|
||||
Here's a view when buttons are responsive.
|
||||
|
||||
@@ -19,6 +19,7 @@ export const buttonIconPropDefs: Record<string, PropDef> = {
|
||||
},
|
||||
icon: { type: 'enum', values: ['ReactNode'], responsive: false },
|
||||
isDisabled: { type: 'boolean', default: 'false', responsive: false },
|
||||
loading: { type: 'boolean', default: 'false', responsive: false },
|
||||
type: {
|
||||
type: 'enum',
|
||||
values: ['button', 'submit', 'reset'],
|
||||
@@ -50,6 +51,8 @@ export const buttonIconSizesSnippet = `<Flex align="center">
|
||||
|
||||
export const buttonIconDisabledSnippet = `<ButtonIcon icon={<Icon name="cloud" />} isDisabled />`;
|
||||
|
||||
export const buttonIconLoadingSnippet = `<ButtonIcon icon={<Icon name="cloud" />} variant="primary" loading={isLoading} onPress={handleClick} />`;
|
||||
|
||||
export const buttonIconResponsiveSnippet = `<ButtonIcon icon={<Icon name="cloud" />} variant={{ initial: 'primary', lg: 'secondary' }} />`;
|
||||
|
||||
export const buttonIconAsLinkSnippet = `import { ButtonLink } from '@backstage/ui';
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
buttonSizesSnippet,
|
||||
buttonIconsSnippet,
|
||||
buttonDisabledSnippet,
|
||||
buttonLoadingSnippet,
|
||||
buttonResponsiveSnippet,
|
||||
buttonAsLinkSnippet,
|
||||
} from './button.props';
|
||||
@@ -86,6 +87,18 @@ Here's a view when buttons are disabled.
|
||||
code={buttonDisabledSnippet}
|
||||
/>
|
||||
|
||||
### Loading
|
||||
|
||||
Here's a view when buttons are in a loading state.
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<ButtonSnippet story="Loading" />}
|
||||
code={buttonLoadingSnippet}
|
||||
/>
|
||||
|
||||
### Responsive
|
||||
|
||||
Here's a view when buttons are responsive.
|
||||
|
||||
@@ -17,6 +17,7 @@ export const buttonPropDefs: Record<string, PropDef> = {
|
||||
iconStart: { type: 'enum', values: ['ReactNode'], responsive: false },
|
||||
iconEnd: { type: 'enum', values: ['ReactNode'], responsive: false },
|
||||
isDisabled: { type: 'boolean', default: 'false', responsive: false },
|
||||
loading: { type: 'boolean', default: 'false', responsive: false },
|
||||
children: { type: 'enum', values: ['ReactNode'], responsive: false },
|
||||
type: {
|
||||
type: 'enum',
|
||||
@@ -65,6 +66,10 @@ export const buttonResponsiveSnippet = `<Button variant={{ initial: 'primary', l
|
||||
Responsive Button
|
||||
</Button>`;
|
||||
|
||||
export const buttonLoadingSnippet = `<Button variant="primary" loading={isLoading} onPress={handleClick}>
|
||||
Load more items
|
||||
</Button>`;
|
||||
|
||||
export const buttonAsLinkSnippet = `import { ButtonLink } from '@backstage/ui';
|
||||
|
||||
<ButtonLink href="https://ui.backstage.io" target="_blank">
|
||||
|
||||
Reference in New Issue
Block a user