@tempoxyz/ds 0.3.9 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/dist/web/components/OtpField.css +1 -1
- package/dist/web/components/OtpField.d.ts +1 -1
- package/dist/web/components/OtpField.d.ts.map +1 -1
- package/dist/web/components/OtpField.js +3 -4
- package/dist/web/components/OtpField.js.map +1 -1
- package/dist/web/components/OtpField.js.zyzz.json +1 -1
- package/dist/web/index.js.zyzz.json +1 -1
- package/package.json +1 -1
- package/src/web/components/OtpField.tsx +2 -24
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
# Snippet
|
|
2
|
+
|
|
3
|
+
Shows a command or value with a copy button.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Snippet.tsx)
|
|
6
|
+
|
|
7
|
+
Figma: [Content/Code Snippet](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=5227-3317)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Snippet renders a command or value in a `<code>` element, with a copy button in the corner. A click anywhere on the command copies it.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### Basic
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
19
|
+
|
|
20
|
+
export const fill = true
|
|
21
|
+
export function Demo() {
|
|
22
|
+
return <Snippet {...styles.snippet()}>pnpm add @tempoxyz/ds</Snippet>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
namespace styles {
|
|
26
|
+
export const snippet = style({ maxWidth: '28rem !custom' })
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Snippet/Basic.tsx)
|
|
31
|
+
|
|
32
|
+
### Wrap
|
|
33
|
+
|
|
34
|
+
The first word, the program, renders in the primary color. Long commands wrap, and wrapped lines align with the arguments.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
38
|
+
|
|
39
|
+
export const fill = true
|
|
40
|
+
export function Demo() {
|
|
41
|
+
return (
|
|
42
|
+
<Snippet {...styles.snippet()}>
|
|
43
|
+
claude "Read https://tempo.xyz/SKILL.md and connect to my Tempo wallet"
|
|
44
|
+
</Snippet>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
namespace styles {
|
|
49
|
+
export const snippet = style({ maxWidth: '24.75rem !custom' })
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Snippet/Wrap.tsx)
|
|
54
|
+
|
|
55
|
+
### Prompt
|
|
56
|
+
|
|
57
|
+
Set `prompt` to a glyph, or to `false` to hide it. It defaults to `$`.
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
61
|
+
|
|
62
|
+
export const fill = true
|
|
63
|
+
export function Demo() {
|
|
64
|
+
return (
|
|
65
|
+
<Snippet prompt={false} {...styles.snippet()}>
|
|
66
|
+
https://ds.tempo.xyz
|
|
67
|
+
</Snippet>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
namespace styles {
|
|
72
|
+
export const snippet = style({ maxWidth: '28rem !custom' })
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Snippet/Prompt.tsx)
|
|
77
|
+
|
|
78
|
+
### Tabs
|
|
79
|
+
|
|
80
|
+
Pass a [Tabs](/docs/components/tabs) list as `tabs` to switch between commands. Wrap the snippet in `Tabs.Root`, and pass the command of the active tab as `children`.
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { Snippet, style, Tabs } from '@tempoxyz/ds'
|
|
84
|
+
import { useState } from 'react'
|
|
85
|
+
|
|
86
|
+
export const fill = true
|
|
87
|
+
const commands = {
|
|
88
|
+
bun: 'bun add @tempoxyz/ds zyzz',
|
|
89
|
+
npm: 'npm install @tempoxyz/ds zyzz',
|
|
90
|
+
pnpm: 'pnpm add @tempoxyz/ds zyzz',
|
|
91
|
+
} as const
|
|
92
|
+
|
|
93
|
+
const managers = ['npm', 'pnpm', 'bun'] as const
|
|
94
|
+
|
|
95
|
+
export function Demo() {
|
|
96
|
+
const [manager, setManager] = useState<(typeof managers)[number]>('npm')
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<Tabs.Root
|
|
100
|
+
onValueChange={(value) => {
|
|
101
|
+
const entry = managers.find((item) => item === value)
|
|
102
|
+
if (entry) setManager(entry)
|
|
103
|
+
}}
|
|
104
|
+
value={manager}
|
|
105
|
+
>
|
|
106
|
+
<Snippet
|
|
107
|
+
labels={{ copy: 'Copy install command' }}
|
|
108
|
+
tabs={
|
|
109
|
+
<Tabs.List aria-label="Package manager">
|
|
110
|
+
{managers.map((entry) => (
|
|
111
|
+
<Tabs.Tab key={entry} value={entry}>
|
|
112
|
+
{entry}
|
|
113
|
+
</Tabs.Tab>
|
|
114
|
+
))}
|
|
115
|
+
<Tabs.Indicator />
|
|
116
|
+
</Tabs.List>
|
|
117
|
+
}
|
|
118
|
+
{...styles.snippet()}
|
|
119
|
+
>
|
|
120
|
+
{commands[manager]}
|
|
121
|
+
</Snippet>
|
|
122
|
+
</Tabs.Root>
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
namespace styles {
|
|
127
|
+
export const snippet = style({ maxWidth: '28rem !custom' })
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Snippet/Tabs.tsx)
|
|
132
|
+
|
|
133
|
+
## Anatomy
|
|
134
|
+
|
|
135
|
+
Import the component and assemble its parts.
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import { Snippet, Tabs } from '@tempoxyz/ds'
|
|
139
|
+
|
|
140
|
+
<Tabs.Root>
|
|
141
|
+
<Snippet
|
|
142
|
+
tabs={
|
|
143
|
+
<Tabs.List>
|
|
144
|
+
<Tabs.Tab />
|
|
145
|
+
<Tabs.Indicator />
|
|
146
|
+
</Tabs.List>
|
|
147
|
+
}
|
|
148
|
+
/>
|
|
149
|
+
</Tabs.Root>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Guidelines
|
|
153
|
+
|
|
154
|
+
### When to Use
|
|
155
|
+
|
|
156
|
+
* Show a command, such as an install command or a `curl` request.
|
|
157
|
+
* Show a value to paste elsewhere, such as a webhook URL or an RPC endpoint, with `prompt={false}`.
|
|
158
|
+
* Show one command per tool, such as an agent or a package manager, with `tabs`.
|
|
159
|
+
|
|
160
|
+
### When Not to Use
|
|
161
|
+
|
|
162
|
+
* Use [SecretValue](/docs/components/secret-value) for API keys and other secrets, which stay masked.
|
|
163
|
+
* Use [Hex](/docs/components/hex) with `copy` for addresses and hashes, which truncates the middle to fit.
|
|
164
|
+
* Use [CopyButton](/docs/components/copy-button) to add copying beside your own text.
|
|
165
|
+
* Use [Tabs](/docs/components/tabs) with panels to switch content other than commands.
|
|
166
|
+
|
|
167
|
+
### Copy Exactly What You Show
|
|
168
|
+
|
|
169
|
+
Snippet copies its `children`, never the prompt.
|
|
170
|
+
|
|
171
|
+
**Do:** Pass only the command, so the pasted text runs as is.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
/**
|
|
175
|
+
* Do example for "Copy Exactly What You Show" on the Snippet page.
|
|
176
|
+
* Pass only the command, so the pasted text runs as is.
|
|
177
|
+
* @module
|
|
178
|
+
*/
|
|
179
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
180
|
+
|
|
181
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
182
|
+
export function Demo() {
|
|
183
|
+
return <Snippet {...styles.snippet()}>pnpm add @tempoxyz/ds</Snippet>
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
namespace styles {
|
|
187
|
+
export const snippet = style({ width: '100% !custom' })
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Don't:** Type a leading `$` into the command.
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
/**
|
|
195
|
+
* Don't example for "Copy Exactly What You Show" on the Snippet page.
|
|
196
|
+
* Don't type a leading `$` into the command.
|
|
197
|
+
* @module
|
|
198
|
+
*/
|
|
199
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
200
|
+
|
|
201
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
202
|
+
export function Demo() {
|
|
203
|
+
return <Snippet {...styles.snippet()}>$ pnpm add @tempoxyz/ds</Snippet>
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
namespace styles {
|
|
207
|
+
export const snippet = style({ width: '100% !custom' })
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Show the Prompt Only for Shell Commands
|
|
212
|
+
|
|
213
|
+
The `$` marks text to run in a terminal.
|
|
214
|
+
|
|
215
|
+
**Do:** Set `prompt={false}` for a URL or other value.
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
/**
|
|
219
|
+
* Do example for "Show the Prompt Only for Shell Commands" on the Snippet page.
|
|
220
|
+
* Set `prompt={false}` for a URL or other value.
|
|
221
|
+
* @module
|
|
222
|
+
*/
|
|
223
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
224
|
+
|
|
225
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
226
|
+
export function Demo() {
|
|
227
|
+
return (
|
|
228
|
+
<Snippet prompt={false} {...styles.snippet()}>
|
|
229
|
+
https://example.com/webhooks/tempo
|
|
230
|
+
</Snippet>
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
namespace styles {
|
|
235
|
+
export const snippet = style({ width: '100% !custom' })
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Don't:** Show a shell prompt before a value that isn't a command.
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
/**
|
|
243
|
+
* Don't example for "Show the Prompt Only for Shell Commands" on the Snippet page.
|
|
244
|
+
* Don't show a shell prompt before a value that isn't a command.
|
|
245
|
+
* @module
|
|
246
|
+
*/
|
|
247
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
248
|
+
|
|
249
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
250
|
+
export function Demo() {
|
|
251
|
+
return <Snippet {...styles.snippet()}>https://example.com/webhooks/tempo</Snippet>
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
namespace styles {
|
|
255
|
+
export const snippet = style({ width: '100% !custom' })
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Keep One Command per Snippet
|
|
260
|
+
|
|
261
|
+
Long commands wrap. Use a code block for multi-line scripts and config files.
|
|
262
|
+
|
|
263
|
+
**Do:** Split a multi-step setup into one snippet per command.
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
/**
|
|
267
|
+
* Do example for "Keep One Command per Snippet" on the Snippet page.
|
|
268
|
+
* Split a multi-step setup into one snippet per command.
|
|
269
|
+
* @module
|
|
270
|
+
*/
|
|
271
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
272
|
+
|
|
273
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
274
|
+
export function Demo() {
|
|
275
|
+
return (
|
|
276
|
+
<div {...styles.stack()}>
|
|
277
|
+
<Snippet>pnpm add @tempoxyz/ds</Snippet>
|
|
278
|
+
<Snippet>pnpm build</Snippet>
|
|
279
|
+
<Snippet>pnpm dev</Snippet>
|
|
280
|
+
</div>
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
namespace styles {
|
|
285
|
+
export const stack = style({ display: 'grid', gap: '8', width: '100% !custom' })
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Don't:** Chain several commands into one snippet.
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
/**
|
|
293
|
+
* Don't example for "Keep One Command per Snippet" on the Snippet page.
|
|
294
|
+
* Don't chain several commands into one snippet.
|
|
295
|
+
* @module
|
|
296
|
+
*/
|
|
297
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
298
|
+
|
|
299
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
300
|
+
export function Demo() {
|
|
301
|
+
return <Snippet {...styles.snippet()}>pnpm add @tempoxyz/ds && pnpm build && pnpm dev</Snippet>
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
namespace styles {
|
|
305
|
+
export const snippet = style({ width: '100% !custom' })
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Switch Alternatives with Tabs
|
|
310
|
+
|
|
311
|
+
If the command differs per tool, such as a package manager, show one snippet with a tab per tool.
|
|
312
|
+
|
|
313
|
+
**Do:** Show one command per package manager in one snippet with tabs.
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
/**
|
|
317
|
+
* Do example for "Switch Alternatives with Tabs" on the Snippet page.
|
|
318
|
+
* Show one command per package manager in one snippet with tabs.
|
|
319
|
+
* @module
|
|
320
|
+
*/
|
|
321
|
+
import { Snippet, style, Tabs } from '@tempoxyz/ds'
|
|
322
|
+
|
|
323
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
324
|
+
export function Demo() {
|
|
325
|
+
return (
|
|
326
|
+
<Tabs.Root defaultValue="npm" {...styles.root()}>
|
|
327
|
+
<Snippet
|
|
328
|
+
tabs={
|
|
329
|
+
<Tabs.List aria-label="Package manager">
|
|
330
|
+
<Tabs.Tab value="npm">npm</Tabs.Tab>
|
|
331
|
+
<Tabs.Tab value="pnpm">pnpm</Tabs.Tab>
|
|
332
|
+
<Tabs.Tab value="bun">bun</Tabs.Tab>
|
|
333
|
+
<Tabs.Indicator />
|
|
334
|
+
</Tabs.List>
|
|
335
|
+
}
|
|
336
|
+
>
|
|
337
|
+
npm install @tempoxyz/ds
|
|
338
|
+
</Snippet>
|
|
339
|
+
</Tabs.Root>
|
|
340
|
+
)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
namespace styles {
|
|
344
|
+
export const root = style({ width: '100% !custom' })
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Don't:** Stack one snippet per package manager.
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
/**
|
|
352
|
+
* Don't example for "Switch Alternatives with Tabs" on the Snippet page.
|
|
353
|
+
* Don't stack one snippet per package manager.
|
|
354
|
+
* @module
|
|
355
|
+
*/
|
|
356
|
+
import { Snippet, style } from '@tempoxyz/ds'
|
|
357
|
+
|
|
358
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
359
|
+
export function Demo() {
|
|
360
|
+
return (
|
|
361
|
+
<div {...styles.stack()}>
|
|
362
|
+
<Snippet>npm install @tempoxyz/ds</Snippet>
|
|
363
|
+
<Snippet>pnpm add @tempoxyz/ds</Snippet>
|
|
364
|
+
<Snippet>bun add @tempoxyz/ds</Snippet>
|
|
365
|
+
</div>
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
namespace styles {
|
|
370
|
+
export const stack = style({ display: 'grid', gap: '8', width: '100% !custom' })
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Content
|
|
375
|
+
|
|
376
|
+
* Write commands that run unchanged. If a value differs per person, read it from an environment variable, such as `$TEMPO_API_KEY`, not a placeholder.
|
|
377
|
+
* Never put a real secret in a snippet.
|
|
378
|
+
* Introduce each snippet with a sentence that states what it does and where to run it.
|
|
379
|
+
|
|
380
|
+
## Accessibility
|
|
381
|
+
|
|
382
|
+
The command renders in a `<code>` element. The copy button follows the [WAI-ARIA button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/), and the tabs follow the [WAI-ARIA tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
|
|
383
|
+
|
|
384
|
+
### Semantics
|
|
385
|
+
|
|
386
|
+
* **Command (code):** Wraps to its width, so the whole command stays visible without scrolling.
|
|
387
|
+
* **Prompt (aria-hidden):** Hidden from screen readers, and never selected or copied with the command.
|
|
388
|
+
* **Copy Button (button):** Named "Copy" unless you pass `labels.copy`. Reads "Copied" for two seconds, and a hidden live region announces each copy.
|
|
389
|
+
* **Tabs (tablist):** Switches the command in place. A click on a tab never copies, and the list needs its own name.
|
|
390
|
+
|
|
391
|
+
### Keyboard
|
|
392
|
+
|
|
393
|
+
* **Move Through the Snippet (Tab):** Moves focus to the active tab, if any, then to the copy button.
|
|
394
|
+
* **Switch the Command (Arrow keys):** Moves between tabs. Enter or Space shows the command of the focused tab.
|
|
395
|
+
* **Copy the Command (Enter or Space):** Copies the command from the copy button. Focus stays on the button.
|
|
396
|
+
|
|
397
|
+
A click anywhere on the command also copies, unless your `onClick` calls `preventDefault()`. The button is the keyboard path.
|
|
398
|
+
|
|
399
|
+
### Your Responsibilities
|
|
400
|
+
|
|
401
|
+
* **Label Each Snippet (labels.copy):** If a page shows several snippets, put a visible heading before each, and name each copy button, such as "Copy install command".
|
|
402
|
+
* **Name the Tabs (SC 4.1.2):** Name the tab list, such as "Package manager", and pass the command of the active tab as the children.
|
|
403
|
+
|
|
404
|
+
## Related
|
|
405
|
+
|
|
406
|
+
[CopyButton](/docs/components/copy-button)
|
|
407
|
+
|
|
408
|
+
Use for copying beside your own layout.
|
|
409
|
+
|
|
410
|
+
[SecretValue](/docs/components/secret-value)
|
|
411
|
+
|
|
412
|
+
Use for secrets.
|
|
413
|
+
|
|
414
|
+
[Hex](/docs/components/hex)
|
|
415
|
+
|
|
416
|
+
Use for addresses and hashes.
|
|
417
|
+
|
|
418
|
+
[Kbd](/docs/components/kbd)
|
|
419
|
+
|
|
420
|
+
Use for keyboard shortcuts.
|
|
421
|
+
|
|
422
|
+
[Tabs](/docs/components/tabs)
|
|
423
|
+
|
|
424
|
+
Use for switching between related views.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Spinner
|
|
2
|
+
|
|
3
|
+
Shows that something is loading.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Spinner.tsx)
|
|
6
|
+
|
|
7
|
+
Figma: [Spinner](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=1186-3872)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
An indeterminate loading indicator whose arc draws in the current text color, optionally on an elevated tile. Pass `aria-label` to name what loads.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### Basic
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Spinner } from '@tempoxyz/ds'
|
|
19
|
+
|
|
20
|
+
export function Demo() {
|
|
21
|
+
return <Spinner aria-label="Loading transactions" />
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Spinner/Basic.tsx)
|
|
26
|
+
|
|
27
|
+
### Elevated
|
|
28
|
+
|
|
29
|
+
Set `elevated` to place the spinner on a 44px raised tile with a shadow.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { Spinner } from '@tempoxyz/ds'
|
|
33
|
+
|
|
34
|
+
export function Demo() {
|
|
35
|
+
return <Spinner aria-label="Loading quote" elevated />
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Spinner/Elevated.tsx)
|
|
40
|
+
|
|
41
|
+
### Size
|
|
42
|
+
|
|
43
|
+
Set `size="40"` for a 40px ring with a thicker stroke, such as a spinner that fills an empty panel.
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
/** Renders the 16px and 40px spinner rings side by side. @module */
|
|
47
|
+
import { Spinner } from '@tempoxyz/ds'
|
|
48
|
+
|
|
49
|
+
export function Demo() {
|
|
50
|
+
return (
|
|
51
|
+
<div style={{ alignItems: 'center', display: 'flex', gap: 24 }}>
|
|
52
|
+
<Spinner aria-label="Loading balance" />
|
|
53
|
+
<Spinner aria-label="Loading activity" size="40" />
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Spinner/Size.tsx)
|
|
60
|
+
|
|
61
|
+
## Anatomy
|
|
62
|
+
|
|
63
|
+
Import the component and assemble its parts.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { Spinner } from '@tempoxyz/ds'
|
|
67
|
+
|
|
68
|
+
<Spinner />
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Guidelines
|
|
72
|
+
|
|
73
|
+
### When to Use
|
|
74
|
+
|
|
75
|
+
* Mark a region busy for a short, unknown time, such as a table that refreshes after a filter change.
|
|
76
|
+
* Mark a small area that fetches data, such as a quote card or an address lookup.
|
|
77
|
+
* Hold the place of a result with no predictable shape, such as a quote that returns a price or an error.
|
|
78
|
+
|
|
79
|
+
### When Not to Use
|
|
80
|
+
|
|
81
|
+
* Use `loading` on a [Button](/docs/components/button) while its action runs, not a spinner beside it.
|
|
82
|
+
* Use [Skeleton](/docs/components/skeleton) for content with a known shape, such as activity rows or metric tiles.
|
|
83
|
+
* Use [Progress](/docs/components/progress) for measurable work, or any wait over about 10 seconds.
|
|
84
|
+
* Use [LoadingDots](/docs/components/loading-dots) for a short wait inside a line of text.
|
|
85
|
+
|
|
86
|
+
### Match the Indicator to the Wait
|
|
87
|
+
|
|
88
|
+
* **Under About 300 ms (nothing):** Show nothing. Render the result when it arrives.
|
|
89
|
+
* **About 300 ms to 10 Seconds (Spinner):** Mark the busy region or control.
|
|
90
|
+
* **Over About 10 Seconds (Progress):** Show a value for measurable work.
|
|
91
|
+
|
|
92
|
+
Once a spinner appears, keep it for at least about 500 ms so it doesn't flash. For whole pages, see [Loading](/docs/patterns/loading).
|
|
93
|
+
|
|
94
|
+
### Use One Spinner per Region
|
|
95
|
+
|
|
96
|
+
**Do:** Center one spinner where the content will appear, and keep loaded content visible.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
/**
|
|
100
|
+
* Do example for "Use One Spinner per Region" on the Spinner page.
|
|
101
|
+
* Center one spinner where the content will appear, and keep loaded content visible.
|
|
102
|
+
* @module
|
|
103
|
+
*/
|
|
104
|
+
import { Spinner, style, Surface } from '@tempoxyz/ds'
|
|
105
|
+
|
|
106
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
107
|
+
export function Demo() {
|
|
108
|
+
return (
|
|
109
|
+
<div {...styles.page()}>
|
|
110
|
+
<Surface size="small" {...styles.card()}>
|
|
111
|
+
<div {...styles.label()}>Balance</div>
|
|
112
|
+
<div {...styles.value()}>1,250.00 USDC</div>
|
|
113
|
+
</Surface>
|
|
114
|
+
<Surface size="small" {...styles.region()}>
|
|
115
|
+
<Spinner aria-label="Loading activity" />
|
|
116
|
+
</Surface>
|
|
117
|
+
</div>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
namespace styles {
|
|
122
|
+
export const card = style({ display: 'flex', flexDirection: 'column', gap: '4' })
|
|
123
|
+
|
|
124
|
+
export const label = style({ color: 'content.secondary', typography: 'body.b3' })
|
|
125
|
+
|
|
126
|
+
export const page = style({
|
|
127
|
+
display: 'flex',
|
|
128
|
+
flexDirection: 'column',
|
|
129
|
+
gap: '12',
|
|
130
|
+
width: '100% !custom',
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
export const region = style({
|
|
134
|
+
alignItems: 'center',
|
|
135
|
+
display: 'flex',
|
|
136
|
+
height: '6rem !custom',
|
|
137
|
+
justifyContent: 'center',
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
export const value = style({ color: 'content.primary', typography: 'heading.h2' })
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Don't:** Cover the whole page, which blocks content that already loaded.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
/**
|
|
148
|
+
* Don't example for "Use One Spinner per Region" on the Spinner page.
|
|
149
|
+
* Don't cover the whole page, which blocks content that already loaded.
|
|
150
|
+
* @module
|
|
151
|
+
*/
|
|
152
|
+
import { Spinner, style, Surface } from '@tempoxyz/ds'
|
|
153
|
+
|
|
154
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
155
|
+
export function Demo() {
|
|
156
|
+
return (
|
|
157
|
+
<Surface size="small" {...styles.page()}>
|
|
158
|
+
<Spinner aria-label="Loading" />
|
|
159
|
+
</Surface>
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
namespace styles {
|
|
164
|
+
export const page = style({
|
|
165
|
+
alignItems: 'center',
|
|
166
|
+
boxSizing: 'border-box',
|
|
167
|
+
display: 'flex',
|
|
168
|
+
height: '10rem !custom',
|
|
169
|
+
justifyContent: 'center',
|
|
170
|
+
width: '100% !custom',
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Place It Beside a Status Line
|
|
176
|
+
|
|
177
|
+
Show the spinner inline beside a short status line, such as Approving. For a pending action, use `loading` on a [Button](/docs/components/button).
|
|
178
|
+
|
|
179
|
+
## Accessibility
|
|
180
|
+
|
|
181
|
+
A spinner renders an indeterminate `progressbar` named "Loading". It is not a live region, so it is read only when the reader reaches it.
|
|
182
|
+
|
|
183
|
+
### Semantics
|
|
184
|
+
|
|
185
|
+
* **Root (progressbar):** Named "Loading", with no value, so it reads as indeterminate.
|
|
186
|
+
* **Custom Name (aria-label):** Replaces the default name.
|
|
187
|
+
* **Ring (aria-hidden):** A hidden SVG that stops rotating under reduced motion.
|
|
188
|
+
* **Color (3:1):** Uses the text color. Keep 3:1 contrast against the background.
|
|
189
|
+
|
|
190
|
+
### Your Responsibilities
|
|
191
|
+
|
|
192
|
+
* **Say What Is Loading (aria-label):** Name what loads, such as "Loading transactions". Several spinners named "Loading" are indistinguishable.
|
|
193
|
+
* **Announce the Result (SC 4.1.3):** A spinner isn't announced. Announce the result or an error in a status message or a [Toast](/docs/components/toast).
|
|
194
|
+
* **Mark the Region Busy (aria-busy):** Set `aria-busy` on the loading region, so assistive technology waits for its content.
|
|
195
|
+
|
|
196
|
+
## Related
|
|
197
|
+
|
|
198
|
+
[Skeleton](/docs/components/skeleton)
|
|
199
|
+
|
|
200
|
+
Use for content with a known shape.
|
|
201
|
+
|
|
202
|
+
[Progress](/docs/components/progress)
|
|
203
|
+
|
|
204
|
+
Use for measurable work.
|
|
205
|
+
|
|
206
|
+
[LoadingDots](/docs/components/loading-dots)
|
|
207
|
+
|
|
208
|
+
Use for a wait inside a line of text.
|
|
209
|
+
|
|
210
|
+
[Button](/docs/components/button)
|
|
211
|
+
|
|
212
|
+
Use for an action's loading state.
|
|
213
|
+
|
|
214
|
+
[Loading](/docs/patterns/loading)
|
|
215
|
+
|
|
216
|
+
Covers choosing a loading indicator.
|