@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,490 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
Shows a short label for a control on hover or focus.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Tooltip.tsx)
|
|
6
|
+
|
|
7
|
+
Figma: [Tooltip](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=3084-1076) (`Tooltip.Popup`)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A tooltip is a visual label that opens on hover and keyboard focus.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### Basic
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Button, Tooltip } from '@tempoxyz/ds'
|
|
19
|
+
import { Plus } from '@tempoxyz/ds/icons'
|
|
20
|
+
|
|
21
|
+
export function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<Tooltip.Provider>
|
|
24
|
+
<Tooltip.Root>
|
|
25
|
+
<Tooltip.Trigger
|
|
26
|
+
render={<Button aria-label="Add funds" shape="icon" variant="secondary" />}
|
|
27
|
+
>
|
|
28
|
+
<Plus />
|
|
29
|
+
</Tooltip.Trigger>
|
|
30
|
+
<Tooltip.Popup>Add funds</Tooltip.Popup>
|
|
31
|
+
</Tooltip.Root>
|
|
32
|
+
</Tooltip.Provider>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Tooltip/Basic.tsx)
|
|
38
|
+
|
|
39
|
+
### Side
|
|
40
|
+
|
|
41
|
+
Set `side` on `Tooltip.Popup` to `top` (default), `bottom`, `left`, or `right`.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { Button, Tooltip } from '@tempoxyz/ds'
|
|
45
|
+
|
|
46
|
+
export function Demo() {
|
|
47
|
+
return (
|
|
48
|
+
<Tooltip.Provider>
|
|
49
|
+
<Tooltip.Root>
|
|
50
|
+
<Tooltip.Trigger render={<Button variant="secondary" />}>Bottom</Tooltip.Trigger>
|
|
51
|
+
<Tooltip.Popup side="bottom">Shown below the trigger</Tooltip.Popup>
|
|
52
|
+
</Tooltip.Root>
|
|
53
|
+
</Tooltip.Provider>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Tooltip/Side.tsx)
|
|
59
|
+
|
|
60
|
+
### Disabled
|
|
61
|
+
|
|
62
|
+
Wrap a disabled control in a focusable trigger. Disabled elements receive no pointer or focus events.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { Button, Tooltip } from '@tempoxyz/ds'
|
|
66
|
+
import { Refresh } from '@tempoxyz/ds/icons'
|
|
67
|
+
|
|
68
|
+
export function Demo() {
|
|
69
|
+
return (
|
|
70
|
+
<Tooltip.Provider>
|
|
71
|
+
<Tooltip.Root>
|
|
72
|
+
<Tooltip.Trigger render={<span tabIndex={0} />}>
|
|
73
|
+
<Button aria-label="Refresh balances" disabled shape="icon" variant="secondary">
|
|
74
|
+
<Refresh />
|
|
75
|
+
</Button>
|
|
76
|
+
</Tooltip.Trigger>
|
|
77
|
+
<Tooltip.Popup>Refresh balances</Tooltip.Popup>
|
|
78
|
+
</Tooltip.Root>
|
|
79
|
+
</Tooltip.Provider>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Tooltip/Disabled.tsx)
|
|
85
|
+
|
|
86
|
+
## Anatomy
|
|
87
|
+
|
|
88
|
+
Import the component and assemble its parts.
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { Tooltip } from '@tempoxyz/ds'
|
|
92
|
+
|
|
93
|
+
<Tooltip.Provider>
|
|
94
|
+
<Tooltip.Root>
|
|
95
|
+
<Tooltip.Trigger />
|
|
96
|
+
<Tooltip.Popup />
|
|
97
|
+
</Tooltip.Root>
|
|
98
|
+
</Tooltip.Provider>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Guidelines
|
|
102
|
+
|
|
103
|
+
### When to Use
|
|
104
|
+
|
|
105
|
+
* Label an icon-only button, such as Refresh balances, Filter activity, or Settings.
|
|
106
|
+
* Name a control whose icon is ambiguous, such as an arrow that could mean Send or Export.
|
|
107
|
+
|
|
108
|
+
### When Not to Use
|
|
109
|
+
|
|
110
|
+
* Use a [Popover](/docs/components/popover) with `openOnHover` on `Popover.Trigger` for info icons, such as the explanation beside a dashboard metric.
|
|
111
|
+
* Use visible text, such as a `Field.Description` from [Field](/docs/components/field), for fees, limits, requirements, and errors.
|
|
112
|
+
* Use an [Alert](/docs/components/alert) for warnings.
|
|
113
|
+
* Write the reason for a disabled [Button](/docs/components/button) in nearby text, not in a tooltip.
|
|
114
|
+
* Don't add a tooltip to a [Button](/docs/components/button) with a visible label. It repeats the label and covers nearby content.
|
|
115
|
+
|
|
116
|
+
### Use Tooltips as Labels Only
|
|
117
|
+
|
|
118
|
+
Focus stays on the trigger while the tooltip is open, so Tab can't reach a link or button inside it.
|
|
119
|
+
|
|
120
|
+
**Do:** Name the action of an icon-only button in a few words.
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
/**
|
|
124
|
+
* Do example for "Use Tooltips as Labels Only" on the Tooltip page.
|
|
125
|
+
* Name the action of an icon-only button in a few words.
|
|
126
|
+
* @module
|
|
127
|
+
*/
|
|
128
|
+
import { Button, style } from '@tempoxyz/ds'
|
|
129
|
+
import { Filter } from '@tempoxyz/ds/icons'
|
|
130
|
+
|
|
131
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
132
|
+
export function Demo() {
|
|
133
|
+
return (
|
|
134
|
+
<div {...styles.stack()}>
|
|
135
|
+
<div {...styles.tooltip()}>Filter activity</div>
|
|
136
|
+
<Button aria-label="Filter activity" shape="icon" variant="secondary">
|
|
137
|
+
<Filter />
|
|
138
|
+
</Button>
|
|
139
|
+
</div>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
namespace styles {
|
|
144
|
+
export const stack = style({
|
|
145
|
+
alignItems: 'center',
|
|
146
|
+
display: 'flex',
|
|
147
|
+
flexDirection: 'column',
|
|
148
|
+
rowGap: '8',
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
export const tooltip = style({
|
|
152
|
+
backgroundColor: 'content.primary',
|
|
153
|
+
borderRadius: 'xs',
|
|
154
|
+
color: 'background.primary',
|
|
155
|
+
paddingBlock: '6px !custom',
|
|
156
|
+
paddingInline: '12',
|
|
157
|
+
typography: 'body.b3',
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Don't:** Put links, buttons, or other controls in a tooltip. Use a
|
|
163
|
+
[Popover](/docs/components/popover).
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
/**
|
|
167
|
+
* Don't example for "Use Tooltips as Labels Only" on the Tooltip page.
|
|
168
|
+
* Don't put links, buttons, or other controls in a tooltip. Use a Popover.
|
|
169
|
+
* @module
|
|
170
|
+
*/
|
|
171
|
+
import { Button, style } from '@tempoxyz/ds'
|
|
172
|
+
import { InfoCircle } from '@tempoxyz/ds/icons'
|
|
173
|
+
|
|
174
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
175
|
+
export function Demo() {
|
|
176
|
+
return (
|
|
177
|
+
<div {...styles.stack()}>
|
|
178
|
+
<div {...styles.tooltip()}>
|
|
179
|
+
Fees depend on network load. <span {...styles.link()}>Learn more</span>
|
|
180
|
+
</div>
|
|
181
|
+
<Button aria-label="About network fees" shape="icon" size="small" variant="tertiary">
|
|
182
|
+
<InfoCircle />
|
|
183
|
+
</Button>
|
|
184
|
+
</div>
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
namespace styles {
|
|
189
|
+
export const link = style({ textDecorationLine: 'underline !custom' })
|
|
190
|
+
|
|
191
|
+
export const stack = style({
|
|
192
|
+
alignItems: 'center',
|
|
193
|
+
display: 'flex',
|
|
194
|
+
flexDirection: 'column',
|
|
195
|
+
rowGap: '8',
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
export const tooltip = style({
|
|
199
|
+
backgroundColor: 'content.primary',
|
|
200
|
+
borderRadius: 'xs',
|
|
201
|
+
color: 'background.primary',
|
|
202
|
+
maxWidth: '14rem !custom',
|
|
203
|
+
paddingBlock: '6px !custom',
|
|
204
|
+
paddingInline: '12',
|
|
205
|
+
typography: 'body.b3',
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Keep Essential Information Visible
|
|
211
|
+
|
|
212
|
+
Touch input never opens a tooltip, and screen readers don't announce it. Show amounts, fees, and requirements as text on the page.
|
|
213
|
+
|
|
214
|
+
**Do:** Show the fee and its explanation as visible text.
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
/**
|
|
218
|
+
* Do example for "Keep Essential Information Visible" on the Tooltip page.
|
|
219
|
+
* Show the fee and its explanation as visible text.
|
|
220
|
+
* @module
|
|
221
|
+
*/
|
|
222
|
+
import { style } from '@tempoxyz/ds'
|
|
223
|
+
|
|
224
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
225
|
+
export function Demo() {
|
|
226
|
+
return (
|
|
227
|
+
<div {...styles.row()}>
|
|
228
|
+
<div {...styles.text()}>
|
|
229
|
+
<span {...styles.label()}>Network fee</span>
|
|
230
|
+
<span {...styles.hint()}>Paid in the token you send</span>
|
|
231
|
+
</div>
|
|
232
|
+
<span {...styles.value()}>0.001 USDC</span>
|
|
233
|
+
</div>
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
namespace styles {
|
|
238
|
+
export const hint = style({ color: 'content.secondary', typography: 'body.b3' })
|
|
239
|
+
|
|
240
|
+
export const label = style({ color: 'content.primary', typography: 'body.b2Strong' })
|
|
241
|
+
|
|
242
|
+
export const row = style({
|
|
243
|
+
alignItems: 'center',
|
|
244
|
+
columnGap: '24',
|
|
245
|
+
display: 'flex',
|
|
246
|
+
justifyContent: 'space-between',
|
|
247
|
+
width: '16rem !custom',
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
export const text = style({ display: 'flex', flexDirection: 'column', rowGap: '4' })
|
|
251
|
+
|
|
252
|
+
export const value = style({ color: 'content.primary', typography: 'body.b2' })
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Don't:** Hide a value you need to decide behind a tooltip.
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
/**
|
|
260
|
+
* Don't example for "Keep Essential Information Visible" on the Tooltip page.
|
|
261
|
+
* Don't hide a value you need to decide behind a tooltip.
|
|
262
|
+
* @module
|
|
263
|
+
*/
|
|
264
|
+
import { Button, style } from '@tempoxyz/ds'
|
|
265
|
+
import { InfoCircle } from '@tempoxyz/ds/icons'
|
|
266
|
+
|
|
267
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
268
|
+
export function Demo() {
|
|
269
|
+
return (
|
|
270
|
+
<div {...styles.stack()}>
|
|
271
|
+
<div {...styles.tooltip()}>0.001 USDC, paid in the token you send</div>
|
|
272
|
+
<div {...styles.row()}>
|
|
273
|
+
<span {...styles.label()}>Network fee</span>
|
|
274
|
+
<Button aria-label="Network fee" shape="icon" size="small" variant="tertiary">
|
|
275
|
+
<InfoCircle />
|
|
276
|
+
</Button>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
namespace styles {
|
|
283
|
+
export const label = style({ color: 'content.primary', typography: 'body.b2Strong' })
|
|
284
|
+
|
|
285
|
+
export const row = style({ alignItems: 'center', columnGap: '4', display: 'flex' })
|
|
286
|
+
|
|
287
|
+
export const stack = style({
|
|
288
|
+
alignItems: 'flex-end',
|
|
289
|
+
display: 'flex',
|
|
290
|
+
flexDirection: 'column',
|
|
291
|
+
rowGap: '8',
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
export const tooltip = style({
|
|
295
|
+
backgroundColor: 'content.primary',
|
|
296
|
+
borderRadius: 'xs',
|
|
297
|
+
color: 'background.primary',
|
|
298
|
+
paddingBlock: '6px !custom',
|
|
299
|
+
paddingInline: '12',
|
|
300
|
+
typography: 'body.b3',
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Group Tooltips With a Provider
|
|
306
|
+
|
|
307
|
+
* **Toolbars (Tooltip.Provider):** Wrap a row of icon buttons, so once one tooltip opens, its neighbors open instantly.
|
|
308
|
+
* **Single Triggers (600ms):** Keep the default `delay`. Shorter delays flash tooltips as the pointer passes.
|
|
309
|
+
|
|
310
|
+
### Place Tooltips Clear of Related Content
|
|
311
|
+
|
|
312
|
+
`Tooltip.Popup` flips when it would overflow the viewport. Set `side="bottom"` for triggers in a header or top toolbar.
|
|
313
|
+
|
|
314
|
+
**Do:** Choose a side that keeps the value the control acts on visible.
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
/**
|
|
318
|
+
* Do example for "Place Tooltips Clear of Related Content" on the Tooltip page.
|
|
319
|
+
* Choose a side that keeps the value the control acts on visible.
|
|
320
|
+
* @module
|
|
321
|
+
*/
|
|
322
|
+
import { Button, style } from '@tempoxyz/ds'
|
|
323
|
+
import { Refresh } from '@tempoxyz/ds/icons'
|
|
324
|
+
|
|
325
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
326
|
+
export function Demo() {
|
|
327
|
+
return (
|
|
328
|
+
<div {...styles.card()}>
|
|
329
|
+
<span {...styles.label()}>Balance</span>
|
|
330
|
+
<div {...styles.row()}>
|
|
331
|
+
<span {...styles.value()}>1,250.00 USDC</span>
|
|
332
|
+
<span {...styles.anchor()}>
|
|
333
|
+
<Button aria-label="Refresh balance" shape="icon" size="small" variant="secondary">
|
|
334
|
+
<Refresh />
|
|
335
|
+
</Button>
|
|
336
|
+
<span {...styles.tooltip()}>Refresh balance</span>
|
|
337
|
+
</span>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
namespace styles {
|
|
344
|
+
export const anchor = style({ display: 'flex', position: 'relative' })
|
|
345
|
+
|
|
346
|
+
export const card = style({
|
|
347
|
+
display: 'flex',
|
|
348
|
+
flexDirection: 'column',
|
|
349
|
+
height: '7rem !custom',
|
|
350
|
+
rowGap: '4',
|
|
351
|
+
width: '17rem !custom',
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
export const label = style({ color: 'content.secondary', typography: 'body.b3' })
|
|
355
|
+
|
|
356
|
+
export const row = style({ alignItems: 'center', columnGap: '8', display: 'flex' })
|
|
357
|
+
|
|
358
|
+
// Tooltips render in a portal, so this preview places one with the popup's styles, below the trigger.
|
|
359
|
+
export const tooltip = style({
|
|
360
|
+
backgroundColor: 'content.primary',
|
|
361
|
+
borderRadius: 'xs',
|
|
362
|
+
color: 'background.primary',
|
|
363
|
+
paddingBlock: '6px !custom',
|
|
364
|
+
paddingInline: '12',
|
|
365
|
+
position: 'absolute',
|
|
366
|
+
right: '0',
|
|
367
|
+
top: 'calc(100% + 8px) !custom',
|
|
368
|
+
typography: 'body.b3',
|
|
369
|
+
whiteSpace: 'nowrap',
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
export const value = style({ color: 'content.primary', typography: 'heading.h2' })
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Don't:** Let the tooltip cover the value beside its trigger.
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
/**
|
|
380
|
+
* Don't example for "Place Tooltips Clear of Related Content" on the Tooltip page.
|
|
381
|
+
* Don't let the tooltip cover the value beside its trigger.
|
|
382
|
+
* @module
|
|
383
|
+
*/
|
|
384
|
+
import { Button, style } from '@tempoxyz/ds'
|
|
385
|
+
import { Refresh } from '@tempoxyz/ds/icons'
|
|
386
|
+
|
|
387
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
388
|
+
export function Demo() {
|
|
389
|
+
return (
|
|
390
|
+
<div {...styles.card()}>
|
|
391
|
+
<span {...styles.label()}>Balance</span>
|
|
392
|
+
<div {...styles.row()}>
|
|
393
|
+
<span {...styles.value()}>1,250.00 USDC</span>
|
|
394
|
+
<span {...styles.anchor()}>
|
|
395
|
+
<Button aria-label="Refresh balance" shape="icon" size="small" variant="secondary">
|
|
396
|
+
<Refresh />
|
|
397
|
+
</Button>
|
|
398
|
+
<span {...styles.tooltip()}>Refresh balance</span>
|
|
399
|
+
</span>
|
|
400
|
+
</div>
|
|
401
|
+
</div>
|
|
402
|
+
)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
namespace styles {
|
|
406
|
+
export const anchor = style({ display: 'flex', position: 'relative' })
|
|
407
|
+
|
|
408
|
+
export const card = style({
|
|
409
|
+
display: 'flex',
|
|
410
|
+
flexDirection: 'column',
|
|
411
|
+
height: '7rem !custom',
|
|
412
|
+
rowGap: '4',
|
|
413
|
+
width: '17rem !custom',
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
export const label = style({ color: 'content.secondary', typography: 'body.b3' })
|
|
417
|
+
|
|
418
|
+
export const row = style({ alignItems: 'center', columnGap: '8', display: 'flex' })
|
|
419
|
+
|
|
420
|
+
// Tooltips render in a portal, so this preview places one with the popup's styles, left of the trigger.
|
|
421
|
+
export const tooltip = style({
|
|
422
|
+
backgroundColor: 'content.primary',
|
|
423
|
+
borderRadius: 'xs',
|
|
424
|
+
color: 'background.primary',
|
|
425
|
+
paddingBlock: '6px !custom',
|
|
426
|
+
paddingInline: '12',
|
|
427
|
+
position: 'absolute',
|
|
428
|
+
right: 'calc(100% + 8px) !custom',
|
|
429
|
+
top: '50% !custom',
|
|
430
|
+
transform: 'translateY(-50%) !custom',
|
|
431
|
+
typography: 'body.b3',
|
|
432
|
+
whiteSpace: 'nowrap',
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
export const value = style({ color: 'content.primary', typography: 'heading.h2' })
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Content
|
|
440
|
+
|
|
441
|
+
### Write a Few Words
|
|
442
|
+
|
|
443
|
+
Use one to four words. Name the action, such as Refresh balances, not the icon, such as Circular arrows.
|
|
444
|
+
|
|
445
|
+
## Accessibility
|
|
446
|
+
|
|
447
|
+
A tooltip is visual only, so the trigger needs its own accessible name.
|
|
448
|
+
|
|
449
|
+
### Semantics
|
|
450
|
+
|
|
451
|
+
* **Tooltip.Trigger (button):** Keeps the role of the element it renders.
|
|
452
|
+
* **Tooltip.Popup:** Has no role and isn't linked to the trigger, so it neither names nor describes it. Mounts only while open.
|
|
453
|
+
* **Contrast (elevated):** Sets primary text on the elevated fill in both schemes.
|
|
454
|
+
|
|
455
|
+
### Keyboard
|
|
456
|
+
|
|
457
|
+
* **Open on Focus (Tab):** Focus on the trigger opens the tooltip at once.
|
|
458
|
+
* **Close the Tooltip (Escape):** Closes the tooltip while focus stays on the trigger.
|
|
459
|
+
|
|
460
|
+
### Focus
|
|
461
|
+
|
|
462
|
+
* **No Focus:** The tooltip never takes focus and holds no interactive content.
|
|
463
|
+
* **Pointer:** Opens after 600ms of hover. The pointer can move onto the popup without closing it.
|
|
464
|
+
* **Touch:** Touch input never opens it, so no task may depend on one.
|
|
465
|
+
|
|
466
|
+
### Your Responsibilities
|
|
467
|
+
|
|
468
|
+
* **Name Icon-Only Triggers (aria-label):** Name an icon-only trigger with the tooltip text.
|
|
469
|
+
|
|
470
|
+
## Related
|
|
471
|
+
|
|
472
|
+
[Popover](/docs/components/popover)
|
|
473
|
+
|
|
474
|
+
Use for info icons and interactive content.
|
|
475
|
+
|
|
476
|
+
[Button](/docs/components/button)
|
|
477
|
+
|
|
478
|
+
Use for icon-only buttons.
|
|
479
|
+
|
|
480
|
+
[CopyButton](/docs/components/copy-button)
|
|
481
|
+
|
|
482
|
+
Use for a copy action that names itself.
|
|
483
|
+
|
|
484
|
+
[Field](/docs/components/field)
|
|
485
|
+
|
|
486
|
+
Use for descriptions that stay visible.
|
|
487
|
+
|
|
488
|
+
[Dashboards](/docs/patterns/dashboards)
|
|
489
|
+
|
|
490
|
+
Covers metric explanations.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# VerificationCode
|
|
2
|
+
|
|
3
|
+
Shows a code that a person compares with the one another app shows.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/VerificationCode.tsx)
|
|
6
|
+
|
|
7
|
+
Figma: [Content/Verification Code](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=5227-3952) (`VerificationCode.Root`)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A verification code renders a centered box with a label above a large code. A person reads the code and checks that it matches the code on another device or app, such as in a device sign-in.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### Basic
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { VerificationCode } from '@tempoxyz/ds'
|
|
19
|
+
|
|
20
|
+
export function Demo() {
|
|
21
|
+
return (
|
|
22
|
+
<VerificationCode.Root>
|
|
23
|
+
<VerificationCode.Label>Confirm this code matches Claude</VerificationCode.Label>
|
|
24
|
+
<VerificationCode.Value>WXYZ-4821</VerificationCode.Value>
|
|
25
|
+
</VerificationCode.Root>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/VerificationCode/Basic.tsx)
|
|
31
|
+
|
|
32
|
+
## Anatomy
|
|
33
|
+
|
|
34
|
+
Import the component and assemble its parts.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { VerificationCode } from '@tempoxyz/ds'
|
|
38
|
+
|
|
39
|
+
<VerificationCode.Root>
|
|
40
|
+
<VerificationCode.Label />
|
|
41
|
+
<VerificationCode.Value />
|
|
42
|
+
</VerificationCode.Root>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Guidelines
|
|
46
|
+
|
|
47
|
+
### When to Use
|
|
48
|
+
|
|
49
|
+
* Confirm a device sign-in by matching the code that an app or a terminal shows.
|
|
50
|
+
* Pair two devices by a code that both show.
|
|
51
|
+
|
|
52
|
+
### When Not to Use
|
|
53
|
+
|
|
54
|
+
* Use [OtpField](/docs/components/otp-field) when the person types a code.
|
|
55
|
+
* Use [Snippet](/docs/components/snippet) for a command or a value to copy.
|
|
56
|
+
|
|
57
|
+
### Match the Other Device
|
|
58
|
+
|
|
59
|
+
**Do:** Name the app that shows the code, and keep its grouping.
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { VerificationCode } from '@tempoxyz/ds'
|
|
63
|
+
|
|
64
|
+
export function Demo() {
|
|
65
|
+
return (
|
|
66
|
+
<VerificationCode.Root>
|
|
67
|
+
<VerificationCode.Label>Confirm this code matches Claude</VerificationCode.Label>
|
|
68
|
+
<VerificationCode.Value>WXYZ-4821</VerificationCode.Value>
|
|
69
|
+
</VerificationCode.Root>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Don't:** Regroup the code, or leave out where it comes from.
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { VerificationCode } from '@tempoxyz/ds'
|
|
78
|
+
|
|
79
|
+
export function Demo() {
|
|
80
|
+
return (
|
|
81
|
+
<VerificationCode.Root>
|
|
82
|
+
<VerificationCode.Label>Your code</VerificationCode.Label>
|
|
83
|
+
<VerificationCode.Value>WX YZ 48 21</VerificationCode.Value>
|
|
84
|
+
</VerificationCode.Root>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Content
|
|
90
|
+
|
|
91
|
+
### Write the Label
|
|
92
|
+
|
|
93
|
+
Start the label with the action, such as Confirm this code matches Claude. Name the app or device that shows the other code.
|
|
94
|
+
|
|
95
|
+
## Accessibility
|
|
96
|
+
|
|
97
|
+
A verification code renders a `<div>` with the label in a `<p>` and the code in a `<span>`. Screen readers read the label, then the code.
|
|
98
|
+
|
|
99
|
+
### Semantics
|
|
100
|
+
|
|
101
|
+
* **Label (p):** Screen readers read the label before the code.
|
|
102
|
+
* **Value (translate=no):** Browsers do not translate the code, and a click selects all of it.
|
|
103
|
+
|
|
104
|
+
### Your Responsibilities
|
|
105
|
+
|
|
106
|
+
* **Keep the Code on Screen (SC 3.3.8):** Show the code until the sign-in finishes, so people can compare it.
|
|
107
|
+
|
|
108
|
+
## Related
|
|
109
|
+
|
|
110
|
+
[OtpField](/docs/components/otp-field)
|
|
111
|
+
|
|
112
|
+
Use for a code that a person types.
|
|
113
|
+
|
|
114
|
+
[Snippet](/docs/components/snippet)
|
|
115
|
+
|
|
116
|
+
Use for a command or a value to copy.
|