@tempoxyz/ds 0.3.9 → 0.3.11

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.
Files changed (128) hide show
  1. package/dist/docs/AGENTS.md +9 -0
  2. package/dist/docs/components/accordion.md +489 -0
  3. package/dist/docs/components/address-card.md +147 -0
  4. package/dist/docs/components/agent-logo.md +194 -0
  5. package/dist/docs/components/alert-dialog.md +631 -0
  6. package/dist/docs/components/alert.md +448 -0
  7. package/dist/docs/components/amount-input.md +305 -0
  8. package/dist/docs/components/amount.md +794 -0
  9. package/dist/docs/components/app-shell.md +559 -0
  10. package/dist/docs/components/asset-chip.md +294 -0
  11. package/dist/docs/components/autocomplete.md +619 -0
  12. package/dist/docs/components/avatar.md +321 -0
  13. package/dist/docs/components/badge.md +339 -0
  14. package/dist/docs/components/badged-logo.md +116 -0
  15. package/dist/docs/components/banner.md +379 -0
  16. package/dist/docs/components/bar-chart.md +208 -0
  17. package/dist/docs/components/breadcrumbs.md +380 -0
  18. package/dist/docs/components/button-group.md +286 -0
  19. package/dist/docs/components/button.md +650 -0
  20. package/dist/docs/components/calendar.md +375 -0
  21. package/dist/docs/components/callout.md +96 -0
  22. package/dist/docs/components/checkbox-group.md +521 -0
  23. package/dist/docs/components/checkbox.md +467 -0
  24. package/dist/docs/components/choice-group.md +516 -0
  25. package/dist/docs/components/choicebox.md +641 -0
  26. package/dist/docs/components/code.md +100 -0
  27. package/dist/docs/components/combobox.md +939 -0
  28. package/dist/docs/components/container.md +257 -0
  29. package/dist/docs/components/copy-button.md +642 -0
  30. package/dist/docs/components/date-picker.md +514 -0
  31. package/dist/docs/components/dialog.md +1332 -0
  32. package/dist/docs/components/drawer.md +966 -0
  33. package/dist/docs/components/empty.md +340 -0
  34. package/dist/docs/components/field.md +570 -0
  35. package/dist/docs/components/fieldset.md +398 -0
  36. package/dist/docs/components/frame.md +434 -0
  37. package/dist/docs/components/gauge.md +299 -0
  38. package/dist/docs/components/get-started-visual.md +117 -0
  39. package/dist/docs/components/grid.md +288 -0
  40. package/dist/docs/components/hero-visual.md +155 -0
  41. package/dist/docs/components/hex.md +487 -0
  42. package/dist/docs/components/icon-tile.md +292 -0
  43. package/dist/docs/components/identicon.md +371 -0
  44. package/dist/docs/components/inline.md +233 -0
  45. package/dist/docs/components/inset.md +225 -0
  46. package/dist/docs/components/kbd.md +423 -0
  47. package/dist/docs/components/list-group.md +981 -0
  48. package/dist/docs/components/loading-dots.md +237 -0
  49. package/dist/docs/components/menu.md +934 -0
  50. package/dist/docs/components/native-select.md +204 -0
  51. package/dist/docs/components/network-logo.md +248 -0
  52. package/dist/docs/components/number-field.md +543 -0
  53. package/dist/docs/components/otp-field.md +616 -0
  54. package/dist/docs/components/pagination.md +516 -0
  55. package/dist/docs/components/popover.md +544 -0
  56. package/dist/docs/components/progress.md +388 -0
  57. package/dist/docs/components/qr.md +314 -0
  58. package/dist/docs/components/radio-group.md +528 -0
  59. package/dist/docs/components/secret-value.md +406 -0
  60. package/dist/docs/components/select.md +751 -0
  61. package/dist/docs/components/separator.md +379 -0
  62. package/dist/docs/components/sidebar-menu.md +922 -0
  63. package/dist/docs/components/skeleton.md +517 -0
  64. package/dist/docs/components/slider.md +539 -0
  65. package/dist/docs/components/snippet.md +424 -0
  66. package/dist/docs/components/spinner.md +216 -0
  67. package/dist/docs/components/split-bar.md +139 -0
  68. package/dist/docs/components/split-button.md +464 -0
  69. package/dist/docs/components/stack.md +299 -0
  70. package/dist/docs/components/status-chip.md +226 -0
  71. package/dist/docs/components/status-indicator.md +119 -0
  72. package/dist/docs/components/status-row.md +174 -0
  73. package/dist/docs/components/stepper.md +451 -0
  74. package/dist/docs/components/success-hero.md +157 -0
  75. package/dist/docs/components/surface.md +639 -0
  76. package/dist/docs/components/switch.md +472 -0
  77. package/dist/docs/components/table.md +967 -0
  78. package/dist/docs/components/tabs.md +627 -0
  79. package/dist/docs/components/tempo-logo.md +185 -0
  80. package/dist/docs/components/text-input.md +624 -0
  81. package/dist/docs/components/textarea.md +352 -0
  82. package/dist/docs/components/toast.md +535 -0
  83. package/dist/docs/components/token-logo.md +371 -0
  84. package/dist/docs/components/token.md +247 -0
  85. package/dist/docs/components/tooltip.md +490 -0
  86. package/dist/docs/components/verification-code.md +116 -0
  87. package/dist/docs/components/visual.md +249 -0
  88. package/dist/docs/components.md +203 -0
  89. package/dist/docs/foundations/accessibility.md +377 -0
  90. package/dist/docs/foundations/agents.md +150 -0
  91. package/dist/docs/foundations/color.md +522 -0
  92. package/dist/docs/foundations/content/tone.md +194 -0
  93. package/dist/docs/foundations/content/voice.md +194 -0
  94. package/dist/docs/foundations/content/writing-style.md +406 -0
  95. package/dist/docs/foundations/iconography.md +282 -0
  96. package/dist/docs/foundations/intent.md +360 -0
  97. package/dist/docs/foundations/layout.md +508 -0
  98. package/dist/docs/foundations/linter.md +296 -0
  99. package/dist/docs/foundations/motion.md +151 -0
  100. package/dist/docs/foundations/radius-and-padding.md +86 -0
  101. package/dist/docs/foundations/typography.md +266 -0
  102. package/dist/docs/index.md +137 -0
  103. package/dist/docs/introduction/faq.md +132 -0
  104. package/dist/docs/introduction/getting-started.md +377 -0
  105. package/dist/docs/patterns/blockchain-values.md +709 -0
  106. package/dist/docs/patterns/dashboards.md +638 -0
  107. package/dist/docs/patterns/destructive-actions.md +626 -0
  108. package/dist/docs/patterns/empty-states.md +612 -0
  109. package/dist/docs/patterns/errors-and-validation.md +808 -0
  110. package/dist/docs/patterns/feedback-and-status.md +518 -0
  111. package/dist/docs/patterns/forms.md +679 -0
  112. package/dist/docs/patterns/loading.md +630 -0
  113. package/dist/docs/patterns/navigation.md +397 -0
  114. package/dist/docs/patterns/payments.md +765 -0
  115. package/dist/docs/patterns/responsive-layout.md +997 -0
  116. package/dist/docs/patterns/tables-and-lists.md +964 -0
  117. package/dist/docs/products/tempo-console.md +671 -0
  118. package/dist/docs/products/tempo-performance.md +437 -0
  119. package/dist/docs/products/tempo-wallet.md +438 -0
  120. package/dist/web/components/OtpField.css +1 -1
  121. package/dist/web/components/OtpField.d.ts +1 -1
  122. package/dist/web/components/OtpField.d.ts.map +1 -1
  123. package/dist/web/components/OtpField.js +3 -4
  124. package/dist/web/components/OtpField.js.map +1 -1
  125. package/dist/web/components/OtpField.js.zyzz.json +1 -1
  126. package/dist/web/index.js.zyzz.json +1 -1
  127. package/package.json +1 -1
  128. package/src/web/components/OtpField.tsx +2 -24
@@ -0,0 +1,517 @@
1
+ # Skeleton
2
+
3
+ Holds the place of content while it loads.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Skeleton.tsx)
6
+
7
+ ## Overview
8
+
9
+ Skeleton renders a loading placeholder at the size of the content it wraps.
10
+
11
+ ## Examples
12
+
13
+ ### Basic
14
+
15
+ ```tsx
16
+ import { Skeleton, style } from '@tempoxyz/ds'
17
+
18
+ export function Demo() {
19
+ return (
20
+ <div {...styles.row()}>
21
+ <div {...styles.column()}>
22
+ <Skeleton style={{ height: 14, width: 160 }} />
23
+ <Skeleton style={{ height: 14, width: 96 }} />
24
+ </div>
25
+ <Skeleton>
26
+ <p {...styles.text()}>Keeps the size of its content</p>
27
+ </Skeleton>
28
+ </div>
29
+ )
30
+ }
31
+
32
+ namespace styles {
33
+ export const column = style({ display: 'flex', flexDirection: 'column', gap: '8' })
34
+
35
+ export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '16' })
36
+
37
+ export const text = style({ margin: '0', typography: 'body.b2' })
38
+ }
39
+ ```
40
+
41
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Skeleton/Basic.tsx)
42
+
43
+ ### Shape
44
+
45
+ Set `shape` to `default` (default), `pill`, or `circle`.
46
+
47
+ ```tsx
48
+ import { Skeleton, style } from '@tempoxyz/ds'
49
+
50
+ export function Demo() {
51
+ return (
52
+ <div {...styles.row()}>
53
+ <Skeleton shape="circle" style={{ height: 40, width: 40 }} />
54
+ <Skeleton shape="default" style={{ height: 14, width: 160 }} />
55
+ <Skeleton shape="pill" style={{ height: 32, width: 96 }} />
56
+ </div>
57
+ )
58
+ }
59
+
60
+ namespace styles {
61
+ export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '16' })
62
+ }
63
+ ```
64
+
65
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Skeleton/Shape.tsx)
66
+
67
+ ### Show
68
+
69
+ Set `show={false}` when data arrives to reveal the content. `show` defaults to `true`.
70
+
71
+ ```tsx
72
+ import { Skeleton, style } from '@tempoxyz/ds'
73
+
74
+ export function Demo() {
75
+ return (
76
+ <div {...styles.row()}>
77
+ <Skeleton>
78
+ <p {...styles.text()}>Loading content</p>
79
+ </Skeleton>
80
+ <Skeleton show={false}>
81
+ <p {...styles.text()}>Loaded content</p>
82
+ </Skeleton>
83
+ </div>
84
+ )
85
+ }
86
+
87
+ namespace styles {
88
+ export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '16' })
89
+
90
+ export const text = style({ margin: '0', typography: 'body.b2' })
91
+ }
92
+ ```
93
+
94
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Skeleton/Show.tsx)
95
+
96
+ ## Anatomy
97
+
98
+ Import the component and assemble its parts.
99
+
100
+ ```tsx
101
+ import { Skeleton } from '@tempoxyz/ds'
102
+
103
+ <Skeleton />
104
+ ```
105
+
106
+ ## Guidelines
107
+
108
+ ### When to Use
109
+
110
+ * Hold the place of content with a known layout, such as balances, activity rows, or metric tiles.
111
+ * Fill table rows, cards, and lists on first load, with the expected or a typical item count.
112
+
113
+ ### When Not to Use
114
+
115
+ * Use [Spinner](/docs/components/spinner) when the shape of the result is unknown, or for a busy control.
116
+ * Use [Progress](/docs/components/progress) for a long task with measurable work.
117
+ * Use `loading` on a [Button](/docs/components/button) while its action runs.
118
+ * Use [Empty](/docs/components/empty) when the request returns no records.
119
+
120
+ ### Match the Final Content's Shape
121
+
122
+ * **`circle`:** Avatars, identicons, and token icons.
123
+ * **`pill`:** Pill-shaped controls, such as an extra-small button.
124
+ * **`default`:** Text, blocks, badges, and buttons.
125
+
126
+ For a list, repeat each row's structure instead of one block.
127
+
128
+ **Do:** Mirror each row's icon, text lines, and amount.
129
+
130
+ ```tsx
131
+ /**
132
+ * Do example for "Match the Final Content's Shape" on the Skeleton page.
133
+ * Mirror each row's icon, text lines, and amount.
134
+ * @module
135
+ */
136
+ import { Skeleton, style } from '@tempoxyz/ds'
137
+
138
+ /** Renders the static preview, which the guideline card shows inert. */
139
+ export function Demo() {
140
+ return (
141
+ <div {...styles.list()}>
142
+ {['0x8f3c…a21b', '0x41d2…9c07', '0xb7e0…3f5a'].map((address) => (
143
+ <div {...styles.row()} key={address}>
144
+ <Skeleton shape="circle" style={{ height: 32, width: 32 }} />
145
+ <div {...styles.text()}>
146
+ <Skeleton>
147
+ <div {...styles.title()}>{address}</div>
148
+ </Skeleton>
149
+ <Skeleton>
150
+ <div {...styles.meta()}>Oct 18, 14:02</div>
151
+ </Skeleton>
152
+ </div>
153
+ <Skeleton>
154
+ <div {...styles.title()}>+50.00 USDC</div>
155
+ </Skeleton>
156
+ </div>
157
+ ))}
158
+ </div>
159
+ )
160
+ }
161
+
162
+ namespace styles {
163
+ export const list = style({ display: 'flex', flexDirection: 'column', gap: '16' })
164
+
165
+ export const meta = style({ typography: 'body.b3' })
166
+
167
+ export const row = style({ alignItems: 'center', display: 'flex', gap: '12' })
168
+
169
+ export const text = style({
170
+ alignItems: 'flex-start',
171
+ display: 'flex',
172
+ flex: '1 !custom',
173
+ flexDirection: 'column',
174
+ gap: '4',
175
+ })
176
+
177
+ export const title = style({ typography: 'body.b2' })
178
+ }
179
+ ```
180
+
181
+ **Don't:** Cover a list with one block that hides its structure.
182
+
183
+ ```tsx
184
+ /**
185
+ * Don't example for "Match the Final Content's Shape" on the Skeleton page.
186
+ * Don't cover a list with one block that hides its structure.
187
+ * @module
188
+ */
189
+ import { Skeleton } from '@tempoxyz/ds'
190
+
191
+ /** Renders the static preview, which the guideline card shows inert. */
192
+ export function Demo() {
193
+ return <Skeleton style={{ height: 144, width: 256 }} />
194
+ }
195
+ ```
196
+
197
+ ### Wrap the Real Content
198
+
199
+ Skeleton takes the size of its children and hides them with `visibility: hidden`. Set `show={false}` when the data arrives, so the content keeps its place in reading order.
200
+
201
+ ```tsx
202
+ <Skeleton show={loading}>
203
+ <Amount currency="USD" value={balance} />
204
+ </Skeleton>
205
+ ```
206
+
207
+ Size an empty skeleton with `style` only when there is nothing to wrap.
208
+
209
+ **Do:** Wrap the element that holds the data, with a placeholder of typical length.
210
+
211
+ ```tsx
212
+ /**
213
+ * Do example for "Wrap the Real Content" on the Skeleton page.
214
+ * Wrap the element that holds the data, with a placeholder of typical length.
215
+ * @module
216
+ */
217
+ import { Skeleton, style } from '@tempoxyz/ds'
218
+
219
+ /** Renders the static preview, which the guideline card shows inert. */
220
+ export function Demo() {
221
+ return (
222
+ <div {...styles.card()}>
223
+ <div {...styles.label()}>Balance</div>
224
+ <Skeleton>
225
+ <div {...styles.value()}>1,250.00 USDC</div>
226
+ </Skeleton>
227
+ </div>
228
+ )
229
+ }
230
+
231
+ namespace styles {
232
+ export const card = style({
233
+ alignItems: 'flex-start',
234
+ display: 'flex',
235
+ flexDirection: 'column',
236
+ gap: '4',
237
+ })
238
+
239
+ export const label = style({ color: 'content.secondary', typography: 'body.b3' })
240
+
241
+ export const value = style({ color: 'content.primary', typography: 'heading.h1' })
242
+ }
243
+ ```
244
+
245
+ **Don't:** Swap in a separately sized block that doesn't match the content.
246
+
247
+ ```tsx
248
+ /**
249
+ * Don't example for "Wrap the Real Content" on the Skeleton page.
250
+ * Don't swap in a separately sized block that doesn't match the content.
251
+ * @module
252
+ */
253
+ import { Skeleton, style } from '@tempoxyz/ds'
254
+
255
+ /** Renders the static preview, which the guideline card shows inert. */
256
+ export function Demo() {
257
+ return (
258
+ <div {...styles.card()}>
259
+ <div {...styles.label()}>Balance</div>
260
+ <Skeleton style={{ height: 12, width: 80 }} />
261
+ </div>
262
+ )
263
+ }
264
+
265
+ namespace styles {
266
+ export const card = style({
267
+ alignItems: 'flex-start',
268
+ display: 'flex',
269
+ flexDirection: 'column',
270
+ gap: '4',
271
+ })
272
+
273
+ export const label = style({ color: 'content.secondary', typography: 'body.b3' })
274
+ }
275
+ ```
276
+
277
+ ### Keep Labels and Controls Visible
278
+
279
+ Keep headings, labels, tabs, filters, and buttons that do not depend on the data on screen.
280
+
281
+ **Do:** Keep the label and actions, and hold the place of the amount.
282
+
283
+ ```tsx
284
+ /**
285
+ * Do example for "Keep Labels and Controls Visible" on the Skeleton page.
286
+ * Keep the label and actions, and hold the place of the amount.
287
+ * @module
288
+ */
289
+ import { Button, Skeleton, style } from '@tempoxyz/ds'
290
+
291
+ /** Renders the static preview, which the guideline card shows inert. */
292
+ export function Demo() {
293
+ return (
294
+ <div {...styles.card()}>
295
+ <div {...styles.label()}>Balance</div>
296
+ <Skeleton>
297
+ <div {...styles.value()}>$1,250.00</div>
298
+ </Skeleton>
299
+ <div {...styles.actions()}>
300
+ <Button size="small">Send</Button>
301
+ <Button size="small" variant="secondary">
302
+ Receive
303
+ </Button>
304
+ </div>
305
+ </div>
306
+ )
307
+ }
308
+
309
+ namespace styles {
310
+ export const actions = style({ display: 'flex', gap: '8', marginBlockStart: '12' })
311
+
312
+ export const card = style({
313
+ alignItems: 'flex-start',
314
+ display: 'flex',
315
+ flexDirection: 'column',
316
+ gap: '4',
317
+ })
318
+
319
+ export const label = style({ color: 'content.secondary', typography: 'body.b3' })
320
+
321
+ export const value = style({ color: 'content.primary', typography: 'heading.h1' })
322
+ }
323
+ ```
324
+
325
+ **Don't:** Turn static labels and buttons into skeletons.
326
+
327
+ ```tsx
328
+ /**
329
+ * Don't example for "Keep Labels and Controls Visible" on the Skeleton page.
330
+ * Don't turn static labels and buttons into skeletons.
331
+ * @module
332
+ */
333
+ import { Button, Skeleton, style } from '@tempoxyz/ds'
334
+
335
+ /** Renders the static preview, which the guideline card shows inert. */
336
+ export function Demo() {
337
+ return (
338
+ <div {...styles.card()}>
339
+ <Skeleton>
340
+ <div {...styles.label()}>Balance</div>
341
+ </Skeleton>
342
+ <Skeleton>
343
+ <div {...styles.value()}>$1,250.00</div>
344
+ </Skeleton>
345
+ <div {...styles.actions()}>
346
+ <Skeleton shape="pill">
347
+ <Button size="small">Send</Button>
348
+ </Skeleton>
349
+ <Skeleton shape="pill">
350
+ <Button size="small" variant="secondary">
351
+ Receive
352
+ </Button>
353
+ </Skeleton>
354
+ </div>
355
+ </div>
356
+ )
357
+ }
358
+
359
+ namespace styles {
360
+ export const actions = style({ display: 'flex', gap: '8', marginBlockStart: '12' })
361
+
362
+ export const card = style({
363
+ alignItems: 'flex-start',
364
+ display: 'flex',
365
+ flexDirection: 'column',
366
+ gap: '4',
367
+ })
368
+
369
+ export const label = style({ color: 'content.secondary', typography: 'body.b3' })
370
+
371
+ export const value = style({ color: 'content.primary', typography: 'heading.h1' })
372
+ }
373
+ ```
374
+
375
+ ### Keep Current Data During a Refresh
376
+
377
+ **Do:** Keep values on screen, such as a polled balance, until the new ones arrive.
378
+
379
+ ```tsx
380
+ /**
381
+ * Do example for "Keep Current Data During a Refresh" on the Skeleton page.
382
+ * Keep values on screen, such as a polled balance, until the new ones arrive.
383
+ * @module
384
+ */
385
+ import { style } from '@tempoxyz/ds'
386
+
387
+ const payments = [
388
+ { address: '0x8f3c…a21b', amount: '+50.00 USDC' },
389
+ { address: '0x41d2…9c07', amount: '-25.00 USDC' },
390
+ ]
391
+
392
+ /** Renders the static preview, which the guideline card shows inert. */
393
+ export function Demo() {
394
+ return (
395
+ <div {...styles.list()}>
396
+ <div {...styles.heading()}>Activity</div>
397
+ {payments.map((payment) => (
398
+ <div {...styles.row()} key={payment.address}>
399
+ <div>{payment.address}</div>
400
+ <div>{payment.amount}</div>
401
+ </div>
402
+ ))}
403
+ </div>
404
+ )
405
+ }
406
+
407
+ namespace styles {
408
+ export const heading = style({ color: 'content.primary', typography: 'body.b2Strong' })
409
+
410
+ export const list = style({
411
+ display: 'flex',
412
+ flexDirection: 'column',
413
+ gap: '12',
414
+ width: '100% !custom',
415
+ })
416
+
417
+ export const row = style({
418
+ alignItems: 'center',
419
+ display: 'flex',
420
+ justifyContent: 'space-between',
421
+ typography: 'body.b2',
422
+ })
423
+ }
424
+ ```
425
+
426
+ **Don't:** Return to skeletons on every refresh.
427
+
428
+ ```tsx
429
+ /**
430
+ * Don't example for "Keep Current Data During a Refresh" on the Skeleton page.
431
+ * Don't return to skeletons on every refresh.
432
+ * @module
433
+ */
434
+ import { Skeleton, style } from '@tempoxyz/ds'
435
+
436
+ const payments = [
437
+ { address: '0x8f3c…a21b', amount: '+50.00 USDC' },
438
+ { address: '0x41d2…9c07', amount: '-25.00 USDC' },
439
+ ]
440
+
441
+ /** Renders the static preview, which the guideline card shows inert. */
442
+ export function Demo() {
443
+ return (
444
+ <div {...styles.list()}>
445
+ <div {...styles.heading()}>Activity</div>
446
+ {payments.map((payment) => (
447
+ <div {...styles.row()} key={payment.address}>
448
+ <Skeleton>
449
+ <div>{payment.address}</div>
450
+ </Skeleton>
451
+ <Skeleton>
452
+ <div>{payment.amount}</div>
453
+ </Skeleton>
454
+ </div>
455
+ ))}
456
+ </div>
457
+ )
458
+ }
459
+
460
+ namespace styles {
461
+ export const heading = style({ color: 'content.primary', typography: 'body.b2Strong' })
462
+
463
+ export const list = style({
464
+ display: 'flex',
465
+ flexDirection: 'column',
466
+ gap: '12',
467
+ width: '100% !custom',
468
+ })
469
+
470
+ export const row = style({
471
+ alignItems: 'center',
472
+ display: 'flex',
473
+ justifyContent: 'space-between',
474
+ typography: 'body.b2',
475
+ })
476
+ }
477
+ ```
478
+
479
+ ### Skip It for Fast Responses
480
+
481
+ * **Fast Responses (Under 300 ms):** Delay the skeleton, so the content renders without a flash.
482
+ * **Typical Waits (300 ms to 10 s):** Show the skeleton.
483
+ * **Long Waits (Over 10 s):** Show [Progress](/docs/components/progress). See [Loading](/docs/patterns/loading).
484
+
485
+ ## Accessibility
486
+
487
+ Skeleton renders a `div` that marks its content busy and hides it until `show={false}`. It has no live region, and most screen readers ignore `aria-busy` on a plain `div`.
488
+
489
+ ### Semantics
490
+
491
+ * **Busy State (aria-busy):** Marks the region busy while `show` is true.
492
+ * **Hidden Content (visibility: hidden):** Screen readers skip the placeholder text, and focus cannot reach hidden controls.
493
+ * **Pointer Events:** The root blocks pointer events while it shows, so placeholder buttons are inert.
494
+ * **Reduced Motion (prefers-reduced-motion):** The sweep stops, and the placeholder stays a static tint.
495
+
496
+ ### Your Responsibilities
497
+
498
+ * **Announce Long Loads (status):** For main content, state what loads in a status message, such as "Loading activity".
499
+ * **Handle Failures:** If loading fails, show an error message. Never leave a skeleton that does not resolve.
500
+
501
+ ## Related
502
+
503
+ [Spinner](/docs/components/spinner)
504
+
505
+ Use for loading with an unknown shape.
506
+
507
+ [Progress](/docs/components/progress)
508
+
509
+ Use for measurable work.
510
+
511
+ [Empty](/docs/components/empty)
512
+
513
+ Use for a region with nothing to show.
514
+
515
+ [Loading](/docs/patterns/loading)
516
+
517
+ Covers choosing a loading indicator.