aural-ui 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
- package/dist/components/avatar/Avatar.stories.tsx +219 -235
- package/dist/components/badge/Badge.stories.tsx +379 -116
- package/dist/components/banner/Banner.stories.tsx +445 -391
- package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
- package/dist/components/button/Button.stories.tsx +585 -230
- package/dist/components/card/Card.stories.tsx +619 -301
- package/dist/components/char-count/CharCount.stories.tsx +350 -248
- package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
- package/dist/components/chip/Chip.stories.tsx +362 -168
- package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
- package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
- package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
- package/dist/components/command/Command.stories.tsx +530 -867
- package/dist/components/dialog/Dialog.stories.tsx +501 -950
- package/dist/components/divider/Divider.stories.tsx +264 -527
- package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
- package/dist/components/drawer/Drawer.stories.tsx +659 -1023
- package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
- package/dist/components/form/Form.stories.tsx +560 -274
- package/dist/components/helper-text/HelperText.stories.tsx +199 -200
- package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
- package/dist/components/icon-button/IconButton.stories.tsx +837 -194
- package/dist/components/if-else/if-else.stories.tsx +370 -83
- package/dist/components/input/Input.stories.tsx +436 -368
- package/dist/components/label/Label.stories.tsx +156 -154
- package/dist/components/list/List.stories.tsx +484 -835
- package/dist/components/marquee/Marquee.stories.tsx +356 -712
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
- package/dist/components/overlay/Overlay.stories.tsx +452 -824
- package/dist/components/pagination/Pagination.stories.tsx +721 -210
- package/dist/components/popover/Popover.stories.tsx +481 -896
- package/dist/components/radio/Radio.stories.tsx +432 -124
- package/dist/components/resizable/Resizable.stories.tsx +495 -799
- package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
- package/dist/components/search/Search.stories.tsx +312 -595
- package/dist/components/select/Select.stories.tsx +684 -789
- package/dist/components/sheet/Sheet.stories.tsx +671 -950
- package/dist/components/skelton/Skelton.stories.tsx +230 -764
- package/dist/components/slider/Slider.stories.tsx +383 -760
- package/dist/components/stepper/Stepper.stories.tsx +371 -514
- package/dist/components/switch/Switch.stories.tsx +461 -208
- package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
- package/dist/components/table/Table.stories.tsx +770 -916
- package/dist/components/tabs/Tabs.stories.tsx +458 -1455
- package/dist/components/tag/Tag.stories.tsx +714 -542
- package/dist/components/textarea/TextArea.stories.tsx +621 -562
- package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
- package/dist/components/toast/Toast.stories.tsx +452 -1339
- package/dist/components/toggle/Toggle.stories.tsx +488 -931
- package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
- package/dist/components/typography/Typography.stories.tsx +406 -89
- package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
- package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
- package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
- package/dist/icons/Icons.stories.tsx +0 -12
- package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
- package/dist/icons/all-icons.tsx +37 -16
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
- package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
- package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
- package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
- package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
- package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
- package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
- package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
- package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
- package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
- package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
- package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
- package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
- package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
- package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
- package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
- package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
- package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
- package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
- package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
- package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
- package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
- package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
- package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
- package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
- package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
- package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
- package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
- package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
- package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
- package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
- package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
- package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
- package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
- package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
- package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
- package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
- package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
- package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
- package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
- package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
- package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
- package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
- package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
- package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
- package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
- package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
- package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
- package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
- package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
- package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
- package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
- package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
- package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
- package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
- package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
- package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
- package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
- package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
- package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
- package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
- package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
- package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
- package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
- package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
- package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
- package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
- package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
- package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
- package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
- package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
- package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react"
|
|
2
2
|
import { Button } from "@components/button"
|
|
3
3
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
4
4
|
|
|
5
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
6
|
+
|
|
5
7
|
import CircularLoader from "."
|
|
6
8
|
|
|
7
9
|
const meta: Meta<typeof CircularLoader> = {
|
|
@@ -9,107 +11,32 @@ const meta: Meta<typeof CircularLoader> = {
|
|
|
9
11
|
component: CircularLoader,
|
|
10
12
|
parameters: {
|
|
11
13
|
layout: "centered",
|
|
12
|
-
backgrounds: {
|
|
13
|
-
default: "dark",
|
|
14
|
-
values: [
|
|
15
|
-
{ name: "dark", value: "#0a0a0a" },
|
|
16
|
-
{ name: "darker", value: "#000000" },
|
|
17
|
-
{ name: "light", value: "#ffffff" },
|
|
18
|
-
],
|
|
19
|
-
},
|
|
20
14
|
docs: {
|
|
21
15
|
description: {
|
|
22
|
-
component:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
An accessible circular loading spinner component with multiple variants, customizable sizing, and comprehensive screen reader support. Built with proper ARIA attributes and semantic HTML.
|
|
26
|
-
|
|
27
|
-
## Features
|
|
28
|
-
|
|
29
|
-
- **Multiple Variants**: Three distinct spinner designs (gradient, solid, neutral)
|
|
30
|
-
- **Size Options**: Four predefined sizes (sm, md, lg, xl) for different contexts
|
|
31
|
-
- **Accessibility First**: Full ARIA support with screen reader compatibility
|
|
32
|
-
- **Customizable Text**: Optional visual text with separate screen reader messages
|
|
33
|
-
- **Live Regions**: Configurable aria-live announcements for dynamic updates
|
|
34
|
-
- **Flexible Styling**: Custom classes for root, loader, and text elements
|
|
35
|
-
- **Semantic HTML**: Proper role and status indicators
|
|
36
|
-
|
|
37
|
-
## Accessibility Features
|
|
38
|
-
|
|
39
|
-
- **ARIA Labels**: Automatic labeling for screen readers
|
|
40
|
-
- **Live Regions**: Announces loading state changes
|
|
41
|
-
- **Screen Reader Text**: Hidden text for assistive technologies
|
|
42
|
-
- **Keyboard Safe**: Non-focusable decorative elements
|
|
43
|
-
- **Status Role**: Proper semantic meaning for loading states
|
|
44
|
-
|
|
45
|
-
## Usage Examples
|
|
46
|
-
|
|
47
|
-
### Basic Loading
|
|
48
|
-
\`\`\`tsx
|
|
49
|
-
import CircularLoader from '@/components/circular-loader'
|
|
50
|
-
|
|
51
|
-
// Simple loading with visual text
|
|
52
|
-
<CircularLoader text="Loading..." />
|
|
53
|
-
|
|
54
|
-
// Screen reader only (no visual text)
|
|
55
|
-
<CircularLoader aria-label="Loading user data" />
|
|
56
|
-
\`\`\`
|
|
57
|
-
|
|
58
|
-
### Different Variants
|
|
59
|
-
\`\`\`tsx
|
|
60
|
-
// Gradient spinner (default)
|
|
61
|
-
<CircularLoader variant="v1" text="Loading..." />
|
|
62
|
-
|
|
63
|
-
// Solid spinner
|
|
64
|
-
<CircularLoader variant="v2" text="Processing..." />
|
|
65
|
-
|
|
66
|
-
// Neutral spinner
|
|
67
|
-
<CircularLoader variant="v3" text="Please wait..." />
|
|
68
|
-
\`\`\`
|
|
69
|
-
|
|
70
|
-
### Size Variations
|
|
71
|
-
\`\`\`tsx
|
|
72
|
-
// Small loader for buttons
|
|
73
|
-
<CircularLoader size="sm" text="Save" />
|
|
74
|
-
|
|
75
|
-
// Large loader for page loading
|
|
76
|
-
<CircularLoader size="xl" text="Loading application..." />
|
|
77
|
-
\`\`\`
|
|
78
|
-
|
|
79
|
-
### Advanced Accessibility
|
|
80
|
-
\`\`\`tsx
|
|
81
|
-
// Custom loading message for screen readers
|
|
82
|
-
<CircularLoader
|
|
83
|
-
text="Submitting form..."
|
|
84
|
-
loadingMessage="Your form is being processed, please wait"
|
|
85
|
-
aria-live="assertive"
|
|
86
|
-
/>
|
|
87
|
-
|
|
88
|
-
// Programmatic control
|
|
89
|
-
<CircularLoader
|
|
90
|
-
id="form-loader"
|
|
91
|
-
aria-label="Saving changes"
|
|
92
|
-
aria-live="polite"
|
|
93
|
-
/>
|
|
94
|
-
\`\`\`
|
|
95
|
-
|
|
96
|
-
### Custom Styling
|
|
97
|
-
\`\`\`tsx
|
|
98
|
-
<CircularLoader
|
|
99
|
-
variant="v2"
|
|
100
|
-
size="lg"
|
|
101
|
-
text="Loading..."
|
|
102
|
-
classes={{
|
|
103
|
-
root: "my-8",
|
|
104
|
-
loader: "text-blue-500",
|
|
105
|
-
text: "text-gray-600 font-medium"
|
|
106
|
-
}}
|
|
107
|
-
/>
|
|
108
|
-
\`\`\`
|
|
109
|
-
`,
|
|
16
|
+
component:
|
|
17
|
+
"An accessible circular loading spinner with three visual variants (gradient, solid, neutral), four sizes (sm/md/lg/xl), optional visible text, and full ARIA support including aria-live regions and screen-reader-only messages.",
|
|
110
18
|
},
|
|
19
|
+
page: () => (
|
|
20
|
+
<AuralComponentDocsPage
|
|
21
|
+
features={[
|
|
22
|
+
{
|
|
23
|
+
title: "3 Visual Variants",
|
|
24
|
+
description: "Gradient, solid, neutral",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: "Size Scale",
|
|
28
|
+
description: "sm to xl scale",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: "ARIA Support",
|
|
32
|
+
description: "Live regions built in",
|
|
33
|
+
},
|
|
34
|
+
]}
|
|
35
|
+
/>
|
|
36
|
+
),
|
|
111
37
|
},
|
|
112
38
|
},
|
|
39
|
+
tags: ["autodocs"],
|
|
113
40
|
argTypes: {
|
|
114
41
|
variant: {
|
|
115
42
|
control: { type: "select" },
|
|
@@ -148,610 +75,268 @@ import CircularLoader from '@/components/circular-loader'
|
|
|
148
75
|
description: "Custom classes for different parts of the component",
|
|
149
76
|
},
|
|
150
77
|
},
|
|
151
|
-
tags: ["autodocs"],
|
|
152
78
|
}
|
|
153
79
|
|
|
154
80
|
export default meta
|
|
155
81
|
type Story = StoryObj<typeof CircularLoader>
|
|
156
82
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
83
|
+
const loaderTextClass = "text-fm-primary"
|
|
84
|
+
|
|
85
|
+
function StoryCircularLoader(
|
|
86
|
+
props: React.ComponentProps<typeof CircularLoader>
|
|
87
|
+
) {
|
|
88
|
+
return (
|
|
89
|
+
<CircularLoader
|
|
90
|
+
{...props}
|
|
91
|
+
classes={{
|
|
92
|
+
...props.classes,
|
|
93
|
+
text: [loaderTextClass, props.classes?.text].filter(Boolean).join(" "),
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
)
|
|
166
97
|
}
|
|
167
98
|
|
|
168
|
-
// 1.
|
|
169
|
-
|
|
99
|
+
// ─── 1. Playground ────────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
export const Playground: Story = {
|
|
170
102
|
args: {
|
|
171
|
-
text: "Loading...",
|
|
172
103
|
variant: "v1",
|
|
173
104
|
size: "md",
|
|
105
|
+
text: "Loading...",
|
|
106
|
+
"aria-label": "Loading",
|
|
107
|
+
"aria-live": "polite",
|
|
108
|
+
loadingMessage: "",
|
|
174
109
|
},
|
|
175
|
-
parameters: storyParameters,
|
|
176
110
|
render: (args) => (
|
|
177
|
-
<div className="
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
),
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// 2. Variant Showcase
|
|
184
|
-
export const Variants: Story = {
|
|
185
|
-
parameters: {
|
|
186
|
-
...storyParameters,
|
|
187
|
-
docs: {
|
|
188
|
-
description: {
|
|
189
|
-
story:
|
|
190
|
-
"Different visual variants of the CircularLoader component with consistent accessibility features.",
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
render: () => (
|
|
195
|
-
<div className="bg-fm-surface-primary space-y-8 rounded-lg p-8">
|
|
196
|
-
<div className="text-center">
|
|
197
|
-
<h3 className="text-fm-primary mb-4 text-xl font-bold">
|
|
198
|
-
Spinner Variants
|
|
199
|
-
</h3>
|
|
200
|
-
<p className="text-fm-secondary text-sm">
|
|
201
|
-
Three distinct visual styles with full accessibility support
|
|
202
|
-
</p>
|
|
111
|
+
<div className="w-full max-w-sm space-y-4">
|
|
112
|
+
<div className="flex justify-center py-6">
|
|
113
|
+
<StoryCircularLoader {...args} />
|
|
203
114
|
</div>
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
<CircularLoader variant="v1" text="Gradient" size="lg" />
|
|
209
|
-
</div>
|
|
210
|
-
<div className="space-y-1">
|
|
211
|
-
<div className="text-fm-primary font-medium">Variant V1</div>
|
|
212
|
-
<div className="text-fm-secondary text-xs">
|
|
213
|
-
Gradient spinner with smooth transitions
|
|
214
|
-
</div>
|
|
215
|
-
</div>
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
<div className="text-center">
|
|
219
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mb-4 flex h-32 items-center justify-center rounded-lg border">
|
|
220
|
-
<CircularLoader variant="v2" text="Solid" size="lg" />
|
|
221
|
-
</div>
|
|
222
|
-
<div className="space-y-1">
|
|
223
|
-
<div className="text-fm-primary font-medium">Variant V2</div>
|
|
224
|
-
<div className="text-fm-secondary text-xs">
|
|
225
|
-
Solid spinner with consistent theming
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
|
|
230
|
-
<div className="text-center">
|
|
231
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mb-4 flex h-32 items-center justify-center rounded-lg border">
|
|
232
|
-
<CircularLoader variant="v3" text="Neutral" size="lg" />
|
|
233
|
-
</div>
|
|
234
|
-
<div className="space-y-1">
|
|
235
|
-
<div className="text-fm-primary font-medium">Variant V3</div>
|
|
236
|
-
<div className="text-fm-secondary text-xs">
|
|
237
|
-
Neutral spinner for any theme
|
|
238
|
-
</div>
|
|
239
|
-
</div>
|
|
240
|
-
</div>
|
|
115
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
116
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">
|
|
117
|
+
{`<CircularLoader variant="${args.variant}" size="${args.size}"${args.text ? ` text="${args.text}"` : ""} />`}
|
|
118
|
+
</code>
|
|
241
119
|
</div>
|
|
242
120
|
</div>
|
|
243
121
|
),
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// 3. Size Variations
|
|
247
|
-
export const Sizes: Story = {
|
|
248
122
|
parameters: {
|
|
249
|
-
...storyParameters,
|
|
250
123
|
docs: {
|
|
251
124
|
description: {
|
|
252
125
|
story:
|
|
253
|
-
"
|
|
126
|
+
"Adjust variant, size, text, and accessibility props using the controls panel in the sidebar.",
|
|
254
127
|
},
|
|
255
128
|
},
|
|
256
129
|
},
|
|
257
|
-
|
|
258
|
-
<div className="bg-fm-surface-primary space-y-8 rounded-lg p-8">
|
|
259
|
-
<div className="text-center">
|
|
260
|
-
<h3 className="text-fm-primary mb-4 text-xl font-bold">
|
|
261
|
-
Size Variations
|
|
262
|
-
</h3>
|
|
263
|
-
<p className="text-fm-secondary text-sm">
|
|
264
|
-
Four predefined sizes for different contexts and use cases
|
|
265
|
-
</p>
|
|
266
|
-
</div>
|
|
267
|
-
|
|
268
|
-
<div className="grid grid-cols-2 gap-6 md:grid-cols-4">
|
|
269
|
-
<div className="text-center">
|
|
270
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mb-4 flex h-24 items-center justify-center rounded-lg border">
|
|
271
|
-
<CircularLoader size="sm" text="Small" />
|
|
272
|
-
</div>
|
|
273
|
-
<div className="space-y-1">
|
|
274
|
-
<div className="text-fm-primary font-medium">Small</div>
|
|
275
|
-
<div className="text-fm-secondary text-xs">
|
|
276
|
-
16×16px - Inline elements
|
|
277
|
-
</div>
|
|
278
|
-
</div>
|
|
279
|
-
</div>
|
|
280
|
-
|
|
281
|
-
<div className="text-center">
|
|
282
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mb-4 flex h-24 items-center justify-center rounded-lg border">
|
|
283
|
-
<CircularLoader size="md" text="Medium" />
|
|
284
|
-
</div>
|
|
285
|
-
<div className="space-y-1">
|
|
286
|
-
<div className="text-fm-primary font-medium">Medium</div>
|
|
287
|
-
<div className="text-fm-secondary text-xs">
|
|
288
|
-
24×24px - Default size
|
|
289
|
-
</div>
|
|
290
|
-
</div>
|
|
291
|
-
</div>
|
|
130
|
+
}
|
|
292
131
|
|
|
293
|
-
|
|
294
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mb-4 flex h-24 items-center justify-center rounded-lg border">
|
|
295
|
-
<CircularLoader size="lg" text="Large" />
|
|
296
|
-
</div>
|
|
297
|
-
<div className="space-y-1">
|
|
298
|
-
<div className="text-fm-primary font-medium">Large</div>
|
|
299
|
-
<div className="text-fm-secondary text-xs">
|
|
300
|
-
32×32px - Prominent loading
|
|
301
|
-
</div>
|
|
302
|
-
</div>
|
|
303
|
-
</div>
|
|
132
|
+
// ─── 2. AllVariants ───────────────────────────────────────────────────────────
|
|
304
133
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
134
|
+
export const AllVariants: Story = {
|
|
135
|
+
render: () => (
|
|
136
|
+
<div className="space-y-8">
|
|
137
|
+
<div className="space-y-4">
|
|
138
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
139
|
+
Spinner Variants
|
|
140
|
+
</h4>
|
|
141
|
+
<div className="flex flex-wrap items-end gap-8">
|
|
142
|
+
<div className="space-y-2 text-center">
|
|
143
|
+
<StoryCircularLoader variant="v1" size="lg" text="Gradient" />
|
|
144
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
145
|
+
V1 — Gradient
|
|
146
|
+
</p>
|
|
147
|
+
</div>
|
|
148
|
+
<div className="space-y-2 text-center">
|
|
149
|
+
<StoryCircularLoader variant="v2" size="lg" text="Solid" />
|
|
150
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
151
|
+
V2 — Solid
|
|
152
|
+
</p>
|
|
153
|
+
</div>
|
|
154
|
+
<div className="space-y-2 text-center">
|
|
155
|
+
<StoryCircularLoader variant="v3" size="lg" text="Neutral" />
|
|
156
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
157
|
+
V3 — Neutral
|
|
158
|
+
</p>
|
|
314
159
|
</div>
|
|
315
160
|
</div>
|
|
316
161
|
</div>
|
|
317
162
|
</div>
|
|
318
163
|
),
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// 4. Accessibility Features
|
|
322
|
-
export const AccessibilityFeatures: Story = {
|
|
323
164
|
parameters: {
|
|
324
|
-
...storyParameters,
|
|
325
165
|
docs: {
|
|
326
166
|
description: {
|
|
327
167
|
story:
|
|
328
|
-
"
|
|
168
|
+
"Three distinct spinner designs — gradient (v1), solid branded (v2), and neutral (v3) — shown at large size for easy comparison.",
|
|
329
169
|
},
|
|
330
170
|
},
|
|
331
171
|
},
|
|
332
|
-
|
|
333
|
-
<div className="bg-fm-surface-primary space-y-8 rounded-lg p-8">
|
|
334
|
-
<div className="text-center">
|
|
335
|
-
<h3 className="text-fm-primary mb-4 text-xl font-bold">
|
|
336
|
-
Accessibility Features
|
|
337
|
-
</h3>
|
|
338
|
-
<p className="text-fm-secondary text-sm">
|
|
339
|
-
Built with comprehensive screen reader support and ARIA attributes
|
|
340
|
-
</p>
|
|
341
|
-
</div>
|
|
342
|
-
|
|
343
|
-
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
344
|
-
<div className="space-y-6">
|
|
345
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
346
|
-
<h4 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
347
|
-
Visual + Screen Reader
|
|
348
|
-
</h4>
|
|
349
|
-
<div className="mb-4 flex items-center justify-center">
|
|
350
|
-
<CircularLoader text="Loading data..." size="lg" />
|
|
351
|
-
</div>
|
|
352
|
-
<div className="text-fm-secondary text-sm">
|
|
353
|
-
Shows visible text and provides the same message to screen readers
|
|
354
|
-
</div>
|
|
355
|
-
</div>
|
|
356
|
-
|
|
357
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
358
|
-
<h4 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
359
|
-
Screen Reader Only
|
|
360
|
-
</h4>
|
|
361
|
-
<div className="mb-4 flex items-center justify-center">
|
|
362
|
-
<CircularLoader
|
|
363
|
-
aria-label="Processing user authentication"
|
|
364
|
-
size="lg"
|
|
365
|
-
/>
|
|
366
|
-
</div>
|
|
367
|
-
<div className="text-fm-secondary text-sm">
|
|
368
|
-
No visible text but provides descriptive label for screen readers
|
|
369
|
-
</div>
|
|
370
|
-
</div>
|
|
371
|
-
</div>
|
|
372
|
-
|
|
373
|
-
<div className="space-y-6">
|
|
374
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
375
|
-
<h4 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
376
|
-
Custom Loading Message
|
|
377
|
-
</h4>
|
|
378
|
-
<div className="mb-4 flex items-center justify-center">
|
|
379
|
-
<CircularLoader
|
|
380
|
-
text="Saving..."
|
|
381
|
-
loadingMessage="Your changes are being saved to the server"
|
|
382
|
-
size="lg"
|
|
383
|
-
/>
|
|
384
|
-
</div>
|
|
385
|
-
<div className="text-fm-secondary text-sm">
|
|
386
|
-
Visual text differs from detailed screen reader message
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
172
|
+
}
|
|
389
173
|
|
|
390
|
-
|
|
391
|
-
<h4 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
392
|
-
Assertive Announcements
|
|
393
|
-
</h4>
|
|
394
|
-
<div className="mb-4 flex items-center justify-center">
|
|
395
|
-
<CircularLoader
|
|
396
|
-
text="Critical process..."
|
|
397
|
-
aria-live="assertive"
|
|
398
|
-
size="lg"
|
|
399
|
-
/>
|
|
400
|
-
</div>
|
|
401
|
-
<div className="text-fm-secondary text-sm">
|
|
402
|
-
Immediately announces changes to screen readers
|
|
403
|
-
</div>
|
|
404
|
-
</div>
|
|
405
|
-
</div>
|
|
406
|
-
</div>
|
|
174
|
+
// ─── 3. Sizes ─────────────────────────────────────────────────────────────────
|
|
407
175
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
176
|
+
export const Sizes: Story = {
|
|
177
|
+
render: () => (
|
|
178
|
+
<div className="space-y-8">
|
|
179
|
+
<div className="space-y-4">
|
|
180
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
181
|
+
Size Scale
|
|
411
182
|
</h4>
|
|
412
|
-
<div className="
|
|
413
|
-
<div>
|
|
414
|
-
<
|
|
415
|
-
<
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
183
|
+
<div className="flex flex-wrap items-end justify-center gap-8">
|
|
184
|
+
<div className="space-y-2 text-center">
|
|
185
|
+
<CircularLoader size="sm" aria-label="Loading small" />
|
|
186
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
187
|
+
Small (16px)
|
|
188
|
+
</p>
|
|
189
|
+
</div>
|
|
190
|
+
<div className="space-y-2 text-center">
|
|
191
|
+
<CircularLoader size="md" aria-label="Loading medium" />
|
|
192
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
193
|
+
Medium (24px)
|
|
194
|
+
</p>
|
|
195
|
+
</div>
|
|
196
|
+
<div className="space-y-2 text-center">
|
|
197
|
+
<CircularLoader size="lg" aria-label="Loading large" />
|
|
198
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
199
|
+
Large (32px)
|
|
200
|
+
</p>
|
|
201
|
+
</div>
|
|
202
|
+
<div className="space-y-2 text-center">
|
|
203
|
+
<CircularLoader size="xl" aria-label="Loading extra large" />
|
|
204
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
205
|
+
Extra Large (48px)
|
|
206
|
+
</p>
|
|
432
207
|
</div>
|
|
433
208
|
</div>
|
|
434
209
|
</div>
|
|
435
210
|
</div>
|
|
436
211
|
),
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// 5. Real-world Usage Examples
|
|
440
|
-
export const UsageExamples: Story = {
|
|
441
212
|
parameters: {
|
|
442
|
-
...storyParameters,
|
|
443
213
|
docs: {
|
|
444
214
|
description: {
|
|
445
215
|
story:
|
|
446
|
-
"
|
|
216
|
+
"Four predefined sizes side by side — sm for inline/button use, md as the default, lg for prominent loading areas, xl for full-page loading states.",
|
|
447
217
|
},
|
|
448
218
|
},
|
|
449
219
|
},
|
|
450
|
-
|
|
451
|
-
const [buttonLoading, setButtonLoading] = useState(false)
|
|
452
|
-
const [cardLoading, setCardLoading] = useState(false)
|
|
453
|
-
const [pageLoading, setPageLoading] = useState(false)
|
|
454
|
-
|
|
455
|
-
const handleButtonClick = () => {
|
|
456
|
-
setButtonLoading(true)
|
|
457
|
-
setTimeout(() => setButtonLoading(false), 3000)
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
const handleCardRefresh = () => {
|
|
461
|
-
setCardLoading(true)
|
|
462
|
-
setTimeout(() => setCardLoading(false), 2000)
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const handlePageRefresh = () => {
|
|
466
|
-
setPageLoading(true)
|
|
467
|
-
setTimeout(() => setPageLoading(false), 4000)
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return (
|
|
471
|
-
<div className="bg-fm-surface-primary space-y-8 rounded-lg p-8">
|
|
472
|
-
<div className="text-center">
|
|
473
|
-
<h3 className="text-fm-primary mb-4 text-xl font-bold">
|
|
474
|
-
Real-world Usage
|
|
475
|
-
</h3>
|
|
476
|
-
<p className="text-fm-secondary text-sm">
|
|
477
|
-
Common UI patterns and contexts where CircularLoader is used
|
|
478
|
-
</p>
|
|
479
|
-
</div>
|
|
480
|
-
|
|
481
|
-
<div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
|
|
482
|
-
{/* Button Loading */}
|
|
483
|
-
<div className="space-y-4">
|
|
484
|
-
<h4 className="text-fm-primary text-lg font-semibold">
|
|
485
|
-
Button Loading
|
|
486
|
-
</h4>
|
|
487
|
-
<div className="space-y-3">
|
|
488
|
-
<Button
|
|
489
|
-
onClick={handleButtonClick}
|
|
490
|
-
disabled={buttonLoading}
|
|
491
|
-
className="w-full"
|
|
492
|
-
>
|
|
493
|
-
{buttonLoading ? (
|
|
494
|
-
<div className="flex items-center gap-2">
|
|
495
|
-
<CircularLoader size="sm" aria-label="Saving changes" />
|
|
496
|
-
<span>Saving...</span>
|
|
497
|
-
</div>
|
|
498
|
-
) : (
|
|
499
|
-
"Save Changes"
|
|
500
|
-
)}
|
|
501
|
-
</Button>
|
|
502
|
-
<div className="text-fm-secondary text-xs">
|
|
503
|
-
Inline loader in button with accessible label
|
|
504
|
-
</div>
|
|
505
|
-
</div>
|
|
506
|
-
</div>
|
|
220
|
+
}
|
|
507
221
|
|
|
508
|
-
|
|
509
|
-
<div className="space-y-4">
|
|
510
|
-
<h4 className="text-fm-primary text-lg font-semibold">
|
|
511
|
-
Card Loading
|
|
512
|
-
</h4>
|
|
513
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
514
|
-
{cardLoading ? (
|
|
515
|
-
<div className="flex h-32 items-center justify-center">
|
|
516
|
-
<CircularLoader
|
|
517
|
-
text="Refreshing data..."
|
|
518
|
-
loadingMessage="Refreshing chart data from server"
|
|
519
|
-
size="lg"
|
|
520
|
-
/>
|
|
521
|
-
</div>
|
|
522
|
-
) : (
|
|
523
|
-
<div className="space-y-3">
|
|
524
|
-
<div className="bg-fm-surface-tertiary h-4 rounded"></div>
|
|
525
|
-
<div className="bg-fm-surface-tertiary h-4 rounded"></div>
|
|
526
|
-
<div className="bg-fm-surface-tertiary h-4 w-3/4 rounded"></div>
|
|
527
|
-
<Button
|
|
528
|
-
onClick={handleCardRefresh}
|
|
529
|
-
size="sm"
|
|
530
|
-
className="mt-2"
|
|
531
|
-
>
|
|
532
|
-
Refresh Data
|
|
533
|
-
</Button>
|
|
534
|
-
</div>
|
|
535
|
-
)}
|
|
536
|
-
</div>
|
|
537
|
-
<div className="text-fm-secondary text-xs">
|
|
538
|
-
Content area with detailed loading message
|
|
539
|
-
</div>
|
|
540
|
-
</div>
|
|
222
|
+
// ─── 4. Accessibility ─────────────────────────────────────────────────────────
|
|
541
223
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
224
|
+
export const Accessibility: Story = {
|
|
225
|
+
render: () => (
|
|
226
|
+
<div className="space-y-8">
|
|
227
|
+
<div className="space-y-4">
|
|
228
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
229
|
+
ARIA Patterns
|
|
230
|
+
</h4>
|
|
231
|
+
<div className="flex flex-wrap items-start gap-8">
|
|
232
|
+
<div className="space-y-2 text-center">
|
|
233
|
+
<StoryCircularLoader
|
|
234
|
+
size="lg"
|
|
235
|
+
text="Loading data..."
|
|
236
|
+
aria-live="polite"
|
|
237
|
+
/>
|
|
238
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
239
|
+
Visual text (polite)
|
|
240
|
+
</p>
|
|
241
|
+
</div>
|
|
242
|
+
<div className="space-y-2 text-center">
|
|
243
|
+
<CircularLoader
|
|
244
|
+
size="lg"
|
|
245
|
+
aria-label="Processing your authentication"
|
|
246
|
+
aria-live="polite"
|
|
247
|
+
/>
|
|
248
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
249
|
+
SR label only
|
|
250
|
+
</p>
|
|
251
|
+
</div>
|
|
252
|
+
<div className="space-y-2 text-center">
|
|
253
|
+
<StoryCircularLoader
|
|
254
|
+
size="lg"
|
|
255
|
+
text="Saving..."
|
|
256
|
+
loadingMessage="Your changes are being saved to the server"
|
|
257
|
+
aria-live="polite"
|
|
258
|
+
/>
|
|
259
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
260
|
+
Custom SR message
|
|
261
|
+
</p>
|
|
262
|
+
</div>
|
|
263
|
+
<div className="space-y-2 text-center">
|
|
264
|
+
<StoryCircularLoader
|
|
265
|
+
size="lg"
|
|
266
|
+
text="Critical update..."
|
|
267
|
+
aria-live="assertive"
|
|
268
|
+
/>
|
|
269
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
270
|
+
Assertive announce
|
|
271
|
+
</p>
|
|
577
272
|
</div>
|
|
578
273
|
</div>
|
|
274
|
+
</div>
|
|
579
275
|
|
|
580
|
-
|
|
581
|
-
<
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
<div className="
|
|
586
|
-
<
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
className="border-fm-divider-secondary bg-fm-surface-tertiary text-fm-primary placeholder:text-fm-tertiary rounded-lg border p-3"
|
|
596
|
-
/>
|
|
597
|
-
</div>
|
|
598
|
-
<textarea
|
|
599
|
-
placeholder="Message"
|
|
600
|
-
rows={3}
|
|
601
|
-
className="border-fm-divider-secondary bg-fm-surface-tertiary text-fm-primary placeholder:text-fm-tertiary w-full rounded-lg border p-3"
|
|
602
|
-
/>
|
|
603
|
-
<div className="flex items-center justify-between">
|
|
604
|
-
<div className="flex items-center gap-2">
|
|
605
|
-
<CircularLoader size="sm" aria-label="Submitting form" />
|
|
606
|
-
<span className="text-fm-secondary text-sm">
|
|
607
|
-
Submitting your message...
|
|
608
|
-
</span>
|
|
609
|
-
</div>
|
|
610
|
-
<Button disabled>Submit</Button>
|
|
611
|
-
</div>
|
|
612
|
-
</div>
|
|
276
|
+
<div className="space-y-4">
|
|
277
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
278
|
+
In-context Usage
|
|
279
|
+
</h4>
|
|
280
|
+
<div className="flex flex-wrap gap-6">
|
|
281
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center gap-3 rounded-lg border px-4 py-3">
|
|
282
|
+
<CircularLoader size="sm" aria-label="Saving changes" />
|
|
283
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
284
|
+
Saving changes...
|
|
285
|
+
</span>
|
|
286
|
+
</div>
|
|
287
|
+
<Button disabled>
|
|
288
|
+
<CircularLoader size="sm" aria-label="Submitting form" />
|
|
289
|
+
Submitting
|
|
290
|
+
</Button>
|
|
613
291
|
</div>
|
|
614
292
|
</div>
|
|
615
|
-
)
|
|
616
|
-
},
|
|
617
|
-
}
|
|
618
293
|
|
|
619
|
-
|
|
620
|
-
|
|
294
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
295
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
296
|
+
<strong className="text-fm-primary">Best practices:</strong>
|
|
297
|
+
</p>
|
|
298
|
+
<ul className="mt-2 space-y-1">
|
|
299
|
+
<li>
|
|
300
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
301
|
+
• Always supply <code>text</code> or <code>aria-label</code> so
|
|
302
|
+
screen readers know what is loading.
|
|
303
|
+
</p>
|
|
304
|
+
</li>
|
|
305
|
+
<li>
|
|
306
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
307
|
+
• Use <code>loadingMessage</code> when the visible text is too
|
|
308
|
+
brief — the message is read instead by screen readers.
|
|
309
|
+
</p>
|
|
310
|
+
</li>
|
|
311
|
+
<li>
|
|
312
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
313
|
+
• Prefer <code>aria-live="polite"</code> for background tasks;
|
|
314
|
+
reserve <code>"assertive"</code> for critical, time-sensitive
|
|
315
|
+
updates.
|
|
316
|
+
</p>
|
|
317
|
+
</li>
|
|
318
|
+
<li>
|
|
319
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
320
|
+
• The spinner icon carries <code>aria-hidden="true"</code> — it is
|
|
321
|
+
purely decorative and excluded from the accessibility tree.
|
|
322
|
+
</p>
|
|
323
|
+
</li>
|
|
324
|
+
<li>
|
|
325
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
326
|
+
• <code>role="status"</code> is set automatically on the root
|
|
327
|
+
element, meeting WCAG 4.1.3 (Status Messages).
|
|
328
|
+
</p>
|
|
329
|
+
</li>
|
|
330
|
+
</ul>
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
),
|
|
621
334
|
parameters: {
|
|
622
|
-
...storyParameters,
|
|
623
335
|
docs: {
|
|
624
336
|
description: {
|
|
625
337
|
story:
|
|
626
|
-
"
|
|
338
|
+
"Accessibility-focused examples covering polite and assertive aria-live regions, screen-reader-only labels, custom loading messages, and inline button integration — with a best-practices reference.",
|
|
627
339
|
},
|
|
628
340
|
},
|
|
629
341
|
},
|
|
630
|
-
args: {
|
|
631
|
-
variant: "v1",
|
|
632
|
-
size: "md",
|
|
633
|
-
text: "Loading...",
|
|
634
|
-
"aria-label": "",
|
|
635
|
-
"aria-live": "polite",
|
|
636
|
-
loadingMessage: "",
|
|
637
|
-
className: "",
|
|
638
|
-
classes: {},
|
|
639
|
-
},
|
|
640
|
-
argTypes: {
|
|
641
|
-
variant: {
|
|
642
|
-
control: { type: "select" },
|
|
643
|
-
options: ["v1", "v2", "v3"],
|
|
644
|
-
description: "Visual variant of the spinner",
|
|
645
|
-
},
|
|
646
|
-
size: {
|
|
647
|
-
control: { type: "select" },
|
|
648
|
-
options: ["sm", "md", "lg", "xl"],
|
|
649
|
-
description: "Size of the spinner",
|
|
650
|
-
},
|
|
651
|
-
text: {
|
|
652
|
-
control: "text",
|
|
653
|
-
description: "Visible text displayed below the spinner",
|
|
654
|
-
},
|
|
655
|
-
"aria-label": {
|
|
656
|
-
control: "text",
|
|
657
|
-
description:
|
|
658
|
-
"Accessible label for screen readers when no text is provided",
|
|
659
|
-
},
|
|
660
|
-
"aria-live": {
|
|
661
|
-
control: { type: "select" },
|
|
662
|
-
options: ["polite", "assertive", "off"],
|
|
663
|
-
description: "How screen readers announce loading state changes",
|
|
664
|
-
},
|
|
665
|
-
loadingMessage: {
|
|
666
|
-
control: "text",
|
|
667
|
-
description: "Custom loading message for screen readers",
|
|
668
|
-
},
|
|
669
|
-
className: {
|
|
670
|
-
control: "text",
|
|
671
|
-
description: "Additional CSS classes for the spinner icon",
|
|
672
|
-
},
|
|
673
|
-
classes: {
|
|
674
|
-
control: "object",
|
|
675
|
-
description: "Custom classes for different parts of the component",
|
|
676
|
-
},
|
|
677
|
-
},
|
|
678
|
-
render: (args) => (
|
|
679
|
-
<div className="bg-fm-surface-primary space-y-8 rounded-lg p-8">
|
|
680
|
-
<div className="text-center">
|
|
681
|
-
<h3 className="text-fm-primary mb-4 text-xl font-bold">
|
|
682
|
-
Interactive Playground
|
|
683
|
-
</h3>
|
|
684
|
-
<p className="text-fm-secondary text-sm">
|
|
685
|
-
Experiment with all CircularLoader configurations and accessibility
|
|
686
|
-
features
|
|
687
|
-
</p>
|
|
688
|
-
</div>
|
|
689
|
-
|
|
690
|
-
<div className="flex items-center justify-center">
|
|
691
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-8">
|
|
692
|
-
<CircularLoader {...args} />
|
|
693
|
-
</div>
|
|
694
|
-
</div>
|
|
695
|
-
|
|
696
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
697
|
-
<h4 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
698
|
-
Current Configuration
|
|
699
|
-
</h4>
|
|
700
|
-
<div className="grid grid-cols-2 gap-4 text-sm">
|
|
701
|
-
<div>
|
|
702
|
-
<div className="text-fm-primary font-medium">Variant:</div>
|
|
703
|
-
<div className="text-fm-secondary">{args.variant}</div>
|
|
704
|
-
</div>
|
|
705
|
-
<div>
|
|
706
|
-
<div className="text-fm-primary font-medium">Size:</div>
|
|
707
|
-
<div className="text-fm-secondary">{args.size}</div>
|
|
708
|
-
</div>
|
|
709
|
-
<div>
|
|
710
|
-
<div className="text-fm-primary font-medium">Visual Text:</div>
|
|
711
|
-
<div className="text-fm-secondary">{args.text || "None"}</div>
|
|
712
|
-
</div>
|
|
713
|
-
<div>
|
|
714
|
-
<div className="text-fm-primary font-medium">ARIA Label:</div>
|
|
715
|
-
<div className="text-fm-secondary">
|
|
716
|
-
{args["aria-label"] || "None"}
|
|
717
|
-
</div>
|
|
718
|
-
</div>
|
|
719
|
-
<div>
|
|
720
|
-
<div className="text-fm-primary font-medium">ARIA Live:</div>
|
|
721
|
-
<div className="text-fm-secondary">{args["aria-live"]}</div>
|
|
722
|
-
</div>
|
|
723
|
-
<div>
|
|
724
|
-
<div className="text-fm-primary font-medium">Loading Message:</div>
|
|
725
|
-
<div className="text-fm-secondary">
|
|
726
|
-
{args.loadingMessage || "None"}
|
|
727
|
-
</div>
|
|
728
|
-
</div>
|
|
729
|
-
</div>
|
|
730
|
-
</div>
|
|
731
|
-
|
|
732
|
-
<div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-6">
|
|
733
|
-
<h4 className="text-fm-positive mb-4 text-lg font-semibold">
|
|
734
|
-
Accessibility Info
|
|
735
|
-
</h4>
|
|
736
|
-
<div className="text-fm-positive-sec space-y-2 text-sm">
|
|
737
|
-
<div>
|
|
738
|
-
<strong>Screen Reader Message:</strong>{" "}
|
|
739
|
-
{args.text ||
|
|
740
|
-
args.loadingMessage ||
|
|
741
|
-
args["aria-label"] ||
|
|
742
|
-
"Loading"}
|
|
743
|
-
</div>
|
|
744
|
-
<div>
|
|
745
|
-
<strong>Announcement Type:</strong> {args["aria-live"]}
|
|
746
|
-
</div>
|
|
747
|
-
<div>
|
|
748
|
-
<strong>Role:</strong> status
|
|
749
|
-
</div>
|
|
750
|
-
<div>
|
|
751
|
-
<strong>Focusable:</strong> No (decorative spinner)
|
|
752
|
-
</div>
|
|
753
|
-
</div>
|
|
754
|
-
</div>
|
|
755
|
-
</div>
|
|
756
|
-
),
|
|
757
342
|
}
|