@tempoxyz/ds 0.3.10 → 0.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/README.md +7 -6
  2. package/dist/docs/AGENTS.md +12 -0
  3. package/dist/docs/index.md +145 -0
  4. package/dist/docs/marketing/introduction/getting-started.md +241 -0
  5. package/dist/docs/product/components/accordion.md +489 -0
  6. package/dist/docs/product/components/address-card.md +147 -0
  7. package/dist/docs/product/components/agent-logo.md +194 -0
  8. package/dist/docs/product/components/alert-dialog.md +631 -0
  9. package/dist/docs/product/components/alert.md +448 -0
  10. package/dist/docs/product/components/amount-input.md +305 -0
  11. package/dist/docs/product/components/amount.md +794 -0
  12. package/dist/docs/product/components/app-shell.md +559 -0
  13. package/dist/docs/product/components/asset-chip.md +294 -0
  14. package/dist/docs/product/components/autocomplete.md +620 -0
  15. package/dist/docs/product/components/avatar.md +321 -0
  16. package/dist/docs/product/components/badge.md +339 -0
  17. package/dist/docs/product/components/badged-logo.md +116 -0
  18. package/dist/docs/product/components/banner.md +379 -0
  19. package/dist/docs/product/components/bar-chart.md +208 -0
  20. package/dist/docs/product/components/breadcrumbs.md +380 -0
  21. package/dist/docs/product/components/button-group.md +286 -0
  22. package/dist/docs/product/components/button.md +650 -0
  23. package/dist/docs/product/components/calendar.md +375 -0
  24. package/dist/docs/product/components/callout.md +96 -0
  25. package/dist/docs/product/components/checkbox-group.md +521 -0
  26. package/dist/docs/product/components/checkbox.md +467 -0
  27. package/dist/docs/product/components/choice-group.md +516 -0
  28. package/dist/docs/product/components/choicebox.md +641 -0
  29. package/dist/docs/product/components/code.md +100 -0
  30. package/dist/docs/product/components/combobox.md +939 -0
  31. package/dist/docs/product/components/container.md +257 -0
  32. package/dist/docs/product/components/copy-button.md +642 -0
  33. package/dist/docs/product/components/date-picker.md +514 -0
  34. package/dist/docs/product/components/dialog.md +1332 -0
  35. package/dist/docs/product/components/drawer.md +966 -0
  36. package/dist/docs/product/components/empty.md +340 -0
  37. package/dist/docs/product/components/field.md +570 -0
  38. package/dist/docs/product/components/fieldset.md +398 -0
  39. package/dist/docs/product/components/frame.md +434 -0
  40. package/dist/docs/product/components/gauge.md +299 -0
  41. package/dist/docs/product/components/get-started-visual.md +117 -0
  42. package/dist/docs/product/components/grid.md +288 -0
  43. package/dist/docs/product/components/hero-visual.md +155 -0
  44. package/dist/docs/product/components/hex.md +487 -0
  45. package/dist/docs/product/components/icon-tile.md +292 -0
  46. package/dist/docs/product/components/identicon.md +371 -0
  47. package/dist/docs/product/components/inline.md +233 -0
  48. package/dist/docs/product/components/inset.md +225 -0
  49. package/dist/docs/product/components/kbd.md +423 -0
  50. package/dist/docs/product/components/list-group.md +981 -0
  51. package/dist/docs/product/components/loading-dots.md +237 -0
  52. package/dist/docs/product/components/menu.md +934 -0
  53. package/dist/docs/product/components/native-select.md +204 -0
  54. package/dist/docs/product/components/network-logo.md +248 -0
  55. package/dist/docs/product/components/number-field.md +543 -0
  56. package/dist/docs/product/components/otp-field.md +616 -0
  57. package/dist/docs/product/components/pagination.md +516 -0
  58. package/dist/docs/product/components/popover.md +544 -0
  59. package/dist/docs/product/components/progress.md +388 -0
  60. package/dist/docs/product/components/qr.md +314 -0
  61. package/dist/docs/product/components/radio-group.md +528 -0
  62. package/dist/docs/product/components/secret-value.md +406 -0
  63. package/dist/docs/product/components/select.md +751 -0
  64. package/dist/docs/product/components/separator.md +379 -0
  65. package/dist/docs/product/components/sidebar-menu.md +922 -0
  66. package/dist/docs/product/components/skeleton.md +517 -0
  67. package/dist/docs/product/components/slider.md +539 -0
  68. package/dist/docs/product/components/snippet.md +424 -0
  69. package/dist/docs/product/components/spinner.md +216 -0
  70. package/dist/docs/product/components/split-bar.md +139 -0
  71. package/dist/docs/product/components/split-button.md +464 -0
  72. package/dist/docs/product/components/stack.md +299 -0
  73. package/dist/docs/product/components/status-chip.md +226 -0
  74. package/dist/docs/product/components/status-indicator.md +119 -0
  75. package/dist/docs/product/components/status-row.md +174 -0
  76. package/dist/docs/product/components/stepper.md +451 -0
  77. package/dist/docs/product/components/success-hero.md +157 -0
  78. package/dist/docs/product/components/surface.md +639 -0
  79. package/dist/docs/product/components/switch.md +472 -0
  80. package/dist/docs/product/components/table.md +967 -0
  81. package/dist/docs/product/components/tabs.md +627 -0
  82. package/dist/docs/product/components/tempo-logo.md +185 -0
  83. package/dist/docs/product/components/text-input.md +624 -0
  84. package/dist/docs/product/components/textarea.md +352 -0
  85. package/dist/docs/product/components/toast.md +535 -0
  86. package/dist/docs/product/components/token-logo.md +371 -0
  87. package/dist/docs/product/components/token.md +247 -0
  88. package/dist/docs/product/components/tooltip.md +490 -0
  89. package/dist/docs/product/components/verification-code.md +116 -0
  90. package/dist/docs/product/components/visual.md +249 -0
  91. package/dist/docs/product/components.md +203 -0
  92. package/dist/docs/product/foundations/accessibility.md +377 -0
  93. package/dist/docs/product/foundations/agents.md +150 -0
  94. package/dist/docs/product/foundations/color.md +522 -0
  95. package/dist/docs/product/foundations/content/tone.md +194 -0
  96. package/dist/docs/product/foundations/content/voice.md +194 -0
  97. package/dist/docs/product/foundations/content/writing-style.md +406 -0
  98. package/dist/docs/product/foundations/iconography.md +282 -0
  99. package/dist/docs/product/foundations/intent.md +360 -0
  100. package/dist/docs/product/foundations/layout.md +508 -0
  101. package/dist/docs/product/foundations/linter.md +496 -0
  102. package/dist/docs/product/foundations/motion.md +151 -0
  103. package/dist/docs/product/foundations/radius-and-padding.md +86 -0
  104. package/dist/docs/product/foundations/typography.md +266 -0
  105. package/dist/docs/product/introduction/faq.md +133 -0
  106. package/dist/docs/product/introduction/getting-started.md +377 -0
  107. package/dist/docs/product/patterns/blockchain-values.md +709 -0
  108. package/dist/docs/product/patterns/dashboards.md +638 -0
  109. package/dist/docs/product/patterns/destructive-actions.md +626 -0
  110. package/dist/docs/product/patterns/empty-states.md +612 -0
  111. package/dist/docs/product/patterns/errors-and-validation.md +808 -0
  112. package/dist/docs/product/patterns/feedback-and-status.md +518 -0
  113. package/dist/docs/product/patterns/forms.md +679 -0
  114. package/dist/docs/product/patterns/loading.md +630 -0
  115. package/dist/docs/product/patterns/navigation.md +397 -0
  116. package/dist/docs/product/patterns/payments.md +765 -0
  117. package/dist/docs/product/patterns/responsive-layout.md +997 -0
  118. package/dist/docs/product/patterns/tables-and-lists.md +964 -0
  119. package/dist/docs/product/products/tempo-console.md +671 -0
  120. package/dist/docs/product/products/tempo-performance.md +437 -0
  121. package/dist/docs/product/products/tempo-wallet.md +438 -0
  122. package/dist/marketing/index.d.ts +4 -0
  123. package/dist/marketing/index.d.ts.map +1 -0
  124. package/dist/marketing/index.js +4 -0
  125. package/dist/marketing/index.js.map +1 -0
  126. package/dist/marketing/index.js.zyzz.json +1 -0
  127. package/dist/marketing/vars.d.ts +907 -0
  128. package/dist/marketing/vars.d.ts.map +1 -0
  129. package/dist/marketing/vars.js +15 -0
  130. package/dist/marketing/vars.js.map +1 -0
  131. package/dist/marketing/vars.js.zyzz.json +1 -0
  132. package/dist/marketing/zyzz.config.d.ts +4512 -0
  133. package/dist/marketing/zyzz.config.d.ts.map +1 -0
  134. package/dist/marketing/zyzz.config.js +63 -0
  135. package/dist/marketing/zyzz.config.js.map +1 -0
  136. package/dist/marketing/zyzz.config.js.zyzz.json +1 -0
  137. package/dist/oxlint/index.d.ts +12 -1
  138. package/dist/oxlint/index.d.ts.map +1 -1
  139. package/dist/oxlint/index.js +39 -1
  140. package/dist/oxlint/index.js.map +1 -1
  141. package/dist/oxlint/internal/Docs.d.ts +9 -0
  142. package/dist/oxlint/internal/Docs.d.ts.map +1 -0
  143. package/dist/oxlint/internal/Docs.js +15 -0
  144. package/dist/oxlint/internal/Docs.js.map +1 -0
  145. package/dist/oxlint/internal/Imports.d.ts +1 -1
  146. package/dist/oxlint/internal/Imports.d.ts.map +1 -1
  147. package/dist/oxlint/internal/Imports.js +2 -0
  148. package/dist/oxlint/internal/Imports.js.map +1 -1
  149. package/dist/oxlint/internal/Styles.d.ts +40 -0
  150. package/dist/oxlint/internal/Styles.d.ts.map +1 -0
  151. package/dist/oxlint/internal/Styles.js +194 -0
  152. package/dist/oxlint/internal/Styles.js.map +1 -0
  153. package/dist/oxlint/internal/Tokens.d.ts +16 -0
  154. package/dist/oxlint/internal/Tokens.d.ts.map +1 -0
  155. package/dist/oxlint/internal/Tokens.js +39 -0
  156. package/dist/oxlint/internal/Tokens.js.map +1 -0
  157. package/dist/oxlint/rules/NoCrossSurface.d.ts +2 -2
  158. package/dist/oxlint/rules/NoCrossSurface.js +3 -3
  159. package/dist/oxlint/rules/NoCrossSurface.js.map +1 -1
  160. package/dist/oxlint/rules/NoCustomValues.d.ts +11 -0
  161. package/dist/oxlint/rules/NoCustomValues.d.ts.map +1 -0
  162. package/dist/oxlint/rules/NoCustomValues.js +150 -0
  163. package/dist/oxlint/rules/NoCustomValues.js.map +1 -0
  164. package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts +11 -0
  165. package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts.map +1 -0
  166. package/dist/oxlint/rules/NoSingleKeyShortcuts.js +158 -0
  167. package/dist/oxlint/rules/NoSingleKeyShortcuts.js.map +1 -0
  168. package/dist/oxlint/rules/PreferComponent.d.ts +3 -2
  169. package/dist/oxlint/rules/PreferComponent.d.ts.map +1 -1
  170. package/dist/oxlint/rules/PreferComponent.js +11 -4
  171. package/dist/oxlint/rules/PreferComponent.js.map +1 -1
  172. package/dist/oxlint/rules/PreferLayout.d.ts +9 -0
  173. package/dist/oxlint/rules/PreferLayout.d.ts.map +1 -0
  174. package/dist/oxlint/rules/PreferLayout.js +90 -0
  175. package/dist/oxlint/rules/PreferLayout.js.map +1 -0
  176. package/dist/oxlint/rules/PreferProgress.d.ts +9 -0
  177. package/dist/oxlint/rules/PreferProgress.d.ts.map +1 -0
  178. package/dist/oxlint/rules/PreferProgress.js +43 -0
  179. package/dist/oxlint/rules/PreferProgress.js.map +1 -0
  180. package/dist/oxlint/rules/PreferSurface.d.ts +9 -0
  181. package/dist/oxlint/rules/PreferSurface.d.ts.map +1 -0
  182. package/dist/oxlint/rules/PreferSurface.js +55 -0
  183. package/dist/oxlint/rules/PreferSurface.js.map +1 -0
  184. package/dist/oxlint/rules/RequireAccessibleName.d.ts.map +1 -1
  185. package/dist/oxlint/rules/RequireAccessibleName.js +3 -1
  186. package/dist/oxlint/rules/RequireAccessibleName.js.map +1 -1
  187. package/dist/oxlint/rules/RequireScrollRegion.d.ts +11 -0
  188. package/dist/oxlint/rules/RequireScrollRegion.d.ts.map +1 -0
  189. package/dist/oxlint/rules/RequireScrollRegion.js +71 -0
  190. package/dist/oxlint/rules/RequireScrollRegion.js.map +1 -0
  191. package/dist/web/icons/index.js.zyzz.json +1 -0
  192. package/package.json +6 -1
  193. package/src/marketing/README.md +21 -0
  194. package/src/marketing/index.ts +3 -0
  195. package/src/marketing/vars.ts +751 -0
  196. package/src/marketing/zyzz.config.ts +376 -0
  197. package/src/oxlint/index.ts +40 -1
  198. package/src/oxlint/internal/Docs.ts +18 -0
  199. package/src/oxlint/internal/Imports.ts +2 -1
  200. package/src/oxlint/internal/Styles.ts +240 -0
  201. package/src/oxlint/internal/Tokens.ts +43 -0
  202. package/src/oxlint/rules/NoCrossSurface.ts +3 -3
  203. package/src/oxlint/rules/NoCustomValues.ts +170 -0
  204. package/src/oxlint/rules/NoSingleKeyShortcuts.ts +190 -0
  205. package/src/oxlint/rules/PreferComponent.ts +11 -4
  206. package/src/oxlint/rules/PreferLayout.ts +96 -0
  207. package/src/oxlint/rules/PreferProgress.ts +49 -0
  208. package/src/oxlint/rules/PreferSurface.ts +70 -0
  209. package/src/oxlint/rules/RequireAccessibleName.ts +3 -1
  210. package/src/oxlint/rules/RequireScrollRegion.ts +92 -0
@@ -0,0 +1,570 @@
1
+ # Field
2
+
3
+ Links a label, description, and error message to a control.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Field.tsx)
6
+
7
+ ## Overview
8
+
9
+ A field links a label, description, and error message to the control inside it.
10
+
11
+ ## Examples
12
+
13
+ ### Basic
14
+
15
+ ```tsx
16
+ import { Field, TextInput } from '@tempoxyz/ds'
17
+
18
+ export function Demo() {
19
+ return (
20
+ <Field.Root>
21
+ <Field.Label>Email</Field.Label>
22
+ <TextInput.Group>
23
+ <TextInput.Control placeholder="alice@example.com" type="email" />
24
+ </TextInput.Group>
25
+ <Field.Description>Used for receipts.</Field.Description>
26
+ </Field.Root>
27
+ )
28
+ }
29
+ ```
30
+
31
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/Basic.tsx)
32
+
33
+ ### Invalid
34
+
35
+ Set `invalid` to fill the control red and show a matching `Field.Error` in place of the description.
36
+
37
+ ```tsx
38
+ import { Field, TextInput } from '@tempoxyz/ds'
39
+
40
+ export function Demo() {
41
+ return (
42
+ <Field.Root invalid>
43
+ <Field.Label>Invalid</Field.Label>
44
+ <TextInput.Group>
45
+ <TextInput.Control defaultValue="alice" type="email" />
46
+ </TextInput.Group>
47
+ <Field.Description>Used for receipts.</Field.Description>
48
+ <Field.Error match>Enter a valid email.</Field.Error>
49
+ </Field.Root>
50
+ )
51
+ }
52
+ ```
53
+
54
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/Invalid.tsx)
55
+
56
+ ### Success
57
+
58
+ Set `success` to end a text field with a check, and to set the description in the positive color.
59
+
60
+ ```tsx
61
+ import { Field, TextInput } from '@tempoxyz/ds'
62
+
63
+ export function Demo() {
64
+ return (
65
+ <Field.Root success>
66
+ <Field.Label>Success</Field.Label>
67
+ <TextInput.Group>
68
+ <TextInput.Control defaultValue="alice@example.com" type="email" />
69
+ </TextInput.Group>
70
+ </Field.Root>
71
+ )
72
+ }
73
+ ```
74
+
75
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/Success.tsx)
76
+
77
+ ### Secondary Label
78
+
79
+ Put a `Field.SecondaryLabel` inside `Field.Label` for a qualifier at the end of the label row, such as Optional. It joins the control's accessible name.
80
+
81
+ ```tsx
82
+ import { Field, style, TextInput } from '@tempoxyz/ds'
83
+
84
+ export const fill = true
85
+ export function Demo() {
86
+ return (
87
+ <Field.Root {...styles.field()}>
88
+ <Field.Label>
89
+ Memo <Field.SecondaryLabel>Optional</Field.SecondaryLabel>
90
+ </Field.Label>
91
+ <TextInput.Group>
92
+ <TextInput.Control placeholder="What is it for?" />
93
+ </TextInput.Group>
94
+ <Field.Description>Only you and Maya can see this</Field.Description>
95
+ </Field.Root>
96
+ )
97
+ }
98
+
99
+ namespace styles {
100
+ export const field = style({ maxWidth: '24rem !custom' })
101
+ }
102
+ ```
103
+
104
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/SecondaryLabel.tsx)
105
+
106
+ ### Size
107
+
108
+ Set `size` to `medium` (default) or `large`. A large field sets the label in the regular weight with its secondary label beside it, sets the description at 14px, and insets a text field or textarea 20px.
109
+
110
+ ```tsx
111
+ import { Field, style, Textarea, TextInput } from '@tempoxyz/ds'
112
+
113
+ export function Demo() {
114
+ return (
115
+ <div {...styles.grid()}>
116
+ <Field.Root size="large">
117
+ <Field.Label>
118
+ Display name<Field.SecondaryLabel>Optional</Field.SecondaryLabel>
119
+ </Field.Label>
120
+ <TextInput.Group>
121
+ <TextInput.Control placeholder="Maya Chen" />
122
+ </TextInput.Group>
123
+ <Field.Description>Shown to people you pay</Field.Description>
124
+ </Field.Root>
125
+ <Field.Root size="large">
126
+ <Field.Label>
127
+ Bio<Field.SecondaryLabel>Optional</Field.SecondaryLabel>
128
+ </Field.Label>
129
+ <Textarea placeholder="A few words about you" rows={2} />
130
+ <Field.Description>Up to 160 characters</Field.Description>
131
+ </Field.Root>
132
+ </div>
133
+ )
134
+ }
135
+
136
+ namespace styles {
137
+ export const grid = style({
138
+ alignItems: 'start',
139
+ display: 'grid',
140
+ gap: '24',
141
+ gridTemplateColumns: 'repeat(auto-fill, minmax(min(280px, 100%), 1fr)) !custom',
142
+ })
143
+ }
144
+ ```
145
+
146
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/Size.tsx)
147
+
148
+ ### Disabled
149
+
150
+ ```tsx
151
+ import { Field, TextInput } from '@tempoxyz/ds'
152
+
153
+ export function Demo() {
154
+ return (
155
+ <Field.Root disabled>
156
+ <Field.Label>Disabled</Field.Label>
157
+ <TextInput.Group>
158
+ <TextInput.Control defaultValue="Locked" />
159
+ </TextInput.Group>
160
+ </Field.Root>
161
+ )
162
+ }
163
+ ```
164
+
165
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/Disabled.tsx)
166
+
167
+ ### Item
168
+
169
+ Wrap a checkbox or radio and its `Field.Label` in `Field.Item` to put them on one row.
170
+
171
+ ```tsx
172
+ import { Checkbox, Field } from '@tempoxyz/ds'
173
+
174
+ export function Demo() {
175
+ return (
176
+ <Field.Root>
177
+ <Field.Item>
178
+ <Checkbox defaultChecked />
179
+ <Field.Label>Item with a checkbox</Field.Label>
180
+ </Field.Item>
181
+ </Field.Root>
182
+ )
183
+ }
184
+ ```
185
+
186
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Field/Item.tsx)
187
+
188
+ ## Anatomy
189
+
190
+ Import the component and assemble its parts.
191
+
192
+ ```tsx
193
+ import { Field } from '@tempoxyz/ds'
194
+
195
+ <Field.Root>
196
+ <Field.Label>
197
+ <Field.SecondaryLabel />
198
+ </Field.Label>
199
+ <Field.Item />
200
+ <Field.Description />
201
+ <Field.Error />
202
+ </Field.Root>
203
+ ```
204
+
205
+ ## Guidelines
206
+
207
+ ### When to Use
208
+
209
+ * Label an input control, such as [TextInput](text-input.md), [AmountInput](amount-input.md), [Textarea](textarea.md), [Select](select.md), or [Combobox](combobox.md).
210
+ * Attach a hint or an error to that control.
211
+ * Put a [Checkbox](checkbox.md) or radio on one row with its label through `Field.Item`.
212
+ * Label a [Switch](switch.md) above it, with its description below.
213
+
214
+ ### When Not to Use
215
+
216
+ * Use [Fieldset](fieldset.md) to name a group of related fields, such as a billing address.
217
+ * Use [ListGroup](list-group.md) for read-only details.
218
+ * Use an [Alert](alert.md) above the form to summarize a failed submission.
219
+
220
+ ### Give Every Control a Visible Label
221
+
222
+ **Do:** Name the control with a `Field.Label` and put the format in the description.
223
+
224
+ ```tsx
225
+ /**
226
+ * Do example for "Give Every Control a Visible Label" on the Field page.
227
+ * Name the control with a `Field.Label` and put the format in the description.
228
+ * @module
229
+ */
230
+ import { Field, style, TextInput } from '@tempoxyz/ds'
231
+
232
+ /** Renders the static preview, which the guideline card shows inert. */
233
+ export function Demo() {
234
+ return (
235
+ <Field.Root {...styles.field()}>
236
+ <Field.Label>Recipient</Field.Label>
237
+ <TextInput.Group>
238
+ <TextInput.Control placeholder="0x…" />
239
+ </TextInput.Group>
240
+ <Field.Description>A Tempo address that starts with 0x.</Field.Description>
241
+ </Field.Root>
242
+ )
243
+ }
244
+
245
+ namespace styles {
246
+ export const field = style({ width: '100% !custom' })
247
+ }
248
+ ```
249
+
250
+ **Don't:** Use the placeholder as the only label.
251
+
252
+ ```tsx
253
+ /**
254
+ * Don't example for "Give Every Control a Visible Label" on the Field page.
255
+ * Don't use the placeholder as the only label.
256
+ * @module
257
+ */
258
+ import { style, TextInput } from '@tempoxyz/ds'
259
+
260
+ /** Renders the static preview, which the guideline card shows inert. */
261
+ export function Demo() {
262
+ return (
263
+ <TextInput.Group {...styles.group()}>
264
+ <TextInput.Control aria-label="Recipient" placeholder="Recipient address" />
265
+ </TextInput.Group>
266
+ )
267
+ }
268
+
269
+ namespace styles {
270
+ export const group = style({ width: '100% !custom' })
271
+ }
272
+ ```
273
+
274
+ ### Keep Hints in the Description
275
+
276
+ Use `Field.Description` for one fact about the value, such as a format or a limit. Keep the label to the name of the value.
277
+
278
+ **Do:** Put the limit in `Field.Description` below the control.
279
+
280
+ ```tsx
281
+ /**
282
+ * Do example for "Keep Hints in the Description" on the Field page.
283
+ * Put the limit in `Field.Description` below the control.
284
+ * @module
285
+ */
286
+ import { Field, style, TextInput } from '@tempoxyz/ds'
287
+
288
+ /** Renders the static preview, which the guideline card shows inert. */
289
+ export function Demo() {
290
+ return (
291
+ <Field.Root {...styles.field()}>
292
+ <Field.Label>Key name</Field.Label>
293
+ <TextInput.Group>
294
+ <TextInput.Control defaultValue="Payroll server" />
295
+ </TextInput.Group>
296
+ <Field.Description>Up to 32 letters, numbers, or spaces.</Field.Description>
297
+ </Field.Root>
298
+ )
299
+ }
300
+
301
+ namespace styles {
302
+ export const field = style({ width: '100% !custom' })
303
+ }
304
+ ```
305
+
306
+ **Don't:** Pack formats and limits into the label.
307
+
308
+ ```tsx
309
+ /**
310
+ * Don't example for "Keep Hints in the Description" on the Field page.
311
+ * Don't pack formats and limits into the label.
312
+ * @module
313
+ */
314
+ import { Field, style, TextInput } from '@tempoxyz/ds'
315
+
316
+ /** Renders the static preview, which the guideline card shows inert. */
317
+ export function Demo() {
318
+ return (
319
+ <Field.Root {...styles.field()}>
320
+ <Field.Label>Key name (up to 32 letters, numbers, or spaces)</Field.Label>
321
+ <TextInput.Group>
322
+ <TextInput.Control defaultValue="Payroll server" />
323
+ </TextInput.Group>
324
+ </Field.Root>
325
+ )
326
+ }
327
+
328
+ namespace styles {
329
+ export const field = style({ width: '100% !custom' })
330
+ }
331
+ ```
332
+
333
+ ### Write Errors That Say How to Fix the Value
334
+
335
+ Start the `Field.Error` with a verb, such as Enter or Choose, and include the limit, such as Enter an amount up to 250.00 USDC. A shown error replaces the description, so repeat any limit the error depends on.
336
+
337
+ **Do:** Say what the value needs, such as the https\:// scheme.
338
+
339
+ ```tsx
340
+ /**
341
+ * Do example for "Write Errors That Say How to Fix the Value" on the Field page.
342
+ * Say what the value needs, such as the https:// scheme.
343
+ * @module
344
+ */
345
+ import { Field, style, TextInput } from '@tempoxyz/ds'
346
+
347
+ /** Renders the static preview, which the guideline card shows inert. */
348
+ export function Demo() {
349
+ return (
350
+ <Field.Root invalid {...styles.field()}>
351
+ <Field.Label>Webhook URL</Field.Label>
352
+ <TextInput.Group>
353
+ <TextInput.Control defaultValue="http://api.example.com/hooks" type="url" />
354
+ </TextInput.Group>
355
+ <Field.Error match>Enter a URL that starts with https://.</Field.Error>
356
+ </Field.Root>
357
+ )
358
+ }
359
+
360
+ namespace styles {
361
+ export const field = style({ width: '100% !custom' })
362
+ }
363
+ ```
364
+
365
+ **Don't:** Show a generic message such as Invalid input.
366
+
367
+ ```tsx
368
+ /**
369
+ * Don't example for "Write Errors That Say How to Fix the Value" on the Field page.
370
+ * Don't show a generic message such as Invalid input.
371
+ * @module
372
+ */
373
+ import { Field, style, TextInput } from '@tempoxyz/ds'
374
+
375
+ /** Renders the static preview, which the guideline card shows inert. */
376
+ export function Demo() {
377
+ return (
378
+ <Field.Root invalid {...styles.field()}>
379
+ <Field.Label>Webhook URL</Field.Label>
380
+ <TextInput.Group>
381
+ <TextInput.Control defaultValue="http://api.example.com/hooks" type="url" />
382
+ </TextInput.Group>
383
+ <Field.Error match>Invalid input.</Field.Error>
384
+ </Field.Root>
385
+ )
386
+ }
387
+
388
+ namespace styles {
389
+ export const field = style({ width: '100% !custom' })
390
+ }
391
+ ```
392
+
393
+ ### Validate When the Value Is Complete
394
+
395
+ `Field.Root` validates on submit, then on each change after a failed submit. For format checks, such as a URL, set `validationMode="onBlur"`. Pass `validate` for custom rules. If another library owns validation, set `invalid`. See [Errors and Validation](../patterns/errors-and-validation.md).
396
+
397
+ **Do:** Leave a partial value unmarked until focus leaves the field.
398
+
399
+ ```tsx
400
+ /**
401
+ * Do example for "Validate When the Value Is Complete" on the Field page.
402
+ * Leave a partial value unmarked until focus leaves the field.
403
+ * @module
404
+ */
405
+ import { Field, style, TextInput } from '@tempoxyz/ds'
406
+
407
+ /** Renders the static preview, which the guideline card shows inert. */
408
+ export function Demo() {
409
+ return (
410
+ <Field.Root validationMode="onBlur" {...styles.field()}>
411
+ <Field.Label>Webhook URL</Field.Label>
412
+ <TextInput.Group>
413
+ <TextInput.Control defaultValue="https://api.exa" type="url" />
414
+ </TextInput.Group>
415
+ <Field.Description>Starts with https://.</Field.Description>
416
+ </Field.Root>
417
+ )
418
+ }
419
+
420
+ namespace styles {
421
+ export const field = style({ width: '100% !custom' })
422
+ }
423
+ ```
424
+
425
+ **Don't:** Flag a format error before the value is complete.
426
+
427
+ ```tsx
428
+ /**
429
+ * Don't example for "Validate When the Value Is Complete" on the Field page.
430
+ * Don't flag a format error before the value is complete.
431
+ * @module
432
+ */
433
+ import { Field, style, TextInput } from '@tempoxyz/ds'
434
+
435
+ /** Renders the static preview, which the guideline card shows inert. */
436
+ export function Demo() {
437
+ return (
438
+ <Field.Root invalid {...styles.field()}>
439
+ <Field.Label>Webhook URL</Field.Label>
440
+ <TextInput.Group>
441
+ <TextInput.Control defaultValue="https://api.exa" type="url" />
442
+ </TextInput.Group>
443
+ <Field.Error match>Enter a URL that starts with https://.</Field.Error>
444
+ </Field.Root>
445
+ )
446
+ }
447
+
448
+ namespace styles {
449
+ export const field = style({ width: '100% !custom' })
450
+ }
451
+ ```
452
+
453
+ ### Reserve Success for Verified Values
454
+
455
+ Set `success` only after the app checks the value, such as an address that resolves to a contact. It sets no ARIA state, so state the result in the description too.
456
+
457
+ **Do:** Mark only the checked value, and state the result in the description.
458
+
459
+ ```tsx
460
+ /**
461
+ * Do example for "Reserve Success for Verified Values" on the Field page.
462
+ * Mark only the checked value, and state the result in the description.
463
+ * @module
464
+ */
465
+ import { Field, style, TextInput } from '@tempoxyz/ds'
466
+
467
+ /** Renders the static preview, which the guideline card shows inert. */
468
+ export function Demo() {
469
+ return (
470
+ <div {...styles.form()}>
471
+ <Field.Root success>
472
+ <Field.Label>Recipient address</Field.Label>
473
+ <TextInput.Group>
474
+ <TextInput.Control defaultValue="0x8f3a…12c4" />
475
+ </TextInput.Group>
476
+ <Field.Description>Matches your contact Alice Chen.</Field.Description>
477
+ </Field.Root>
478
+ <Field.Root>
479
+ <Field.Label>Memo</Field.Label>
480
+ <TextInput.Group>
481
+ <TextInput.Control defaultValue="Rent for May" />
482
+ </TextInput.Group>
483
+ </Field.Root>
484
+ </div>
485
+ )
486
+ }
487
+
488
+ namespace styles {
489
+ export const form = style({ display: 'grid', gap: '16', width: '100% !custom' })
490
+ }
491
+ ```
492
+
493
+ **Don't:** Mark every filled field successful.
494
+
495
+ ```tsx
496
+ /**
497
+ * Don't example for "Reserve Success for Verified Values" on the Field page.
498
+ * Don't turn every filled field green.
499
+ * @module
500
+ */
501
+ import { Field, style, TextInput } from '@tempoxyz/ds'
502
+
503
+ /** Renders the static preview, which the guideline card shows inert. */
504
+ export function Demo() {
505
+ return (
506
+ <div {...styles.form()}>
507
+ <Field.Root success>
508
+ <Field.Label>Recipient address</Field.Label>
509
+ <TextInput.Group>
510
+ <TextInput.Control defaultValue="0x8f3a…12c4" />
511
+ </TextInput.Group>
512
+ </Field.Root>
513
+ <Field.Root success>
514
+ <Field.Label>Memo</Field.Label>
515
+ <TextInput.Group>
516
+ <TextInput.Control defaultValue="Rent for May" />
517
+ </TextInput.Group>
518
+ </Field.Root>
519
+ </div>
520
+ )
521
+ }
522
+
523
+ namespace styles {
524
+ export const form = style({ display: 'grid', gap: '16', width: '100% !custom' })
525
+ }
526
+ ```
527
+
528
+ ## Accessibility
529
+
530
+ A field connects a control to its label, description, and error. See [Accessibility](../foundations/accessibility.md) for the baseline.
531
+
532
+ ### Semantics
533
+
534
+ * **Field.Label (label):** Names the control. A click focuses or toggles it.
535
+ * **Field.Description (aria-describedby):** Read after the control's name.
536
+ * **Field.Error (aria-describedby):** Once shown, read after the description.
537
+ * **Invalid State (aria-invalid):** Set on failed validation or `invalid`.
538
+ * **Disabled (disabled):** Disables the control and dims the label and description.
539
+ * **Field.Item:** Labels one checkbox or radio inside a group.
540
+
541
+ ### Your Responsibilities
542
+
543
+ * **Label Every Control (Field.Label):** A placeholder disappears once the reader types, so it can't replace a label.
544
+ * **Explain the Fix:** State the fix in the error, not only the problem, such as "Enter an email address."
545
+ * **Focus the First Error:** The error is not a live region. If a submit fails, focus the first invalid field.
546
+ * **Confirm Success in Text (success):** The `success` check sets no ARIA state and isn't announced. Confirm a verified value in text.
547
+ * **State Requirements:** State requirements and formats in text, such as "(required)" in the label, not only with a symbol.
548
+ * **Label a Date Picker Trigger (aria-labelledby):** `Field.Label` doesn't name a [DatePicker](date-picker.md) trigger. Point `aria-labelledby` at a visible label.
549
+
550
+ ## Related
551
+
552
+ [TextInput](text-input.md)
553
+
554
+ Use for single-line text.
555
+
556
+ [Fieldset](fieldset.md)
557
+
558
+ Use for grouping fields under a legend.
559
+
560
+ [Textarea](textarea.md)
561
+
562
+ Use for multi-line text.
563
+
564
+ [Forms](../patterns/forms.md)
565
+
566
+ Covers laying out and submitting forms.
567
+
568
+ [Errors and Validation](../patterns/errors-and-validation.md)
569
+
570
+ Covers when and how to show errors.