@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.
- package/README.md +7 -6
- package/dist/docs/AGENTS.md +12 -0
- package/dist/docs/index.md +145 -0
- package/dist/docs/marketing/introduction/getting-started.md +241 -0
- package/dist/docs/product/components/accordion.md +489 -0
- package/dist/docs/product/components/address-card.md +147 -0
- package/dist/docs/product/components/agent-logo.md +194 -0
- package/dist/docs/product/components/alert-dialog.md +631 -0
- package/dist/docs/product/components/alert.md +448 -0
- package/dist/docs/product/components/amount-input.md +305 -0
- package/dist/docs/product/components/amount.md +794 -0
- package/dist/docs/product/components/app-shell.md +559 -0
- package/dist/docs/product/components/asset-chip.md +294 -0
- package/dist/docs/product/components/autocomplete.md +620 -0
- package/dist/docs/product/components/avatar.md +321 -0
- package/dist/docs/product/components/badge.md +339 -0
- package/dist/docs/product/components/badged-logo.md +116 -0
- package/dist/docs/product/components/banner.md +379 -0
- package/dist/docs/product/components/bar-chart.md +208 -0
- package/dist/docs/product/components/breadcrumbs.md +380 -0
- package/dist/docs/product/components/button-group.md +286 -0
- package/dist/docs/product/components/button.md +650 -0
- package/dist/docs/product/components/calendar.md +375 -0
- package/dist/docs/product/components/callout.md +96 -0
- package/dist/docs/product/components/checkbox-group.md +521 -0
- package/dist/docs/product/components/checkbox.md +467 -0
- package/dist/docs/product/components/choice-group.md +516 -0
- package/dist/docs/product/components/choicebox.md +641 -0
- package/dist/docs/product/components/code.md +100 -0
- package/dist/docs/product/components/combobox.md +939 -0
- package/dist/docs/product/components/container.md +257 -0
- package/dist/docs/product/components/copy-button.md +642 -0
- package/dist/docs/product/components/date-picker.md +514 -0
- package/dist/docs/product/components/dialog.md +1332 -0
- package/dist/docs/product/components/drawer.md +966 -0
- package/dist/docs/product/components/empty.md +340 -0
- package/dist/docs/product/components/field.md +570 -0
- package/dist/docs/product/components/fieldset.md +398 -0
- package/dist/docs/product/components/frame.md +434 -0
- package/dist/docs/product/components/gauge.md +299 -0
- package/dist/docs/product/components/get-started-visual.md +117 -0
- package/dist/docs/product/components/grid.md +288 -0
- package/dist/docs/product/components/hero-visual.md +155 -0
- package/dist/docs/product/components/hex.md +487 -0
- package/dist/docs/product/components/icon-tile.md +292 -0
- package/dist/docs/product/components/identicon.md +371 -0
- package/dist/docs/product/components/inline.md +233 -0
- package/dist/docs/product/components/inset.md +225 -0
- package/dist/docs/product/components/kbd.md +423 -0
- package/dist/docs/product/components/list-group.md +981 -0
- package/dist/docs/product/components/loading-dots.md +237 -0
- package/dist/docs/product/components/menu.md +934 -0
- package/dist/docs/product/components/native-select.md +204 -0
- package/dist/docs/product/components/network-logo.md +248 -0
- package/dist/docs/product/components/number-field.md +543 -0
- package/dist/docs/product/components/otp-field.md +616 -0
- package/dist/docs/product/components/pagination.md +516 -0
- package/dist/docs/product/components/popover.md +544 -0
- package/dist/docs/product/components/progress.md +388 -0
- package/dist/docs/product/components/qr.md +314 -0
- package/dist/docs/product/components/radio-group.md +528 -0
- package/dist/docs/product/components/secret-value.md +406 -0
- package/dist/docs/product/components/select.md +751 -0
- package/dist/docs/product/components/separator.md +379 -0
- package/dist/docs/product/components/sidebar-menu.md +922 -0
- package/dist/docs/product/components/skeleton.md +517 -0
- package/dist/docs/product/components/slider.md +539 -0
- package/dist/docs/product/components/snippet.md +424 -0
- package/dist/docs/product/components/spinner.md +216 -0
- package/dist/docs/product/components/split-bar.md +139 -0
- package/dist/docs/product/components/split-button.md +464 -0
- package/dist/docs/product/components/stack.md +299 -0
- package/dist/docs/product/components/status-chip.md +226 -0
- package/dist/docs/product/components/status-indicator.md +119 -0
- package/dist/docs/product/components/status-row.md +174 -0
- package/dist/docs/product/components/stepper.md +451 -0
- package/dist/docs/product/components/success-hero.md +157 -0
- package/dist/docs/product/components/surface.md +639 -0
- package/dist/docs/product/components/switch.md +472 -0
- package/dist/docs/product/components/table.md +967 -0
- package/dist/docs/product/components/tabs.md +627 -0
- package/dist/docs/product/components/tempo-logo.md +185 -0
- package/dist/docs/product/components/text-input.md +624 -0
- package/dist/docs/product/components/textarea.md +352 -0
- package/dist/docs/product/components/toast.md +535 -0
- package/dist/docs/product/components/token-logo.md +371 -0
- package/dist/docs/product/components/token.md +247 -0
- package/dist/docs/product/components/tooltip.md +490 -0
- package/dist/docs/product/components/verification-code.md +116 -0
- package/dist/docs/product/components/visual.md +249 -0
- package/dist/docs/product/components.md +203 -0
- package/dist/docs/product/foundations/accessibility.md +377 -0
- package/dist/docs/product/foundations/agents.md +150 -0
- package/dist/docs/product/foundations/color.md +522 -0
- package/dist/docs/product/foundations/content/tone.md +194 -0
- package/dist/docs/product/foundations/content/voice.md +194 -0
- package/dist/docs/product/foundations/content/writing-style.md +406 -0
- package/dist/docs/product/foundations/iconography.md +282 -0
- package/dist/docs/product/foundations/intent.md +360 -0
- package/dist/docs/product/foundations/layout.md +508 -0
- package/dist/docs/product/foundations/linter.md +496 -0
- package/dist/docs/product/foundations/motion.md +151 -0
- package/dist/docs/product/foundations/radius-and-padding.md +86 -0
- package/dist/docs/product/foundations/typography.md +266 -0
- package/dist/docs/product/introduction/faq.md +133 -0
- package/dist/docs/product/introduction/getting-started.md +377 -0
- package/dist/docs/product/patterns/blockchain-values.md +709 -0
- package/dist/docs/product/patterns/dashboards.md +638 -0
- package/dist/docs/product/patterns/destructive-actions.md +626 -0
- package/dist/docs/product/patterns/empty-states.md +612 -0
- package/dist/docs/product/patterns/errors-and-validation.md +808 -0
- package/dist/docs/product/patterns/feedback-and-status.md +518 -0
- package/dist/docs/product/patterns/forms.md +679 -0
- package/dist/docs/product/patterns/loading.md +630 -0
- package/dist/docs/product/patterns/navigation.md +397 -0
- package/dist/docs/product/patterns/payments.md +765 -0
- package/dist/docs/product/patterns/responsive-layout.md +997 -0
- package/dist/docs/product/patterns/tables-and-lists.md +964 -0
- package/dist/docs/product/products/tempo-console.md +671 -0
- package/dist/docs/product/products/tempo-performance.md +437 -0
- package/dist/docs/product/products/tempo-wallet.md +438 -0
- package/dist/marketing/index.d.ts +4 -0
- package/dist/marketing/index.d.ts.map +1 -0
- package/dist/marketing/index.js +4 -0
- package/dist/marketing/index.js.map +1 -0
- package/dist/marketing/index.js.zyzz.json +1 -0
- package/dist/marketing/vars.d.ts +907 -0
- package/dist/marketing/vars.d.ts.map +1 -0
- package/dist/marketing/vars.js +15 -0
- package/dist/marketing/vars.js.map +1 -0
- package/dist/marketing/vars.js.zyzz.json +1 -0
- package/dist/marketing/zyzz.config.d.ts +4512 -0
- package/dist/marketing/zyzz.config.d.ts.map +1 -0
- package/dist/marketing/zyzz.config.js +63 -0
- package/dist/marketing/zyzz.config.js.map +1 -0
- package/dist/marketing/zyzz.config.js.zyzz.json +1 -0
- package/dist/oxlint/index.d.ts +12 -1
- package/dist/oxlint/index.d.ts.map +1 -1
- package/dist/oxlint/index.js +39 -1
- package/dist/oxlint/index.js.map +1 -1
- package/dist/oxlint/internal/Docs.d.ts +9 -0
- package/dist/oxlint/internal/Docs.d.ts.map +1 -0
- package/dist/oxlint/internal/Docs.js +15 -0
- package/dist/oxlint/internal/Docs.js.map +1 -0
- package/dist/oxlint/internal/Imports.d.ts +1 -1
- package/dist/oxlint/internal/Imports.d.ts.map +1 -1
- package/dist/oxlint/internal/Imports.js +2 -0
- package/dist/oxlint/internal/Imports.js.map +1 -1
- package/dist/oxlint/internal/Styles.d.ts +40 -0
- package/dist/oxlint/internal/Styles.d.ts.map +1 -0
- package/dist/oxlint/internal/Styles.js +194 -0
- package/dist/oxlint/internal/Styles.js.map +1 -0
- package/dist/oxlint/internal/Tokens.d.ts +16 -0
- package/dist/oxlint/internal/Tokens.d.ts.map +1 -0
- package/dist/oxlint/internal/Tokens.js +39 -0
- package/dist/oxlint/internal/Tokens.js.map +1 -0
- package/dist/oxlint/rules/NoCrossSurface.d.ts +2 -2
- package/dist/oxlint/rules/NoCrossSurface.js +3 -3
- package/dist/oxlint/rules/NoCrossSurface.js.map +1 -1
- package/dist/oxlint/rules/NoCustomValues.d.ts +11 -0
- package/dist/oxlint/rules/NoCustomValues.d.ts.map +1 -0
- package/dist/oxlint/rules/NoCustomValues.js +150 -0
- package/dist/oxlint/rules/NoCustomValues.js.map +1 -0
- package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts +11 -0
- package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts.map +1 -0
- package/dist/oxlint/rules/NoSingleKeyShortcuts.js +158 -0
- package/dist/oxlint/rules/NoSingleKeyShortcuts.js.map +1 -0
- package/dist/oxlint/rules/PreferComponent.d.ts +3 -2
- package/dist/oxlint/rules/PreferComponent.d.ts.map +1 -1
- package/dist/oxlint/rules/PreferComponent.js +11 -4
- package/dist/oxlint/rules/PreferComponent.js.map +1 -1
- package/dist/oxlint/rules/PreferLayout.d.ts +9 -0
- package/dist/oxlint/rules/PreferLayout.d.ts.map +1 -0
- package/dist/oxlint/rules/PreferLayout.js +90 -0
- package/dist/oxlint/rules/PreferLayout.js.map +1 -0
- package/dist/oxlint/rules/PreferProgress.d.ts +9 -0
- package/dist/oxlint/rules/PreferProgress.d.ts.map +1 -0
- package/dist/oxlint/rules/PreferProgress.js +43 -0
- package/dist/oxlint/rules/PreferProgress.js.map +1 -0
- package/dist/oxlint/rules/PreferSurface.d.ts +9 -0
- package/dist/oxlint/rules/PreferSurface.d.ts.map +1 -0
- package/dist/oxlint/rules/PreferSurface.js +55 -0
- package/dist/oxlint/rules/PreferSurface.js.map +1 -0
- package/dist/oxlint/rules/RequireAccessibleName.d.ts.map +1 -1
- package/dist/oxlint/rules/RequireAccessibleName.js +3 -1
- package/dist/oxlint/rules/RequireAccessibleName.js.map +1 -1
- package/dist/oxlint/rules/RequireScrollRegion.d.ts +11 -0
- package/dist/oxlint/rules/RequireScrollRegion.d.ts.map +1 -0
- package/dist/oxlint/rules/RequireScrollRegion.js +71 -0
- package/dist/oxlint/rules/RequireScrollRegion.js.map +1 -0
- package/dist/web/icons/index.js.zyzz.json +1 -0
- package/package.json +6 -1
- package/src/marketing/README.md +21 -0
- package/src/marketing/index.ts +3 -0
- package/src/marketing/vars.ts +751 -0
- package/src/marketing/zyzz.config.ts +376 -0
- package/src/oxlint/index.ts +40 -1
- package/src/oxlint/internal/Docs.ts +18 -0
- package/src/oxlint/internal/Imports.ts +2 -1
- package/src/oxlint/internal/Styles.ts +240 -0
- package/src/oxlint/internal/Tokens.ts +43 -0
- package/src/oxlint/rules/NoCrossSurface.ts +3 -3
- package/src/oxlint/rules/NoCustomValues.ts +170 -0
- package/src/oxlint/rules/NoSingleKeyShortcuts.ts +190 -0
- package/src/oxlint/rules/PreferComponent.ts +11 -4
- package/src/oxlint/rules/PreferLayout.ts +96 -0
- package/src/oxlint/rules/PreferProgress.ts +49 -0
- package/src/oxlint/rules/PreferSurface.ts +70 -0
- package/src/oxlint/rules/RequireAccessibleName.ts +3 -1
- package/src/oxlint/rules/RequireScrollRegion.ts +92 -0
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
# Autocomplete
|
|
2
|
+
|
|
3
|
+
A text input that suggests values while people type.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Autocomplete.tsx)
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
A text input with a suggestion list. Any typed string is a valid value, so suggestions only speed up entry.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
### Basic
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { Autocomplete } from '@tempoxyz/ds'
|
|
17
|
+
|
|
18
|
+
const actions = ['Send payment', 'Send request', 'Swap tokens', 'View activity']
|
|
19
|
+
|
|
20
|
+
export function Demo() {
|
|
21
|
+
return (
|
|
22
|
+
<Autocomplete.Root items={actions}>
|
|
23
|
+
<Autocomplete.InputGroup>
|
|
24
|
+
<Autocomplete.Input aria-label="Search" placeholder="Search actions" />
|
|
25
|
+
<Autocomplete.Clear />
|
|
26
|
+
</Autocomplete.InputGroup>
|
|
27
|
+
<Autocomplete.Popup>
|
|
28
|
+
<Autocomplete.Empty>No matches</Autocomplete.Empty>
|
|
29
|
+
<Autocomplete.List>
|
|
30
|
+
{(action: string) => (
|
|
31
|
+
<Autocomplete.Item key={action} value={action}>
|
|
32
|
+
{action}
|
|
33
|
+
</Autocomplete.Item>
|
|
34
|
+
)}
|
|
35
|
+
</Autocomplete.List>
|
|
36
|
+
</Autocomplete.Popup>
|
|
37
|
+
</Autocomplete.Root>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Autocomplete/Basic.tsx)
|
|
43
|
+
|
|
44
|
+
## Anatomy
|
|
45
|
+
|
|
46
|
+
Import the component and assemble its parts.
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { Autocomplete } from '@tempoxyz/ds'
|
|
50
|
+
|
|
51
|
+
<Autocomplete.Root>
|
|
52
|
+
<Autocomplete.InputGroup>
|
|
53
|
+
<Autocomplete.Input />
|
|
54
|
+
<Autocomplete.Clear />
|
|
55
|
+
</Autocomplete.InputGroup>
|
|
56
|
+
<Autocomplete.Popup>
|
|
57
|
+
<Autocomplete.Empty />
|
|
58
|
+
<Autocomplete.List>
|
|
59
|
+
<Autocomplete.Group>
|
|
60
|
+
<Autocomplete.GroupLabel />
|
|
61
|
+
<Autocomplete.Collection>
|
|
62
|
+
<Autocomplete.Item />
|
|
63
|
+
</Autocomplete.Collection>
|
|
64
|
+
</Autocomplete.Group>
|
|
65
|
+
<Autocomplete.Separator />
|
|
66
|
+
</Autocomplete.List>
|
|
67
|
+
</Autocomplete.Popup>
|
|
68
|
+
</Autocomplete.Root>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Guidelines
|
|
72
|
+
|
|
73
|
+
### When to Use
|
|
74
|
+
|
|
75
|
+
* Enter free text with suggested values, such as a recipient address with recent recipients below it.
|
|
76
|
+
* Search actions or pages from one field, such as Send payment or View activity.
|
|
77
|
+
|
|
78
|
+
### When Not to Use
|
|
79
|
+
|
|
80
|
+
* If the value must be one of the items, such as the asset to send, use [Combobox](combobox.md).
|
|
81
|
+
* Use [Select](select.md) for a short list of fixed options.
|
|
82
|
+
* If there is nothing useful to suggest, use [TextInput](text-input.md).
|
|
83
|
+
|
|
84
|
+
### Accept Any Typed Value
|
|
85
|
+
|
|
86
|
+
Validate the text as you would a plain [TextInput](text-input.md), such as a 0x prefix on an address, and explain problems in a `Field.Error`.
|
|
87
|
+
|
|
88
|
+
**Do:** Accept a new 0x address that isn't among the suggestions.
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
/**
|
|
92
|
+
* Do example for "Accept Any Typed Value" on the Autocomplete page.
|
|
93
|
+
* Accept a new 0x address that isn't among the suggestions.
|
|
94
|
+
* @module
|
|
95
|
+
*/
|
|
96
|
+
import { Autocomplete, Field, style } from '@tempoxyz/ds'
|
|
97
|
+
|
|
98
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
99
|
+
|
|
100
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
101
|
+
export function Demo() {
|
|
102
|
+
return (
|
|
103
|
+
<Field.Root {...styles.field()}>
|
|
104
|
+
<Field.Label>Recipient</Field.Label>
|
|
105
|
+
<Autocomplete.Root defaultValue="0x8f3a…c21d" items={recipients}>
|
|
106
|
+
<Autocomplete.InputGroup>
|
|
107
|
+
<Autocomplete.Input placeholder="Name or 0x address" />
|
|
108
|
+
</Autocomplete.InputGroup>
|
|
109
|
+
</Autocomplete.Root>
|
|
110
|
+
<Field.Description>A new address. Check it before you send.</Field.Description>
|
|
111
|
+
</Field.Root>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
namespace styles {
|
|
116
|
+
export const field = style({ maxWidth: '16rem !custom', width: '100% !custom' })
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Don't:** Clear or reject text because it doesn't match a suggestion.
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
/**
|
|
124
|
+
* Don't example for "Accept Any Typed Value" on the Autocomplete page.
|
|
125
|
+
* Don't clear or reject text because it doesn't match a suggestion.
|
|
126
|
+
* @module
|
|
127
|
+
*/
|
|
128
|
+
import { Autocomplete, Field, style } from '@tempoxyz/ds'
|
|
129
|
+
|
|
130
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
131
|
+
|
|
132
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
133
|
+
export function Demo() {
|
|
134
|
+
return (
|
|
135
|
+
<Field.Root invalid {...styles.field()}>
|
|
136
|
+
<Field.Label>Recipient</Field.Label>
|
|
137
|
+
<Autocomplete.Root defaultValue="0x8f3a…c21d" items={recipients}>
|
|
138
|
+
<Autocomplete.InputGroup invalid>
|
|
139
|
+
<Autocomplete.Input aria-invalid placeholder="Name or 0x address" />
|
|
140
|
+
</Autocomplete.InputGroup>
|
|
141
|
+
</Autocomplete.Root>
|
|
142
|
+
<Field.Error match>Select a saved recipient</Field.Error>
|
|
143
|
+
</Field.Root>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
namespace styles {
|
|
148
|
+
export const field = style({ maxWidth: '16rem !custom', width: '100% !custom' })
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Suggest Likely Values
|
|
153
|
+
|
|
154
|
+
* **`items`:** Filters automatically.
|
|
155
|
+
* **`filteredItems`:** Accepts items you filter yourself, such as results from a server.
|
|
156
|
+
|
|
157
|
+
**Do:** List recent, frequent, or saved values first, such as the last few recipients.
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
/**
|
|
161
|
+
* Do example for "Suggest Likely Values" on the Autocomplete page.
|
|
162
|
+
* List recent, frequent, or saved values first, such as the last few recipients.
|
|
163
|
+
* @module
|
|
164
|
+
*/
|
|
165
|
+
import { style } from '@tempoxyz/ds'
|
|
166
|
+
|
|
167
|
+
const recipients = ['alice.tempo', 'payroll.tempo', 'treasury.tempo']
|
|
168
|
+
|
|
169
|
+
// A static copy of the open popup, since the real one portals and opens on input.
|
|
170
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
171
|
+
export function Demo() {
|
|
172
|
+
return (
|
|
173
|
+
<div {...styles.popup()}>
|
|
174
|
+
<div {...styles.label()}>Recent recipients</div>
|
|
175
|
+
{recipients.map((recipient) => (
|
|
176
|
+
<div key={recipient} {...styles.item()}>
|
|
177
|
+
{recipient}
|
|
178
|
+
</div>
|
|
179
|
+
))}
|
|
180
|
+
</div>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
namespace styles {
|
|
185
|
+
export const item = style({
|
|
186
|
+
alignItems: 'center',
|
|
187
|
+
display: 'flex',
|
|
188
|
+
minHeight: '40',
|
|
189
|
+
paddingInline: '16',
|
|
190
|
+
typography: 'body.b2Strong',
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
export const label = style({
|
|
194
|
+
color: 'content.secondary',
|
|
195
|
+
paddingBlock: '8',
|
|
196
|
+
paddingInline: '16',
|
|
197
|
+
typography: 'body.b3',
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
export const popup = style({
|
|
201
|
+
backgroundColor: 'background.elevated',
|
|
202
|
+
borderRadius: 'sm',
|
|
203
|
+
boxShadow: 'regular',
|
|
204
|
+
padding: '6px !custom',
|
|
205
|
+
width: '16rem !custom',
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Don't:** Suggest a list too long to scan without scrolling.
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
/**
|
|
214
|
+
* Don't example for "Suggest Likely Values" on the Autocomplete page.
|
|
215
|
+
* Don't suggest a list too long to scan without scrolling.
|
|
216
|
+
* @module
|
|
217
|
+
*/
|
|
218
|
+
import { style } from '@tempoxyz/ds'
|
|
219
|
+
|
|
220
|
+
const recipients = [
|
|
221
|
+
'acme.tempo',
|
|
222
|
+
'alice.tempo',
|
|
223
|
+
'bob.tempo',
|
|
224
|
+
'carol.tempo',
|
|
225
|
+
'dave.tempo',
|
|
226
|
+
'erin.tempo',
|
|
227
|
+
'frank.tempo',
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
// A static copy of the open popup, since the real one portals and opens on input.
|
|
231
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
232
|
+
export function Demo() {
|
|
233
|
+
return (
|
|
234
|
+
// oxlint-disable-next-line tds/require-scroll-region -- An inert picture of a popup, which never takes focus.
|
|
235
|
+
<div {...styles.popup()}>
|
|
236
|
+
{recipients.map((recipient) => (
|
|
237
|
+
<div key={recipient} {...styles.item()}>
|
|
238
|
+
{recipient}
|
|
239
|
+
</div>
|
|
240
|
+
))}
|
|
241
|
+
</div>
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
namespace styles {
|
|
246
|
+
export const item = style({
|
|
247
|
+
alignItems: 'center',
|
|
248
|
+
display: 'flex',
|
|
249
|
+
flexShrink: '0 !custom',
|
|
250
|
+
minHeight: '40',
|
|
251
|
+
paddingInline: '16',
|
|
252
|
+
typography: 'body.b2Strong',
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
export const popup = style({
|
|
256
|
+
backgroundColor: 'background.elevated',
|
|
257
|
+
borderRadius: 'sm',
|
|
258
|
+
boxShadow: 'regular',
|
|
259
|
+
display: 'flex',
|
|
260
|
+
flexDirection: 'column',
|
|
261
|
+
maxHeight: '10rem !custom',
|
|
262
|
+
overflowY: 'auto',
|
|
263
|
+
padding: '6px !custom',
|
|
264
|
+
width: '16rem !custom',
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Show the Text a Suggestion Inserts
|
|
270
|
+
|
|
271
|
+
Pressing an `Autocomplete.Item` fills the input with the string form of its `value`.
|
|
272
|
+
|
|
273
|
+
**Do:** Show the same text in the item that it inserts.
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
/**
|
|
277
|
+
* Do example for "Show the Text a Suggestion Inserts" on the Autocomplete page.
|
|
278
|
+
* Show the same text in the item that it inserts.
|
|
279
|
+
* @module
|
|
280
|
+
*/
|
|
281
|
+
import { Autocomplete, style } from '@tempoxyz/ds'
|
|
282
|
+
|
|
283
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
284
|
+
|
|
285
|
+
// The popup portals and opens on input, so a static copy shows the picked suggestion.
|
|
286
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
287
|
+
export function Demo() {
|
|
288
|
+
return (
|
|
289
|
+
<div {...styles.column()}>
|
|
290
|
+
<Autocomplete.Root defaultValue="alice.tempo" items={recipients}>
|
|
291
|
+
<Autocomplete.InputGroup>
|
|
292
|
+
<Autocomplete.Input aria-label="Recipient" />
|
|
293
|
+
</Autocomplete.InputGroup>
|
|
294
|
+
</Autocomplete.Root>
|
|
295
|
+
<div {...styles.popup()}>
|
|
296
|
+
<div {...styles.item()}>alice.tempo</div>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
namespace styles {
|
|
303
|
+
export const column = style({
|
|
304
|
+
display: 'flex',
|
|
305
|
+
flexDirection: 'column',
|
|
306
|
+
gap: '8',
|
|
307
|
+
maxWidth: '16rem !custom',
|
|
308
|
+
width: '100% !custom',
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
export const item = style({
|
|
312
|
+
alignItems: 'center',
|
|
313
|
+
display: 'flex',
|
|
314
|
+
minHeight: '40',
|
|
315
|
+
paddingInline: '16',
|
|
316
|
+
typography: 'body.b2Strong',
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
export const popup = style({
|
|
320
|
+
backgroundColor: 'background.elevated',
|
|
321
|
+
borderRadius: 'sm',
|
|
322
|
+
boxShadow: 'regular',
|
|
323
|
+
padding: '6px !custom',
|
|
324
|
+
})
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**Don't:** Show a name that inserts an address.
|
|
329
|
+
|
|
330
|
+
```tsx
|
|
331
|
+
/**
|
|
332
|
+
* Don't example for "Show the Text a Suggestion Inserts" on the Autocomplete page.
|
|
333
|
+
* Don't show a name that inserts an address.
|
|
334
|
+
* @module
|
|
335
|
+
*/
|
|
336
|
+
import { Autocomplete, style } from '@tempoxyz/ds'
|
|
337
|
+
|
|
338
|
+
const recipients = ['0x8f3a…c21d', '0x51b0…9e04']
|
|
339
|
+
|
|
340
|
+
// The popup portals and opens on input, so a static copy shows the picked suggestion.
|
|
341
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
342
|
+
export function Demo() {
|
|
343
|
+
return (
|
|
344
|
+
<div {...styles.column()}>
|
|
345
|
+
<Autocomplete.Root defaultValue="0x8f3a…c21d" items={recipients}>
|
|
346
|
+
<Autocomplete.InputGroup>
|
|
347
|
+
<Autocomplete.Input aria-label="Recipient" />
|
|
348
|
+
</Autocomplete.InputGroup>
|
|
349
|
+
</Autocomplete.Root>
|
|
350
|
+
<div {...styles.popup()}>
|
|
351
|
+
<div {...styles.item()}>Alice</div>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
namespace styles {
|
|
358
|
+
export const column = style({
|
|
359
|
+
display: 'flex',
|
|
360
|
+
flexDirection: 'column',
|
|
361
|
+
gap: '8',
|
|
362
|
+
maxWidth: '16rem !custom',
|
|
363
|
+
width: '100% !custom',
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
export const item = style({
|
|
367
|
+
alignItems: 'center',
|
|
368
|
+
display: 'flex',
|
|
369
|
+
minHeight: '40',
|
|
370
|
+
paddingInline: '16',
|
|
371
|
+
typography: 'body.b2Strong',
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
export const popup = style({
|
|
375
|
+
backgroundColor: 'background.elevated',
|
|
376
|
+
borderRadius: 'sm',
|
|
377
|
+
boxShadow: 'regular',
|
|
378
|
+
padding: '6px !custom',
|
|
379
|
+
})
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Keep Autocomplete.Empty Mounted
|
|
384
|
+
|
|
385
|
+
`Autocomplete.Empty` shows its children only when nothing matches, and announces them politely. It requires `items` on `Autocomplete.Root`.
|
|
386
|
+
|
|
387
|
+
**Do:** Keep it mounted, and say that people can continue.
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
/**
|
|
391
|
+
* Do example for "Keep Autocomplete.Empty Mounted" on the Autocomplete page.
|
|
392
|
+
* Keep it mounted, and say that people can continue.
|
|
393
|
+
* @module
|
|
394
|
+
*/
|
|
395
|
+
import { Autocomplete, style } from '@tempoxyz/ds'
|
|
396
|
+
|
|
397
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
398
|
+
|
|
399
|
+
// The popup portals and opens on input, so a static copy shows it open.
|
|
400
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
401
|
+
export function Demo() {
|
|
402
|
+
return (
|
|
403
|
+
<div {...styles.column()}>
|
|
404
|
+
<Autocomplete.Root defaultValue="0x8f3a…c21d" items={recipients}>
|
|
405
|
+
<Autocomplete.InputGroup>
|
|
406
|
+
<Autocomplete.Input aria-label="Recipient" />
|
|
407
|
+
</Autocomplete.InputGroup>
|
|
408
|
+
</Autocomplete.Root>
|
|
409
|
+
<div {...styles.popup()}>
|
|
410
|
+
<div {...styles.empty()}>No saved recipients. You can still send to this address.</div>
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
namespace styles {
|
|
417
|
+
export const column = style({
|
|
418
|
+
display: 'flex',
|
|
419
|
+
flexDirection: 'column',
|
|
420
|
+
gap: '8',
|
|
421
|
+
maxWidth: '16rem !custom',
|
|
422
|
+
width: '100% !custom',
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
export const empty = style({
|
|
426
|
+
color: 'content.secondary',
|
|
427
|
+
paddingBlock: '12',
|
|
428
|
+
paddingInline: '16',
|
|
429
|
+
typography: 'body.b2',
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
export const popup = style({
|
|
433
|
+
backgroundColor: 'background.elevated',
|
|
434
|
+
borderRadius: 'sm',
|
|
435
|
+
boxShadow: 'regular',
|
|
436
|
+
padding: '6px !custom',
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Don't:** Hide it. Hiding it stops the announcement.
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
/**
|
|
445
|
+
* Don't example for "Keep Autocomplete.Empty Mounted" on the Autocomplete page.
|
|
446
|
+
* Don't hide it. Hiding it stops the announcement.
|
|
447
|
+
* @module
|
|
448
|
+
*/
|
|
449
|
+
import { Autocomplete, style } from '@tempoxyz/ds'
|
|
450
|
+
|
|
451
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
452
|
+
|
|
453
|
+
// The popup portals and opens on input, so a static copy shows it open.
|
|
454
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
455
|
+
export function Demo() {
|
|
456
|
+
return (
|
|
457
|
+
<div {...styles.column()}>
|
|
458
|
+
<Autocomplete.Root defaultValue="0x8f3a…c21d" items={recipients}>
|
|
459
|
+
<Autocomplete.InputGroup>
|
|
460
|
+
<Autocomplete.Input aria-label="Recipient" />
|
|
461
|
+
</Autocomplete.InputGroup>
|
|
462
|
+
</Autocomplete.Root>
|
|
463
|
+
<div {...styles.popup()} />
|
|
464
|
+
</div>
|
|
465
|
+
)
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
namespace styles {
|
|
469
|
+
export const column = style({
|
|
470
|
+
display: 'flex',
|
|
471
|
+
flexDirection: 'column',
|
|
472
|
+
gap: '8',
|
|
473
|
+
maxWidth: '16rem !custom',
|
|
474
|
+
width: '100% !custom',
|
|
475
|
+
})
|
|
476
|
+
|
|
477
|
+
export const popup = style({
|
|
478
|
+
backgroundColor: 'background.elevated',
|
|
479
|
+
borderRadius: 'sm',
|
|
480
|
+
boxShadow: 'regular',
|
|
481
|
+
padding: '6px !custom',
|
|
482
|
+
})
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### Add Clear for Long Values
|
|
487
|
+
|
|
488
|
+
`Autocomplete.Clear` mounts only while there is text.
|
|
489
|
+
|
|
490
|
+
**Do:** Add `Autocomplete.Clear` to fields with long values, such as addresses.
|
|
491
|
+
|
|
492
|
+
```tsx
|
|
493
|
+
/**
|
|
494
|
+
* Do example for "Add Clear for Long Values" on the Autocomplete page.
|
|
495
|
+
* Add `Autocomplete.Clear` to fields with long values, such as addresses.
|
|
496
|
+
* @module
|
|
497
|
+
*/
|
|
498
|
+
import { Autocomplete, Field, style } from '@tempoxyz/ds'
|
|
499
|
+
|
|
500
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
501
|
+
|
|
502
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
503
|
+
export function Demo() {
|
|
504
|
+
return (
|
|
505
|
+
<Field.Root {...styles.field()}>
|
|
506
|
+
<Field.Label>Recipient</Field.Label>
|
|
507
|
+
<Autocomplete.Root
|
|
508
|
+
defaultValue="0x8f3a2b7c9d1e4f60a5b3c2d1e0f9a8b7c6d5c21d"
|
|
509
|
+
items={recipients}
|
|
510
|
+
>
|
|
511
|
+
<Autocomplete.InputGroup>
|
|
512
|
+
<Autocomplete.Input placeholder="Name or 0x address" />
|
|
513
|
+
<Autocomplete.Clear />
|
|
514
|
+
</Autocomplete.InputGroup>
|
|
515
|
+
</Autocomplete.Root>
|
|
516
|
+
</Field.Root>
|
|
517
|
+
)
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
namespace styles {
|
|
521
|
+
export const field = style({ maxWidth: '16rem !custom', width: '100% !custom' })
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
**Don't:** Make people delete a long address one character at a time.
|
|
526
|
+
|
|
527
|
+
```tsx
|
|
528
|
+
/**
|
|
529
|
+
* Don't example for "Add Clear for Long Values" on the Autocomplete page.
|
|
530
|
+
* Don't make people delete a long address one character at a time.
|
|
531
|
+
* @module
|
|
532
|
+
*/
|
|
533
|
+
import { Autocomplete, Field, style } from '@tempoxyz/ds'
|
|
534
|
+
|
|
535
|
+
const recipients = ['alice.tempo', 'payroll.tempo']
|
|
536
|
+
|
|
537
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
538
|
+
export function Demo() {
|
|
539
|
+
return (
|
|
540
|
+
<Field.Root {...styles.field()}>
|
|
541
|
+
<Field.Label>Recipient</Field.Label>
|
|
542
|
+
<Autocomplete.Root
|
|
543
|
+
defaultValue="0x8f3a2b7c9d1e4f60a5b3c2d1e0f9a8b7c6d5c21d"
|
|
544
|
+
items={recipients}
|
|
545
|
+
>
|
|
546
|
+
<Autocomplete.InputGroup>
|
|
547
|
+
<Autocomplete.Input placeholder="Name or 0x address" />
|
|
548
|
+
</Autocomplete.InputGroup>
|
|
549
|
+
</Autocomplete.Root>
|
|
550
|
+
</Field.Root>
|
|
551
|
+
)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
namespace styles {
|
|
555
|
+
export const field = style({ maxWidth: '16rem !custom', width: '100% !custom' })
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
## Content
|
|
560
|
+
|
|
561
|
+
* **Label:** Use a noun, such as Recipient, or Search for a search field.
|
|
562
|
+
* **Placeholder:** Name what people can enter, such as Search actions.
|
|
563
|
+
* **Suggestions:** Use the typed format, so a pasted value and a picked one look alike.
|
|
564
|
+
|
|
565
|
+
## Accessibility
|
|
566
|
+
|
|
567
|
+
Follows the [WAI-ARIA combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) with list autocomplete.
|
|
568
|
+
|
|
569
|
+
### Semantics
|
|
570
|
+
|
|
571
|
+
* **Autocomplete.Input (combobox):** A text input that announces a suggestion list and whether it is open.
|
|
572
|
+
* **Highlighted Suggestion (aria-activedescendant):** Points to the highlighted suggestion while focus stays in the input.
|
|
573
|
+
* **Autocomplete.List and Autocomplete.Item (listbox and option):** Each suggestion is announced as an option inside a listbox.
|
|
574
|
+
* **Autocomplete.Group (group):** Named by the `Autocomplete.GroupLabel` inside it, and announced as a group.
|
|
575
|
+
* **Autocomplete.Clear (button):** Named "Clear" by default. Renders only while the input has text.
|
|
576
|
+
|
|
577
|
+
### Keyboard
|
|
578
|
+
|
|
579
|
+
* **Move to the TextInput (Tab):** Moves focus to the input.
|
|
580
|
+
* **Filter the Suggestions (Typing):** Filters the suggestions and opens the list.
|
|
581
|
+
* **Highlight the Next Suggestion (Down Arrow):** Opens the list, then highlights the next suggestion.
|
|
582
|
+
* **Highlight the Previous Suggestion (Up Arrow):** Highlights the previous one, then the typed text.
|
|
583
|
+
* **Choose the Suggestion (Enter):** Enters the highlighted suggestion and closes the list.
|
|
584
|
+
* **Close or Clear (Escape):** Closes the list. A second press clears the input.
|
|
585
|
+
|
|
586
|
+
### Focus
|
|
587
|
+
|
|
588
|
+
DOM focus stays on the input while the arrow keys highlight suggestions, so typing continues at any point.
|
|
589
|
+
|
|
590
|
+
### Announcements
|
|
591
|
+
|
|
592
|
+
* **Highlighted Suggestion (aria-activedescendant):** Each suggestion is announced on highlight.
|
|
593
|
+
* **No Matches (Autocomplete.Empty):** Announces "No matches" politely.
|
|
594
|
+
|
|
595
|
+
### Your Responsibilities
|
|
596
|
+
|
|
597
|
+
* **Label the TextInput (aria-label):** Name the input with `Field.Label`, or `aria-label` if no label fits. The placeholder disappears.
|
|
598
|
+
* **Set aria-invalid on the TextInput (aria-invalid):** The group's `invalid` prop only fills it red. Set the attribute on the input, and explain the error.
|
|
599
|
+
|
|
600
|
+
## Related
|
|
601
|
+
|
|
602
|
+
[Combobox](combobox.md)
|
|
603
|
+
|
|
604
|
+
Use for choosing from fixed options.
|
|
605
|
+
|
|
606
|
+
[TextInput](text-input.md)
|
|
607
|
+
|
|
608
|
+
Use for text without suggestions.
|
|
609
|
+
|
|
610
|
+
[Field](field.md)
|
|
611
|
+
|
|
612
|
+
Use for the label and error.
|
|
613
|
+
|
|
614
|
+
[Select](select.md)
|
|
615
|
+
|
|
616
|
+
Use for short lists.
|
|
617
|
+
|
|
618
|
+
[Blockchain Values](../patterns/blockchain-values.md)
|
|
619
|
+
|
|
620
|
+
Covers entering and showing addresses.
|