docs(storybook): update Spinner stories with a11y documentation (#16454)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Václav Vančura 2026-03-06 10:29:26 +01:00 committed by GitHub
parent 7b5195d651
commit 862cd8e788
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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',
},
];
</script>
{#snippet template({ _children, ...args })}
@ -51,6 +118,30 @@ const sizeVariants: { label: string; size?: string }[] = [
{/each}
</div>
</div>
{:else if args.kind === 'accessibility'}
<div class="flex flex-col gap-4">
<div class="text-sm text-(--pd-content-text)">
Accessibility features: ARIA attributes and color inheritance via <code>currentColor</code>.
</div>
<div class="grid grid-cols-2 gap-4 sm:grid-cols-3">
{#each accessibilityVariants as variant (variant.heading)}
<div class="flex flex-col gap-2 rounded border border-(--pd-content-divider) p-3">
<div class="text-xs font-semibold text-(--pd-content-header)">{variant.heading}</div>
<div class="flex items-center justify-center py-2 {variant.containerClass ?? ''}">
{#if variant.label}
<Spinner label={variant.label} />
{:else}
<Spinner />
{/if}
</div>
<code class="text-[10px] text-(--pd-content-text) break-all">{variant.aria}</code>
</div>
{/each}
</div>
</div>
{:else if args.kind === 'contexts'}
<div class="flex flex-col gap-6 text-(--pd-content-text)">
<div class="flex flex-col gap-2">
@ -128,6 +219,11 @@ const sizeVariants: { label: string; size?: string }[] = [
args={{
kind: 'sizes',
}} />
<Story
name="Accessibility"
args={{
kind: 'accessibility',
}} />
<Story
name="Contexts"
args={{