@abuzareal/contour-ui 0.6.1 → 0.6.3

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 (46) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/COMBOBOX.md +1 -1
  3. package/COMPONENT-GUIDES.md +3534 -0
  4. package/COMPOSITION.md +1 -1
  5. package/CONTRIBUTING.md +4 -0
  6. package/DOCS.md +61 -61
  7. package/FORMS.md +1 -1
  8. package/GETTING-STARTED.md +3 -3
  9. package/HELPERS.md +1 -1
  10. package/HOOKS.md +1 -1
  11. package/MANUAL-QA.md +1 -1
  12. package/MIGRATION.md +1 -1
  13. package/MODELS.md +1 -1
  14. package/OVERLAYS.md +3 -1
  15. package/PROP-REFERENCE.md +4 -4
  16. package/PUBLIC-API.md +166 -166
  17. package/README.md +5 -3
  18. package/RECIPES.md +1 -1
  19. package/REFERENCE.md +55 -55
  20. package/STYLING.md +1 -1
  21. package/SUPPORT.md +1 -1
  22. package/THREE.md +1 -1
  23. package/dist/components/ui/Tooltip.js +1 -1
  24. package/docs/component-guides.json +2217 -0
  25. package/docs/prop-metadata.json +5734 -751
  26. package/examples/catalogue/buttons.tsx +27 -0
  27. package/examples/catalogue/choices.tsx +51 -0
  28. package/examples/catalogue/combobox.tsx +119 -0
  29. package/examples/catalogue/content.tsx +108 -0
  30. package/examples/catalogue/data-table.tsx +18 -0
  31. package/examples/catalogue/dialogs.tsx +20 -0
  32. package/examples/catalogue/feedback.tsx +24 -0
  33. package/examples/catalogue/field.tsx +18 -0
  34. package/examples/catalogue/floating.tsx +41 -0
  35. package/examples/catalogue/identity.tsx +35 -0
  36. package/examples/catalogue/metadata.tsx +17 -0
  37. package/examples/catalogue/motion.tsx +47 -0
  38. package/examples/catalogue/navigation.tsx +43 -0
  39. package/examples/catalogue/scene-boundary.tsx +37 -0
  40. package/examples/catalogue/text-inputs.tsx +60 -0
  41. package/examples/catalogue/theme-copy.tsx +32 -0
  42. package/examples/catalogue/toasts.tsx +21 -0
  43. package/examples/reproduction/package.json +1 -1
  44. package/examples/starters/next/package.json +1 -1
  45. package/examples/starters/vite/package.json +1 -1
  46. package/package.json +5 -2
@@ -0,0 +1,3534 @@
1
+ # Component guides
2
+
3
+ Authored contracts for 0.6.3, generated from [docs/component-guides.json](docs/component-guides.json). All 54 existing core component guides share the same maintained source with the catalogue. Types/defaults and executable family examples are checked against the emitted release. This is pre-1.0 documentation, not a new stability or accessibility certification. Optional scene exports retain [THREE.md](THREE.md).
4
+
5
+ ## Setup
6
+
7
+ Import scoped.css once and render inside contour-root or ThemeScope; system fonts need no extra import. Reset/fonts/providers are opt-in by need. Copy a linked complete TSX family example into your React application; its actions/data are local illustrations. No private catalogue source is required. Existing JavaScript onboarding remains in [GETTING-STARTED.md](GETTING-STARTED.md).
8
+
9
+ ```tsx
10
+ import { Button } from "@abuzareal/contour-ui";
11
+ import "@abuzareal/contour-ui/scoped.css";
12
+ export default function Example() {
13
+ return <div className="contour-root"><Button>Example action</Button></div>;
14
+ }
15
+ ```
16
+
17
+ ## Index
18
+
19
+ - [Alert](#alert)
20
+ - [Avatar](#avatar)
21
+ - [Badge](#badge)
22
+ - [BrandMark](#brandmark)
23
+ - [Breadcrumbs](#breadcrumbs)
24
+ - [Button](#button)
25
+ - [Card](#card)
26
+ - [Checkbox](#checkbox)
27
+ - [Combobox](#combobox)
28
+ - [CountUp](#countup)
29
+ - [DataTable](#datatable)
30
+ - [DepthButton](#depthbutton)
31
+ - [Dialog](#dialog)
32
+ - [Disclosure](#disclosure)
33
+ - [Divider](#divider)
34
+ - [DropdownMenu](#dropdownmenu)
35
+ - [EmptyState](#emptystate)
36
+ - [ExternalLink](#externallink)
37
+ - [Field](#field)
38
+ - [FlipCard](#flipcard)
39
+ - [GitHubIcon](#githubicon)
40
+ - [IconButton](#iconbutton)
41
+ - [Kbd](#kbd)
42
+ - [LinkedInIcon](#linkedinicon)
43
+ - [Magnetic](#magnetic)
44
+ - [Marquee](#marquee)
45
+ - [Pagination](#pagination)
46
+ - [Popover](#popover)
47
+ - [ProgressBar](#progressbar)
48
+ - [RadioGroup](#radiogroup)
49
+ - [Reveal](#reveal)
50
+ - [RevealHeading](#revealheading)
51
+ - [SceneBoundary](#sceneboundary)
52
+ - [ScrollProgress](#scrollprogress)
53
+ - [SectionLabel](#sectionlabel)
54
+ - [SegmentedControl](#segmentedcontrol)
55
+ - [SelectField](#selectfield)
56
+ - [Skeleton](#skeleton)
57
+ - [Slider](#slider)
58
+ - [Spinner](#spinner)
59
+ - [Stat](#stat)
60
+ - [Stepper](#stepper)
61
+ - [Switch](#switch)
62
+ - [Table](#table)
63
+ - [Tabs](#tabs)
64
+ - [Tag](#tag)
65
+ - [TextArea](#textarea)
66
+ - [TextField](#textfield)
67
+ - [ThemeScope](#themescope)
68
+ - [ThemeToggle](#themetoggle)
69
+ - [TiltCard](#tiltcard)
70
+ - [Timeline](#timeline)
71
+ - [ToastProvider](#toastprovider)
72
+ - [Tooltip](#tooltip)
73
+
74
+ ## Alert
75
+
76
+ A status or urgent alert with tone, title, optional action and dismiss request.
77
+
78
+ ### Import and runnable source
79
+
80
+ `import { Alert } from "@abuzareal/contour-ui";`
81
+
82
+ [Complete feedback TSX example](examples/catalogue/feedback.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
83
+
84
+ ### Props and explicit defaults
85
+
86
+ | Prop | Type | Default | Responsibility |
87
+ | --- | --- | --- | --- |
88
+ | title / children | string / ReactNode | Title required; body omitted | Explain the actual outcome and next step. |
89
+ | tone / layout | AlertTone / inline \| banner | neutral / inline | Tone also determines alert versus status semantics. |
90
+ | action | ReactNode | Omitted | Use a separately labelled native action. |
91
+ | onDismiss / dismissLabel | () => void / string | Omitted / Dismiss | Parent removes it; translate the accessible dismiss label. |
92
+
93
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
94
+
95
+ ### Purpose and alternatives
96
+
97
+ Use for meaningful inline or banner feedback. Reserve warning/danger for urgency; use nearby field errors for invalid inputs and do not fabricate successful requests.
98
+
99
+ ### Anatomy and parts
100
+
101
+ Root role is alert for warning/danger and status otherwise. Decorative tone icon, strong title, optional body/action and dismiss button form the message; banner is the same component layout.
102
+
103
+ ### State ownership
104
+
105
+ Parent owns visibility and service status. onDismiss requests removal; the component does not hide itself. tone defaults neutral and layout inline.
106
+
107
+ ### Native forms and reset
108
+
109
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
110
+
111
+ ### Ref target
112
+
113
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
114
+
115
+ ### CSS and tokens
116
+
117
+ Use .contour-alert and tone/layout hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
118
+
119
+ ### Loading, errors and long content
120
+
121
+ Show pending, service/permission failure and retry truthfully. Long titles/actions must wrap; do not use color alone or hide persistent actionable errors only in a toast.
122
+
123
+ ### RTL and localization
124
+
125
+ Translate title/body/action/dismissLabel. Direction and text length are application context; test actual live-region announcements manually.
126
+
127
+ ### Keyboard and focus
128
+
129
+ Message content is not a tab stop. Native action and dismiss buttons retain keyboard activation; the application owns focus after removing a focused message.
130
+
131
+ ### Limits and evidence
132
+
133
+ No auto-dismiss, fetching, retry engine, native form value or external root props/ref. Repeated urgent announcements can be disruptive.
134
+
135
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
136
+
137
+ [Report Alert 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Alert&version=0.6.3) using the [public reproduction](examples/reproduction).
138
+
139
+ ## Avatar
140
+
141
+ A name-based image/initials display with an optional labelled presence dot.
142
+
143
+ ### Import and runnable source
144
+
145
+ `import { Avatar } from "@abuzareal/contour-ui";`
146
+
147
+ [Complete metadata TSX example](examples/catalogue/metadata.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
148
+
149
+ ### Props and explicit defaults
150
+
151
+ | Prop | Type | Default | Responsibility |
152
+ | --- | --- | --- | --- |
153
+ | name | string | Required | Nonempty identity name; image alt/initials accessible label. |
154
+ | initials / src | string | Derived initials / omitted | No automatic failed-image-to-initials switch. |
155
+ | size | sm \| md \| lg \| xl | md | Visual size only. |
156
+ | status / statusLabel | online \| away / string | Omitted / Online or Away | Status is app data; translate/customize the dot description. |
157
+
158
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
159
+
160
+ ### Purpose and alternatives
161
+
162
+ Use for identity context. Do not use initials or a presence color as the sole explanation of a person/action; put actionable behavior on a separate native control.
163
+
164
+ ### Anatomy and parts
165
+
166
+ Wrapper holds an img with alt=name or a role=img initials span; optional presence dot has its own accessible label.
167
+
168
+ ### State ownership
169
+
170
+ src chooses image versus initials. initials overrides a basic first-two-space-separated-name-parts derivation. size defaults md; status is caller-supplied online/away.
171
+
172
+ ### Native forms and reset
173
+
174
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
175
+
176
+ ### Ref target
177
+
178
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
179
+
180
+ ### CSS and tokens
181
+
182
+ Use .contour-avatar, size and presence hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
183
+
184
+ ### Loading, errors and long content
185
+
186
+ If an image fails, native alt text remains; the app must remove/change src to select initials. Test empty/long names and unavailable status without inventing live presence.
187
+
188
+ ### RTL and localization
189
+
190
+ Supply explicit initials for scripts/emoji/name order that basic splitting cannot handle. Translate statusLabel and keep full accessible names meaningful.
191
+
192
+ ### Keyboard and focus
193
+
194
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
195
+
196
+ ### Limits and evidence
197
+
198
+ No upload/presence service, fallback on image-error, arbitrary native image props or forwarded ref. Initial derivation is not locale/grapheme-aware.
199
+
200
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
201
+
202
+ [Report Avatar 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Avatar&version=0.6.3) using the [public reproduction](examples/reproduction).
203
+
204
+ ## Badge
205
+
206
+ A compact textual status label with optional dot or icon.
207
+
208
+ ### Import and runnable source
209
+
210
+ `import { Badge } from "@abuzareal/contour-ui";`
211
+
212
+ [Complete metadata TSX example](examples/catalogue/metadata.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
213
+
214
+ ### Props and explicit defaults
215
+
216
+ | Prop | Type | Default | Responsibility |
217
+ | --- | --- | --- | --- |
218
+ | children | ReactNode | Required | Include readable status text. |
219
+ | tone | BadgeTone | accent | accent/neutral/invert/success/info/warning/danger. |
220
+ | dot / icon | boolean / ReactNode | false / omitted | A dot is decorative; caller icon semantics remain caller-owned. |
221
+
222
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
223
+
224
+ ### Purpose and alternatives
225
+
226
+ Use for short metadata/status text. Use an action button for interaction and Alert for a meaningful announced service message; color alone is insufficient.
227
+
228
+ ### Anatomy and parts
229
+
230
+ Inline span with tone class, optional decorative dot, caller icon and text children. It has no automatic live-region role.
231
+
232
+ ### State ownership
233
+
234
+ Pure display; tone defaults accent, dot false. Parent updates the actual status.
235
+
236
+ ### Native forms and reset
237
+
238
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
239
+
240
+ ### Ref target
241
+
242
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
243
+
244
+ ### CSS and tokens
245
+
246
+ Use .contour-badge and tone/dot hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
247
+
248
+ ### Loading, errors and long content
249
+
250
+ Check long text and contrast in every used tone, both themes and forced colors; business failure/loading remains parent-owned.
251
+
252
+ ### RTL and localization
253
+
254
+ Translate visible labels and optional icon descriptions where needed. Stable data status values should not depend on translated labels.
255
+
256
+ ### Keyboard and focus
257
+
258
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
259
+
260
+ ### Limits and evidence
261
+
262
+ No click/dismiss/selection behavior, root attributes/ref or automatic announcements. Icons and tone must not be the sole status explanation.
263
+
264
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
265
+
266
+ [Report Badge 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Badge&version=0.6.3) using the [public reproduction](examples/reproduction).
267
+
268
+ ## BrandMark
269
+
270
+ A fixed legacy aa. monogram rendered as a safe anchor.
271
+
272
+ ### Import and runnable source
273
+
274
+ `import { BrandMark } from "@abuzareal/contour-ui";`
275
+
276
+ [Complete identity TSX example](examples/catalogue/identity.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
277
+
278
+ ### Props and explicit defaults
279
+
280
+ | Prop | Type | Default | Responsibility |
281
+ | --- | --- | --- | --- |
282
+ | label | string | Required | Accessible name explains the actual legacy brand/link. |
283
+ | href | string | #hero | Supply a real destination/anchor for your page. |
284
+ | onClick | () => void | Omitted | No MouseEvent parameter/veto API is declared. |
285
+
286
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
287
+
288
+ ### Purpose and alternatives
289
+
290
+ Use only when that existing mark is appropriate. It is not a customizable brand/logo system or the catalogue C mark; use your own labelled native logo link for another identity.
291
+
292
+ ### Anatomy and parts
293
+
294
+ Native anchor displays literal aa plus a dot, with caller aria-label, safe href and onClick callback.
295
+
296
+ ### State ownership
297
+
298
+ No state; href defaults#hero. The target anchor and application navigation remain caller-owned.
299
+
300
+ ### Native forms and reset
301
+
302
+ Native navigation link, not a form value/submit/reset control.
303
+
304
+ ### Ref target
305
+
306
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
307
+
308
+ ### CSS and tokens
309
+
310
+ Use .contour-brand with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
311
+
312
+ ### Loading, errors and long content
313
+
314
+ Verify the default#hero actually exists or supply another destination. No loading/error/selection behavior is added.
315
+
316
+ ### RTL and localization
317
+
318
+ Translate label where appropriate; literal legacy lettering does not localize or change from props.
319
+
320
+ ### Keyboard and focus
321
+
322
+ Native anchor Enter/modified-click behavior applies when href is valid. Keep the accessible name and actual target meaningful.
323
+
324
+ ### Limits and evidence
325
+
326
+ Fixed aa. content, not a logo slot. No target/rel/native-props forwarding, configurable mark or ref; unsafe href is rejected.
327
+
328
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
329
+
330
+ [Report BrandMark 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=BrandMark&version=0.6.3) using the [public reproduction](examples/reproduction).
331
+
332
+ ## Breadcrumbs
333
+
334
+ A native breadcrumb navigation list with a current-page item.
335
+
336
+ ### Import and runnable source
337
+
338
+ `import { Breadcrumbs } from "@abuzareal/contour-ui";`
339
+
340
+ [Complete navigation TSX example](examples/catalogue/navigation.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
341
+
342
+ ### Props and explicit defaults
343
+
344
+ | Prop | Type | Default | Responsibility |
345
+ | --- | --- | --- | --- |
346
+ | items | {label:string;href?:string}[] | Required | Supply hierarchy in reading order; last item is current. |
347
+ | label | string | Breadcrumb | Translate the navigation name. |
348
+
349
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
350
+
351
+ ### Purpose and alternatives
352
+
353
+ Use for hierarchy context. Use a page heading and primary navigation separately; this is not a client router or application history manager.
354
+
355
+ ### Anatomy and parts
356
+
357
+ Named nav contains an ordered list. The final item is a span with aria-current=page; earlier items with href use safe native anchors.
358
+
359
+ ### State ownership
360
+
361
+ Pure caller-owned items; item labels serve as React keys and should be unique in a trail. Missing href means noninteractive text.
362
+
363
+ ### Native forms and reset
364
+
365
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
366
+
367
+ ### Ref target
368
+
369
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
370
+
371
+ ### CSS and tokens
372
+
373
+ Use .contour-breadcrumbs and [aria-current=page] with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
374
+
375
+ ### Loading, errors and long content
376
+
377
+ Check empty/single-item and lengthy trails, both themes and narrow wrapping. Failed data loading belongs outside this static navigation.
378
+
379
+ ### RTL and localization
380
+
381
+ Translate labels and navigation name; preserve hierarchy order with surrounding dir rather than reversing the array for appearance.
382
+
383
+ ### Keyboard and focus
384
+
385
+ Only actual anchors enter Tab order and retain native modified-click behavior. The current page is text rather than an unnecessary link.
386
+
387
+ ### Limits and evidence
388
+
389
+ No router element slot, generated destinations, native root props/ref or automatic label deduplication. safeHref does not verify a destination exists.
390
+
391
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
392
+
393
+ [Report Breadcrumbs 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Breadcrumbs&version=0.6.3) using the [public reproduction](examples/reproduction).
394
+
395
+ ## Button
396
+
397
+ A native action button with loading, icon slots and explicit native refs.
398
+
399
+ ### Import and runnable source
400
+
401
+ `import { Button } from "@abuzareal/contour-ui";`
402
+
403
+ [Complete buttons TSX example](examples/catalogue/buttons.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
404
+
405
+ ### Props and explicit defaults
406
+
407
+ | Prop | Type | Default | Responsibility |
408
+ | --- | --- | --- | --- |
409
+ | variant | primary \| accent \| secondary \| ghost \| danger | primary | Visual emphasis; navigation remains an anchor. |
410
+ | size | sm \| md \| lg | md | Choose size while retaining useful targets. |
411
+ | loading / loadingLabel | boolean / string | false / Loading | Loading disables activation and exposes a named spinner. |
412
+ | leadingIcon / icon | ReactNode | Omitted | Before/after the label; decorative icons should be hidden from AT. |
413
+ | type / disabled / ref | Native button props and ref | type=button | Use type=submit deliberately; ref targets HTMLButtonElement. |
414
+
415
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
416
+
417
+ ### Purpose and alternatives
418
+
419
+ Use for an application action. Use ExternalLink or a styled anchor for navigation; a button that looks like a link still has button semantics.
420
+
421
+ ### Anatomy and parts
422
+
423
+ Native button contains a label span, optional leadingIcon or loading spinner, and optional trailing icon. Native attributes/handlers and the composed ref remain attached to the button.
424
+
425
+ ### State ownership
426
+
427
+ loading defaults false and disables the button along with disabled. loadingLabel defaults Loading. The component starts no request and never invents success. Variants default primary and sizes default md through buttonClassName.
428
+
429
+ ### Native forms and reset
430
+
431
+ Default type is button. Set submit/reset explicitly, and use native name/value/form when appropriate. The application owns save validation, pending guards and outcome messages.
432
+
433
+ ### Ref target
434
+
435
+ Forwarded ref targets HTMLButtonElement in React 18/19. Render through React; the ref-enabled export is not an ordinary callable function.
436
+
437
+ ### CSS and tokens
438
+
439
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
440
+
441
+ ### Loading, errors and long content
442
+
443
+ Do not put nested controls inside the label or icon slots. Check long labels and narrow rows, show a truthful pending label, and retain failure recovery beside the task.
444
+
445
+ ### RTL and localization
446
+
447
+ Translate children/loadingLabel and ensure icons are decorative or separately named. Button labels are not translated by a global provider; verify RTL icon order in the composition.
448
+
449
+ ### Keyboard and focus
450
+
451
+ Native Tab focus and Enter/Space activation. Disabled or loading buttons cannot activate.
452
+
453
+ ### Limits and evidence
454
+
455
+ No polymorphic as prop or routing integration. Use a styled native anchor or the pinned Next Link recipe for navigation.
456
+
457
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
458
+
459
+ [Report Button 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Button&version=0.6.3) using the [public reproduction](examples/reproduction).
460
+
461
+ ## Card
462
+
463
+ A semantic article container with optional slots and three visual tones.
464
+
465
+ ### Import and runnable source
466
+
467
+ `import { Card } from "@abuzareal/contour-ui";`
468
+
469
+ [Complete content TSX example](examples/catalogue/content.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
470
+
471
+ ### Props and explicit defaults
472
+
473
+ | Prop | Type | Default | Responsibility |
474
+ | --- | --- | --- | --- |
475
+ | title / children | string / ReactNode | Title required; body omitted | Fit the fixed h3 into your hierarchy. |
476
+ | eyebrow / footer / icon | string / ReactNode / ReactNode | Omitted | Use meaningful content and independently labelled actions. |
477
+ | tone / interactive | surface \| ink \| acid / boolean | surface / false | Hover appearance does not add keyboard or navigation semantics. |
478
+
479
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
480
+
481
+ ### Purpose and alternatives
482
+
483
+ Use to group related content. interactive adds hover styling only; compose real anchors/buttons for actions instead of making the article behave like a control.
484
+
485
+ ### Anatomy and parts
486
+
487
+ Article contains optional eyebrow/icon row, fixed h3 title, optional body and footer. Children/footer are content slots, not implicit links.
488
+
489
+ ### State ownership
490
+
491
+ Pure display; tone defaults surface and interactive false. No selection, expansion or request state is stored.
492
+
493
+ ### Native forms and reset
494
+
495
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
496
+
497
+ ### Ref target
498
+
499
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
500
+
501
+ ### CSS and tokens
502
+
503
+ Use .contour-card, tone hooks and slot hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
504
+
505
+ ### Loading, errors and long content
506
+
507
+ Keep long body/footer/actions readable in both themes; handle loading/errors with actual content states. A lift effect is not a focus/activation contract.
508
+
509
+ ### RTL and localization
510
+
511
+ Translate all authored text and preserve heading order; slots may contain localized content and native controls.
512
+
513
+ ### Keyboard and focus
514
+
515
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
516
+
517
+ ### Limits and evidence
518
+
519
+ No href/onClick/root native props, selected state or forwarded ref. Do not nest conflicting controls in an artificial full-card hit area.
520
+
521
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
522
+
523
+ [Report Card 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Card&version=0.6.3) using the [public reproduction](examples/reproduction).
524
+
525
+ ## Checkbox
526
+
527
+ A labelled native checkbox with optional description, error and an indeterminate appearance.
528
+
529
+ ### Import and runnable source
530
+
531
+ `import { Checkbox } from "@abuzareal/contour-ui";`
532
+
533
+ [Complete choices TSX example](examples/catalogue/choices.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
534
+
535
+ ### Props and explicit defaults
536
+
537
+ | Prop | Type | Default | Responsibility |
538
+ | --- | --- | --- | --- |
539
+ | label | string | Required | Use a clear action or setting name. |
540
+ | checked / defaultChecked / onChange | Native input props | Uncontrolled when checked is omitted | Read event.currentTarget.checked. Use one state-ownership model. |
541
+ | name / value / form | Native input props | Native defaults | Checked controls contribute to FormData. The application owns validation and submission. |
542
+ | description / error | string | Omitted | Use error for the installed component's linked validation message. |
543
+ | indeterminate | boolean | false | Set the mixed appearance explicitly; it does not choose child values or replace checked. |
544
+ | disabled / required | boolean | false | Native disabled and required behavior. Disable only when the action is unavailable. |
545
+
546
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
547
+
548
+ ### Purpose and alternatives
549
+
550
+ Use for an independent binary choice or multi-selection. Use RadioGroup for exactly one option, or Switch for an immediately applicable setting.
551
+
552
+ ### Anatomy and parts
553
+
554
+ Label wraps a native checkbox with a visual mark and text. Description/error IDs merge with caller aria-describedby. Caller id is retained.
555
+
556
+ ### State ownership
557
+
558
+ checked/onChange is controlled; defaultChecked is uncontrolled. indeterminate defaults false and does not calculate a mixed selection or replace checked.
559
+
560
+ ### Native forms and reset
561
+
562
+ Checked, enabled, named controls submit value (native default on). Unchecked controls are omitted. required uses native validity. Reset restores defaultChecked; a controlled owner changes its own state explicitly; the library restores the parent-controlled value after reset.
563
+
564
+ ### Ref target
565
+
566
+ Forwarded ref targets HTMLInputElement for focus and form controllers.
567
+
568
+ ### CSS and tokens
569
+
570
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
571
+
572
+ ### Loading, errors and long content
573
+
574
+ Disabled controls cannot activate. Keep long descriptions readable; display business errors with error and retain values on service failure. Indeterminate and disabled together still need an understandable label.
575
+
576
+ ### RTL and localization
577
+
578
+ Translate the label, description and error. Native checkbox interaction follows the browser; check RTL order and long translations in the application.
579
+
580
+ ### Keyboard and focus
581
+
582
+ Tab focuses the checkbox; Space toggles it. Its visible label also activates the control. A disabled checkbox is not keyboard-focusable.
583
+
584
+ ### Limits and evidence
585
+
586
+ Native input refs and caller id are supported. Caller aria-describedby is merged with description/error IDs. Checked named controls submit; unchecked/disabled controls are omitted. Native reset restores defaults; controlled values stay parent-owned until the application resets state. Indeterminate does not calculate mixed selection or replace checked.
587
+
588
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
589
+
590
+ [Report Checkbox 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Checkbox&version=0.6.3) using the [public reproduction](examples/reproduction).
591
+
592
+ ## Combobox
593
+
594
+ Searchable allowed-value selection with native submission, reset and independent query state.
595
+
596
+ ### Import and runnable source
597
+
598
+ `import { Combobox } from "@abuzareal/contour-ui";`
599
+
600
+ [Complete selection TSX example](examples/catalogue/combobox.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
601
+
602
+ ### Props and explicit defaults
603
+
604
+ | Prop | Type | Default | Responsibility |
605
+ | --- | --- | --- | --- |
606
+ | label / options | string / readonly ComboboxOption[] | Required | Options use unique value/label records; disabled is optional. |
607
+ | value / defaultValue / onValueChange | string \| null / callback | Uncontrolled when value is omitted | The selection is separate from inputValue/onInputValueChange query state. |
608
+ | name / form / required / disabled | Native form ownership | Optional | Submit the selected value, not arbitrary typed text. |
609
+ | loading / searchError / onRetry | boolean / string / callback | Optional | Application-owned fetching and recovery. |
610
+ | ref | React.Ref<HTMLInputElement> | Omitted | Focus the visible input. |
611
+
612
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
613
+
614
+ ### Purpose and alternatives
615
+
616
+ Use for searchable allowed-value selection. Use TextField for free text or SelectField when native selection is enough. Multi-select and custom values are not supported.
617
+
618
+ ### Anatomy and parts
619
+
620
+ Label, visible input/trigger, hidden submitted value and labelled listbox/options. inputProps/rootProps/popupProps target parts. Portal geometry is shared with floating layers; no popup focus trap is used.
621
+
622
+ ### State ownership
623
+
624
+ Selected value, query and open state have separate controlled/default APIs. A query is not a selected value. Missing selected options retain explicit missing-value behavior; disabled options cannot be newly chosen.
625
+
626
+ ### Native forms and reset
627
+
628
+ name/form submit the selected allowed value. required validates selection, not typed text. Native reset restores default selection/query while controlled owners explicitly reset their own state; use the forms reference for exact semantics.
629
+
630
+ ### Ref target
631
+
632
+ Forwarded ref targets the visible HTMLInputElement. The hidden value is not the focus target.
633
+
634
+ ### CSS and tokens
635
+
636
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
637
+
638
+ ### Loading, errors and long content
639
+
640
+ loading/searchError/onRetry/emptyText describe application fetching; filteredOptions opts into external filtering. Debounce, abort and stale-result protection live in the async recipe. Open-state automated axe passes in 0.6.1; manual AT review remains pending.
641
+
642
+ ### RTL and localization
643
+
644
+ Translate label, loadingText, emptyText, retryLabel, triggerLabel and missingValueText. Test RTL and long options; search matching and remote result ordering remain your responsibility.
645
+
646
+ ### Keyboard and focus
647
+
648
+ Arrow keys navigate enabled options; Enter selects. Escape dismisses the deepest open layer. Tab closes without consuming normal focus navigation. Query and selected value are separate.
649
+
650
+ ### Limits and evidence
651
+
652
+ Single allowed value only; no free text, multi-select or virtualized list. Remote fetching/filtering is application-owned. Manual VoiceOver/NVDA review remains pending.
653
+
654
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
655
+
656
+ [Report Combobox 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Combobox&version=0.6.3) using the [public reproduction](examples/reproduction).
657
+
658
+ ## CountUp
659
+
660
+ A decorative one-time numeric count with a static accessible final value.
661
+
662
+ ### Import and runnable source
663
+
664
+ `import { CountUp } from "@abuzareal/contour-ui";`
665
+
666
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
667
+
668
+ ### Props and explicit defaults
669
+
670
+ | Prop | Type | Default | Responsibility |
671
+ | --- | --- | --- | --- |
672
+ | to | number | Required | Supply a finite meaningful final value; no validation is added. |
673
+ | duration / digits / suffix | number / number / string | 1400 / 0 / empty string | Milliseconds, minimum digit padding and suffix. |
674
+ | formatValue | (value:number)=>string | Omitted | Formats both visual and accessible values; replaces padding/suffix formatting. |
675
+
676
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
677
+
678
+ ### Purpose and alternatives
679
+
680
+ Use only when animation adds useful emphasis. Do not present illustrative counts as live measurements or repeatedly announce each animation frame.
681
+
682
+ ### Anatomy and parts
683
+
684
+ Root span contains aria-hidden animated text and a visually hidden final value. An observer activates requestAnimationFrame; cleanup disconnects/cancels.
685
+
686
+ ### State ownership
687
+
688
+ to is caller data; duration defaults to 1400 ms, digits0, suffix empty. Reduced/paused motion, nonpositive duration or missing observer goes straight to final value. Custom formatValue replaces default padding/suffix output.
689
+
690
+ ### Native forms and reset
691
+
692
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
693
+
694
+ ### Ref target
695
+
696
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
697
+
698
+ ### CSS and tokens
699
+
700
+ Use .contour-count-up and visually-hidden final value with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
701
+
702
+ ### Loading, errors and long content
703
+
704
+ Label source/units/timestamp outside the count. Test zero/negative values, long formatted strings, missing data and reduced motion; never fabricate a known value to make animation work.
705
+
706
+ ### RTL and localization
707
+
708
+ Use formatValue for localized numerals/units; default String/padStart is not locale-aware. Supply an adjacent meaningful quantity label.
709
+
710
+ ### Keyboard and focus
711
+
712
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
713
+
714
+ ### Limits and evidence
715
+
716
+ Decorative integer-rounded animation, not streaming data, locale parsing or an alert/live region. No forwarded ref/reset API; prop changes can start a new effect.
717
+
718
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
719
+
720
+ [Report CountUp 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=CountUp&version=0.6.3) using the [public reproduction](examples/reproduction).
721
+
722
+ ## DataTable
723
+
724
+ A semantic table with bounded local sorting of scalar records.
725
+
726
+ ### Import and runnable source
727
+
728
+ `import { DataTable } from "@abuzareal/contour-ui";`
729
+
730
+ [Complete data-table TSX example](examples/catalogue/data-table.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
731
+
732
+ ### Props and explicit defaults
733
+
734
+ | Prop | Type | Default | Responsibility |
735
+ | --- | --- | --- | --- |
736
+ | caption | string | Required | Accessible caption is visually hidden by the Table composition. |
737
+ | columns | TableColumn<Row>[] | Required | key/header plus optional align/sortable/compare/render; headers must be meaningful. |
738
+ | rows / rowKey | Row[] / keyof Row & string | Required | Unique stable row keys; rows extend Record<string,string \| number>. |
739
+
740
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
741
+
742
+ ### Purpose and alternatives
743
+
744
+ Use for small local scalar datasets. Use Table plus a mature engine for controlled remote query/page/sort; neither this component nor its row count is an enterprise grid.
745
+
746
+ ### Anatomy and parts
747
+
748
+ Table supplies a caption and scroll wrapper; native thead/tbody/tr/th/td render columns/rows. Sortable headers contain buttons and aria-sort.
749
+
750
+ ### State ownership
751
+
752
+ Rows/columns are application data; local sort starts null and toggles ascending/descending. A compare function overrides scalar comparison. Sorting copies rows instead of mutating the input.
753
+
754
+ ### Native forms and reset
755
+
756
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
757
+
758
+ ### Ref target
759
+
760
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
761
+
762
+ ### CSS and tokens
763
+
764
+ Use .contour-data-table wrapper/table and native header controls with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
765
+
766
+ ### Loading, errors and long content
767
+
768
+ Own loading, empty dataset, no matches and service/permission errors outside the table. Keep stable row identity, long-cell scroll and a text/table data equivalent rather than masking errors as empty success.
769
+
770
+ ### RTL and localization
771
+
772
+ Translate captions/headers/cells. Supply compare for locale-aware order; built-in scalar comparison is not a locale collation service.
773
+
774
+ ### Keyboard and focus
775
+
776
+ Native header buttons activate sorting with Enter/Space. The table uses semantic reading navigation, not grid arrow-key focus or cell editing.
777
+
778
+ ### Limits and evidence
779
+
780
+ Internal local sorting only; no controlled sorting, pagination, selection, virtualization, requests, built-in empty/error state or forwarded table ref. Object/date/nested records are outside its scalar generic contract.
781
+
782
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
783
+
784
+ [Report DataTable 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=DataTable&version=0.6.3) using the [public reproduction](examples/reproduction).
785
+
786
+ ## DepthButton
787
+
788
+ A native action button with CSS depth and a pressed face.
789
+
790
+ ### Import and runnable source
791
+
792
+ `import { DepthButton } from "@abuzareal/contour-ui";`
793
+
794
+ [Complete buttons TSX example](examples/catalogue/buttons.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
795
+
796
+ ### Props and explicit defaults
797
+
798
+ | Prop | Type | Default | Responsibility |
799
+ | --- | --- | --- | --- |
800
+ | children | ReactNode | Required | Provide an understandable accessible action name. |
801
+ | type | Native button type | button | Opt into submit only deliberately. |
802
+ | disabled / onClick / className | Native button props | Native defaults | Caller owns pending/error and disabled policy. |
803
+
804
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
805
+
806
+ ### Purpose and alternatives
807
+
808
+ Use for an intentional prominent action, preserving the same native activation contract as a button. Use an anchor for navigation; CSS depth needs no Three.js.
809
+
810
+ ### Anatomy and parts
811
+
812
+ Native button contains a visual face span. className appends to public root hooks; children supply the action name.
813
+
814
+ ### State ownership
815
+
816
+ No request/loading state. Native type defaults button; disabled and event handlers remain native caller props.
817
+
818
+ ### Native forms and reset
819
+
820
+ Native type=button avoids accidental submit; type=submit/name/value/form work when explicitly supplied. Disabled controls follow native successful-control rules.
821
+
822
+ ### Ref target
823
+
824
+ Forwarded HTMLButtonElement, including focus access.
825
+
826
+ ### CSS and tokens
827
+
828
+ Use .contour-depth-button and .contour-depth-button-face with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
829
+
830
+ ### Loading, errors and long content
831
+
832
+ Keep long labels readable, including translated pending/error messages nearby. Use native disabled and adjacent request feedback; no built-in loader is promised.
833
+
834
+ ### RTL and localization
835
+
836
+ Translate action text. Verify RTL and long labels; geometric depth is visual rather than a directional navigation cue.
837
+
838
+ ### Keyboard and focus
839
+
840
+ Enter/Space activate the native button; disabled prevents interaction. Keep a visible focus indication and sufficient target size.
841
+
842
+ ### Limits and evidence
843
+
844
+ No Button variant/size/loading API or polymorphic navigation mode. Decorative depth must not displace or clip the focused hit target.
845
+
846
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
847
+
848
+ [Report DepthButton 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=DepthButton&version=0.6.3) using the [public reproduction](examples/reproduction).
849
+
850
+ ## Dialog
851
+
852
+ A controlled native modal or side drawer with focus return and background scroll locking.
853
+
854
+ ### Import and runnable source
855
+
856
+ `import { Dialog } from "@abuzareal/contour-ui";`
857
+
858
+ [Complete dialogs TSX example](examples/catalogue/dialogs.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
859
+
860
+ ### Props and explicit defaults
861
+
862
+ | Prop | Type | Default | Responsibility |
863
+ | --- | --- | --- | --- |
864
+ | open | boolean | Required | Your application owns visibility. |
865
+ | onClose | () => void | Required | Update open to false on Escape, close button or backdrop dismissal. |
866
+ | title / description | string | Title required | Name the task and optionally explain its scope. |
867
+ | children / footer | ReactNode | Children required; footer optional | Keep actions, pending and error states inside the modal. |
868
+ | placement | "center" \| "left" \| "right" | "center" | Choose a modal or drawer composition. |
869
+
870
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
871
+
872
+ ### Purpose and alternatives
873
+
874
+ Use for a task that needs modal focus confinement; placement left/right is the drawer composition. Use Popover for nonmodal supplementary content.
875
+
876
+ ### Anatomy and parts
877
+
878
+ Native dialog contains panel, heading/description, close button, scrollable body and optional footer. panelProps/bodyProps/footerProps/closeButtonProps customize typed parts; preserve owned semantics.
879
+
880
+ ### State ownership
881
+
882
+ open/onClose is controlled. Escape, close button and backdrop request closure; the application changes open. initialFocus selects a mounted descendant; onOpenAutoFocus can cancel that explicit override, not native showModal autofocus.
883
+
884
+ ### Native forms and reset
885
+
886
+ Dialog is not a form. Compose a form or use external form attributes for footer actions. Pending, validation, unsaved changes and destructive confirmation remain application-owned.
887
+
888
+ ### Ref target
889
+
890
+ Forwarded ref targets HTMLDialogElement. Part props can expose their native refs. There is no Dialog onCloseAutoFocus prop.
891
+
892
+ ### CSS and tokens
893
+
894
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
895
+
896
+ ### Loading, errors and long content
897
+
898
+ Native top-layer focus confinement and nested background-scroll locks are supported. Portalled child layers stay inside the modal. Check short screens, long content and removed openers; keep a workflow focus fallback if the opener is removed.
899
+
900
+ ### RTL and localization
901
+
902
+ Translate title, description, actions and closeButtonProps accessible label. Placement is physical left/right; select it deliberately for RTL. Verify your complete keyboard/AT flow.
903
+
904
+ ### Keyboard and focus
905
+
906
+ Focus enters the native modal; Tab remains within it. Escape requests onClose. Focus returns to the opener when the modal closes.
907
+
908
+ ### Limits and evidence
909
+
910
+ Does not confirm business operations, fetch content or prevent dismissal of unsaved data automatically. Browser native-dialog support is required; test your complete composition and nested overlays.
911
+
912
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
913
+
914
+ [Report Dialog 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Dialog&version=0.6.3) using the [public reproduction](examples/reproduction).
915
+
916
+ ## Disclosure
917
+
918
+ Native details/summary with an expandable body and decorative plus icon.
919
+
920
+ ### Import and runnable source
921
+
922
+ `import { Disclosure } from "@abuzareal/contour-ui";`
923
+
924
+ [Complete content TSX example](examples/catalogue/content.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
925
+
926
+ ### Props and explicit defaults
927
+
928
+ | Prop | Type | Default | Responsibility |
929
+ | --- | --- | --- | --- |
930
+ | className / summary / children | string / ReactNode / ReactNode | Required | Keep summary a clear textual disclosure control. |
931
+ | defaultOpen | boolean | false | Initial native open value; not a controlled state API. |
932
+ | iconSize / iconStrokeWidth | number | 23 / 1.25 | Decorative icon geometry. |
933
+
934
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
935
+
936
+ ### Purpose and alternatives
937
+
938
+ Use for supplementary content a user can expand. Do not hide essential instructions or place competing interactive controls inside summary.
939
+
940
+ ### Anatomy and parts
941
+
942
+ Native details contains summary, decorative icon and children. Caller className is required; ccx adds public hooks.
943
+
944
+ ### State ownership
945
+
946
+ defaultOpen defaults false and is passed to native details.open at render. Browser owns user toggling; no controlled open/onToggle API is exposed.
947
+
948
+ ### Native forms and reset
949
+
950
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
951
+
952
+ ### Ref target
953
+
954
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
955
+
956
+ ### CSS and tokens
957
+
958
+ Use .contour-disclosure and native [open] with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
959
+
960
+ ### Loading, errors and long content
961
+
962
+ Keep long summary/body content readable. Applications own loading/error/retry and any state persistence; repeated rerender should not be treated as a controlled accordion contract.
963
+
964
+ ### RTL and localization
965
+
966
+ Translate summary/body. Browser supplies native summary semantics; preserve logical reading order and test long RTL content.
967
+
968
+ ### Keyboard and focus
969
+
970
+ Native summary toggles with Enter/Space and participates in Tab order; expanded children retain native behavior. No extra button is needed inside summary.
971
+
972
+ ### Limits and evidence
973
+
974
+ No root ref or forwarded native props, async request model, controlled open callback or accordion single-open coordination.
975
+
976
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
977
+
978
+ [Report Disclosure 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Disclosure&version=0.6.3) using the [public reproduction](examples/reproduction).
979
+
980
+ ## Divider
981
+
982
+ A native horizontal rule, or a labelled separator presentation.
983
+
984
+ ### Import and runnable source
985
+
986
+ `import { Divider } from "@abuzareal/contour-ui";`
987
+
988
+ [Complete content TSX example](examples/catalogue/content.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
989
+
990
+ ### Props and explicit defaults
991
+
992
+ | Prop | Type | Default | Responsibility |
993
+ | --- | --- | --- | --- |
994
+ | label | string | Omitted | Optional centered visible text; not a heading. |
995
+
996
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
997
+
998
+ ### Purpose and alternatives
999
+
1000
+ Use to separate related content areas. Do not replace headings/navigation or use a visual rule as an interactive resize handle.
1001
+
1002
+ ### Anatomy and parts
1003
+
1004
+ Without label renders hr; with label renders role=separator containing label text.
1005
+
1006
+ ### State ownership
1007
+
1008
+ Pure presentation; omitted/empty label chooses the native hr variant.
1009
+
1010
+ ### Native forms and reset
1011
+
1012
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1013
+
1014
+ ### Ref target
1015
+
1016
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1017
+
1018
+ ### CSS and tokens
1019
+
1020
+ Use .contour-divider and labelled hook with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1021
+
1022
+ ### Loading, errors and long content
1023
+
1024
+ Check contrast, narrow/long labels and surrounding spacing. Loading/error/form state is not applicable to a separator.
1025
+
1026
+ ### RTL and localization
1027
+
1028
+ Translate label and preserve reading order; the labelled variant does not create a section heading.
1029
+
1030
+ ### Keyboard and focus
1031
+
1032
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1033
+
1034
+ ### Limits and evidence
1035
+
1036
+ No vertical/orientation control, resize behavior, arbitrary root attributes or forwarded ref.
1037
+
1038
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1039
+
1040
+ [Report Divider 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Divider&version=0.6.3) using the [public reproduction](examples/reproduction).
1041
+
1042
+ ## DropdownMenu
1043
+
1044
+ A button-triggered local action menu with focus movement and dismissal.
1045
+
1046
+ ### Import and runnable source
1047
+
1048
+ `import { DropdownMenu } from "@abuzareal/contour-ui";`
1049
+
1050
+ [Complete floating TSX example](examples/catalogue/floating.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1051
+
1052
+ ### Props and explicit defaults
1053
+
1054
+ | Prop | Type | Default | Responsibility |
1055
+ | --- | --- | --- | --- |
1056
+ | label | string | Required | Accessible trigger and menu name. |
1057
+ | items | {id?, label, onSelect, icon?, danger?, disabled?}[] | Required | Supply stable ids when labels can repeat or change. Disabled items cannot be selected; decorative icons need aria-hidden. |
1058
+ | align | "start" \| "center" \| "end" | "start" | Align against the trigger within its container. |
1059
+ | open / defaultOpen / onOpenChange | boolean / boolean / (open: boolean) => void | Uncontrolled; defaultOpen is false | Provide open and update it from onOpenChange for controlled visibility. defaultOpen is only the initial uncontrolled state. |
1060
+
1061
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1062
+
1063
+ ### Purpose and alternatives
1064
+
1065
+ Use for a short list of actions. Use SelectField/Combobox for a submitted value and links for navigation semantics.
1066
+
1067
+ ### Anatomy and parts
1068
+
1069
+ Wrapper, native trigger button and portalled menu/items. triggerProps/panelProps and renderTrigger customize typed parts; render exactly one ref-forwarding button with supplied props.
1070
+
1071
+ ### State ownership
1072
+
1073
+ open/onOpenChange is controlled or defaultOpen initializes local state. Stable item IDs and disabled entries are supported. Selection invokes your callback and requests closure.
1074
+
1075
+ ### Native forms and reset
1076
+
1077
+ Default trigger is type=button, not a selection field. Menu actions perform application commands; no named form value or reset is supplied.
1078
+
1079
+ ### Ref target
1080
+
1081
+ Root ref targets the div; triggerProps.ref targets its button and panelProps.ref its panel. Do not treat the root as the trigger.
1082
+
1083
+ ### CSS and tokens
1084
+
1085
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
1086
+
1087
+ ### Loading, errors and long content
1088
+
1089
+ Portal defaults true with collision-aware placement and native-dialog containment. First Escape dismisses the deepest layer; Tab dismisses without consuming navigation. No general submenus. Changing portal containers can remount child state.
1090
+
1091
+ ### RTL and localization
1092
+
1093
+ Translate label/actions and use stable IDs rather than labels as identity. Alignment is logical in RTL; typeahead searches labels. Test long labels at the viewport edge.
1094
+
1095
+ ### Keyboard and focus
1096
+
1097
+ Enter/Space open the trigger; ArrowDown/ArrowUp open at the first/last enabled item. Arrow keys and Home/End skip disabled items. Typing searches enabled labels. Escape dismisses with focus return; Tab dismisses and continues navigation.
1098
+
1099
+ ### Limits and evidence
1100
+
1101
+ Portal positioning, collision handling and native-dialog integration are supported. triggerProps targets the native button; renderTrigger composes one ref-forwarding button. There is no general submenu contract. Keep controlled or uncontrolled visibility consistent and verify focus return in the complete composition.
1102
+
1103
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1104
+
1105
+ [Report DropdownMenu 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=DropdownMenu&version=0.6.3) using the [public reproduction](examples/reproduction).
1106
+
1107
+ ## EmptyState
1108
+
1109
+ An icon, heading, explanation and optional recovery action for a labelled empty situation.
1110
+
1111
+ ### Import and runnable source
1112
+
1113
+ `import { EmptyState } from "@abuzareal/contour-ui";`
1114
+
1115
+ [Complete content TSX example](examples/catalogue/content.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1116
+
1117
+ ### Props and explicit defaults
1118
+
1119
+ | Prop | Type | Default | Responsibility |
1120
+ | --- | --- | --- | --- |
1121
+ | icon / title / message | ReactNode / string / string | Required | State the actual situation and useful next step. |
1122
+ | action | ReactNode | Omitted | Use a labelled native button/anchor with application behavior. |
1123
+
1124
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1125
+
1126
+ ### Purpose and alternatives
1127
+
1128
+ Use to explain a genuinely empty result, not to hide a failed request. Differentiate no saved data, no filter matches, permissions and service failure in parent state.
1129
+
1130
+ ### Anatomy and parts
1131
+
1132
+ Decorative icon span, h3 title, message paragraph and optional action slot; no implicit live-region or request behavior.
1133
+
1134
+ ### State ownership
1135
+
1136
+ Pure display. Caller decides when to show each state and owns retry/create/filter-reset actions.
1137
+
1138
+ ### Native forms and reset
1139
+
1140
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1141
+
1142
+ ### Ref target
1143
+
1144
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1145
+
1146
+ ### CSS and tokens
1147
+
1148
+ Use .contour-empty-state and semantic text/action tokens with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1149
+
1150
+ ### Loading, errors and long content
1151
+
1152
+ Do not claim a successful response when permissions/network failed. Keep long copy/actions readable; avoid a dead primary action.
1153
+
1154
+ ### RTL and localization
1155
+
1156
+ Translate title/message/action and verify heading order/RTL. Decorative icon supplies no accessible name; visible text carries meaning.
1157
+
1158
+ ### Keyboard and focus
1159
+
1160
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1161
+
1162
+ ### Limits and evidence
1163
+
1164
+ No automatic loading/error classification, alert role, title-level prop, forwarding ref or data service. Its fixed h3 must fit the surrounding heading hierarchy.
1165
+
1166
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1167
+
1168
+ [Report EmptyState 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=EmptyState&version=0.6.3) using the [public reproduction](examples/reproduction).
1169
+
1170
+ ## ExternalLink
1171
+
1172
+ A safe native anchor that opens an external destination in a new tab.
1173
+
1174
+ ### Import and runnable source
1175
+
1176
+ `import { ExternalLink } from "@abuzareal/contour-ui";`
1177
+
1178
+ [Complete buttons TSX example](examples/catalogue/buttons.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1179
+
1180
+ ### Props and explicit defaults
1181
+
1182
+ | Prop | Type | Default | Responsibility |
1183
+ | --- | --- | --- | --- |
1184
+ | href / children | Native anchor props | Omitted | Use an allowed destination and a clear link name. |
1185
+ | className / onClick / aria-label | Native anchor props | Native defaults | Preserve modified clicks and label icon-only links. |
1186
+
1187
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1188
+
1189
+ ### Purpose and alternatives
1190
+
1191
+ Use for off-site navigation where a new tab is appropriate. Use native anchors/router links for in-app destinations; do not implement navigation with a button.
1192
+
1193
+ ### Anatomy and parts
1194
+
1195
+ Forwarded native anchor retains caller attributes/children. safeHref validates href; target=_blank and rel=noopener noreferrer are owned.
1196
+
1197
+ ### State ownership
1198
+
1199
+ No selection/request state. Destination and accessible name are application content; rejected URLs do not become a working link.
1200
+
1201
+ ### Native forms and reset
1202
+
1203
+ Navigation is not a successful form control or submit button; no native reset contract.
1204
+
1205
+ ### Ref target
1206
+
1207
+ Forwarded HTMLAnchorElement for focus and compatible semantic link integrations.
1208
+
1209
+ ### CSS and tokens
1210
+
1211
+ Use Caller anchor class plus semantic link/focus tokens with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1212
+
1213
+ ### Loading, errors and long content
1214
+
1215
+ Handle missing/unsafe destinations by presenting useful text or another valid action. Do not imply a disabled or loading-link prop exists.
1216
+
1217
+ ### RTL and localization
1218
+
1219
+ Translate the link name/new-tab explanation and test mixed-direction URLs. Icon children need an accessible name on the link.
1220
+
1221
+ ### Keyboard and focus
1222
+
1223
+ Native anchor Enter and modified/middle clicks retain browser behavior. Explain new-tab behavior when it matters; no custom keyboard interception.
1224
+
1225
+ ### Limits and evidence
1226
+
1227
+ target/rel are deliberately excluded from caller props. URL validation is not a server authorization/security boundary or destination availability check.
1228
+
1229
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1230
+
1231
+ [Report ExternalLink 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=ExternalLink&version=0.6.3) using the [public reproduction](examples/reproduction).
1232
+
1233
+ ## Field
1234
+
1235
+ A label/supporting-text frame for an application-owned native control.
1236
+
1237
+ ### Import and runnable source
1238
+
1239
+ `import { Field } from "@abuzareal/contour-ui";`
1240
+
1241
+ [Complete field TSX example](examples/catalogue/field.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1242
+
1243
+ ### Props and explicit defaults
1244
+
1245
+ | Prop | Type | Default | Responsibility |
1246
+ | --- | --- | --- | --- |
1247
+ | id / label / children | string / string / ReactNode | Required | Give the actual child the same id; children own native attributes. |
1248
+ | hint / error / counter | string | Omitted | Connect descriptions with fieldDescribedBy; counter is caller-provided text. |
1249
+ | required / hideLabel / disabled | boolean | Omitted | These affect the frame; set required/disabled on the child too. |
1250
+
1251
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1252
+
1253
+ ### Purpose and alternatives
1254
+
1255
+ Use when composing a control that TextField/SelectField do not already cover. Prefer those wrappers for their existing native wiring; Field does not validate or clone its child.
1256
+
1257
+ ### Anatomy and parts
1258
+
1259
+ Frame renders label htmlFor=id, optional required marker, child slot and footer. Label ID is id-label; footer exposes id-hint or id-error and optional counter.
1260
+
1261
+ ### State ownership
1262
+
1263
+ Pure presentation. Parent owns value, errors, counters and any hidden-label/disabled appearance. Error takes precedence over hint.
1264
+
1265
+ ### Native forms and reset
1266
+
1267
+ The frame does not submit. Give the child id/name/form/required/disabled and native reset semantics explicitly; use fieldDescribedBy and aria-invalid for the child.
1268
+
1269
+ ### Ref target
1270
+
1271
+ Attach a ref to the actual native child; Field forwards none.
1272
+
1273
+ ### CSS and tokens
1274
+
1275
+ Use .contour-field, .contour-field-label and footer states with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1276
+
1277
+ ### Loading, errors and long content
1278
+
1279
+ Business/server errors and pending states are application-owned. Test long hints/errors/counters and empty content; do not rely on the required asterisk as validation.
1280
+
1281
+ ### RTL and localization
1282
+
1283
+ Translate label/hint/error/counter. Use suitable native inputMode/autoComplete/dir on the actual control and sensible localized count wording.
1284
+
1285
+ ### Keyboard and focus
1286
+
1287
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1288
+
1289
+ ### Limits and evidence
1290
+
1291
+ No automatic child aria-invalid/aria-describedby/required/disabled wiring, no input state or forwarded ref. hideLabel hides visually rather than removing the accessible name.
1292
+
1293
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1294
+
1295
+ [Report Field 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Field&version=0.6.3) using the [public reproduction](examples/reproduction).
1296
+
1297
+ ## FlipCard
1298
+
1299
+ A two-face CSS card with an explicit accessible toggle.
1300
+
1301
+ ### Import and runnable source
1302
+
1303
+ `import { FlipCard } from "@abuzareal/contour-ui";`
1304
+
1305
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1306
+
1307
+ ### Props and explicit defaults
1308
+
1309
+ | Prop | Type | Default | Responsibility |
1310
+ | --- | --- | --- | --- |
1311
+ | front / back | ReactNode | Required | Use meaningful face content and valid focusable children. |
1312
+ | label | string | Required | A clear toggle name; aria-pressed exposes the flipped state. |
1313
+
1314
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1315
+
1316
+ ### Purpose and alternatives
1317
+
1318
+ Use for supplementary paired content, keeping essential information discoverable. Do not require hover or hide critical form instructions on the reverse.
1319
+
1320
+ ### Anatomy and parts
1321
+
1322
+ Front/back faces sit inside a flipped-state card; a separate native toggle remains stationary. Inactive face receives aria-hidden and inert in React18/19-compatible form.
1323
+
1324
+ ### State ownership
1325
+
1326
+ Internal boolean starts front-visible; toggle changes it. No controlled flipped prop or animation engine is exposed.
1327
+
1328
+ ### Native forms and reset
1329
+
1330
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1331
+
1332
+ ### Ref target
1333
+
1334
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1335
+
1336
+ ### CSS and tokens
1337
+
1338
+ Use .contour-flip-card, visible-state and face/toggle hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1339
+
1340
+ ### Loading, errors and long content
1341
+
1342
+ Check long faces, fixed toggle position, reduced motion and inactive face focus/reading exclusion. A flip animation does not prove data loading/success.
1343
+
1344
+ ### RTL and localization
1345
+
1346
+ Translate label/face content and verify RTL reading order. A single label is used for both states with aria-pressed.
1347
+
1348
+ ### Keyboard and focus
1349
+
1350
+ Tab reaches the native toggle; Enter/Space flips. Hidden-face interactive content is inert. Caller should keep focus on the stable toggle rather than programmatically focus an inactive face.
1351
+
1352
+ ### Limits and evidence
1353
+
1354
+ No controlled flip/ref/hover-only contract. React18/19 inert behavior is deliberately supported; manual screen-reader review remains separate.
1355
+
1356
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1357
+
1358
+ [Report FlipCard 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=FlipCard&version=0.6.3) using the [public reproduction](examples/reproduction).
1359
+
1360
+ ## GitHubIcon
1361
+
1362
+ A decorative GitHub brand SVG for a separately labelled link.
1363
+
1364
+ ### Import and runnable source
1365
+
1366
+ `import { GitHubIcon } from "@abuzareal/contour-ui";`
1367
+
1368
+ [Complete identity TSX example](examples/catalogue/identity.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1369
+
1370
+ ### Props and explicit defaults
1371
+
1372
+ | Prop | Type | Default | Responsibility |
1373
+ | --- | --- | --- | --- |
1374
+ | size | number | 17 | Caller chooses sensible finite SVG dimensions. |
1375
+
1376
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1377
+
1378
+ ### Purpose and alternatives
1379
+
1380
+ Use only to identify the GitHub destination. A logo is not a link or accessible name; pair it with a native labelled anchor and appropriate brand attribution.
1381
+
1382
+ ### Anatomy and parts
1383
+
1384
+ Fixed SVG viewBox/path uses currentColor and aria-hidden=true. size sets equal width/height; no link is created.
1385
+
1386
+ ### State ownership
1387
+
1388
+ Pure vector display; size defaults to 17. No interaction/state or network integration.
1389
+
1390
+ ### Native forms and reset
1391
+
1392
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1393
+
1394
+ ### Ref target
1395
+
1396
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1397
+
1398
+ ### CSS and tokens
1399
+
1400
+ Use The SVG inherits currentColor from its labelled parent with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1401
+
1402
+ ### Loading, errors and long content
1403
+
1404
+ Keep a suitable link target size/focus indication independent of icon dimensions; test contrast/forced colors and never use logo color alone.
1405
+
1406
+ ### RTL and localization
1407
+
1408
+ The vector is fixed; translate the surrounding link label or explanatory text. The GitHub brand name remains an identity.
1409
+
1410
+ ### Keyboard and focus
1411
+
1412
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1413
+
1414
+ ### Limits and evidence
1415
+
1416
+ No children/title/aria-label/native SVG props/ref, social API request or automatic profile destination. The surrounding link supplies the name.
1417
+
1418
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1419
+
1420
+ [Report GitHubIcon 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=GitHubIcon&version=0.6.3) using the [public reproduction](examples/reproduction).
1421
+
1422
+ ## IconButton
1423
+
1424
+ A native icon-only button with a mandatory accessible label and native ref.
1425
+
1426
+ ### Import and runnable source
1427
+
1428
+ `import { IconButton } from "@abuzareal/contour-ui";`
1429
+
1430
+ [Complete buttons TSX example](examples/catalogue/buttons.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1431
+
1432
+ ### Props and explicit defaults
1433
+
1434
+ | Prop | Type | Default | Responsibility |
1435
+ | --- | --- | --- | --- |
1436
+ | label / children | string / ReactNode | Required | The label supplies the accessible name; children supply the icon. |
1437
+ | variant | outline \| solid \| accent | outline | Visual emphasis. |
1438
+ | size / spin | sm \| md \| lg / boolean | md / false | Spin is optional decorative hover feedback. |
1439
+ | type / title / ref | Native button props and ref | button / label / omitted | Caller title is preserved; the ref targets HTMLButtonElement. |
1440
+
1441
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1442
+
1443
+ ### Purpose and alternatives
1444
+
1445
+ Use for a familiar compact action with a clear accessible label. Prefer Button text for an unfamiliar or consequential action.
1446
+
1447
+ ### Anatomy and parts
1448
+
1449
+ One native circular button contains caller icon children. label owns aria-label; title defaults to label unless caller title is supplied. Native props/ref stay on the button.
1450
+
1451
+ ### State ownership
1452
+
1453
+ variant defaults outline, size md and spin false. Disabled is native. Decorative spin does not indicate pending or successful work.
1454
+
1455
+ ### Native forms and reset
1456
+
1457
+ Default type is button. Use native submit/reset deliberately and keep form validation/application requests outside the component.
1458
+
1459
+ ### Ref target
1460
+
1461
+ Forwarded ref targets HTMLButtonElement. Do not nest a button/anchor inside its children.
1462
+
1463
+ ### CSS and tokens
1464
+
1465
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
1466
+
1467
+ ### Loading, errors and long content
1468
+
1469
+ label is mandatory even when the icon seems obvious. Check target size, disabled contrast and focus in both themes. Essential meaning cannot depend on rotation or hover title.
1470
+
1471
+ ### RTL and localization
1472
+
1473
+ Translate label and optional title. Consider direction-specific icon meaning and preserve a useful name when the visual is mirrored.
1474
+
1475
+ ### Keyboard and focus
1476
+
1477
+ Native button keyboard behavior. The icon's accessible label remains available without a tooltip or hover.
1478
+
1479
+ ### Limits and evidence
1480
+
1481
+ No anchor or arbitrary-element polymorphism. Keep decorative spin separate from essential state.
1482
+
1483
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1484
+
1485
+ [Report IconButton 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=IconButton&version=0.6.3) using the [public reproduction](examples/reproduction).
1486
+
1487
+ ## Kbd
1488
+
1489
+ A native keyboard-key text treatment.
1490
+
1491
+ ### Import and runnable source
1492
+
1493
+ `import { Kbd } from "@abuzareal/contour-ui";`
1494
+
1495
+ [Complete metadata TSX example](examples/catalogue/metadata.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1496
+
1497
+ ### Props and explicit defaults
1498
+
1499
+ | Prop | Type | Default | Responsibility |
1500
+ | --- | --- | --- | --- |
1501
+ | children | ReactNode | Required | Use understandable platform-appropriate key names. |
1502
+
1503
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1504
+
1505
+ ### Purpose and alternatives
1506
+
1507
+ Use to describe an actual shortcut/key. Do not imply that displaying a key registers a shortcut or makes a noninteractive element operable.
1508
+
1509
+ ### Anatomy and parts
1510
+
1511
+ Native kbd wraps caller children with a visual keycap class.
1512
+
1513
+ ### State ownership
1514
+
1515
+ Pure text display, with no key listeners or shortcut registry.
1516
+
1517
+ ### Native forms and reset
1518
+
1519
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1520
+
1521
+ ### Ref target
1522
+
1523
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1524
+
1525
+ ### CSS and tokens
1526
+
1527
+ Use .contour-kbd with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1528
+
1529
+ ### Loading, errors and long content
1530
+
1531
+ Keep chord instructions readable and provide a real keyboard interaction separately; loading/error states do not apply to a key label.
1532
+
1533
+ ### RTL and localization
1534
+
1535
+ Translate key/instruction text and distinguish platform conventions such as Control versus Command. A drawn symbol may need nearby explanation.
1536
+
1537
+ ### Keyboard and focus
1538
+
1539
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1540
+
1541
+ ### Limits and evidence
1542
+
1543
+ No activation, key handling, platform detection, forwarded props or ref.
1544
+
1545
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1546
+
1547
+ [Report Kbd 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Kbd&version=0.6.3) using the [public reproduction](examples/reproduction).
1548
+
1549
+ ## LinkedInIcon
1550
+
1551
+ A decorative LinkedIn brand SVG for a separately labelled link.
1552
+
1553
+ ### Import and runnable source
1554
+
1555
+ `import { LinkedInIcon } from "@abuzareal/contour-ui";`
1556
+
1557
+ [Complete identity TSX example](examples/catalogue/identity.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1558
+
1559
+ ### Props and explicit defaults
1560
+
1561
+ | Prop | Type | Default | Responsibility |
1562
+ | --- | --- | --- | --- |
1563
+ | size | number | 17 | Caller chooses sensible finite SVG dimensions. |
1564
+
1565
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1566
+
1567
+ ### Purpose and alternatives
1568
+
1569
+ Use only to identify the LinkedIn destination. A logo is not a link or accessible name; pair it with a native labelled anchor and appropriate brand attribution.
1570
+
1571
+ ### Anatomy and parts
1572
+
1573
+ Fixed SVG viewBox/path uses currentColor and aria-hidden=true. size sets equal width/height; no link is created.
1574
+
1575
+ ### State ownership
1576
+
1577
+ Pure vector display; size defaults to 17. No interaction/state or network integration.
1578
+
1579
+ ### Native forms and reset
1580
+
1581
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1582
+
1583
+ ### Ref target
1584
+
1585
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1586
+
1587
+ ### CSS and tokens
1588
+
1589
+ Use The SVG inherits currentColor from its labelled parent with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1590
+
1591
+ ### Loading, errors and long content
1592
+
1593
+ Keep a suitable link target size/focus indication independent of icon dimensions; test contrast/forced colors and never use logo color alone.
1594
+
1595
+ ### RTL and localization
1596
+
1597
+ The vector is fixed; translate the surrounding link label or explanatory text. The LinkedIn brand name remains an identity.
1598
+
1599
+ ### Keyboard and focus
1600
+
1601
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1602
+
1603
+ ### Limits and evidence
1604
+
1605
+ No children/title/aria-label/native SVG props/ref, social API request or automatic profile destination. The surrounding link supplies the name.
1606
+
1607
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1608
+
1609
+ [Report LinkedInIcon 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=LinkedInIcon&version=0.6.3) using the [public reproduction](examples/reproduction).
1610
+
1611
+ ## Magnetic
1612
+
1613
+ A CSS pointer-follow wrapper that leaves native child semantics intact.
1614
+
1615
+ ### Import and runnable source
1616
+
1617
+ `import { Magnetic } from "@abuzareal/contour-ui";`
1618
+
1619
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1620
+
1621
+ ### Props and explicit defaults
1622
+
1623
+ | Prop | Type | Default | Responsibility |
1624
+ | --- | --- | --- | --- |
1625
+ | children | ReactNode | Required | Use a real labelled native control when interactive. |
1626
+ | strength | number | 0.35 | Choose a sensible finite fractional displacement. |
1627
+
1628
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1629
+
1630
+ ### Purpose and alternatives
1631
+
1632
+ Use for optional motion around a real control. Do not make essential targets depend on pointer movement or move them so far they become difficult to activate.
1633
+
1634
+ ### Anatomy and parts
1635
+
1636
+ Span wrapper writes a magnet CSS custom property from mouse offset and resets it on pointer leave. Children retain their native semantics.
1637
+
1638
+ ### State ownership
1639
+
1640
+ strength defaults to 0.35 of pointer offset. Only mouse movement with enabled motion applies displacement; no state/persistence/service is owned.
1641
+
1642
+ ### Native forms and reset
1643
+
1644
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1645
+
1646
+ ### Ref target
1647
+
1648
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1649
+
1650
+ ### CSS and tokens
1651
+
1652
+ Use .contour-magnetic and its --magnet geometry variable with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1653
+
1654
+ ### Loading, errors and long content
1655
+
1656
+ Keep target usability, focus indication and surrounding hit areas stable; test reduced/paused motion, long labels and narrow screens.
1657
+
1658
+ ### RTL and localization
1659
+
1660
+ Children supply language/direction; pointer displacement has no semantic directional meaning.
1661
+
1662
+ ### Keyboard and focus
1663
+
1664
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1665
+
1666
+ ### Limits and evidence
1667
+
1668
+ No click/drag/key interaction, forwarded ref or touch/pen magnet. The presentation wrapper is not a new control.
1669
+
1670
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1671
+
1672
+ [Report Magnetic 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Magnetic&version=0.6.3) using the [public reproduction](examples/reproduction).
1673
+
1674
+ ## Marquee
1675
+
1676
+ A labelled repeating visual ticker with one accessible item sequence.
1677
+
1678
+ ### Import and runnable source
1679
+
1680
+ `import { Marquee } from "@abuzareal/contour-ui";`
1681
+
1682
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1683
+
1684
+ ### Props and explicit defaults
1685
+
1686
+ | Prop | Type | Default | Responsibility |
1687
+ | --- | --- | --- | --- |
1688
+ | items / label | string[] / string | Required | Unique items and a meaningful region name. |
1689
+ | duration | number | 28 | Seconds per loop; validate a sensible positive finite value. |
1690
+
1691
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1692
+
1693
+ ### Purpose and alternatives
1694
+
1695
+ Use for nonessential repeated metadata. Keep essential content available statically and provide an application pause control for ongoing motion.
1696
+
1697
+ ### Anatomy and parts
1698
+
1699
+ Named region contains two list tracks for seamless motion; the duplicated track is aria-hidden and decorative icons carry no meaning.
1700
+
1701
+ ### State ownership
1702
+
1703
+ Caller owns unique string items and positive duration (default 28 seconds). CSS handles hover/system reduction and surrounding app pause.
1704
+
1705
+ ### Native forms and reset
1706
+
1707
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1708
+
1709
+ ### Ref target
1710
+
1711
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1712
+
1713
+ ### CSS and tokens
1714
+
1715
+ Use .contour-marquee, track hooks and --marquee-duration with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1716
+
1717
+ ### Loading, errors and long content
1718
+
1719
+ Pause ongoing motion from the app, test reduced/paused states and long items. Loading/error/empty data belongs outside the ticker.
1720
+
1721
+ ### RTL and localization
1722
+
1723
+ Translate label/items and verify RTL visual direction/reading order. Do not treat track motion as navigation.
1724
+
1725
+ ### Keyboard and focus
1726
+
1727
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
1728
+
1729
+ ### Limits and evidence
1730
+
1731
+ No built-in pause button, live updates/announcements, arbitrary children or root ref. Do not imply the decorative duplicate is another dataset.
1732
+
1733
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1734
+
1735
+ [Report Marquee 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Marquee&version=0.6.3) using the [public reproduction](examples/reproduction).
1736
+
1737
+ ## Pagination
1738
+
1739
+ Controlled one-based page navigation with translated labels and condensed page buttons.
1740
+
1741
+ ### Import and runnable source
1742
+
1743
+ `import { Pagination } from "@abuzareal/contour-ui";`
1744
+
1745
+ [Complete navigation TSX example](examples/catalogue/navigation.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1746
+
1747
+ ### Props and explicit defaults
1748
+
1749
+ | Prop | Type | Default | Responsibility |
1750
+ | --- | --- | --- | --- |
1751
+ | page / pageCount / onChange | number / number / (page:number)=>void | Required | Supply1 <= page <= pageCount and update state after requests as appropriate. |
1752
+ | label / previousLabel / nextLabel | string | Pagination / Previous page / Next page | Translate navigation and button names. |
1753
+ | pageLabel / formatPage | (page:number)=>string | Page N / formatIndex | Accessible names and visual numeral formatting are separate. |
1754
+
1755
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1756
+
1757
+ ### Purpose and alternatives
1758
+
1759
+ Use to move through known result pages. Own URL/data loading separately; hide pagination or show an empty state when no pages exist.
1760
+
1761
+ ### Anatomy and parts
1762
+
1763
+ Named nav contains previous/next buttons and an ordered condensed list; current page has aria-current=page. Gaps are decorative.
1764
+
1765
+ ### State ownership
1766
+
1767
+ page and pageCount are caller-owned positive finite integers. onChange requests another one-based page; component neither clamps invalid inputs nor fetches rows.
1768
+
1769
+ ### Native forms and reset
1770
+
1771
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
1772
+
1773
+ ### Ref target
1774
+
1775
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
1776
+
1777
+ ### CSS and tokens
1778
+
1779
+ Use .contour-pagination, native buttons and [aria-current=page] with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1780
+
1781
+ ### Loading, errors and long content
1782
+
1783
+ Preserve current results/query on request failure; show retry/loading in the application. Check large page counts, narrow width and long translations.
1784
+
1785
+ ### RTL and localization
1786
+
1787
+ Use all label callbacks and formatPage for localized numerals. Verify RTL previous/next meaning with logical order and your product convention.
1788
+
1789
+ ### Keyboard and focus
1790
+
1791
+ Tab reaches native enabled buttons; Enter/Space requests a page. First/last boundaries disable previous/next. No grid/radio arrow model or automatic result focus is added.
1792
+
1793
+ ### Limits and evidence
1794
+
1795
+ No zero-page/invalid-number sanitization, router hrefs, pending/disabled prop or server operation. Callback success does not establish fetched data.
1796
+
1797
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1798
+
1799
+ [Report Pagination 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Pagination&version=0.6.3) using the [public reproduction](examples/reproduction).
1800
+
1801
+ ## Popover
1802
+
1803
+ A nonmodal floating panel with collision-aware portals and typed focus/trigger composition.
1804
+
1805
+ ### Import and runnable source
1806
+
1807
+ `import { Popover } from "@abuzareal/contour-ui";`
1808
+
1809
+ [Complete floating TSX example](examples/catalogue/floating.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1810
+
1811
+ ### Props and explicit defaults
1812
+
1813
+ | Prop | Type | Default | Responsibility |
1814
+ | --- | --- | --- | --- |
1815
+ | trigger / title / children | ReactNode / string / ReactNode | Required | Default trigger content must not be another button. |
1816
+ | open / defaultOpen / onOpenChange | boolean / boolean / callback | Uncontrolled / false | Keep one ownership model. |
1817
+ | portal / side / align | boolean / top \| bottom \| left \| right / start \| center \| end | true / bottom / start | Placement follows collision bounds and logical alignment. |
1818
+ | renderTrigger / triggerProps / panelProps | Typed button renderer / native part props | Omitted | Spread supplied props into one ref-forwarding button. |
1819
+ | initialFocus | ref \| false | Panel focus on entry | Override entry deliberately and retain a usable close path. |
1820
+
1821
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1822
+
1823
+ ### Purpose and alternatives
1824
+
1825
+ Use for supplementary interactive content that leaves the background available. Use Tooltip only for noninteractive hints and Dialog for a modal task.
1826
+
1827
+ ### Anatomy and parts
1828
+
1829
+ Root wrapper and button trigger own the panel relationship. Panel is a named nonmodal dialog. Typed triggerProps/panelProps expose parts; renderTrigger spreads owned attributes/handlers/ref into one button.
1830
+
1831
+ ### State ownership
1832
+
1833
+ Use open/onOpenChange or defaultOpen. Default portal is true; side bottom, align start and sideOffset/collisionPadding eight pixels. initialFocus=false preserves trigger focus. Cancelable focus/dismiss events permit explicit workflow ownership.
1834
+
1835
+ ### Native forms and reset
1836
+
1837
+ The trigger defaults type=button. Popover is not a form; portal movement can change DOM form ancestry, so use explicit form association when required.
1838
+
1839
+ ### Ref target
1840
+
1841
+ Root ref targets HTMLDivElement; triggerProps.ref and panelProps.ref target their native parts. Portals can detach/reattach panel refs when the container changes.
1842
+
1843
+ ### CSS and tokens
1844
+
1845
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
1846
+
1847
+ ### Loading, errors and long content
1848
+
1849
+ Native-dialog containment keeps the panel in the modal top layer. Collision observers update on scroll/resize and clean up on close. No focus trap; portalled DOM order may require an application focus policy. Changing containers may remount unsaved children.
1850
+
1851
+ ### RTL and localization
1852
+
1853
+ Translate title and trigger content. Alignment follows inherited RTL; physical side remains an explicit choice. Check long content, small viewports and a usable dismissal path.
1854
+
1855
+ ### Keyboard and focus
1856
+
1857
+ Nonmodal panel entry focuses its panel or requested target. Escape closes the deepest layer and returns focus; outside press keeps destination focus. Tab is not trapped.
1858
+
1859
+ ### Limits and evidence
1860
+
1861
+ Portals affect DOM Tab order. No arbitrary link trigger or modal focus trap. Use Dialog when background interaction must be blocked.
1862
+
1863
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1864
+
1865
+ [Report Popover 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Popover&version=0.6.3) using the [public reproduction](examples/reproduction).
1866
+
1867
+ ## ProgressBar
1868
+
1869
+ Labelled determinate or indeterminate progress for work managed by your application.
1870
+
1871
+ ### Import and runnable source
1872
+
1873
+ `import { ProgressBar } from "@abuzareal/contour-ui";`
1874
+
1875
+ [Complete feedback TSX example](examples/catalogue/feedback.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1876
+
1877
+ ### Props and explicit defaults
1878
+
1879
+ | Prop | Type | Default | Responsibility |
1880
+ | --- | --- | --- | --- |
1881
+ | label | string | Required | Describe the operation being reported. |
1882
+ | value | number | Omitted: indeterminate | Supply a finite number from 0 to 100 only when progress is known. Validate and bound it before rendering. |
1883
+ | tone | "accent" \| "success" \| "danger" | "accent" | Use text as well as color to explain completion or failure. |
1884
+
1885
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1886
+
1887
+ ### Purpose and alternatives
1888
+
1889
+ Use for measured completion or unknown-duration work. Use Spinner for a compact indicator; do not imply measured progress when the total is unknown.
1890
+
1891
+ ### Anatomy and parts
1892
+
1893
+ A named progressbar, visual track/fill and visible rounded percentage when determinate. No interactive parts or native input ref.
1894
+
1895
+ ### State ownership
1896
+
1897
+ Omitted value is indeterminate. Caller supplies a finite 0–100 value; tone defaults accent and also supports success/danger. The component does not clamp invalid input or calculate progress.
1898
+
1899
+ ### Native forms and reset
1900
+
1901
+ Informational output: no successful form control, required constraint or reset behavior. The application resets its progress state.
1902
+
1903
+ ### Ref target
1904
+
1905
+ No native ref contract. Put pause/cancel/retry in separate labelled controls.
1906
+
1907
+ ### CSS and tokens
1908
+
1909
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
1910
+
1911
+ ### Loading, errors and long content
1912
+
1913
+ Unknown, stalled and failed requests need truthful adjacent status. An animation does not prove success. Check 0 and 100, long labels, both themes and reduced motion.
1914
+
1915
+ ### RTL and localization
1916
+
1917
+ Translate label/status text. The built-in rounded percent is not a locale formatting service; use adjacent localized wording when needed.
1918
+
1919
+ ### Keyboard and focus
1920
+
1921
+ Progress is informational and does not take focus. Put cancel, retry or pause actions in separate labelled controls.
1922
+
1923
+ ### Limits and evidence
1924
+
1925
+ The component does not start work, calculate percentages or clamp invalid inputs. Omit value for unknown progress. An indeterminate animation is not evidence that a request is succeeding; applications own status, recovery and cancellation.
1926
+
1927
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1928
+
1929
+ [Report ProgressBar 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=ProgressBar&version=0.6.3) using the [public reproduction](examples/reproduction).
1930
+
1931
+ ## RadioGroup
1932
+
1933
+ A named native radio set with a legend, controlled/default selection and per-option input access.
1934
+
1935
+ ### Import and runnable source
1936
+
1937
+ `import { RadioGroup } from "@abuzareal/contour-ui";`
1938
+
1939
+ [Complete choices TSX example](examples/catalogue/choices.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
1940
+
1941
+ ### Props and explicit defaults
1942
+
1943
+ | Prop | Type | Default | Responsibility |
1944
+ | --- | --- | --- | --- |
1945
+ | legend / options | string / option records | Required | Supply a meaningful group name and unique value/label pairs. |
1946
+ | value / defaultValue / onChange | Value / Value / (value: Value) => void | Uncontrolled if value omitted | Callback receives the selected string, not an event. |
1947
+ | name / form / required / disabled | Native fieldset and group props | Generated name; other props omitted | Supply a caller name for stable FormData and form for an external owner. |
1948
+ | inline | boolean | false | Changes layout, not radio semantics. |
1949
+ | description / error | string | Omitted | Keep validation linked and visible. |
1950
+
1951
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
1952
+
1953
+ ### Purpose and alternatives
1954
+
1955
+ Use for one choice from a visible list. Use independent Checkbox controls for multiple choices, or SelectField/Combobox when a popup is more appropriate.
1956
+
1957
+ ### Anatomy and parts
1958
+
1959
+ Fieldset and legend contain labelled native radio inputs. description/error IDs merge with caller descriptions; each option may have its own description, disabled flag and inputProps.
1960
+
1961
+ ### State ownership
1962
+
1963
+ value/onChange controls selection; otherwise defaultValue captures an uncontrolled initial selection. Keep unique stable string values. No singular root focus ref is exposed.
1964
+
1965
+ ### Native forms and reset
1966
+
1967
+ A named checked enabled radio submits its string value; required uses native validity. Disabled values are omitted. Native/external form reset restores captured defaults; controlled owners reset their state and cancelled reset is respected.
1968
+
1969
+ ### Ref target
1970
+
1971
+ Use options[index].inputProps.ref for HTMLInputElement. No forwarded fieldset or aggregate native-input ref.
1972
+
1973
+ ### CSS and tokens
1974
+
1975
+ Use .contour-radio-group and .contour-choice with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
1976
+
1977
+ ### Loading, errors and long content
1978
+
1979
+ Show request failure/loading/empty choices outside the group. Keep long legends/descriptions readable and do not replace selection silently when choices change.
1980
+
1981
+ ### RTL and localization
1982
+
1983
+ Translate legend, labels, descriptions and errors. Native browser validation and radio key behavior vary by platform; test RTL and long labels.
1984
+
1985
+ ### Keyboard and focus
1986
+
1987
+ Tab enters the native radio set; arrow/Space behavior follows the browser. options.inputProps.ref targets each native input for focus/blur integration. Disabled choices cannot activate.
1988
+
1989
+ ### Limits and evidence
1990
+
1991
+ Native radios, not a custom listbox. No multi-select, asynchronous loading model or root forwarded ref; values must remain unique and stable.
1992
+
1993
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
1994
+
1995
+ [Report RadioGroup 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=RadioGroup&version=0.6.3) using the [public reproduction](examples/reproduction).
1996
+
1997
+ ## Reveal
1998
+
1999
+ A one-time observer-driven entrance wrapper with a static reduced-motion path.
2000
+
2001
+ ### Import and runnable source
2002
+
2003
+ `import { Reveal } from "@abuzareal/contour-ui";`
2004
+
2005
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2006
+
2007
+ ### Props and explicit defaults
2008
+
2009
+ | Prop | Type | Default | Responsibility |
2010
+ | --- | --- | --- | --- |
2011
+ | children | ReactNode | Required | Keep native content semantics inside the wrapper. |
2012
+ | className / delay | string / number | empty string / 0 | Append scoped classes and optional millisecond visual stagger. |
2013
+
2014
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2015
+
2016
+ ### Purpose and alternatives
2017
+
2018
+ Use for optional presentation around already meaningful content. Essential content must remain usable without animation; do not use entrance timing as a loading state.
2019
+
2020
+ ### Anatomy and parts
2021
+
2022
+ Div wrapper observes entry, adds public visible state hooks and disconnects. className appends; delay sets transition delay.
2023
+
2024
+ ### State ownership
2025
+
2026
+ One-time viewport activation; className defaults empty and delay 0 ms. If IntersectionObserver is missing, visible hooks are applied immediately. System/app motion styling controls the animation.
2027
+
2028
+ ### Native forms and reset
2029
+
2030
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2031
+
2032
+ ### Ref target
2033
+
2034
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2035
+
2036
+ ### CSS and tokens
2037
+
2038
+ Use .contour-reveal and .contour-is-visible with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2039
+
2040
+ ### Loading, errors and long content
2041
+
2042
+ Check static/reduced-motion/no-observer visibility, unmount cleanup and long content. Avoid stacking large delays on essential controls.
2043
+
2044
+ ### RTL and localization
2045
+
2046
+ Text is caller content; translate normally and preserve source reading order regardless of stagger.
2047
+
2048
+ ### Keyboard and focus
2049
+
2050
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2051
+
2052
+ ### Limits and evidence
2053
+
2054
+ No enter/exit lifecycle API, repeated visibility callback, forwarded ref or data-loading orchestration.
2055
+
2056
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2057
+
2058
+ [Report Reveal 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Reveal&version=0.6.3) using the [public reproduction](examples/reproduction).
2059
+
2060
+ ## RevealHeading
2061
+
2062
+ A fixed h2 whose line spans can animate inside a Reveal.
2063
+
2064
+ ### Import and runnable source
2065
+
2066
+ `import { RevealHeading } from "@abuzareal/contour-ui";`
2067
+
2068
+ [Complete identity TSX example](examples/catalogue/identity.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2069
+
2070
+ ### Props and explicit defaults
2071
+
2072
+ | Prop | Type | Default | Responsibility |
2073
+ | --- | --- | --- | --- |
2074
+ | id / lines | string / {text:ReactNode;accent?:boolean}[] | Required | Keep a unique heading id and meaningful text in semantic order. |
2075
+
2076
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2077
+
2078
+ ### Purpose and alternatives
2079
+
2080
+ Use for an actual second-level section heading. Use native headings of the appropriate level elsewhere rather than forcing every heading into this visual style.
2081
+
2082
+ ### Anatomy and parts
2083
+
2084
+ h2 with caller id contains line spans and inner type-run spans; each line accepts ReactNode text and optional accent.
2085
+
2086
+ ### State ownership
2087
+
2088
+ Pure heading data. Reveal or app state controls entrance styling; this component adds no observer or animation state itself.
2089
+
2090
+ ### Native forms and reset
2091
+
2092
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2093
+
2094
+ ### Ref target
2095
+
2096
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2097
+
2098
+ ### CSS and tokens
2099
+
2100
+ Use .contour-type-line, .contour-type-run and accent hook with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2101
+
2102
+ ### Loading, errors and long content
2103
+
2104
+ Long lines and rich text must remain readable at narrow widths. Reduced-motion/static visibility belongs to the surrounding reveal/style contract.
2105
+
2106
+ ### RTL and localization
2107
+
2108
+ Translate lines without using decorative line breaks to change reading order. Test scripts/RTL that wrap differently.
2109
+
2110
+ ### Keyboard and focus
2111
+
2112
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2113
+
2114
+ ### Limits and evidence
2115
+
2116
+ Always h2; no as/heading-level prop, controlled animation, root class/ref or arbitrary native attributes.
2117
+
2118
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2119
+
2120
+ [Report RevealHeading 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=RevealHeading&version=0.6.3) using the [public reproduction](examples/reproduction).
2121
+
2122
+ ## SceneBoundary
2123
+
2124
+ An error boundary that hides a failed optional child without removing surrounding content.
2125
+
2126
+ ### Import and runnable source
2127
+
2128
+ `import { SceneBoundary } from "@abuzareal/contour-ui";`
2129
+
2130
+ [Complete scene-boundary TSX example](examples/catalogue/scene-boundary.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2131
+
2132
+ ### Props and explicit defaults
2133
+
2134
+ | Prop | Type | Default | Responsibility |
2135
+ | --- | --- | --- | --- |
2136
+ | children | ReactNode | Required | Keep a usable static fallback and any retry control outside the boundary. |
2137
+
2138
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2139
+
2140
+ ### Purpose and alternatives
2141
+
2142
+ Use around an optional scene/rendering child with a useful static fallback outside it. Do not use it to hide essential UI failures or silently imply a failed operation succeeded.
2143
+
2144
+ ### Anatomy and parts
2145
+
2146
+ React class error boundary renders children or null after a caught descendant render/lifecycle error. It renders no wrapper DOM and owns no renderer resources.
2147
+
2148
+ ### State ownership
2149
+
2150
+ Internal failed=false becomes true after a caught error. A caller key/remount resets the boundary; no reset/fallback/callback prop is exposed.
2151
+
2152
+ ### Native forms and reset
2153
+
2154
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2155
+
2156
+ ### Ref target
2157
+
2158
+ A React class ref is an instance, not a native focus target; no public focus/retry command is defined.
2159
+
2160
+ ### CSS and tokens
2161
+
2162
+ No component-specific visual wrapper contract. Style application content with released semantic tokens; preserve its native semantics and meaningful fallback.
2163
+
2164
+ ### Loading, errors and long content
2165
+
2166
+ Test missing/failed lazy modules, render failures and unmount. Dispose GPU work in the scene owner and keep honest external fallback text; remounting must not imply a service recovered.
2167
+
2168
+ ### RTL and localization
2169
+
2170
+ Translate app-owned static fallback/retry/status text. The boundary supplies no user-facing strings itself.
2171
+
2172
+ ### Keyboard and focus
2173
+
2174
+ No added focus behavior or control. Keep fallback/retry in native labelled controls and restore useful focus in the application when replacing interactive children.
2175
+
2176
+ ### Limits and evidence
2177
+
2178
+ Not a catch-all for event-handler, asynchronous callback, server-render or network errors. No automatic retry/fallback slot, loading state or GPU disposal. Existing optional3D APIs remain experimental.
2179
+
2180
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2181
+
2182
+ [Report SceneBoundary 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=SceneBoundary&version=0.6.3) using the [public reproduction](examples/reproduction).
2183
+
2184
+ ## ScrollProgress
2185
+
2186
+ A decorative page-scroll progress line without interactive semantics.
2187
+
2188
+ ### Import and runnable source
2189
+
2190
+ `import { ScrollProgress } from "@abuzareal/contour-ui";`
2191
+
2192
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2193
+
2194
+ ### Props and explicit defaults
2195
+
2196
+ No component props. State and geometry are derived from the surrounding document.
2197
+
2198
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2199
+
2200
+ ### Purpose and alternatives
2201
+
2202
+ Use as a supplemental document-position cue. Keep real navigation/headings and reading order; this is not measured upload/task completion.
2203
+
2204
+ ### Anatomy and parts
2205
+
2206
+ aria-hidden div is fixed by CSS; a frame-coalesced listener reads document scroll height/window scroll and writes its progress variable.
2207
+
2208
+ ### State ownership
2209
+
2210
+ No props. Initial measurement plus scroll/resize updates; non-scrollable documents yield 0. Cleanup removes listeners and pending frame.
2211
+
2212
+ ### Native forms and reset
2213
+
2214
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2215
+
2216
+ ### Ref target
2217
+
2218
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2219
+
2220
+ ### CSS and tokens
2221
+
2222
+ Use .contour-scroll-progress and --scroll-progress with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2223
+
2224
+ ### Loading, errors and long content
2225
+
2226
+ Check non-scrollable/long documents, resize/unmount and layout changes. It does not observe every asynchronous content-height change unless scroll/resize updates occur.
2227
+
2228
+ ### RTL and localization
2229
+
2230
+ No text; keep accessible document navigation separate and verify surrounding direction/styles.
2231
+
2232
+ ### Keyboard and focus
2233
+
2234
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2235
+
2236
+ ### Limits and evidence
2237
+
2238
+ Document/window scope, not nested-scroll containers. No progress label, callback/ref, controlled value or business completion semantics.
2239
+
2240
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2241
+
2242
+ [Report ScrollProgress 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=ScrollProgress&version=0.6.3) using the [public reproduction](examples/reproduction).
2243
+
2244
+ ## SectionLabel
2245
+
2246
+ A numbered eyebrow using section metadata and a secondary note.
2247
+
2248
+ ### Import and runnable source
2249
+
2250
+ `import { SectionLabel } from "@abuzareal/contour-ui";`
2251
+
2252
+ [Complete identity TSX example](examples/catalogue/identity.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2253
+
2254
+ ### Props and explicit defaults
2255
+
2256
+ | Prop | Type | Default | Responsibility |
2257
+ | --- | --- | --- | --- |
2258
+ | section | Section | Required | Supply id/number/label/title; only number/title are displayed. |
2259
+ | aside | string | Required | Secondary nonessential note; may be hidden on small screens. |
2260
+
2261
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2262
+
2263
+ ### Purpose and alternatives
2264
+
2265
+ Use as supporting section context beside a real heading. It is not itself a heading, anchor, scroll-spy target or navigation control.
2266
+
2267
+ ### Anatomy and parts
2268
+
2269
+ Div contains formatIndex(section.number) plus section.title, and an aside span that may hide at narrow widths.
2270
+
2271
+ ### State ownership
2272
+
2273
+ Pure section/aside data. Section id/label remain caller metadata; this component does not create that section anchor.
2274
+
2275
+ ### Native forms and reset
2276
+
2277
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2278
+
2279
+ ### Ref target
2280
+
2281
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2282
+
2283
+ ### CSS and tokens
2284
+
2285
+ Use .contour-section-label with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2286
+
2287
+ ### Loading, errors and long content
2288
+
2289
+ Keep actual section anchors/headings in application markup and long section text bounded. No request/form lifecycle is supplied.
2290
+
2291
+ ### RTL and localization
2292
+
2293
+ Translate title/aside. formatIndex uses the library two-digit representation; localized numbering is not a prop.
2294
+
2295
+ ### Keyboard and focus
2296
+
2297
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2298
+
2299
+ ### Limits and evidence
2300
+
2301
+ No configurable heading level, formatting callback, forwarded ref or automatic navigation. The aside must not contain essential instructions.
2302
+
2303
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2304
+
2305
+ [Report SectionLabel 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=SectionLabel&version=0.6.3) using the [public reproduction](examples/reproduction).
2306
+
2307
+ ## SegmentedControl
2308
+
2309
+ A controlled single-choice button group with radio semantics and roving focus.
2310
+
2311
+ ### Import and runnable source
2312
+
2313
+ `import { SegmentedControl } from "@abuzareal/contour-ui";`
2314
+
2315
+ [Complete choices TSX example](examples/catalogue/choices.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2316
+
2317
+ ### Props and explicit defaults
2318
+
2319
+ | Prop | Type | Default | Responsibility |
2320
+ | --- | --- | --- | --- |
2321
+ | label / options | string / {value,label}[] | Required | Name the group and keep options nonempty with unique values. |
2322
+ | value / onChange | Value / (value:Value)=>void | Required | Update the selected value; no default/uncontrolled API. |
2323
+
2324
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2325
+
2326
+ ### Purpose and alternatives
2327
+
2328
+ Use for a small mutually exclusive view/filter choice. Use native RadioGroup for successful form inputs and required validation; this does not create a global density/theme API.
2329
+
2330
+ ### Anatomy and parts
2331
+
2332
+ Named radiogroup contains native button role=radio for each option. Selected item is the tab stop and has aria-checked.
2333
+
2334
+ ### State ownership
2335
+
2336
+ value and onChange are required controlled state; options use unique stable string values. Caller must keep value present in the set.
2337
+
2338
+ ### Native forms and reset
2339
+
2340
+ Buttons are type=button and are not submitted. Use RadioGroup or an application-owned successful control if the selection must be in FormData.
2341
+
2342
+ ### Ref target
2343
+
2344
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2345
+
2346
+ ### CSS and tokens
2347
+
2348
+ Use .contour-segmented and [aria-checked] buttons with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2349
+
2350
+ ### Loading, errors and long content
2351
+
2352
+ Own pending/error and keep query/results stable while a view changes. Long labels should wrap rather than create offscreen controls.
2353
+
2354
+ ### RTL and localization
2355
+
2356
+ Translate group/options and supply dir. Stable IDs survive translation; do not use translated labels as selection identity.
2357
+
2358
+ ### Keyboard and focus
2359
+
2360
+ Tab enters the selected button. Arrows/Home/End move and select with RTL-aware horizontal navigation; Enter/Space uses native button activation.
2361
+
2362
+ ### Limits and evidence
2363
+
2364
+ No name/form/required serialization, disabled-option support, async state or forwarded aggregate ref. An absent selected value leaves no selected tab stop; validate it in the parent.
2365
+
2366
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2367
+
2368
+ [Report SegmentedControl 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=SegmentedControl&version=0.6.3) using the [public reproduction](examples/reproduction).
2369
+
2370
+ ## SelectField
2371
+
2372
+ A native select with a visible label, linked supporting text and a native ref.
2373
+
2374
+ ### Import and runnable source
2375
+
2376
+ `import { SelectField } from "@abuzareal/contour-ui";`
2377
+
2378
+ [Complete text-inputs TSX example](examples/catalogue/text-inputs.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2379
+
2380
+ ### Props and explicit defaults
2381
+
2382
+ | Prop | Type | Default | Responsibility |
2383
+ | --- | --- | --- | --- |
2384
+ | label / options | string / {value: string; label: string}[] | Required | Supply unique values and understandable labels. |
2385
+ | value / defaultValue / onChange | Native select props | Uncontrolled when value is omitted | Read event.currentTarget.value. Keep controlled state in the application. |
2386
+ | placeholder | string | Omitted | Adds a disabled empty option. Use an empty initial value when the visitor must choose. |
2387
+ | hint / error | string | Omitted | Messages are linked to the select; error sets aria-invalid. |
2388
+ | id / name / form / ref | Native select props and React.Ref<HTMLSelectElement> | Generated id | Use a name for FormData and a ref for focus. Caller descriptions are preserved. |
2389
+
2390
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2391
+
2392
+ ### Purpose and alternatives
2393
+
2394
+ Use for a short native allowed-value list. Use Combobox for search or remote results; no free-text selection is offered here.
2395
+
2396
+ ### Anatomy and parts
2397
+
2398
+ Field connects label and supporting text to a native select; options are value/label records. Placeholder renders a disabled empty option.
2399
+
2400
+ ### State ownership
2401
+
2402
+ Native value/onChange or defaultValue ownership. Loading, unavailable data and failed requests belong outside the select.
2403
+
2404
+ ### Native forms and reset
2405
+
2406
+ name/form participate in native FormData and external form ownership. Native reset restores defaults; controlled owners restore their value. Use required and an empty initial value when a choice is mandatory.
2407
+
2408
+ ### Ref target
2409
+
2410
+ Forwarded ref targets HTMLSelectElement. Caller id and descriptions are preserved.
2411
+
2412
+ ### CSS and tokens
2413
+
2414
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
2415
+
2416
+ ### Loading, errors and long content
2417
+
2418
+ Use unique option values. Explain empty or failed option sources rather than presenting a disabled select as a successful response. Native popup geometry and styling vary by platform.
2419
+
2420
+ ### RTL and localization
2421
+
2422
+ Translate labels/options and test long translations. Browser/OS supply native popup keys and localized validation; verify your target platforms.
2423
+
2424
+ ### Keyboard and focus
2425
+
2426
+ The platform supplies native select keyboard behavior. Tab enters and leaves the control; selection and popup keys follow the browser and operating system.
2427
+
2428
+ ### Limits and evidence
2429
+
2430
+ No searchable list, asynchronous option fetching or grouped-option contract. Supply loading, failed and empty option states in the surrounding application. Native styling and popup behavior vary by platform.
2431
+
2432
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2433
+
2434
+ [Report SelectField 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=SelectField&version=0.6.3) using the [public reproduction](examples/reproduction).
2435
+
2436
+ ## Skeleton
2437
+
2438
+ A hidden-from-assistive-tech visual placeholder with line, block or circle shape.
2439
+
2440
+ ### Import and runnable source
2441
+
2442
+ `import { Skeleton } from "@abuzareal/contour-ui";`
2443
+
2444
+ [Complete feedback TSX example](examples/catalogue/feedback.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2445
+
2446
+ ### Props and explicit defaults
2447
+
2448
+ | Prop | Type | Default | Responsibility |
2449
+ | --- | --- | --- | --- |
2450
+ | shape | line \| block \| circle | line | Match the expected visual footprint. |
2451
+ | width / height | CSS length strings | Omitted | Caller-owned dimensions; ensure narrow layouts remain bounded. |
2452
+
2453
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2454
+
2455
+ ### Purpose and alternatives
2456
+
2457
+ Use while real content loads. Pair with an accessible loading/status description; use a truthful empty/error state if work ends without content.
2458
+
2459
+ ### Anatomy and parts
2460
+
2461
+ Noninteractive aria-hidden span takes width/height CSS strings and shape hooks. It contains no actual data or accessible text.
2462
+
2463
+ ### State ownership
2464
+
2465
+ Pure visual placeholder. shape defaults line; caller owns when it disappears and any aria-busy state on the content region.
2466
+
2467
+ ### Native forms and reset
2468
+
2469
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2470
+
2471
+ ### Ref target
2472
+
2473
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2474
+
2475
+ ### CSS and tokens
2476
+
2477
+ Use .contour-skeleton and shape hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2478
+
2479
+ ### Loading, errors and long content
2480
+
2481
+ Reserve sensible layout space without clipping; make completion/error visible outside the skeleton. Motion may stop under reduced motion.
2482
+
2483
+ ### RTL and localization
2484
+
2485
+ Shape has no translatable text. Translate the surrounding real loading/error status and check direction/width on translated content.
2486
+
2487
+ ### Keyboard and focus
2488
+
2489
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2490
+
2491
+ ### Limits and evidence
2492
+
2493
+ No text label, data fetch, role=status, automatic layout measurement or forwarded ref. A placeholder is not content or an error recovery flow.
2494
+
2495
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2496
+
2497
+ [Report Skeleton 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Skeleton&version=0.6.3) using the [public reproduction](examples/reproduction).
2498
+
2499
+ ## Slider
2500
+
2501
+ A native range input with numeric callbacks, formatted value text and reset-aware readout.
2502
+
2503
+ ### Import and runnable source
2504
+
2505
+ `import { Slider } from "@abuzareal/contour-ui";`
2506
+
2507
+ [Complete choices TSX example](examples/catalogue/choices.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2508
+
2509
+ ### Props and explicit defaults
2510
+
2511
+ | Prop | Type | Default | Responsibility |
2512
+ | --- | --- | --- | --- |
2513
+ | label | string | Required | Provide the quantity name and nearby units. |
2514
+ | value / defaultValue / onChange | number / number / (value: number) => void | Uncontrolled native-sanitized midpoint | Callback is numeric, not a native event. |
2515
+ | min / max / step | number / number / number \| "any" | 0 / 100 / 1 | Provide finite consistent bounds and a valid positive step. |
2516
+ | format | (value: number) => string | String | Readout and aria-valuetext formatting, not submission parsing. |
2517
+ | name / form / disabled | Native input props | Omitted | Native successful-control and external form ownership. |
2518
+
2519
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2520
+
2521
+ ### Purpose and alternatives
2522
+
2523
+ Use for a bounded approximate numeric choice. Use a native number/text input for precise typed entry or locale-sensitive parsing; this is not NumberField.
2524
+
2525
+ ### Anatomy and parts
2526
+
2527
+ Visible label/output accompany input type=range and linked hint/error. The native range owns sanitization, min/max/step and keyboard interaction.
2528
+
2529
+ ### State ownership
2530
+
2531
+ value/onChange controls a number; defaultValue captures the initial uncontrolled value. If omitted, the initial midpoint is (min + max(min,max))/2 and the browser sanitizes it. format customizes readout/accessible text.
2532
+
2533
+ ### Native forms and reset
2534
+
2535
+ name/form support native and external-owner submission as a numeric string; disabled omits the control. required is deliberately not supported by range. Reset restores uncontrolled input/readout or the parent-controlled value, and cancellation is respected.
2536
+
2537
+ ### Ref target
2538
+
2539
+ Forwarded HTMLInputElement for the visible native range.
2540
+
2541
+ ### CSS and tokens
2542
+
2543
+ Use .contour-slider wrapper and its native range/output with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2544
+
2545
+ ### Loading, errors and long content
2546
+
2547
+ Check bounds, step, zero-length/reversed inputs in your application and keep long formatted readouts readable. Request loading/failure and reset of controlled state belong to the parent.
2548
+
2549
+ ### RTL and localization
2550
+
2551
+ Use format for localized units/value text. Native serialized value remains a numeric string; verify RTL range behavior and real mobile controls.
2552
+
2553
+ ### Keyboard and focus
2554
+
2555
+ Native range arrows/Home/End/Page keys follow the browser and direction. The forwarded input ref supports focus. Do not replace keyboard interaction with a drag-only wrapper.
2556
+
2557
+ ### Limits and evidence
2558
+
2559
+ One scalar range only; no multi-thumb/rich numeric parsing/required constraint. Display formatting does not change FormData serialization or native sanitization.
2560
+
2561
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2562
+
2563
+ [Report Slider 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Slider&version=0.6.3) using the [public reproduction](examples/reproduction).
2564
+
2565
+ ## Spinner
2566
+
2567
+ A decorative spinning mark with an accessible status label.
2568
+
2569
+ ### Import and runnable source
2570
+
2571
+ `import { Spinner } from "@abuzareal/contour-ui";`
2572
+
2573
+ [Complete feedback TSX example](examples/catalogue/feedback.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2574
+
2575
+ ### Props and explicit defaults
2576
+
2577
+ | Prop | Type | Default | Responsibility |
2578
+ | --- | --- | --- | --- |
2579
+ | size | sm \| md \| lg | md | Icon sizes16/24/40; no percentage meaning. |
2580
+ | label | string | Loading | Name the actual task and translate it. |
2581
+ | className | string | Omitted | Append scoped styling without removing the status label. |
2582
+
2583
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2584
+
2585
+ ### Purpose and alternatives
2586
+
2587
+ Use for unknown-duration ongoing work, with context. Use ProgressBar for real measured completion and adjacent errors/retry for failed work.
2588
+
2589
+ ### Anatomy and parts
2590
+
2591
+ Root span role=status contains a hidden label and decorative asterisk. Size controls icon geometry; className appends root hooks.
2592
+
2593
+ ### State ownership
2594
+
2595
+ Pure indication of caller-owned work; size defaults md and label Loading. The animation is not evidence of request success.
2596
+
2597
+ ### Native forms and reset
2598
+
2599
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2600
+
2601
+ ### Ref target
2602
+
2603
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2604
+
2605
+ ### CSS and tokens
2606
+
2607
+ Use .contour-spinner and size hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2608
+
2609
+ ### Loading, errors and long content
2610
+
2611
+ Show truthful pending/failed/retry states. Reduced-motion appearance may be static; retain a meaningful textual status and avoid duplicate live announcements.
2612
+
2613
+ ### RTL and localization
2614
+
2615
+ Translate label and related status/error/action text. Actual live-region behavior requires manual platform checks.
2616
+
2617
+ ### Keyboard and focus
2618
+
2619
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2620
+
2621
+ ### Limits and evidence
2622
+
2623
+ No request lifecycle, progress value, cancellation control or forwarded ref. Do not leave a permanent spinner when a failure is known.
2624
+
2625
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2626
+
2627
+ [Report Spinner 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Spinner&version=0.6.3) using the [public reproduction](examples/reproduction).
2628
+
2629
+ ## Stat
2630
+
2631
+ A value, optional suffix and descriptive label without automatic animation.
2632
+
2633
+ ### Import and runnable source
2634
+
2635
+ `import { Stat } from "@abuzareal/contour-ui";`
2636
+
2637
+ [Complete metadata TSX example](examples/catalogue/metadata.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2638
+
2639
+ ### Props and explicit defaults
2640
+
2641
+ | Prop | Type | Default | Responsibility |
2642
+ | --- | --- | --- | --- |
2643
+ | value / label | ReactNode / string | Required | Explain the quantity and its source/period nearby. |
2644
+ | suffix | string | Omitted | Units/suffix are visual text, not numeric parsing. |
2645
+
2646
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2647
+
2648
+ ### Purpose and alternatives
2649
+
2650
+ Use for a meaningful measured value with units/context. Label illustrative counts and estimates; use CountUp only when decorative numeric animation is appropriate.
2651
+
2652
+ ### Anatomy and parts
2653
+
2654
+ Container holds a strong value/optional suffix and a mono label. It is not a live region or a chart.
2655
+
2656
+ ### State ownership
2657
+
2658
+ Pure caller-owned value; no calculation, data source, formatting or refresh lifecycle.
2659
+
2660
+ ### Native forms and reset
2661
+
2662
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2663
+
2664
+ ### Ref target
2665
+
2666
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2667
+
2668
+ ### CSS and tokens
2669
+
2670
+ Use .contour-stat and suffix hook with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2671
+
2672
+ ### Loading, errors and long content
2673
+
2674
+ Show unavailable/stale/error state honestly instead of a fabricated value. Check long values/units, both themes and responsive overflow.
2675
+
2676
+ ### RTL and localization
2677
+
2678
+ Format the value/units with application locale APIs before rendering; suffix does not automatically pluralize or format numbers.
2679
+
2680
+ ### Keyboard and focus
2681
+
2682
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2683
+
2684
+ ### Limits and evidence
2685
+
2686
+ No calculation, CountUp behavior, invalid-number validation, automatic live announcement or external root ref.
2687
+
2688
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2689
+
2690
+ [Report Stat 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Stat&version=0.6.3) using the [public reproduction](examples/reproduction).
2691
+
2692
+ ## Stepper
2693
+
2694
+ A read-only ordered progress sequence with one zero-based current step.
2695
+
2696
+ ### Import and runnable source
2697
+
2698
+ `import { Stepper } from "@abuzareal/contour-ui";`
2699
+
2700
+ [Complete navigation TSX example](examples/catalogue/navigation.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2701
+
2702
+ ### Props and explicit defaults
2703
+
2704
+ | Prop | Type | Default | Responsibility |
2705
+ | --- | --- | --- | --- |
2706
+ | steps / current | step records[] / number | Required | Unique labels and a valid zero-based current index. |
2707
+ | label | string | Progress | Translate the ordered-list accessible name. |
2708
+
2709
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2710
+
2711
+ ### Purpose and alternatives
2712
+
2713
+ Use to describe progress through known stages. Supply separate real navigation controls; it is not a wizard engine or clickable step navigation.
2714
+
2715
+ ### Anatomy and parts
2716
+
2717
+ Ordered list with named progress, decorative number/check markers, labels/descriptions and aria-current=step on the current item.
2718
+
2719
+ ### State ownership
2720
+
2721
+ Caller supplies steps/current; current is a zero-based index. Previous items are complete, following items upcoming; no validation or transitions are owned.
2722
+
2723
+ ### Native forms and reset
2724
+
2725
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2726
+
2727
+ ### Ref target
2728
+
2729
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2730
+
2731
+ ### CSS and tokens
2732
+
2733
+ Use .contour-stepper and current/complete/upcoming hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2734
+
2735
+ ### Loading, errors and long content
2736
+
2737
+ Show failed/pending business state beside the steps rather than claiming completion. Keep long descriptions/narrow layouts and zero/last step correct.
2738
+
2739
+ ### RTL and localization
2740
+
2741
+ Translate label/step text. Hidden state suffixes are currently English and numbers use formatIndex; do not claim complete localization.
2742
+
2743
+ ### Keyboard and focus
2744
+
2745
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
2746
+
2747
+ ### Limits and evidence
2748
+
2749
+ No onChange, disabled/async/error state, clicking or current-range sanitization. Built-in hidden state words complete/current/upcoming and numeric formatting are not configurable.
2750
+
2751
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2752
+
2753
+ [Report Stepper 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Stepper&version=0.6.3) using the [public reproduction](examples/reproduction).
2754
+
2755
+ ## Switch
2756
+
2757
+ A button-based switch with native checkbox-backed submission, validation and reset.
2758
+
2759
+ ### Import and runnable source
2760
+
2761
+ `import { Switch } from "@abuzareal/contour-ui";`
2762
+
2763
+ [Complete choices TSX example](examples/catalogue/choices.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2764
+
2765
+ ### Props and explicit defaults
2766
+
2767
+ | Prop | Type | Default | Responsibility |
2768
+ | --- | --- | --- | --- |
2769
+ | label | string | Required | Use an understandable setting name. |
2770
+ | checked / defaultChecked / onChange | boolean / boolean / (checked: boolean) => void | Uncontrolled false | Choose controlled or default ownership. |
2771
+ | name / form / value | string | value="on"; name/form omitted | Checked, enabled backing input submits this value. |
2772
+ | required / requiredMessage | boolean / string | Message: Turn on this option to continue. | Native invalid feedback focuses the visible button unless caller owns onInvalid. |
2773
+ | description / error / onInvalid | string / string / native invalid handler | Omitted | Preserve linked supporting text and caller-owned validation. |
2774
+
2775
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2776
+
2777
+ ### Purpose and alternatives
2778
+
2779
+ Use for an on/off setting. Use Checkbox when the user is selecting an item or acknowledging a statement; a switch does not perform a backend operation by itself.
2780
+
2781
+ ### Anatomy and parts
2782
+
2783
+ Visible button role=switch links to its label, description and error. A hidden native checkbox supplies form participation; it is not the focus target.
2784
+
2785
+ ### State ownership
2786
+
2787
+ checked/onChange is controlled; defaultChecked captures initial uncontrolled state, otherwise false. onChange receives the next boolean. A caller onClick may prevent activation.
2788
+
2789
+ ### Native forms and reset
2790
+
2791
+ Named checked enabled state submits value (default "on"); unchecked/disabled is omitted. form supports external owners; required uses the backing checkbox with visible-button feedback. Native reset restores uncontrolled defaults without synthetic change callbacks; controlled owners reset explicitly.
2792
+
2793
+ ### Ref target
2794
+
2795
+ Forwarded HTMLButtonElement, not the hidden HTMLInputElement.
2796
+
2797
+ ### CSS and tokens
2798
+
2799
+ Use .contour-switch, .contour-switch-track and checked/invalid states with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2800
+
2801
+ ### Loading, errors and long content
2802
+
2803
+ Expose pending/save failure without claiming a successful setting change. Keep the label and validation visible; loading is an application composition rather than a Switch prop.
2804
+
2805
+ ### RTL and localization
2806
+
2807
+ Translate label/description/error/requiredMessage. RTL follows surrounding direction; browser validation and actual announcements still require platform checks.
2808
+
2809
+ ### Keyboard and focus
2810
+
2811
+ The native button toggles on Enter/Space. Its role and aria-checked communicate state; disabled prevents activation. The forwarded button ref supports programmatic focus.
2812
+
2813
+ ### Limits and evidence
2814
+
2815
+ The ref is a button, not the hidden checkbox. Callback is boolean, not a native change event. Persistence, service errors and immediate-save policy remain application-owned.
2816
+
2817
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2818
+
2819
+ [Report Switch 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Switch&version=0.6.3) using the [public reproduction](examples/reproduction).
2820
+
2821
+ ## Table
2822
+
2823
+ Semantic table styling for native rows, cells and application-owned table engines.
2824
+
2825
+ ### Import and runnable source
2826
+
2827
+ `import { Table } from "@abuzareal/contour-ui";`
2828
+
2829
+ [Complete selection TSX example](examples/catalogue/combobox.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2830
+
2831
+ ### Props and explicit defaults
2832
+
2833
+ | Prop | Type | Default | Responsibility |
2834
+ | --- | --- | --- | --- |
2835
+ | caption / children | string / ReactNode | Required | Supply semantic table children; the component owns caption. |
2836
+ | showCaption | boolean | false | Caption remains accessible when visually hidden. |
2837
+ | scrollProps | NativePartProps<div> | Omitted | Configure the scroll wrapper, including its native ref. |
2838
+ | ref | React.Ref<HTMLTableElement> | Omitted | Targets the table, not its wrapper. |
2839
+
2840
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2841
+
2842
+ ### Purpose and alternatives
2843
+
2844
+ Use for semantic application-owned rows/cells or a table-engine integration. DataTable provides a bounded local-sort convenience API. Neither is a virtualized grid.
2845
+
2846
+ ### Anatomy and parts
2847
+
2848
+ Scrollable wrapper contains native table and an owned caption. Supply thead/tbody/tr/th/td with correct scopes; do not add a second caption. scrollProps customizes the wrapper.
2849
+
2850
+ ### State ownership
2851
+
2852
+ Table has no fetching, sorting, pagination or selection state. showCaption defaults false while the caption remains accessible. The remote recipe owns its query and results.
2853
+
2854
+ ### Native forms and reset
2855
+
2856
+ Not a form control. Place explicit labelled controls in cells where needed and own selection/submission separately.
2857
+
2858
+ ### Ref target
2859
+
2860
+ Forwarded ref targets HTMLTableElement; scrollProps.ref targets the wrapper div.
2861
+
2862
+ ### CSS and tokens
2863
+
2864
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
2865
+
2866
+ ### Loading, errors and long content
2867
+
2868
+ Provide truthful loading, empty, no-match, permission and service-failure states. Stable row IDs, remote totals, cancellation and stale-result protection are application contracts. Long cells can scroll at narrow widths.
2869
+
2870
+ ### RTL and localization
2871
+
2872
+ Translate caption/headings/status and format numbers/dates using your application locale. Use appropriate th scope and check RTL horizontal scrolling; a visual sort arrow alone is insufficient.
2873
+
2874
+ ### Keyboard and focus
2875
+
2876
+ Native table reading order. Interactive cell controls retain native keyboard behavior; Table adds no grid roving focus.
2877
+
2878
+ ### Limits and evidence
2879
+
2880
+ No built-in data model, remote fetch, pagination, selection or virtualization. Compose the public recipe for controlled TanStack table integration.
2881
+
2882
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2883
+
2884
+ [Report Table 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Table&version=0.6.3) using the [public reproduction](examples/reproduction).
2885
+
2886
+ ## Tabs
2887
+
2888
+ Automatic-selection horizontal tabs for switching related local views.
2889
+
2890
+ ### Import and runnable source
2891
+
2892
+ `import { Tabs } from "@abuzareal/contour-ui";`
2893
+
2894
+ [Complete navigation TSX example](examples/catalogue/navigation.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2895
+
2896
+ ### Props and explicit defaults
2897
+
2898
+ | Prop | Type | Default | Responsibility |
2899
+ | --- | --- | --- | --- |
2900
+ | label | string | Required | Accessible name of the tab list. |
2901
+ | tabs | {id, label, content}[] | Required | Use stable, unique ids and keep content relevant to the same task. |
2902
+ | defaultTabId | string | First available tab | Initial selection. Invalid ids fall back to the first tab; an empty list renders no selected tab. |
2903
+ | activeTabId / onTabChange | string / (id: string) => void | Uncontrolled when activeTabId is omitted | Update activeTabId in response to onTabChange for controlled selection. The application owns persistence and URL synchronization. |
2904
+
2905
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2906
+
2907
+ ### Purpose and alternatives
2908
+
2909
+ Use for related local views. Use anchors/navigation for routes, and avoid automatic activation for panels with expensive work that should require confirmation.
2910
+
2911
+ ### Anatomy and parts
2912
+
2913
+ Root div contains a named tablist and matched tab/button-panel IDs. listProps and each item's buttonProps/panelProps target typed native parts.
2914
+
2915
+ ### State ownership
2916
+
2917
+ activeTabId/onTabChange is controlled; defaultTabId initializes uncontrolled selection. Stable IDs survive reorder. Invalid selection falls back to an available tab; empty arrays have no selected panel.
2918
+
2919
+ ### Native forms and reset
2920
+
2921
+ Tab buttons are type=button and do not submit a form. Tabs does not reset application panel state or synchronize URL/history.
2922
+
2923
+ ### Ref target
2924
+
2925
+ Forwarded ref targets the root div; part refs target list, tab buttons and panels.
2926
+
2927
+ ### CSS and tokens
2928
+
2929
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
2930
+
2931
+ ### Loading, errors and long content
2932
+
2933
+ There is no disabled-tab contract. Keep ownership consistent and preserve important panel state explicitly. Loading/error belong inside the relevant panel; test long labels without clipped navigation.
2934
+
2935
+ ### RTL and localization
2936
+
2937
+ Translate the list name and labels. Left/Right follows inherited RTL; Home/End choose endpoints. Check your panel reading direction and mixed-language labels.
2938
+
2939
+ ### Keyboard and focus
2940
+
2941
+ Left/Right select and focus the adjacent tab. Home/End move to first/last. The active panel follows the focused tab.
2942
+
2943
+ ### Limits and evidence
2944
+
2945
+ No disabled-tab contract or automatic URL synchronization. Use stable ids, and keep controlled or uncontrolled ownership consistent.
2946
+
2947
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
2948
+
2949
+ [Report Tabs 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Tabs&version=0.6.3) using the [public reproduction](examples/reproduction).
2950
+
2951
+ ## Tag
2952
+
2953
+ Text metadata that optionally exposes a native remove action.
2954
+
2955
+ ### Import and runnable source
2956
+
2957
+ `import { Tag } from "@abuzareal/contour-ui";`
2958
+
2959
+ [Complete metadata TSX example](examples/catalogue/metadata.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
2960
+
2961
+ ### Props and explicit defaults
2962
+
2963
+ | Prop | Type | Default | Responsibility |
2964
+ | --- | --- | --- | --- |
2965
+ | children | string | Required | Readable tag text and default removal-name input. |
2966
+ | onRemove | () => void | Omitted | Supplying it renders the remove button; update parent data. |
2967
+ | removeLabel | string | Remove plus tag text | Translate/customize the accessible action name. |
2968
+
2969
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
2970
+
2971
+ ### Purpose and alternatives
2972
+
2973
+ Use for a tag or removable chosen item. This is not a searchable multi-select, command chip or toggle button.
2974
+
2975
+ ### Anatomy and parts
2976
+
2977
+ Without onRemove it is a text span. With onRemove it includes a type=button remove control named from removeLabel or Remove plus children.
2978
+
2979
+ ### State ownership
2980
+
2981
+ Parent owns the tag collection and actually removes items. No internal selected/removed state or focus-reassignment policy.
2982
+
2983
+ ### Native forms and reset
2984
+
2985
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
2986
+
2987
+ ### Ref target
2988
+
2989
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
2990
+
2991
+ ### CSS and tokens
2992
+
2993
+ Use .contour-tag and .contour-tag-remove with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
2994
+
2995
+ ### Loading, errors and long content
2996
+
2997
+ Keep long names/remove targets usable; preserve data on service failure and label optimistic state if used. Removing the DOM node does not automatically focus its neighbor.
2998
+
2999
+ ### RTL and localization
3000
+
3001
+ Translate removeLabel; the default Remove prefix is English. Keep stable record IDs independent of display text.
3002
+
3003
+ ### Keyboard and focus
3004
+
3005
+ Only a present remove button is focusable; Enter/Space requests removal. Parent chooses useful focus after deleting the focused tag.
3006
+
3007
+ ### Limits and evidence
3008
+
3009
+ No arbitrary children, selection semantics, keyboard chip-list model, input parsing or successful-control serialization.
3010
+
3011
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3012
+
3013
+ [Report Tag 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Tag&version=0.6.3) using the [public reproduction](examples/reproduction).
3014
+
3015
+ ## TextArea
3016
+
3017
+ A labelled multiline control with optional growth and a character count.
3018
+
3019
+ ### Import and runnable source
3020
+
3021
+ `import { TextArea } from "@abuzareal/contour-ui";`
3022
+
3023
+ [Complete text-inputs TSX example](examples/catalogue/text-inputs.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3024
+
3025
+ ### Props and explicit defaults
3026
+
3027
+ | Prop | Type | Default | Responsibility |
3028
+ | --- | --- | --- | --- |
3029
+ | label | string | Required | Visible accessible label; do not replace it with placeholder text. |
3030
+ | value / defaultValue | Native control props | Uncontrolled when value is omitted | Use value with onChange for application-controlled state. Keep one ownership model. |
3031
+ | id / name / form | string | Generated id; native form association | Supply name for FormData and a stable id when other content describes the field. |
3032
+ | hint / error | string | Omitted | Descriptions are linked to the control; error also sets aria-invalid. |
3033
+ | maxLength | number | Omitted | Native limit plus a counter, including a zero limit. Uncontrolled counters synchronize after native form.reset(). |
3034
+ | disabled / required / onChange | Native control props | Native defaults | Supply business validation, loading state and change handling in your application. |
3035
+ | ref | React.Ref<HTMLTextAreaElement> | Omitted | Access the native textarea for focus or a form controller. |
3036
+ | autoResize | boolean | false | Grows with content; check long values and constrained containers. |
3037
+ | rows | number | 3 | Native initial row count. |
3038
+
3039
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3040
+
3041
+ ### Purpose and alternatives
3042
+
3043
+ Use for native text entry. Use SelectField or Combobox when only an allowed value is valid; TextArea is not a rich-text editor.
3044
+
3045
+ ### Anatomy and parts
3046
+
3047
+ Field renders the label, control slot and linked hint/error/counter. The actual input or textarea owns native attributes and focus. Error takes precedence over hint.
3048
+
3049
+ ### State ownership
3050
+
3051
+ value/onChange controls the value; otherwise defaultValue initializes native state. Do not switch ownership after mount. Disabled and readOnly retain their native meanings.
3052
+
3053
+ ### Native forms and reset
3054
+
3055
+ Set name to include the value in FormData, and form for an external form owner. Uncontrolled native reset restores value, counter and textarea measurement. Controlled owners must restore their state; reset cancellation is respected.
3056
+
3057
+ ### Ref target
3058
+
3059
+ The forwarded ref targets the native input (TextField) or textarea (TextArea), not the Field wrapper.
3060
+
3061
+ ### CSS and tokens
3062
+
3063
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
3064
+
3065
+ ### Loading, errors and long content
3066
+
3067
+ maxLength=0 is a real limit. Keep lengthy labels, errors and counters readable at narrow widths. Application loading, server validation and retry are separate; retain valid input after a failed save.
3068
+
3069
+ ### RTL and localization
3070
+
3071
+ Translate labels, hints and errors; use inputMode, autoComplete and dir where appropriate. The counter is not a locale-aware grapheme validator. Check mixed-direction values and your own formatting.
3072
+
3073
+ ### Keyboard and focus
3074
+
3075
+ Native multiline editing, selection and Tab order.
3076
+
3077
+ ### Limits and evidence
3078
+
3079
+ Native reset restores uncontrolled values, counters and auto-resized height. Controlled values require an application state reset. Auto-resize measures the rendered control; verify constrained containers and long text.
3080
+
3081
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3082
+
3083
+ [Report TextArea 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=TextArea&version=0.6.3) using the [public reproduction](examples/reproduction).
3084
+
3085
+ ## TextField
3086
+
3087
+ A labelled native input with linked hint, error and character count.
3088
+
3089
+ ### Import and runnable source
3090
+
3091
+ `import { TextField } from "@abuzareal/contour-ui";`
3092
+
3093
+ [Complete text-inputs TSX example](examples/catalogue/text-inputs.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3094
+
3095
+ ### Props and explicit defaults
3096
+
3097
+ | Prop | Type | Default | Responsibility |
3098
+ | --- | --- | --- | --- |
3099
+ | label | string | Required | Visible accessible label; do not replace it with placeholder text. |
3100
+ | value / defaultValue | Native control props | Uncontrolled when value is omitted | Use value with onChange for application-controlled state. Keep one ownership model. |
3101
+ | id / name / form | string | Generated id; native form association | Supply name for FormData and a stable id when other content describes the field. |
3102
+ | hint / error | string | Omitted | Descriptions are linked to the control; error also sets aria-invalid. |
3103
+ | maxLength | number | Omitted | Native limit plus a counter, including a zero limit. Uncontrolled counters synchronize after native form.reset(). |
3104
+ | disabled / required / onChange | Native control props | Native defaults | Supply business validation, loading state and change handling in your application. |
3105
+ | ref | React.Ref<HTMLInputElement> | Omitted | Access the native input for focus or a form controller. |
3106
+ | leadingIcon / trailing | ReactNode | Omitted | Decorative icons need aria-hidden; interactive content needs its own label. |
3107
+
3108
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3109
+
3110
+ ### Purpose and alternatives
3111
+
3112
+ Use for native text entry. Use SelectField or Combobox when only an allowed value is valid; TextArea is not a rich-text editor.
3113
+
3114
+ ### Anatomy and parts
3115
+
3116
+ Field renders the label, control slot and linked hint/error/counter. The actual input or textarea owns native attributes and focus. Error takes precedence over hint.
3117
+
3118
+ ### State ownership
3119
+
3120
+ value/onChange controls the value; otherwise defaultValue initializes native state. Do not switch ownership after mount. Disabled and readOnly retain their native meanings.
3121
+
3122
+ ### Native forms and reset
3123
+
3124
+ Set name to include the value in FormData, and form for an external form owner. Uncontrolled native reset restores value, counter and textarea measurement. Controlled owners must restore their state; reset cancellation is respected.
3125
+
3126
+ ### Ref target
3127
+
3128
+ The forwarded ref targets the native input (TextField) or textarea (TextArea), not the Field wrapper.
3129
+
3130
+ ### CSS and tokens
3131
+
3132
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
3133
+
3134
+ ### Loading, errors and long content
3135
+
3136
+ maxLength=0 is a real limit. Keep lengthy labels, errors and counters readable at narrow widths. Application loading, server validation and retry are separate; retain valid input after a failed save.
3137
+
3138
+ ### RTL and localization
3139
+
3140
+ Translate labels, hints and errors; use inputMode, autoComplete and dir where appropriate. The counter is not a locale-aware grapheme validator. Check mixed-direction values and your own formatting.
3141
+
3142
+ ### Keyboard and focus
3143
+
3144
+ Native input editing and Tab order. Errors are descriptions, not a focus manager.
3145
+
3146
+ ### Limits and evidence
3147
+
3148
+ Business validation and submission remain application-owned. Native reset updates uncontrolled values and counters; controlled fields require your application to reset state. Keep one ownership model for the lifetime of the field.
3149
+
3150
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3151
+
3152
+ [Report TextField 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=TextField&version=0.6.3) using the [public reproduction](examples/reproduction).
3153
+
3154
+ ## ThemeScope
3155
+
3156
+ An independently controlled theme boundary for embedded Contour components and their portals.
3157
+
3158
+ ### Import and runnable source
3159
+
3160
+ `import { ThemeScope } from "@abuzareal/contour-ui";`
3161
+
3162
+ [Complete selection TSX example](examples/catalogue/combobox.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3163
+
3164
+ ### Props and explicit defaults
3165
+
3166
+ | Prop | Type | Default | Responsibility |
3167
+ | --- | --- | --- | --- |
3168
+ | theme | light \| dark | Required | Explicit independent theme. |
3169
+ | onThemeChange | (theme: Theme) => void | Omitted | Caller accepts embedded theme requests and owns persistence. |
3170
+ | children / dir / lang | Native div props | Optional | Compose content and direction inside the scope. |
3171
+ | ref | React.Ref<HTMLDivElement> | Omitted | Access the scope root. |
3172
+
3173
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3174
+
3175
+ ### Purpose and alternatives
3176
+
3177
+ Use to embed a light/dark Contour surface inside a host that owns its own theme. A document-wide theme control can use useTheme without a scope.
3178
+
3179
+ ### Anatomy and parts
3180
+
3181
+ A div with contour-root and explicit theme tokens supplies context to descendants and owned portalled layers. Use scoped.css for isolated component selectors.
3182
+
3183
+ ### State ownership
3184
+
3185
+ theme is required and controlled. onThemeChange allows embedded useTheme/ThemeToggle to request a new value; omitting it makes those controls read-only. Persistence is caller-owned.
3186
+
3187
+ ### Native forms and reset
3188
+
3189
+ No form value, validation or reset contract. A theme change does not submit the enclosing form.
3190
+
3191
+ ### Ref target
3192
+
3193
+ Forwarded ref targets HTMLDivElement. ThemeScope does not supply a motion setting or storage-key prop.
3194
+
3195
+ ### CSS and tokens
3196
+
3197
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
3198
+
3199
+ ### Loading, errors and long content
3200
+
3201
+ Check both light-in-dark and dark-in-light, nested scopes and portalled overlays. scoped.css does not rename the host's generic classes. Do not import the global reset unless its document-wide effect is intended.
3202
+
3203
+ ### RTL and localization
3204
+
3205
+ Native dir/lang attributes can be applied to the root. Translate toggle labels separately; theme selection does not determine language or direction.
3206
+
3207
+ ### Keyboard and focus
3208
+
3209
+ The root adds no keyboard control. Descendant theme buttons are type=button and keep their own focus behavior.
3210
+
3211
+ ### Limits and evidence
3212
+
3213
+ Use scoped.css. Omitting onThemeChange makes embedded theme controls read-only. No motion or persistence prop is supplied.
3214
+
3215
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3216
+
3217
+ [Report ThemeScope 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=ThemeScope&version=0.6.3) using the [public reproduction](examples/reproduction).
3218
+
3219
+ ## ThemeToggle
3220
+
3221
+ A native button that toggles the current theme owner when it is writable.
3222
+
3223
+ ### Import and runnable source
3224
+
3225
+ `import { ThemeToggle } from "@abuzareal/contour-ui";`
3226
+
3227
+ [Complete theme-copy TSX example](examples/catalogue/theme-copy.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3228
+
3229
+ ### Props and explicit defaults
3230
+
3231
+ | Prop | Type | Default | Responsibility |
3232
+ | --- | --- | --- | --- |
3233
+ | animate | boolean | Required | False switches instantly; system reduction/pause still governs motion. |
3234
+ | darkLabel / lightTitle / darkTitle | string | Dark theme / Switch to light theme / Switch to dark theme | Translate button name and action titles. |
3235
+
3236
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3237
+
3238
+ ### Purpose and alternatives
3239
+
3240
+ Use for a document preference or a writable ThemeScope. A controlled read-only scope cannot toggle itself; the owner must supply its change handler.
3241
+
3242
+ ### Anatomy and parts
3243
+
3244
+ Native button with decorative moon/sun icons uses aria-pressed for dark state, an accessible darkLabel and a direction-specific title.
3245
+
3246
+ ### State ownership
3247
+
3248
+ useTheme(animate) resolves the nearest theme owner; animate is required. Root integration owns aa-theme/storage/meta behavior; scoped owners own their state instead.
3249
+
3250
+ ### Native forms and reset
3251
+
3252
+ Native type=button never submits a form; no name/value/reset contract. Theme state resets only through its owner.
3253
+
3254
+ ### Ref target
3255
+
3256
+ Forwarded HTMLButtonElement.
3257
+
3258
+ ### CSS and tokens
3259
+
3260
+ Use .contour-theme-toggle and aria-pressed with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
3261
+
3262
+ ### Loading, errors and long content
3263
+
3264
+ Handle blocked storage in root integration and verify nested scopes/portals. A theme change must not imply data was saved; actual animation depends on browser/reduced-motion support.
3265
+
3266
+ ### RTL and localization
3267
+
3268
+ Translate all supplied strings; surrounding dir governs layout. Verify both themes, focus/forced colors and read-only scope behavior.
3269
+
3270
+ ### Keyboard and focus
3271
+
3272
+ Native Enter/Space activation and visible button focus. Disabled when the nearest scope is read-only; aria-pressed communicates dark state.
3273
+
3274
+ ### Limits and evidence
3275
+
3276
+ No native arbitrary button props or separate persistence namespace API. The accessible name is darkLabel in both states; title describes the next action.
3277
+
3278
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3279
+
3280
+ [Report ThemeToggle 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=ThemeToggle&version=0.6.3) using the [public reproduction](examples/reproduction).
3281
+
3282
+ ## TiltCard
3283
+
3284
+ A CSS depth wrapper reacting to mouse movement with a glare highlight.
3285
+
3286
+ ### Import and runnable source
3287
+
3288
+ `import { TiltCard } from "@abuzareal/contour-ui";`
3289
+
3290
+ [Complete motion TSX example](examples/catalogue/motion.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3291
+
3292
+ ### Props and explicit defaults
3293
+
3294
+ | Prop | Type | Default | Responsibility |
3295
+ | --- | --- | --- | --- |
3296
+ | children | ReactNode | Required | Meaningful content stays usable without tilt. |
3297
+ | maxTilt | number | 12 | Caller chooses a sensible finite rotation bound. |
3298
+
3299
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3300
+
3301
+ ### Purpose and alternatives
3302
+
3303
+ Use for optional visual emphasis. Put essential content/actions in native children; do not make pointer tilt necessary to discover or use them.
3304
+
3305
+ ### Anatomy and parts
3306
+
3307
+ Outer stage contains inner tilt card, children and decorative glare span; pointer geometry writes CSS custom properties.
3308
+
3309
+ ### State ownership
3310
+
3311
+ maxTilt defaults to 12 degrees. Mouse movement applies tilt unless motion is disabled; pointer leave removes tilt/glare overrides. Touch/pen do not drive the effect.
3312
+
3313
+ ### Native forms and reset
3314
+
3315
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
3316
+
3317
+ ### Ref target
3318
+
3319
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
3320
+
3321
+ ### CSS and tokens
3322
+
3323
+ Use .contour-tilt-stage, .contour-tilt-card and glare hook with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
3324
+
3325
+ ### Loading, errors and long content
3326
+
3327
+ Test long content, stationary focus targets, touch/reduced/paused motion and both themes. Overflow/glare must not cover essential controls.
3328
+
3329
+ ### RTL and localization
3330
+
3331
+ Children carry all language/direction. Tilt is decorative; do not reinterpret its direction as navigation.
3332
+
3333
+ ### Keyboard and focus
3334
+
3335
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
3336
+
3337
+ ### Limits and evidence
3338
+
3339
+ No gesture navigation, keyboard activation, forwarded ref or scene/GPU dependency. This is CSS, not a Three.js primitive.
3340
+
3341
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3342
+
3343
+ [Report TiltCard 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=TiltCard&version=0.6.3) using the [public reproduction](examples/reproduction).
3344
+
3345
+ ## Timeline
3346
+
3347
+ A read-only ordered list of dated descriptions.
3348
+
3349
+ ### Import and runnable source
3350
+
3351
+ `import { Timeline } from "@abuzareal/contour-ui";`
3352
+
3353
+ [Complete content TSX example](examples/catalogue/content.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3354
+
3355
+ ### Props and explicit defaults
3356
+
3357
+ | Prop | Type | Default | Responsibility |
3358
+ | --- | --- | --- | --- |
3359
+ | entries | {date,title,body?,current?}[] | Required | Provide correctly ordered entries and meaningful date/time context. |
3360
+
3361
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3362
+
3363
+ ### Purpose and alternatives
3364
+
3365
+ Use for an explicit chronological sequence. Dates are display strings; sort/parse/time-zone and factual versus illustrative provenance remain application-owned.
3366
+
3367
+ ### Anatomy and parts
3368
+
3369
+ Ordered list contains date, title, optional body and current class. Keys combine date/title; they must be unique and stable.
3370
+
3371
+ ### State ownership
3372
+
3373
+ Pure supplied entries; current is a visual flag, not automatic time comparison or native navigation.
3374
+
3375
+ ### Native forms and reset
3376
+
3377
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
3378
+
3379
+ ### Ref target
3380
+
3381
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
3382
+
3383
+ ### CSS and tokens
3384
+
3385
+ Use .contour-timeline and current-entry hook with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
3386
+
3387
+ ### Loading, errors and long content
3388
+
3389
+ Distinguish an empty history from failed loading. Keep long titles/descriptions readable; duplicate date/title combinations are unsupported identity.
3390
+
3391
+ ### RTL and localization
3392
+
3393
+ Format date strings with explicit application calendar/time-zone rules; translate text and verify long RTL sequences.
3394
+
3395
+ ### Keyboard and focus
3396
+
3397
+ Not a keyboard control and does not add a tab stop. Interactive children retain their native behavior; do not use this display as a substitute for a button or link.
3398
+
3399
+ ### Limits and evidence
3400
+
3401
+ No date parser, sorting/time-zone conversion, semantic time datetime prop, async loading or event interaction.
3402
+
3403
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3404
+
3405
+ [Report Timeline 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Timeline&version=0.6.3) using the [public reproduction](examples/reproduction).
3406
+
3407
+ ## ToastProvider
3408
+
3409
+ A notification region and useToast().show() for outcomes your application has already established.
3410
+
3411
+ ### Import and runnable source
3412
+
3413
+ `import { ToastProvider } from "@abuzareal/contour-ui";`
3414
+
3415
+ [Complete toasts TSX example](examples/catalogue/toasts.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3416
+
3417
+ ### Props and explicit defaults
3418
+
3419
+ | Prop | Type | Default | Responsibility |
3420
+ | --- | --- | --- | --- |
3421
+ | children | ReactNode | Required | Wrap components that call useToast(). |
3422
+ | show({title, message, tone}) | useToast() command | Title required; message optional | Report actual outcomes. A notification does not perform or persist the operation. |
3423
+ | tone | "neutral" \| "accent" \| "info" \| "success" \| "warning" \| "danger" | "neutral" | Match the result; do not use success before a request completes. |
3424
+
3425
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3426
+
3427
+ ### Purpose and alternatives
3428
+
3429
+ Use for brief established outcomes. Keep actionable errors beside the task; use an in-page alert for a failure that needs sustained attention.
3430
+
3431
+ ### Anatomy and parts
3432
+
3433
+ Provider owns a polite notification region with up to the latest three messages and dismiss buttons. Descendants call useToast().show({title,message?,tone?}).
3434
+
3435
+ ### State ownership
3436
+
3437
+ The queue auto-dismisses after five seconds and pauses while hovered/focused. show reports an outcome; it does not run an operation. There are no IDs, update commands, undo or durable inbox.
3438
+
3439
+ ### Native forms and reset
3440
+
3441
+ No native form value or reset contract. Notify only after a real save result, and preserve field validation in the form.
3442
+
3443
+ ### Ref target
3444
+
3445
+ No native provider ref. Calling useToast outside the provider throws; mount a provider around actual consumers.
3446
+
3447
+ ### CSS and tokens
3448
+
3449
+ Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md.
3450
+
3451
+ ### Loading, errors and long content
3452
+
3453
+ Rapid messages displace older entries. Do not put the only record of a failure in a temporary toast. Respect focus/motion and test translated long messages.
3454
+
3455
+ ### RTL and localization
3456
+
3457
+ Set label and dismissLabel on the provider and translate each title/message. Manual screen-reader announcement review remains pending; polite markup is not proof of every announcement.
3458
+
3459
+ ### Keyboard and focus
3460
+
3461
+ The close control is keyboard accessible. Messages appear in a polite live region; essential failures should also remain beside the task.
3462
+
3463
+ ### Limits and evidence
3464
+
3465
+ Notifications are temporary. This is not a durable inbox, async request controller or undo mechanism. Calling useToast outside the provider throws.
3466
+
3467
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3468
+
3469
+ [Report ToastProvider 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=ToastProvider&version=0.6.3) using the [public reproduction](examples/reproduction).
3470
+
3471
+ ## Tooltip
3472
+
3473
+ Supplemental noninteractive text associated with one focusable child.
3474
+
3475
+ ### Import and runnable source
3476
+
3477
+ `import { Tooltip } from "@abuzareal/contour-ui";`
3478
+
3479
+ [Complete floating TSX example](examples/catalogue/floating.tsx) uses the same public components as this guide. The family may compose several exports; it is not another package component.
3480
+
3481
+ ### Props and explicit defaults
3482
+
3483
+ | Prop | Type | Default | Responsibility |
3484
+ | --- | --- | --- | --- |
3485
+ | content / children | string / one focusable ReactElement | Required | Supply supplemental text and a child that accepts its description attribute. |
3486
+ | placement / align | top \| bottom \| left \| right / start \| center \| end | top / center | Collision placement may flip/shift. |
3487
+ | sideOffset / collisionPadding | number | 10 / 8 | Spacing and viewport collision padding. |
3488
+ | portal / container | boolean / HTMLElement | true / inferred owner target | Same-document custom container; disabling portals changes clipping/ancestor behavior. |
3489
+
3490
+ The emitted declaration is authoritative; [metadata](PROP-REFERENCE.md) preserves inherited props and call/construct signatures without inventing browser defaults.
3491
+
3492
+ ### Purpose and alternatives
3493
+
3494
+ Use for a short nonessential hint. Keep essential instructions visible; use Popover/Dialog for interactive content and never use a tooltip as the only label.
3495
+
3496
+ ### Anatomy and parts
3497
+
3498
+ Anchor wraps one React element and merges its aria-describedby with the hint ID. The noninteractive tooltip portal uses owner-body/native-dialog placement and collision handling.
3499
+
3500
+ ### State ownership
3501
+
3502
+ Hover/focus opens; pointer travel between anchor and content retains the hint. Escape suppresses it until the current hover/focus session ends. Closed portals are hidden in 0.6.2 and later without losing trigger description linkage.
3503
+
3504
+ ### Native forms and reset
3505
+
3506
+ Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.
3507
+
3508
+ ### Ref target
3509
+
3510
+ No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.
3511
+
3512
+ ### CSS and tokens
3513
+
3514
+ Use .contour-tooltip and placement/state hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract.
3515
+
3516
+ ### Loading, errors and long content
3517
+
3518
+ Test edge/long content, clipped ancestors, nested native dialogs, pointer corridors and description merging. Keep a usable visible explanation if the hint cannot display.
3519
+
3520
+ ### RTL and localization
3521
+
3522
+ Translate content and child label; use surrounding dir for logical alignment. Long translations may wrap and collision positioning may change side.
3523
+
3524
+ ### Keyboard and focus
3525
+
3526
+ Focus the child with its native keyboard mechanism. Escape dismisses only the active topmost layer; the hint is not a focus target. Interactive hint content is unsupported.
3527
+
3528
+ ### Limits and evidence
3529
+
3530
+ One focusable child and string content; no interactive popup, validation message replacement or focus trap. Manual screen-reader announcements remain pending.
3531
+
3532
+ [Support and pending manual checks](SUPPORT.md), [migration](MIGRATION.md), [defining source/types](PUBLIC-API.md). Validate the actual application, platform, content and request flow; automated fixtures are not universal WCAG/device evidence.
3533
+
3534
+ [Report Tooltip 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Tooltip&version=0.6.3) using the [public reproduction](examples/reproduction).