@tempoxyz/ds 0.3.10 → 0.3.13

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 (210) hide show
  1. package/README.md +7 -6
  2. package/dist/docs/AGENTS.md +12 -0
  3. package/dist/docs/index.md +145 -0
  4. package/dist/docs/marketing/introduction/getting-started.md +241 -0
  5. package/dist/docs/product/components/accordion.md +489 -0
  6. package/dist/docs/product/components/address-card.md +147 -0
  7. package/dist/docs/product/components/agent-logo.md +194 -0
  8. package/dist/docs/product/components/alert-dialog.md +631 -0
  9. package/dist/docs/product/components/alert.md +448 -0
  10. package/dist/docs/product/components/amount-input.md +305 -0
  11. package/dist/docs/product/components/amount.md +794 -0
  12. package/dist/docs/product/components/app-shell.md +559 -0
  13. package/dist/docs/product/components/asset-chip.md +294 -0
  14. package/dist/docs/product/components/autocomplete.md +620 -0
  15. package/dist/docs/product/components/avatar.md +321 -0
  16. package/dist/docs/product/components/badge.md +339 -0
  17. package/dist/docs/product/components/badged-logo.md +116 -0
  18. package/dist/docs/product/components/banner.md +379 -0
  19. package/dist/docs/product/components/bar-chart.md +208 -0
  20. package/dist/docs/product/components/breadcrumbs.md +380 -0
  21. package/dist/docs/product/components/button-group.md +286 -0
  22. package/dist/docs/product/components/button.md +650 -0
  23. package/dist/docs/product/components/calendar.md +375 -0
  24. package/dist/docs/product/components/callout.md +96 -0
  25. package/dist/docs/product/components/checkbox-group.md +521 -0
  26. package/dist/docs/product/components/checkbox.md +467 -0
  27. package/dist/docs/product/components/choice-group.md +516 -0
  28. package/dist/docs/product/components/choicebox.md +641 -0
  29. package/dist/docs/product/components/code.md +100 -0
  30. package/dist/docs/product/components/combobox.md +939 -0
  31. package/dist/docs/product/components/container.md +257 -0
  32. package/dist/docs/product/components/copy-button.md +642 -0
  33. package/dist/docs/product/components/date-picker.md +514 -0
  34. package/dist/docs/product/components/dialog.md +1332 -0
  35. package/dist/docs/product/components/drawer.md +966 -0
  36. package/dist/docs/product/components/empty.md +340 -0
  37. package/dist/docs/product/components/field.md +570 -0
  38. package/dist/docs/product/components/fieldset.md +398 -0
  39. package/dist/docs/product/components/frame.md +434 -0
  40. package/dist/docs/product/components/gauge.md +299 -0
  41. package/dist/docs/product/components/get-started-visual.md +117 -0
  42. package/dist/docs/product/components/grid.md +288 -0
  43. package/dist/docs/product/components/hero-visual.md +155 -0
  44. package/dist/docs/product/components/hex.md +487 -0
  45. package/dist/docs/product/components/icon-tile.md +292 -0
  46. package/dist/docs/product/components/identicon.md +371 -0
  47. package/dist/docs/product/components/inline.md +233 -0
  48. package/dist/docs/product/components/inset.md +225 -0
  49. package/dist/docs/product/components/kbd.md +423 -0
  50. package/dist/docs/product/components/list-group.md +981 -0
  51. package/dist/docs/product/components/loading-dots.md +237 -0
  52. package/dist/docs/product/components/menu.md +934 -0
  53. package/dist/docs/product/components/native-select.md +204 -0
  54. package/dist/docs/product/components/network-logo.md +248 -0
  55. package/dist/docs/product/components/number-field.md +543 -0
  56. package/dist/docs/product/components/otp-field.md +616 -0
  57. package/dist/docs/product/components/pagination.md +516 -0
  58. package/dist/docs/product/components/popover.md +544 -0
  59. package/dist/docs/product/components/progress.md +388 -0
  60. package/dist/docs/product/components/qr.md +314 -0
  61. package/dist/docs/product/components/radio-group.md +528 -0
  62. package/dist/docs/product/components/secret-value.md +406 -0
  63. package/dist/docs/product/components/select.md +751 -0
  64. package/dist/docs/product/components/separator.md +379 -0
  65. package/dist/docs/product/components/sidebar-menu.md +922 -0
  66. package/dist/docs/product/components/skeleton.md +517 -0
  67. package/dist/docs/product/components/slider.md +539 -0
  68. package/dist/docs/product/components/snippet.md +424 -0
  69. package/dist/docs/product/components/spinner.md +216 -0
  70. package/dist/docs/product/components/split-bar.md +139 -0
  71. package/dist/docs/product/components/split-button.md +464 -0
  72. package/dist/docs/product/components/stack.md +299 -0
  73. package/dist/docs/product/components/status-chip.md +226 -0
  74. package/dist/docs/product/components/status-indicator.md +119 -0
  75. package/dist/docs/product/components/status-row.md +174 -0
  76. package/dist/docs/product/components/stepper.md +451 -0
  77. package/dist/docs/product/components/success-hero.md +157 -0
  78. package/dist/docs/product/components/surface.md +639 -0
  79. package/dist/docs/product/components/switch.md +472 -0
  80. package/dist/docs/product/components/table.md +967 -0
  81. package/dist/docs/product/components/tabs.md +627 -0
  82. package/dist/docs/product/components/tempo-logo.md +185 -0
  83. package/dist/docs/product/components/text-input.md +624 -0
  84. package/dist/docs/product/components/textarea.md +352 -0
  85. package/dist/docs/product/components/toast.md +535 -0
  86. package/dist/docs/product/components/token-logo.md +371 -0
  87. package/dist/docs/product/components/token.md +247 -0
  88. package/dist/docs/product/components/tooltip.md +490 -0
  89. package/dist/docs/product/components/verification-code.md +116 -0
  90. package/dist/docs/product/components/visual.md +249 -0
  91. package/dist/docs/product/components.md +203 -0
  92. package/dist/docs/product/foundations/accessibility.md +377 -0
  93. package/dist/docs/product/foundations/agents.md +150 -0
  94. package/dist/docs/product/foundations/color.md +522 -0
  95. package/dist/docs/product/foundations/content/tone.md +194 -0
  96. package/dist/docs/product/foundations/content/voice.md +194 -0
  97. package/dist/docs/product/foundations/content/writing-style.md +406 -0
  98. package/dist/docs/product/foundations/iconography.md +282 -0
  99. package/dist/docs/product/foundations/intent.md +360 -0
  100. package/dist/docs/product/foundations/layout.md +508 -0
  101. package/dist/docs/product/foundations/linter.md +496 -0
  102. package/dist/docs/product/foundations/motion.md +151 -0
  103. package/dist/docs/product/foundations/radius-and-padding.md +86 -0
  104. package/dist/docs/product/foundations/typography.md +266 -0
  105. package/dist/docs/product/introduction/faq.md +133 -0
  106. package/dist/docs/product/introduction/getting-started.md +377 -0
  107. package/dist/docs/product/patterns/blockchain-values.md +709 -0
  108. package/dist/docs/product/patterns/dashboards.md +638 -0
  109. package/dist/docs/product/patterns/destructive-actions.md +626 -0
  110. package/dist/docs/product/patterns/empty-states.md +612 -0
  111. package/dist/docs/product/patterns/errors-and-validation.md +808 -0
  112. package/dist/docs/product/patterns/feedback-and-status.md +518 -0
  113. package/dist/docs/product/patterns/forms.md +679 -0
  114. package/dist/docs/product/patterns/loading.md +630 -0
  115. package/dist/docs/product/patterns/navigation.md +397 -0
  116. package/dist/docs/product/patterns/payments.md +765 -0
  117. package/dist/docs/product/patterns/responsive-layout.md +997 -0
  118. package/dist/docs/product/patterns/tables-and-lists.md +964 -0
  119. package/dist/docs/product/products/tempo-console.md +671 -0
  120. package/dist/docs/product/products/tempo-performance.md +437 -0
  121. package/dist/docs/product/products/tempo-wallet.md +438 -0
  122. package/dist/marketing/index.d.ts +4 -0
  123. package/dist/marketing/index.d.ts.map +1 -0
  124. package/dist/marketing/index.js +4 -0
  125. package/dist/marketing/index.js.map +1 -0
  126. package/dist/marketing/index.js.zyzz.json +1 -0
  127. package/dist/marketing/vars.d.ts +907 -0
  128. package/dist/marketing/vars.d.ts.map +1 -0
  129. package/dist/marketing/vars.js +15 -0
  130. package/dist/marketing/vars.js.map +1 -0
  131. package/dist/marketing/vars.js.zyzz.json +1 -0
  132. package/dist/marketing/zyzz.config.d.ts +4512 -0
  133. package/dist/marketing/zyzz.config.d.ts.map +1 -0
  134. package/dist/marketing/zyzz.config.js +63 -0
  135. package/dist/marketing/zyzz.config.js.map +1 -0
  136. package/dist/marketing/zyzz.config.js.zyzz.json +1 -0
  137. package/dist/oxlint/index.d.ts +12 -1
  138. package/dist/oxlint/index.d.ts.map +1 -1
  139. package/dist/oxlint/index.js +39 -1
  140. package/dist/oxlint/index.js.map +1 -1
  141. package/dist/oxlint/internal/Docs.d.ts +9 -0
  142. package/dist/oxlint/internal/Docs.d.ts.map +1 -0
  143. package/dist/oxlint/internal/Docs.js +15 -0
  144. package/dist/oxlint/internal/Docs.js.map +1 -0
  145. package/dist/oxlint/internal/Imports.d.ts +1 -1
  146. package/dist/oxlint/internal/Imports.d.ts.map +1 -1
  147. package/dist/oxlint/internal/Imports.js +2 -0
  148. package/dist/oxlint/internal/Imports.js.map +1 -1
  149. package/dist/oxlint/internal/Styles.d.ts +40 -0
  150. package/dist/oxlint/internal/Styles.d.ts.map +1 -0
  151. package/dist/oxlint/internal/Styles.js +194 -0
  152. package/dist/oxlint/internal/Styles.js.map +1 -0
  153. package/dist/oxlint/internal/Tokens.d.ts +16 -0
  154. package/dist/oxlint/internal/Tokens.d.ts.map +1 -0
  155. package/dist/oxlint/internal/Tokens.js +39 -0
  156. package/dist/oxlint/internal/Tokens.js.map +1 -0
  157. package/dist/oxlint/rules/NoCrossSurface.d.ts +2 -2
  158. package/dist/oxlint/rules/NoCrossSurface.js +3 -3
  159. package/dist/oxlint/rules/NoCrossSurface.js.map +1 -1
  160. package/dist/oxlint/rules/NoCustomValues.d.ts +11 -0
  161. package/dist/oxlint/rules/NoCustomValues.d.ts.map +1 -0
  162. package/dist/oxlint/rules/NoCustomValues.js +150 -0
  163. package/dist/oxlint/rules/NoCustomValues.js.map +1 -0
  164. package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts +11 -0
  165. package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts.map +1 -0
  166. package/dist/oxlint/rules/NoSingleKeyShortcuts.js +158 -0
  167. package/dist/oxlint/rules/NoSingleKeyShortcuts.js.map +1 -0
  168. package/dist/oxlint/rules/PreferComponent.d.ts +3 -2
  169. package/dist/oxlint/rules/PreferComponent.d.ts.map +1 -1
  170. package/dist/oxlint/rules/PreferComponent.js +11 -4
  171. package/dist/oxlint/rules/PreferComponent.js.map +1 -1
  172. package/dist/oxlint/rules/PreferLayout.d.ts +9 -0
  173. package/dist/oxlint/rules/PreferLayout.d.ts.map +1 -0
  174. package/dist/oxlint/rules/PreferLayout.js +90 -0
  175. package/dist/oxlint/rules/PreferLayout.js.map +1 -0
  176. package/dist/oxlint/rules/PreferProgress.d.ts +9 -0
  177. package/dist/oxlint/rules/PreferProgress.d.ts.map +1 -0
  178. package/dist/oxlint/rules/PreferProgress.js +43 -0
  179. package/dist/oxlint/rules/PreferProgress.js.map +1 -0
  180. package/dist/oxlint/rules/PreferSurface.d.ts +9 -0
  181. package/dist/oxlint/rules/PreferSurface.d.ts.map +1 -0
  182. package/dist/oxlint/rules/PreferSurface.js +55 -0
  183. package/dist/oxlint/rules/PreferSurface.js.map +1 -0
  184. package/dist/oxlint/rules/RequireAccessibleName.d.ts.map +1 -1
  185. package/dist/oxlint/rules/RequireAccessibleName.js +3 -1
  186. package/dist/oxlint/rules/RequireAccessibleName.js.map +1 -1
  187. package/dist/oxlint/rules/RequireScrollRegion.d.ts +11 -0
  188. package/dist/oxlint/rules/RequireScrollRegion.d.ts.map +1 -0
  189. package/dist/oxlint/rules/RequireScrollRegion.js +71 -0
  190. package/dist/oxlint/rules/RequireScrollRegion.js.map +1 -0
  191. package/dist/web/icons/index.js.zyzz.json +1 -0
  192. package/package.json +6 -1
  193. package/src/marketing/README.md +21 -0
  194. package/src/marketing/index.ts +3 -0
  195. package/src/marketing/vars.ts +751 -0
  196. package/src/marketing/zyzz.config.ts +376 -0
  197. package/src/oxlint/index.ts +40 -1
  198. package/src/oxlint/internal/Docs.ts +18 -0
  199. package/src/oxlint/internal/Imports.ts +2 -1
  200. package/src/oxlint/internal/Styles.ts +240 -0
  201. package/src/oxlint/internal/Tokens.ts +43 -0
  202. package/src/oxlint/rules/NoCrossSurface.ts +3 -3
  203. package/src/oxlint/rules/NoCustomValues.ts +170 -0
  204. package/src/oxlint/rules/NoSingleKeyShortcuts.ts +190 -0
  205. package/src/oxlint/rules/PreferComponent.ts +11 -4
  206. package/src/oxlint/rules/PreferLayout.ts +96 -0
  207. package/src/oxlint/rules/PreferProgress.ts +49 -0
  208. package/src/oxlint/rules/PreferSurface.ts +70 -0
  209. package/src/oxlint/rules/RequireAccessibleName.ts +3 -1
  210. package/src/oxlint/rules/RequireScrollRegion.ts +92 -0
@@ -0,0 +1,539 @@
1
+ # Slider
2
+
3
+ Picks a single value or a range by dragging.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Slider.tsx)
6
+
7
+ ## Overview
8
+
9
+ Slider renders a horizontal control for a single value or a range, with one `Slider.Thumb` per value.
10
+
11
+ ## Examples
12
+
13
+ ### Basic
14
+
15
+ ```tsx
16
+ import { Slider, style } from '@tempoxyz/ds'
17
+ import { useState } from 'react'
18
+
19
+ export const fill = true
20
+ export function Demo() {
21
+ const [amount, setAmount] = useState(40)
22
+
23
+ return (
24
+ <Slider.Root aria-label="Amount" onValueChange={setAmount} value={amount} {...styles.root()}>
25
+ <div {...styles.header()}>
26
+ <span>Amount</span>
27
+ <Slider.Value />
28
+ </div>
29
+ <Slider.Control>
30
+ <Slider.Track>
31
+ <Slider.Indicator />
32
+ <Slider.Thumb aria-label="Amount" />
33
+ </Slider.Track>
34
+ </Slider.Control>
35
+ </Slider.Root>
36
+ )
37
+ }
38
+
39
+ namespace styles {
40
+ export const header = style({
41
+ display: 'flex',
42
+ justifyContent: 'space-between',
43
+ marginBottom: '8',
44
+ })
45
+
46
+ export const root = style({ maxWidth: '360px !custom' })
47
+ }
48
+ ```
49
+
50
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Slider/Basic.tsx)
51
+
52
+ ### Range
53
+
54
+ Pass an array to `defaultValue` or `value` and add one `Slider.Thumb` per value, each with its `index`.
55
+
56
+ ```tsx
57
+ import { Slider, style } from '@tempoxyz/ds'
58
+
59
+ export const fill = true
60
+ export function Demo() {
61
+ return (
62
+ <Slider.Root aria-label="Range" defaultValue={[20, 70]} {...styles.root()}>
63
+ <Slider.Control>
64
+ <Slider.Track>
65
+ <Slider.Indicator />
66
+ <Slider.Thumb aria-label="Minimum" index={0} />
67
+ <Slider.Thumb aria-label="Maximum" index={1} />
68
+ </Slider.Track>
69
+ </Slider.Control>
70
+ </Slider.Root>
71
+ )
72
+ }
73
+
74
+ namespace styles {
75
+ export const root = style({ maxWidth: '360px !custom' })
76
+ }
77
+ ```
78
+
79
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Slider/Range.tsx)
80
+
81
+ ### Disabled
82
+
83
+ Set `disabled` to lock the slider at its current value.
84
+
85
+ ```tsx
86
+ import { Slider, style } from '@tempoxyz/ds'
87
+
88
+ export const fill = true
89
+ export function Demo() {
90
+ return (
91
+ <Slider.Root aria-label="Locked" defaultValue={60} disabled {...styles.root()}>
92
+ <Slider.Control>
93
+ <Slider.Track>
94
+ <Slider.Indicator />
95
+ <Slider.Thumb aria-label="Locked" />
96
+ </Slider.Track>
97
+ </Slider.Control>
98
+ </Slider.Root>
99
+ )
100
+ }
101
+
102
+ namespace styles {
103
+ export const root = style({ maxWidth: '360px !custom' })
104
+ }
105
+ ```
106
+
107
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Slider/Disabled.tsx)
108
+
109
+ ## Anatomy
110
+
111
+ Import the component and assemble its parts.
112
+
113
+ ```tsx
114
+ import { Slider } from '@tempoxyz/ds'
115
+
116
+ <Slider.Root>
117
+ <Slider.Value />
118
+ <Slider.Control>
119
+ <Slider.Track>
120
+ <Slider.Indicator />
121
+ <Slider.Thumb />
122
+ </Slider.Track>
123
+ </Slider.Control>
124
+ </Slider.Root>
125
+ ```
126
+
127
+ ## Guidelines
128
+
129
+ ### When to Use
130
+
131
+ * Set a value where position matters more than the exact number, such as a benchmark's target load.
132
+ * Pick a range with two thumbs, such as the block heights on a chart.
133
+ * Preview a setting live, such as a chart's moving-average window.
134
+
135
+ ### When Not to Use
136
+
137
+ * Use [AmountInput](amount-input.md) for amounts and [NumberField](number-field.md) for exact counts.
138
+ * Use [ChoiceGroup](choice-group.md) for a few presets, such as 25%, 50%, and Max.
139
+ * Use [Progress](progress.md) or [Gauge](gauge.md) for a value that people cannot change.
140
+
141
+ ### Always Show the Value
142
+
143
+ **Do:** Show the current value and its unit beside the label.
144
+
145
+ ```tsx
146
+ /**
147
+ * Do example for "Always Show the Value" on the Slider page.
148
+ * Show the current value and its unit beside the label.
149
+ * @module
150
+ */
151
+ import { Slider, style } from '@tempoxyz/ds'
152
+
153
+ /** Renders the static preview, which the guideline card shows inert. */
154
+ export function Demo() {
155
+ return (
156
+ <Slider.Root
157
+ aria-labelledby="guideline-target-load"
158
+ defaultValue={4000}
159
+ max={10000}
160
+ step={500}
161
+ {...styles.root()}
162
+ >
163
+ <div {...styles.header()}>
164
+ <span id="guideline-target-load">Target load</span>
165
+ <span>
166
+ <Slider.Value /> TPS
167
+ </span>
168
+ </div>
169
+ <Slider.Control>
170
+ <Slider.Track>
171
+ <Slider.Indicator />
172
+ <Slider.Thumb />
173
+ </Slider.Track>
174
+ </Slider.Control>
175
+ </Slider.Root>
176
+ )
177
+ }
178
+
179
+ namespace styles {
180
+ export const header = style({
181
+ display: 'flex',
182
+ justifyContent: 'space-between',
183
+ marginBottom: '8',
184
+ typography: 'body.b2',
185
+ })
186
+
187
+ export const root = style({ maxWidth: '18rem !custom', width: '100% !custom' })
188
+ }
189
+ ```
190
+
191
+ **Don't:** Show a slider without its value.
192
+
193
+ ```tsx
194
+ /** Don't example for "Always Show the Value" on the Slider page. Don't show a slider without its value. @module */
195
+ import { Slider, style } from '@tempoxyz/ds'
196
+
197
+ /** Renders the static preview, which the guideline card shows inert. */
198
+ export function Demo() {
199
+ return (
200
+ <Slider.Root
201
+ aria-labelledby="guideline-target-load-hidden"
202
+ defaultValue={4000}
203
+ max={10000}
204
+ step={500}
205
+ {...styles.root()}
206
+ >
207
+ <div {...styles.header()}>
208
+ <span id="guideline-target-load-hidden">Target load</span>
209
+ </div>
210
+ <Slider.Control>
211
+ <Slider.Track>
212
+ <Slider.Indicator />
213
+ <Slider.Thumb />
214
+ </Slider.Track>
215
+ </Slider.Control>
216
+ </Slider.Root>
217
+ )
218
+ }
219
+
220
+ namespace styles {
221
+ export const header = style({ marginBottom: '8', typography: 'body.b2' })
222
+
223
+ export const root = style({ maxWidth: '18rem !custom', width: '100% !custom' })
224
+ }
225
+ ```
226
+
227
+ `Slider.Value` renders an `<output>` with tabular figures, so the label does not shift. Format it with `format` and `locale` on `Slider.Root`, or pass a function as `children`.
228
+
229
+ ### Pair With an Input for Exact Values
230
+
231
+ Some people cannot drag. Where precision matters, add a [NumberField](number-field.md) beside the slider.
232
+
233
+ **Do:** Share one value between the slider and the input.
234
+
235
+ ```tsx
236
+ /**
237
+ * Do example for "Pair With an Input for Exact Values" on the Slider page.
238
+ * Share one value between the slider and the input.
239
+ * @module
240
+ */
241
+ import { NumberField, Slider, style } from '@tempoxyz/ds'
242
+
243
+ /** Renders the static preview, which the guideline card shows inert. */
244
+ export function Demo() {
245
+ return (
246
+ <div {...styles.root()}>
247
+ <span {...styles.label()}>Target load (TPS)</span>
248
+ <div {...styles.row()}>
249
+ <Slider.Root
250
+ aria-label="Target load"
251
+ defaultValue={4000}
252
+ max={10000}
253
+ step={500}
254
+ {...styles.slider()}
255
+ >
256
+ <Slider.Control>
257
+ <Slider.Track>
258
+ <Slider.Indicator />
259
+ <Slider.Thumb />
260
+ </Slider.Track>
261
+ </Slider.Control>
262
+ </Slider.Root>
263
+ <NumberField.Root defaultValue={4000} max={10000} min={0} step={500} {...styles.number()}>
264
+ <NumberField.Group>
265
+ <NumberField.Input aria-label="Target load" />
266
+ </NumberField.Group>
267
+ </NumberField.Root>
268
+ </div>
269
+ </div>
270
+ )
271
+ }
272
+
273
+ namespace styles {
274
+ export const label = style({ typography: 'body.b2' })
275
+
276
+ // The root keeps its full width, so a maximum narrows it.
277
+ export const number = style({ maxWidth: '6rem !custom' })
278
+
279
+ export const root = style({
280
+ display: 'flex',
281
+ flexDirection: 'column',
282
+ gap: '8',
283
+ maxWidth: '20rem !custom',
284
+ width: '100% !custom',
285
+ })
286
+
287
+ export const row = style({ alignItems: 'center', display: 'flex', gap: '16' })
288
+
289
+ export const slider = style({ flexGrow: '1 !custom' })
290
+ }
291
+ ```
292
+
293
+ **Don't:** Let the slider and the input hold different values.
294
+
295
+ ```tsx
296
+ /**
297
+ * Don't example for "Pair With an Input for Exact Values" on the Slider page.
298
+ * Don't let the slider and the input hold different values.
299
+ * @module
300
+ */
301
+ import { NumberField, Slider, style } from '@tempoxyz/ds'
302
+
303
+ /** Renders the static preview, which the guideline card shows inert. */
304
+ export function Demo() {
305
+ return (
306
+ <div {...styles.root()}>
307
+ <span {...styles.label()}>Target load (TPS)</span>
308
+ <div {...styles.row()}>
309
+ <Slider.Root
310
+ aria-label="Target load"
311
+ defaultValue={4000}
312
+ max={10000}
313
+ step={500}
314
+ {...styles.slider()}
315
+ >
316
+ <Slider.Control>
317
+ <Slider.Track>
318
+ <Slider.Indicator />
319
+ <Slider.Thumb />
320
+ </Slider.Track>
321
+ </Slider.Control>
322
+ </Slider.Root>
323
+ <NumberField.Root defaultValue={2500} max={10000} min={0} step={500} {...styles.number()}>
324
+ <NumberField.Group>
325
+ <NumberField.Input aria-label="Target load" />
326
+ </NumberField.Group>
327
+ </NumberField.Root>
328
+ </div>
329
+ </div>
330
+ )
331
+ }
332
+
333
+ namespace styles {
334
+ export const label = style({ typography: 'body.b2' })
335
+
336
+ // The root keeps its full width, so a maximum narrows it.
337
+ export const number = style({ maxWidth: '6rem !custom' })
338
+
339
+ export const root = style({
340
+ display: 'flex',
341
+ flexDirection: 'column',
342
+ gap: '8',
343
+ maxWidth: '20rem !custom',
344
+ width: '100% !custom',
345
+ })
346
+
347
+ export const row = style({ alignItems: 'center', display: 'flex', gap: '16' })
348
+
349
+ export const slider = style({ flexGrow: '1 !custom' })
350
+ }
351
+ ```
352
+
353
+ ### Choose a Range and Steps That Fit the Data
354
+
355
+ * **`largeStep`:** Applies to Page Up and Page Down. Size it to cross the range in a few presses.
356
+ * **Bounds:** If the label does not make them obvious, show them below the track.
357
+ * **`minStepsBetweenValues`:** If an empty range is not valid, set it to keep the thumbs apart.
358
+
359
+ **Do:** Set `min`, `max`, and `step` to values people think in, such as 500 TPS steps.
360
+
361
+ ```tsx
362
+ /**
363
+ * Do example for "Choose a Range and Steps That Fit the Data" on the Slider page.
364
+ * Set `min`, `max`, and `step` to values people think in, such as 500 TPS steps.
365
+ * @module
366
+ */
367
+ import { Slider, style } from '@tempoxyz/ds'
368
+
369
+ /** Renders the static preview, which the guideline card shows inert. */
370
+ export function Demo() {
371
+ return (
372
+ <Slider.Root
373
+ aria-label="Target load"
374
+ defaultValue={4000}
375
+ max={10000}
376
+ step={500}
377
+ {...styles.root()}
378
+ >
379
+ <div {...styles.header()}>
380
+ <span>Target load</span>
381
+ <span>
382
+ <Slider.Value /> TPS
383
+ </span>
384
+ </div>
385
+ <Slider.Control>
386
+ <Slider.Track>
387
+ <Slider.Indicator />
388
+ <Slider.Thumb />
389
+ </Slider.Track>
390
+ </Slider.Control>
391
+ <div {...styles.bounds()}>
392
+ <span>0</span>
393
+ <span>10,000</span>
394
+ </div>
395
+ </Slider.Root>
396
+ )
397
+ }
398
+
399
+ namespace styles {
400
+ export const bounds = style({
401
+ color: 'content.secondary',
402
+ display: 'flex',
403
+ justifyContent: 'space-between',
404
+ marginTop: '8',
405
+ typography: 'body.b3',
406
+ })
407
+
408
+ export const header = style({
409
+ display: 'flex',
410
+ justifyContent: 'space-between',
411
+ marginBottom: '8',
412
+ typography: 'body.b2',
413
+ })
414
+
415
+ export const root = style({ maxWidth: '18rem !custom', width: '100% !custom' })
416
+ }
417
+ ```
418
+
419
+ **Don't:** Use a step or bounds that produce values such as 4,137.
420
+
421
+ ```tsx
422
+ /**
423
+ * Don't example for "Choose a Range and Steps That Fit the Data" on the Slider page.
424
+ * Don't use a step or bounds that produce values such as 4,137.
425
+ * @module
426
+ */
427
+ import { Slider, style } from '@tempoxyz/ds'
428
+
429
+ /** Renders the static preview, which the guideline card shows inert. */
430
+ export function Demo() {
431
+ return (
432
+ <Slider.Root
433
+ aria-label="Target load"
434
+ defaultValue={4137}
435
+ max={10240}
436
+ step={1}
437
+ {...styles.root()}
438
+ >
439
+ <div {...styles.header()}>
440
+ <span>Target load</span>
441
+ <span>
442
+ <Slider.Value /> TPS
443
+ </span>
444
+ </div>
445
+ <Slider.Control>
446
+ <Slider.Track>
447
+ <Slider.Indicator />
448
+ <Slider.Thumb />
449
+ </Slider.Track>
450
+ </Slider.Control>
451
+ <div {...styles.bounds()}>
452
+ <span>0</span>
453
+ <span>10,240</span>
454
+ </div>
455
+ </Slider.Root>
456
+ )
457
+ }
458
+
459
+ namespace styles {
460
+ export const bounds = style({
461
+ color: 'content.secondary',
462
+ display: 'flex',
463
+ justifyContent: 'space-between',
464
+ marginTop: '8',
465
+ typography: 'body.b3',
466
+ })
467
+
468
+ export const header = style({
469
+ display: 'flex',
470
+ justifyContent: 'space-between',
471
+ marginBottom: '8',
472
+ typography: 'body.b2',
473
+ })
474
+
475
+ export const root = style({ maxWidth: '18rem !custom', width: '100% !custom' })
476
+ }
477
+ ```
478
+
479
+ ### Commit Expensive Work on Release
480
+
481
+ * **Every Movement (onValueChange):** Fires on every movement. Use it to update the visible value.
482
+ * **Release (onValueCommitted):** Fires once when the drag, track press, or key press ends. Use it to refetch data or save.
483
+
484
+ ## Content
485
+
486
+ * **Label:** Name the quantity, such as Target load. Show the unit with the value, such as 4,000 TPS.
487
+
488
+ ## Accessibility
489
+
490
+ Slider accepts keyboard, pointer, and touch input. It follows the [WAI-ARIA Authoring Practices slider pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slider/), and the [multi-thumb slider pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/) for a range.
491
+
492
+ ### Semantics
493
+
494
+ * **Slider.Root (group):** Holds the thumbs as one named group.
495
+ * **Slider.Thumb (input type=range):** Wraps a native range input, which holds the name and keyboard focus.
496
+ * **Range Values (aria-valuetext):** Each range thumb reads as "20 start range" or "70 end range". `getAriaValueText` replaces it.
497
+ * **Slider.Value (output):** Linked to its thumb, and silent during a drag.
498
+ * **Disabled (disabled):** Locks every thumb and dims the slider. Explain why nearby.
499
+ * **Size and Motion (24px):** The thumb grows slightly during a drag, except under reduced motion.
500
+
501
+ ### Keyboard
502
+
503
+ * **Move to a Thumb (Tab):** Moves focus to each thumb in order.
504
+ * **Increase by Step (Right Arrow or Up Arrow):** Increases the value by `step`.
505
+ * **Decrease by Step (Left Arrow or Down Arrow):** Decreases the value by `step`.
506
+ * **Increase by Large Step (Page Up or Shift+Right Arrow):** Increases the value by `largeStep`.
507
+ * **Decrease by Large Step (Page Down or Shift+Left Arrow):** Decreases the value by `largeStep`.
508
+ * **Set to Minimum (Home):** Sets the value to `min`.
509
+ * **Set to Maximum (End):** Sets the value to `max`.
510
+
511
+ In a range, a thumb stops at the other thumb's value.
512
+
513
+ ### Dragging
514
+
515
+ Every drag has a single-press alternative ([SC 2.5.7](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html)). A press on `Slider.Control` moves the nearest thumb, and the keys above set any value.
516
+
517
+ ### Your Responsibilities
518
+
519
+ * **Name Every Thumb (aria-label):** Label each thumb with `getAriaLabel` or a field label. A root `aria-label` names only the group.
520
+ * **Name Range Thumbs by Role:** Label the thumbs by role, such as "Minimum" and "Maximum".
521
+ * **Announce Units (getAriaValueText):** Announce the unit with each value, such as "20 percent".
522
+
523
+ ## Related
524
+
525
+ [NumberField](number-field.md)
526
+
527
+ Use for exact numbers.
528
+
529
+ [ChoiceGroup](choice-group.md)
530
+
531
+ Use for a few preset values.
532
+
533
+ [Progress](progress.md)
534
+
535
+ Use for showing progress you can't change.
536
+
537
+ [Dashboards](../patterns/dashboards.md)
538
+
539
+ Covers chart controls and filters.