@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.
Files changed (128) hide show
  1. package/dist/docs/AGENTS.md +9 -0
  2. package/dist/docs/components/accordion.md +489 -0
  3. package/dist/docs/components/address-card.md +147 -0
  4. package/dist/docs/components/agent-logo.md +194 -0
  5. package/dist/docs/components/alert-dialog.md +631 -0
  6. package/dist/docs/components/alert.md +448 -0
  7. package/dist/docs/components/amount-input.md +305 -0
  8. package/dist/docs/components/amount.md +794 -0
  9. package/dist/docs/components/app-shell.md +559 -0
  10. package/dist/docs/components/asset-chip.md +294 -0
  11. package/dist/docs/components/autocomplete.md +619 -0
  12. package/dist/docs/components/avatar.md +321 -0
  13. package/dist/docs/components/badge.md +339 -0
  14. package/dist/docs/components/badged-logo.md +116 -0
  15. package/dist/docs/components/banner.md +379 -0
  16. package/dist/docs/components/bar-chart.md +208 -0
  17. package/dist/docs/components/breadcrumbs.md +380 -0
  18. package/dist/docs/components/button-group.md +286 -0
  19. package/dist/docs/components/button.md +650 -0
  20. package/dist/docs/components/calendar.md +375 -0
  21. package/dist/docs/components/callout.md +96 -0
  22. package/dist/docs/components/checkbox-group.md +521 -0
  23. package/dist/docs/components/checkbox.md +467 -0
  24. package/dist/docs/components/choice-group.md +516 -0
  25. package/dist/docs/components/choicebox.md +641 -0
  26. package/dist/docs/components/code.md +100 -0
  27. package/dist/docs/components/combobox.md +939 -0
  28. package/dist/docs/components/container.md +257 -0
  29. package/dist/docs/components/copy-button.md +642 -0
  30. package/dist/docs/components/date-picker.md +514 -0
  31. package/dist/docs/components/dialog.md +1332 -0
  32. package/dist/docs/components/drawer.md +966 -0
  33. package/dist/docs/components/empty.md +340 -0
  34. package/dist/docs/components/field.md +570 -0
  35. package/dist/docs/components/fieldset.md +398 -0
  36. package/dist/docs/components/frame.md +434 -0
  37. package/dist/docs/components/gauge.md +299 -0
  38. package/dist/docs/components/get-started-visual.md +117 -0
  39. package/dist/docs/components/grid.md +288 -0
  40. package/dist/docs/components/hero-visual.md +155 -0
  41. package/dist/docs/components/hex.md +487 -0
  42. package/dist/docs/components/icon-tile.md +292 -0
  43. package/dist/docs/components/identicon.md +371 -0
  44. package/dist/docs/components/inline.md +233 -0
  45. package/dist/docs/components/inset.md +225 -0
  46. package/dist/docs/components/kbd.md +423 -0
  47. package/dist/docs/components/list-group.md +981 -0
  48. package/dist/docs/components/loading-dots.md +237 -0
  49. package/dist/docs/components/menu.md +934 -0
  50. package/dist/docs/components/native-select.md +204 -0
  51. package/dist/docs/components/network-logo.md +248 -0
  52. package/dist/docs/components/number-field.md +543 -0
  53. package/dist/docs/components/otp-field.md +616 -0
  54. package/dist/docs/components/pagination.md +516 -0
  55. package/dist/docs/components/popover.md +544 -0
  56. package/dist/docs/components/progress.md +388 -0
  57. package/dist/docs/components/qr.md +314 -0
  58. package/dist/docs/components/radio-group.md +528 -0
  59. package/dist/docs/components/secret-value.md +406 -0
  60. package/dist/docs/components/select.md +751 -0
  61. package/dist/docs/components/separator.md +379 -0
  62. package/dist/docs/components/sidebar-menu.md +922 -0
  63. package/dist/docs/components/skeleton.md +517 -0
  64. package/dist/docs/components/slider.md +539 -0
  65. package/dist/docs/components/snippet.md +424 -0
  66. package/dist/docs/components/spinner.md +216 -0
  67. package/dist/docs/components/split-bar.md +139 -0
  68. package/dist/docs/components/split-button.md +464 -0
  69. package/dist/docs/components/stack.md +299 -0
  70. package/dist/docs/components/status-chip.md +226 -0
  71. package/dist/docs/components/status-indicator.md +119 -0
  72. package/dist/docs/components/status-row.md +174 -0
  73. package/dist/docs/components/stepper.md +451 -0
  74. package/dist/docs/components/success-hero.md +157 -0
  75. package/dist/docs/components/surface.md +639 -0
  76. package/dist/docs/components/switch.md +472 -0
  77. package/dist/docs/components/table.md +967 -0
  78. package/dist/docs/components/tabs.md +627 -0
  79. package/dist/docs/components/tempo-logo.md +185 -0
  80. package/dist/docs/components/text-input.md +624 -0
  81. package/dist/docs/components/textarea.md +352 -0
  82. package/dist/docs/components/toast.md +535 -0
  83. package/dist/docs/components/token-logo.md +371 -0
  84. package/dist/docs/components/token.md +247 -0
  85. package/dist/docs/components/tooltip.md +490 -0
  86. package/dist/docs/components/verification-code.md +116 -0
  87. package/dist/docs/components/visual.md +249 -0
  88. package/dist/docs/components.md +203 -0
  89. package/dist/docs/foundations/accessibility.md +377 -0
  90. package/dist/docs/foundations/agents.md +150 -0
  91. package/dist/docs/foundations/color.md +522 -0
  92. package/dist/docs/foundations/content/tone.md +194 -0
  93. package/dist/docs/foundations/content/voice.md +194 -0
  94. package/dist/docs/foundations/content/writing-style.md +406 -0
  95. package/dist/docs/foundations/iconography.md +282 -0
  96. package/dist/docs/foundations/intent.md +360 -0
  97. package/dist/docs/foundations/layout.md +508 -0
  98. package/dist/docs/foundations/linter.md +296 -0
  99. package/dist/docs/foundations/motion.md +151 -0
  100. package/dist/docs/foundations/radius-and-padding.md +86 -0
  101. package/dist/docs/foundations/typography.md +266 -0
  102. package/dist/docs/index.md +137 -0
  103. package/dist/docs/introduction/faq.md +132 -0
  104. package/dist/docs/introduction/getting-started.md +377 -0
  105. package/dist/docs/patterns/blockchain-values.md +709 -0
  106. package/dist/docs/patterns/dashboards.md +638 -0
  107. package/dist/docs/patterns/destructive-actions.md +626 -0
  108. package/dist/docs/patterns/empty-states.md +612 -0
  109. package/dist/docs/patterns/errors-and-validation.md +808 -0
  110. package/dist/docs/patterns/feedback-and-status.md +518 -0
  111. package/dist/docs/patterns/forms.md +679 -0
  112. package/dist/docs/patterns/loading.md +630 -0
  113. package/dist/docs/patterns/navigation.md +397 -0
  114. package/dist/docs/patterns/payments.md +765 -0
  115. package/dist/docs/patterns/responsive-layout.md +997 -0
  116. package/dist/docs/patterns/tables-and-lists.md +964 -0
  117. package/dist/docs/products/tempo-console.md +671 -0
  118. package/dist/docs/products/tempo-performance.md +437 -0
  119. package/dist/docs/products/tempo-wallet.md +438 -0
  120. package/dist/web/components/OtpField.css +1 -1
  121. package/dist/web/components/OtpField.d.ts +1 -1
  122. package/dist/web/components/OtpField.d.ts.map +1 -1
  123. package/dist/web/components/OtpField.js +3 -4
  124. package/dist/web/components/OtpField.js.map +1 -1
  125. package/dist/web/components/OtpField.js.zyzz.json +1 -1
  126. package/dist/web/index.js.zyzz.json +1 -1
  127. package/package.json +1 -1
  128. package/src/web/components/OtpField.tsx +2 -24
@@ -0,0 +1,299 @@
1
+ # Gauge
2
+
3
+ Shows a measurement within a range as a ring.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Gauge.tsx)
6
+
7
+ ## Overview
8
+
9
+ A gauge is a ring that shows a measurement within a range, such as usage or a score.
10
+
11
+ ## Examples
12
+
13
+ ### Basic
14
+
15
+ ```tsx
16
+ import { Gauge } from '@tempoxyz/ds'
17
+
18
+ export function Demo() {
19
+ return <Gauge aria-label="Storage used" showValue value={72} />
20
+ }
21
+ ```
22
+
23
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Gauge/Basic.tsx)
24
+
25
+ ### Intent
26
+
27
+ Set `intent` to `neutral` (default) or `positive`.
28
+
29
+ ```tsx
30
+ import { Gauge, style } from '@tempoxyz/ds'
31
+
32
+ export function Demo() {
33
+ return (
34
+ <div {...styles.row()}>
35
+ {(['neutral', 'positive'] as const).map((intent, index) => (
36
+ <Gauge aria-label={intent} intent={intent} key={intent} showValue value={20 + index * 20} />
37
+ ))}
38
+ </div>
39
+ )
40
+ }
41
+
42
+ namespace styles {
43
+ export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '16' })
44
+ }
45
+ ```
46
+
47
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Gauge/Intent.tsx)
48
+
49
+ ### Size
50
+
51
+ Set `size` to `small`, `medium` (default), or `large`.
52
+
53
+ ```tsx
54
+ import { Gauge, style } from '@tempoxyz/ds'
55
+
56
+ export function Demo() {
57
+ return (
58
+ <div {...styles.row()}>
59
+ <Gauge aria-label="Small" size="small" value={72} />
60
+ <Gauge aria-label="Medium" size="medium" value={72} />
61
+ <Gauge aria-label="Large" showValue size="large" value={72} />
62
+ </div>
63
+ )
64
+ }
65
+
66
+ namespace styles {
67
+ export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '16' })
68
+ }
69
+ ```
70
+
71
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Gauge/Size.tsx)
72
+
73
+ ### ShowValue
74
+
75
+ Set `showValue` to print the value inside the ring.
76
+
77
+ ```tsx
78
+ import { Gauge, style } from '@tempoxyz/ds'
79
+
80
+ export function Demo() {
81
+ return (
82
+ <div {...styles.row()}>
83
+ <Gauge aria-label="Hidden value" value={40} />
84
+ <Gauge aria-label="Shown value" showValue value={40} />
85
+ </div>
86
+ )
87
+ }
88
+
89
+ namespace styles {
90
+ export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '16' })
91
+ }
92
+ ```
93
+
94
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Gauge/ShowValue.tsx)
95
+
96
+ ## Anatomy
97
+
98
+ Import the component and assemble its parts.
99
+
100
+ ```tsx
101
+ import { Gauge } from '@tempoxyz/ds'
102
+
103
+ <Gauge />
104
+ ```
105
+
106
+ ## Guidelines
107
+
108
+ ### When to Use
109
+
110
+ * Show how much of a limit is used, such as API requests against a quota.
111
+ * Show a ratio in a metric tile, such as gas used against the gas limit.
112
+ * Show a score with a fixed range, such as validator uptime.
113
+
114
+ ### When Not to Use
115
+
116
+ * Use [Progress](/docs/components/progress) for a task that advances, such as an upload.
117
+ * Use [Skeleton](/docs/components/skeleton) or [Spinner](/docs/components/spinner) while the measurement loads.
118
+ * Use [Slider](/docs/components/slider) when the user sets the value.
119
+ * Use plain text if the value has no fixed maximum, such as 4,812 TPS.
120
+
121
+ ### Show the Value in Text
122
+
123
+ Set `showValue` to print the percentage in the ring.
124
+
125
+ **Do:** Pair the ring with its label and the absolute values beside it.
126
+
127
+ ```tsx
128
+ /**
129
+ * Do example for "Show the Value in Text" on the Gauge page.
130
+ * Pair the ring with its label and the absolute values beside it.
131
+ * @module
132
+ */
133
+ import { Gauge, style } from '@tempoxyz/ds'
134
+
135
+ /** Renders the static preview, which the guideline card shows inert. */
136
+ export function Demo() {
137
+ return (
138
+ <div {...styles.row()}>
139
+ <Gauge aria-labelledby="gauge-requests" max={10000} showValue value={7200} />
140
+ <div {...styles.text()}>
141
+ <div {...styles.label()} id="gauge-requests">
142
+ API requests this month
143
+ </div>
144
+ <div {...styles.value()}>7,200 of 10,000</div>
145
+ </div>
146
+ </div>
147
+ )
148
+ }
149
+
150
+ namespace styles {
151
+ export const label = style({ color: 'content.primary', typography: 'body.b2' })
152
+
153
+ export const row = style({ alignItems: 'center', display: 'flex', gap: '12' })
154
+
155
+ export const text = style({ display: 'flex', flexDirection: 'column', gap: '4' })
156
+
157
+ export const value = style({ color: 'content.secondary', typography: 'body.b3' })
158
+ }
159
+ ```
160
+
161
+ **Don't:** Show a ring without its value or what it measures.
162
+
163
+ ```tsx
164
+ /**
165
+ * Don't example for "Show the Value in Text" on the Gauge page.
166
+ * Don't show a ring without its value or what it measures.
167
+ * @module
168
+ */
169
+ import { Gauge } from '@tempoxyz/ds'
170
+
171
+ /** Renders the static preview, which the guideline card shows inert. */
172
+ export function Demo() {
173
+ return <Gauge aria-label="Usage" max={10000} value={7200} />
174
+ }
175
+ ```
176
+
177
+ ### Pass the Real Range
178
+
179
+ The ring, `showValue`, and the accessible value derive the percentage from `min` (default 0) and `max` (default 100).
180
+
181
+ **Do:** Set `max` to the actual bound, such as `value={7200}` with `max={10000}`.
182
+
183
+ ```tsx
184
+ /**
185
+ * Do example for "Pass the Real Range" on the Gauge page.
186
+ * Set `max` to the actual bound, such as `value={7200}` with `max={10000}`.
187
+ * @module
188
+ */
189
+ import { Gauge, style } from '@tempoxyz/ds'
190
+
191
+ /** Renders the static preview, which the guideline card shows inert. */
192
+ export function Demo() {
193
+ return (
194
+ <div {...styles.row()}>
195
+ <Gauge aria-labelledby="gauge-range" max={10000} showValue value={7200} />
196
+ <div {...styles.text()}>
197
+ <div {...styles.label()} id="gauge-range">
198
+ API requests this month
199
+ </div>
200
+ <div {...styles.value()}>7,200 of 10,000</div>
201
+ </div>
202
+ </div>
203
+ )
204
+ }
205
+
206
+ namespace styles {
207
+ export const label = style({ color: 'content.primary', typography: 'body.b2' })
208
+
209
+ export const row = style({ alignItems: 'center', display: 'flex', gap: '12' })
210
+
211
+ export const text = style({ display: 'flex', flexDirection: 'column', gap: '4' })
212
+
213
+ export const value = style({ color: 'content.secondary', typography: 'body.b3' })
214
+ }
215
+ ```
216
+
217
+ **Don't:** Pass a raw count against the default `max` of 100.
218
+
219
+ ```tsx
220
+ /**
221
+ * Don't example for "Pass the Real Range" on the Gauge page.
222
+ * Don't pass a raw count against the default `max` of 100.
223
+ * @module
224
+ */
225
+ import { Gauge, style } from '@tempoxyz/ds'
226
+
227
+ /** Renders the static preview, which the guideline card shows inert. */
228
+ export function Demo() {
229
+ return (
230
+ <div {...styles.row()}>
231
+ <Gauge aria-labelledby="gauge-default" showValue value={7200} />
232
+ <div {...styles.text()}>
233
+ <div {...styles.label()} id="gauge-default">
234
+ API requests this month
235
+ </div>
236
+ <div {...styles.value()}>7,200 of 10,000</div>
237
+ </div>
238
+ </div>
239
+ )
240
+ }
241
+
242
+ namespace styles {
243
+ export const label = style({ color: 'content.primary', typography: 'body.b2' })
244
+
245
+ export const row = style({ alignItems: 'center', display: 'flex', gap: '12' })
246
+
247
+ export const text = style({ display: 'flex', flexDirection: 'column', gap: '4' })
248
+
249
+ export const value = style({ color: 'content.secondary', typography: 'body.b3' })
250
+ }
251
+ ```
252
+
253
+ ### Choose an Intent
254
+
255
+ * **Most Measurements (neutral):** The default, for a measurement such as API requests against a quota.
256
+ * **Full Is Good (positive):** A measurement where a full value is good, such as 100% uptime.
257
+ * **Nearing a Limit (Alert):** There is no `warning` intent. Add a `warning` [Alert](/docs/components/alert) with the next step.
258
+
259
+ ### Match Size to Context
260
+
261
+ * **Small (32px):** Table cells and dense lists. Print the value beside it.
262
+ * **Medium (48px):** The default, for metric tiles and cards.
263
+ * **Large (80px):** A featured measurement, such as plan usage in billing.
264
+
265
+ ## Content
266
+
267
+ * **Label:** Name the measurement, not the component, such as Gas used.
268
+
269
+ ## Accessibility
270
+
271
+ A gauge renders a `meter`. It follows the [WAI-ARIA Authoring Practices meter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/meter/). It is not a live region, so a changed value is read only on the next visit.
272
+
273
+ ### Semantics
274
+
275
+ * **Root (meter):** Reports its minimum, maximum, and value to assistive technology.
276
+ * **Value Text (72%):** Defaults to the value as a locale-formatted percentage of the range.
277
+ * **Ring (aria-hidden):** Hidden. Assistive technology reads the value text instead.
278
+ * **Visible Value (showValue):** Shows the number. It ignores `format`, which changes only the announced text.
279
+ * **Arc Color (foreground):** Green for positive intent, on a gray track. Keep the gauge on a plain surface.
280
+ * **Reduced Motion (reduce):** Under reduced motion, the arc doesn't animate between values.
281
+
282
+ ### Your Responsibilities
283
+
284
+ * **Name the Gauge (SC 4.1.2):** Use `aria-label` or `aria-labelledby`. The gauge renders no label.
285
+ * **Describe Non-Percentage Values (getAriaValueText):** Use it if a percentage doesn't describe the value, such as "7.2 of 10 GB".
286
+
287
+ ## Related
288
+
289
+ [Progress](/docs/components/progress)
290
+
291
+ Use for a task that advances.
292
+
293
+ [Alert](/docs/components/alert)
294
+
295
+ Use for a warning when usage nears a limit.
296
+
297
+ [Dashboards](/docs/patterns/dashboards)
298
+
299
+ Covers laying out metric tiles.
@@ -0,0 +1,117 @@
1
+ # GetStartedVisual
2
+
3
+ Illustrates one step of a get started flow at the top of its card.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/GetStartedVisual.tsx)
6
+
7
+ Figma: [Content/Get Started Visual](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=5227-3110)
8
+
9
+ ## Overview
10
+
11
+ A get started visual renders a 320 by 160px illustration on a dark ground. `step` selects the artwork of connecting, adding funds, or adding a passkey.
12
+
13
+ ## Examples
14
+
15
+ ### Basic
16
+
17
+ Set `step` to `connect` (default), `funds`, or `passkey`.
18
+
19
+ ```tsx
20
+ /** Demonstrates GetStartedVisual in the documentation. @module */
21
+ import { GetStartedVisual, style } from '@tempoxyz/ds'
22
+
23
+ export function Demo() {
24
+ return (
25
+ <div {...styles.frame()}>
26
+ <GetStartedVisual step="connect" />
27
+ </div>
28
+ )
29
+ }
30
+
31
+ namespace styles {
32
+ export const frame = style({ maxWidth: '20rem !custom', width: '100% !custom' })
33
+ }
34
+ ```
35
+
36
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/GetStartedVisual/Basic.tsx)
37
+
38
+ ### Steps
39
+
40
+ Each step of the flow has its own artwork.
41
+
42
+ ```tsx
43
+ /** Demonstrates GetStartedVisual in the documentation. @module */
44
+ import { GetStartedVisual, style } from '@tempoxyz/ds'
45
+
46
+ export function Demo() {
47
+ return (
48
+ <div {...styles.row()}>
49
+ <GetStartedVisual step="connect" />
50
+ <GetStartedVisual step="funds" />
51
+ <GetStartedVisual step="passkey" />
52
+ </div>
53
+ )
54
+ }
55
+
56
+ namespace styles {
57
+ export const row = style({ display: 'flex', flexWrap: 'wrap', gap: '16' })
58
+ }
59
+ ```
60
+
61
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/GetStartedVisual/Steps.tsx)
62
+
63
+ ## Anatomy
64
+
65
+ Import the component.
66
+
67
+ ```tsx
68
+ import { GetStartedVisual } from '@tempoxyz/ds'
69
+
70
+ <GetStartedVisual />
71
+ ```
72
+
73
+ ## Guidelines
74
+
75
+ ### When to Use
76
+
77
+ * Open each card of a get started list, above the title of its step.
78
+
79
+ ### When Not to Use
80
+
81
+ * Use [Visual](/docs/components/visual) for the top of a modal.
82
+ * Use [IconTile](/docs/components/icon-tile) for a step that needs only an icon.
83
+
84
+ ### Match the Artwork to the Step
85
+
86
+ **Do:** Show the funds artwork on the step that adds funds.
87
+
88
+ ```tsx
89
+ <GetStartedVisual step="funds" />
90
+ ```
91
+
92
+ **Don't:** Reuse one artwork for every step.
93
+
94
+ ```tsx
95
+ <GetStartedVisual step="passkey" />
96
+ ```
97
+
98
+ ### Use One Visual per Card
99
+
100
+ Place one visual at the top of a card. Two visuals in one card compete for attention.
101
+
102
+ ## Accessibility
103
+
104
+ The visual renders a `<div>` with no role and takes no focus. Screen readers skip the artwork.
105
+
106
+ * **Artwork (aria-hidden):** Decorative, so screen readers skip it.
107
+ * **Name the Step in Text (Your task):** The title of the card names the step.
108
+
109
+ ## Related
110
+
111
+ [Visual](/docs/components/visual)
112
+
113
+ Use for the illustration at the top of a modal.
114
+
115
+ [HeroVisual](/docs/components/hero-visual)
116
+
117
+ Use for the hero card beside a setup flow.
@@ -0,0 +1,288 @@
1
+ # Grid
2
+
3
+ Lays out children on a responsive grid.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Grid.tsx)
6
+
7
+ ## Overview
8
+
9
+ Grid places children on equal tracks, either a fixed `columns` count or as many as the width allows with `fit`.
10
+
11
+ ## Examples
12
+
13
+ ### Basic
14
+
15
+ ```tsx
16
+ import { Grid, Inset, style } from '@tempoxyz/ds'
17
+
18
+ export const fill = true
19
+ export function Demo() {
20
+ return (
21
+ <Grid columns="3" gap="16">
22
+ {[1, 2, 3].map((n) => (
23
+ <Inset key={n} space="16" {...styles.card()}>
24
+ Column {n}
25
+ </Inset>
26
+ ))}
27
+ </Grid>
28
+ )
29
+ }
30
+
31
+ namespace styles {
32
+ export const card = style({ backgroundColor: 'background.elevated', borderRadius: 'sm' })
33
+ }
34
+ ```
35
+
36
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Grid/Basic.tsx)
37
+
38
+ ### Fit
39
+
40
+ Set `fit` to `small`, `medium`, or `large` for tracks of at least 10rem, 14rem, or 20rem. It overrides `columns`.
41
+
42
+ ```tsx
43
+ import { Grid, Inset, style } from '@tempoxyz/ds'
44
+
45
+ export const fill = true
46
+ export function Demo() {
47
+ return (
48
+ <Grid fit="medium" gap="16">
49
+ {[1, 2, 3, 4].map((n) => (
50
+ <Inset key={n} block="24" inline="32" {...styles.card()}>
51
+ Fit {n}
52
+ </Inset>
53
+ ))}
54
+ </Grid>
55
+ )
56
+ }
57
+
58
+ namespace styles {
59
+ export const card = style({ backgroundColor: 'background.elevated', borderRadius: 'sm' })
60
+ }
61
+ ```
62
+
63
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Grid/Fit.tsx)
64
+
65
+ ### Columns
66
+
67
+ Set `columns` to `1`, `2`, `3`, `4`, `6`, or `12` equal tracks.
68
+
69
+ ```tsx
70
+ import { Grid, Inset, Stack, style } from '@tempoxyz/ds'
71
+
72
+ export const fill = true
73
+ export function Demo() {
74
+ return (
75
+ <Stack gap="24">
76
+ {(['2', '3', '4'] as const).map((columns) => (
77
+ <Grid columns={columns} gap="8" key={columns}>
78
+ {Array.from({ length: Number(columns) }, (_, index) => (
79
+ <Inset key={index} space="16" {...styles.card()}>
80
+ {columns} columns
81
+ </Inset>
82
+ ))}
83
+ </Grid>
84
+ ))}
85
+ </Stack>
86
+ )
87
+ }
88
+
89
+ namespace styles {
90
+ export const card = style({ backgroundColor: 'background.elevated', borderRadius: 'sm' })
91
+ }
92
+ ```
93
+
94
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Grid/Columns.tsx)
95
+
96
+ ### Gap
97
+
98
+ Set `gap` to a spacing token. `rowGap` and `columnGap` override it on one axis.
99
+
100
+ ```tsx
101
+ import { Grid, Inset, style } from '@tempoxyz/ds'
102
+
103
+ export const fill = true
104
+ export function Demo() {
105
+ return (
106
+ <Grid columnGap="8" columns="3" rowGap="32">
107
+ {[1, 2, 3, 4, 5, 6].map((n) => (
108
+ <Inset key={n} space="16" {...styles.card()}>
109
+ Column {n}
110
+ </Inset>
111
+ ))}
112
+ </Grid>
113
+ )
114
+ }
115
+
116
+ namespace styles {
117
+ export const card = style({ backgroundColor: 'background.elevated', borderRadius: 'sm' })
118
+ }
119
+ ```
120
+
121
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Grid/Gap.tsx)
122
+
123
+ ## Anatomy
124
+
125
+ Import the component and assemble its parts.
126
+
127
+ ```tsx
128
+ import { Grid } from '@tempoxyz/ds'
129
+
130
+ <Grid />
131
+ ```
132
+
133
+ ## Guidelines
134
+
135
+ ### When to Use
136
+
137
+ * Lay out similar items, such as metric tiles, token balance cards, or API key cards.
138
+ * Build a two-dimensional page layout with a fixed structure, such as a 12-column dashboard.
139
+
140
+ ### When Not to Use
141
+
142
+ * Use [Table](/docs/components/table) for records to compare across columns, such as transactions.
143
+ * Use [Stack](/docs/components/stack) for one column, and [Inline](/docs/components/inline) for one row.
144
+
145
+ ### Prefer Fit Over Fixed Columns
146
+
147
+ **Do:** Set `fit` so tiles drop to fewer columns as the width shrinks.
148
+
149
+ ```tsx
150
+ /**
151
+ * Do example for "Prefer Fit Over Fixed Columns" on the Grid page.
152
+ * Set `fit` so tiles drop to fewer columns as the width shrinks.
153
+ * @module
154
+ */
155
+ import { Grid, style, Surface } from '@tempoxyz/ds'
156
+
157
+ const metrics = [
158
+ ['TPS', '4,218'],
159
+ ['Block time', '0.5s'],
160
+ ['Finality', '0.6s'],
161
+ ] as const
162
+
163
+ /** Renders the static preview, which the guideline card shows inert. */
164
+ export function Demo() {
165
+ return (
166
+ <Grid fit="small" gap="12" {...styles.canvas()}>
167
+ {metrics.map(([label, value]) => (
168
+ <Surface key={label} size="medium">
169
+ <span {...styles.label()}>{label}</span>
170
+ <span {...styles.value()}>{value}</span>
171
+ </Surface>
172
+ ))}
173
+ </Grid>
174
+ )
175
+ }
176
+
177
+ namespace styles {
178
+ export const canvas = style({
179
+ backgroundColor: 'background.primary',
180
+ borderRadius: 'sm',
181
+ boxSizing: 'border-box',
182
+ padding: '12',
183
+ width: '100% !custom',
184
+ })
185
+
186
+ export const label = style({
187
+ color: 'content.secondary',
188
+ display: 'block',
189
+ typography: 'body.b3',
190
+ })
191
+
192
+ export const value = style({ display: 'block', typography: 'heading.h3' })
193
+ }
194
+ ```
195
+
196
+ **Don't:** Force four fixed columns into a narrow container.
197
+
198
+ ```tsx
199
+ /**
200
+ * Don't example for "Prefer Fit Over Fixed Columns" on the Grid page.
201
+ * Don't force four fixed columns into a narrow container.
202
+ * @module
203
+ */
204
+ import { Grid, style, Surface } from '@tempoxyz/ds'
205
+
206
+ const metrics = [
207
+ ['TPS', '4,218'],
208
+ ['Block time', '0.5s'],
209
+ ['Finality', '0.6s'],
210
+ ['Gas price', '0.1 gwei'],
211
+ ] as const
212
+
213
+ /** Renders the static preview, which the guideline card shows inert. */
214
+ export function Demo() {
215
+ return (
216
+ <Grid columns="4" gap="12" {...styles.canvas()}>
217
+ {metrics.map(([label, value]) => (
218
+ <Surface key={label} size="medium">
219
+ <span {...styles.label()}>{label}</span>
220
+ <span {...styles.value()}>{value}</span>
221
+ </Surface>
222
+ ))}
223
+ </Grid>
224
+ )
225
+ }
226
+
227
+ namespace styles {
228
+ export const canvas = style({
229
+ backgroundColor: 'background.primary',
230
+ borderRadius: 'sm',
231
+ boxSizing: 'border-box',
232
+ padding: '12',
233
+ width: '100% !custom',
234
+ })
235
+
236
+ export const label = style({
237
+ color: 'content.secondary',
238
+ display: 'block',
239
+ typography: 'body.b3',
240
+ })
241
+
242
+ export const value = style({ display: 'block', typography: 'heading.h3' })
243
+ }
244
+ ```
245
+
246
+ ### Change Columns at Breakpoints
247
+
248
+ If a layout needs a set count per width, change `gridTemplateColumns` under a [breakpoint](/docs/foundations/layout#breakpoints) key. Write the narrowest layout as the base style.
249
+
250
+ * **Base (0 to 767px):** One column on phones, with no media key.
251
+ * **Tablet ('@media 768'):** More columns from 48rem.
252
+ * **Desktop ('@media 1024'):** The full count from 64rem. Use `'@media <1024'` for anything narrower.
253
+
254
+ ### Pick a Gap From the Scale
255
+
256
+ * **Cards (24):** The default, for cards.
257
+ * **Dense Tiles (12 or 16):** For dense dashboard tiles.
258
+
259
+ ## Accessibility
260
+
261
+ Grid has no role, name, or keyboard behavior.
262
+
263
+ ### Semantics
264
+
265
+ * **Default Element (div):** Has no role. Screen readers pass over it.
266
+ * **Semantic Element (render):** If the children are items or links, render a list or nav, such as `render={<ul />}`.
267
+
268
+ ### Your Responsibilities
269
+
270
+ * **Match DOM and Visual Order (Tab):** Don't reorder children with CSS or grid placement. Reading and focus follow the DOM ([SC 1.3.2](https://www.w3.org/WAI/WCAG22/Understanding/meaningful-sequence.html), [SC 2.4.3](https://www.w3.org/WAI/WCAG22/Understanding/focus-order.html)).
271
+
272
+ ## Related
273
+
274
+ [Surface](/docs/components/surface)
275
+
276
+ Use for the cards inside a grid.
277
+
278
+ [Table](/docs/components/table)
279
+
280
+ Use for comparing records.
281
+
282
+ [Dashboards](/docs/patterns/dashboards)
283
+
284
+ Covers metric tile layouts.
285
+
286
+ [Responsive Layout](/docs/patterns/responsive-layout)
287
+
288
+ Covers adapting pages across breakpoints.