diff --git a/storybook/src/stories/progress/Spinner.stories.svelte b/storybook/src/stories/progress/Spinner.stories.svelte index 38aa518cf49..feb142f7e0f 100644 --- a/storybook/src/stories/progress/Spinner.stories.svelte +++ b/storybook/src/stories/progress/Spinner.stories.svelte @@ -5,7 +5,16 @@ import { defineMeta } from '@storybook/addon-svelte-csf'; /** * These are the stories for the `Spinner` component. - * Displays indeterminate progress through a circle/spinner. + * An SVG-based indeterminate loading spinner for ongoing processes with unknown duration. + * + * **Accessibility**: The wrapper element uses `role="status"` with `aria-live="polite"` so screen readers + * announce loading state changes. The SVG graphic is marked `aria-hidden="true"`. The `label` prop sets + * `aria-label` on the wrapper (default: `"Loading"`). + * + * **Color**: The spinner stroke uses `currentColor`, so it inherits the text color of its container. + * + * **Motion**: Support for `prefers-reduced-motion` is planned in + * [#15806](https://github.com/podman-desktop/podman-desktop/issues/15806). */ const { Story } = defineMeta({ component: Spinner, @@ -13,6 +22,24 @@ const { Story } = defineMeta({ title: 'Progress/Spinner', tags: ['autodocs'], argTypes: { + size: { + control: 'text', + description: 'CSS size value for SVG width and height', + defaultValue: '2em', + }, + class: { + control: 'text', + description: 'Additional CSS classes on the wrapper element', + }, + style: { + control: 'text', + description: 'Inline CSS styles on the wrapper element', + }, + label: { + control: 'text', + description: 'Accessible label for screen readers via aria-label', + defaultValue: 'Loading', + }, kind: { table: { disable: true }, }, @@ -28,6 +55,46 @@ const sizeVariants: { label: string; size?: string }[] = [ { label: '12px', size: '12px' }, { label: '16px', size: '16px' }, ]; + +const accessibilityVariants: { heading: string; label?: string; containerClass?: string; aria: string }[] = [ + { + heading: 'Default label', + aria: 'role="status" aria-label="Loading" aria-live="polite"', + }, + { + heading: 'Custom label: Pulling image', + label: 'Pulling image', + aria: 'role="status" aria-label="Pulling image" aria-live="polite"', + }, + { + heading: 'Custom label: Checking prerequisites', + label: 'Checking prerequisites', + aria: 'role="status" aria-label="Checking prerequisites" aria-live="polite"', + }, + { + heading: 'Custom label: Building container', + label: 'Building container', + aria: 'role="status" aria-label="Building container" aria-live="polite"', + }, + { + heading: 'Color inheritance: Info', + label: 'Loading info', + containerClass: 'text-(--pd-state-info)', + aria: 'Inherits currentColor from info context', + }, + { + heading: 'Color inheritance: Warning', + label: 'Loading warning', + containerClass: 'text-(--pd-state-warning)', + aria: 'Inherits currentColor from warning context', + }, + { + heading: 'Color inheritance: Muted', + label: 'Loading muted', + containerClass: 'text-(--pd-content-invert-text)', + aria: 'Inherits currentColor from muted context', + }, +]; {#snippet template({ _children, ...args })} @@ -51,6 +118,30 @@ const sizeVariants: { label: string; size?: string }[] = [ {/each} + {:else if args.kind === 'accessibility'} +
currentColor.
+ {variant.aria}
+