@tempoxyz/ds 0.3.10 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/AGENTS.md +9 -0
- package/dist/docs/components/accordion.md +489 -0
- package/dist/docs/components/address-card.md +147 -0
- package/dist/docs/components/agent-logo.md +194 -0
- package/dist/docs/components/alert-dialog.md +631 -0
- package/dist/docs/components/alert.md +448 -0
- package/dist/docs/components/amount-input.md +305 -0
- package/dist/docs/components/amount.md +794 -0
- package/dist/docs/components/app-shell.md +559 -0
- package/dist/docs/components/asset-chip.md +294 -0
- package/dist/docs/components/autocomplete.md +619 -0
- package/dist/docs/components/avatar.md +321 -0
- package/dist/docs/components/badge.md +339 -0
- package/dist/docs/components/badged-logo.md +116 -0
- package/dist/docs/components/banner.md +379 -0
- package/dist/docs/components/bar-chart.md +208 -0
- package/dist/docs/components/breadcrumbs.md +380 -0
- package/dist/docs/components/button-group.md +286 -0
- package/dist/docs/components/button.md +650 -0
- package/dist/docs/components/calendar.md +375 -0
- package/dist/docs/components/callout.md +96 -0
- package/dist/docs/components/checkbox-group.md +521 -0
- package/dist/docs/components/checkbox.md +467 -0
- package/dist/docs/components/choice-group.md +516 -0
- package/dist/docs/components/choicebox.md +641 -0
- package/dist/docs/components/code.md +100 -0
- package/dist/docs/components/combobox.md +939 -0
- package/dist/docs/components/container.md +257 -0
- package/dist/docs/components/copy-button.md +642 -0
- package/dist/docs/components/date-picker.md +514 -0
- package/dist/docs/components/dialog.md +1332 -0
- package/dist/docs/components/drawer.md +966 -0
- package/dist/docs/components/empty.md +340 -0
- package/dist/docs/components/field.md +570 -0
- package/dist/docs/components/fieldset.md +398 -0
- package/dist/docs/components/frame.md +434 -0
- package/dist/docs/components/gauge.md +299 -0
- package/dist/docs/components/get-started-visual.md +117 -0
- package/dist/docs/components/grid.md +288 -0
- package/dist/docs/components/hero-visual.md +155 -0
- package/dist/docs/components/hex.md +487 -0
- package/dist/docs/components/icon-tile.md +292 -0
- package/dist/docs/components/identicon.md +371 -0
- package/dist/docs/components/inline.md +233 -0
- package/dist/docs/components/inset.md +225 -0
- package/dist/docs/components/kbd.md +423 -0
- package/dist/docs/components/list-group.md +981 -0
- package/dist/docs/components/loading-dots.md +237 -0
- package/dist/docs/components/menu.md +934 -0
- package/dist/docs/components/native-select.md +204 -0
- package/dist/docs/components/network-logo.md +248 -0
- package/dist/docs/components/number-field.md +543 -0
- package/dist/docs/components/otp-field.md +616 -0
- package/dist/docs/components/pagination.md +516 -0
- package/dist/docs/components/popover.md +544 -0
- package/dist/docs/components/progress.md +388 -0
- package/dist/docs/components/qr.md +314 -0
- package/dist/docs/components/radio-group.md +528 -0
- package/dist/docs/components/secret-value.md +406 -0
- package/dist/docs/components/select.md +751 -0
- package/dist/docs/components/separator.md +379 -0
- package/dist/docs/components/sidebar-menu.md +922 -0
- package/dist/docs/components/skeleton.md +517 -0
- package/dist/docs/components/slider.md +539 -0
- package/dist/docs/components/snippet.md +424 -0
- package/dist/docs/components/spinner.md +216 -0
- package/dist/docs/components/split-bar.md +139 -0
- package/dist/docs/components/split-button.md +464 -0
- package/dist/docs/components/stack.md +299 -0
- package/dist/docs/components/status-chip.md +226 -0
- package/dist/docs/components/status-indicator.md +119 -0
- package/dist/docs/components/status-row.md +174 -0
- package/dist/docs/components/stepper.md +451 -0
- package/dist/docs/components/success-hero.md +157 -0
- package/dist/docs/components/surface.md +639 -0
- package/dist/docs/components/switch.md +472 -0
- package/dist/docs/components/table.md +967 -0
- package/dist/docs/components/tabs.md +627 -0
- package/dist/docs/components/tempo-logo.md +185 -0
- package/dist/docs/components/text-input.md +624 -0
- package/dist/docs/components/textarea.md +352 -0
- package/dist/docs/components/toast.md +535 -0
- package/dist/docs/components/token-logo.md +371 -0
- package/dist/docs/components/token.md +247 -0
- package/dist/docs/components/tooltip.md +490 -0
- package/dist/docs/components/verification-code.md +116 -0
- package/dist/docs/components/visual.md +249 -0
- package/dist/docs/components.md +203 -0
- package/dist/docs/foundations/accessibility.md +377 -0
- package/dist/docs/foundations/agents.md +150 -0
- package/dist/docs/foundations/color.md +522 -0
- package/dist/docs/foundations/content/tone.md +194 -0
- package/dist/docs/foundations/content/voice.md +194 -0
- package/dist/docs/foundations/content/writing-style.md +406 -0
- package/dist/docs/foundations/iconography.md +282 -0
- package/dist/docs/foundations/intent.md +360 -0
- package/dist/docs/foundations/layout.md +508 -0
- package/dist/docs/foundations/linter.md +296 -0
- package/dist/docs/foundations/motion.md +151 -0
- package/dist/docs/foundations/radius-and-padding.md +86 -0
- package/dist/docs/foundations/typography.md +266 -0
- package/dist/docs/index.md +137 -0
- package/dist/docs/introduction/faq.md +132 -0
- package/dist/docs/introduction/getting-started.md +377 -0
- package/dist/docs/patterns/blockchain-values.md +709 -0
- package/dist/docs/patterns/dashboards.md +638 -0
- package/dist/docs/patterns/destructive-actions.md +626 -0
- package/dist/docs/patterns/empty-states.md +612 -0
- package/dist/docs/patterns/errors-and-validation.md +808 -0
- package/dist/docs/patterns/feedback-and-status.md +518 -0
- package/dist/docs/patterns/forms.md +679 -0
- package/dist/docs/patterns/loading.md +630 -0
- package/dist/docs/patterns/navigation.md +397 -0
- package/dist/docs/patterns/payments.md +765 -0
- package/dist/docs/patterns/responsive-layout.md +997 -0
- package/dist/docs/patterns/tables-and-lists.md +964 -0
- package/dist/docs/products/tempo-console.md +671 -0
- package/dist/docs/products/tempo-performance.md +437 -0
- package/dist/docs/products/tempo-wallet.md +438 -0
- package/package.json +1 -1
|
@@ -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](/docs/components/amount-input) for amounts and [NumberField](/docs/components/number-field) for exact counts.
|
|
138
|
+
* Use [ChoiceGroup](/docs/components/choice-group) for a few presets, such as 25%, 50%, and Max.
|
|
139
|
+
* Use [Progress](/docs/components/progress) or [Gauge](/docs/components/gauge) 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](/docs/components/number-field) 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](/docs/components/number-field)
|
|
526
|
+
|
|
527
|
+
Use for exact numbers.
|
|
528
|
+
|
|
529
|
+
[ChoiceGroup](/docs/components/choice-group)
|
|
530
|
+
|
|
531
|
+
Use for a few preset values.
|
|
532
|
+
|
|
533
|
+
[Progress](/docs/components/progress)
|
|
534
|
+
|
|
535
|
+
Use for showing progress you can't change.
|
|
536
|
+
|
|
537
|
+
[Dashboards](/docs/patterns/dashboards)
|
|
538
|
+
|
|
539
|
+
Covers chart controls and filters.
|