@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,639 @@
1
+ # Surface
2
+
3
+ A card container for grouping related content.
4
+
5
+ [View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Surface.tsx)
6
+
7
+ Figma: [Content/Card](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=5227-5510)
8
+
9
+ ## Overview
10
+
11
+ A surface renders a `div` with a thin border by default. Its `size` sets the corner radius and the padding to the same value.
12
+
13
+ ## Examples
14
+
15
+ ### Basic
16
+
17
+ ```tsx
18
+ import { style, Surface } from '@tempoxyz/ds'
19
+ import { SwapHorizontal } from '@tempoxyz/ds/icons'
20
+
21
+ export function Demo() {
22
+ return (
23
+ <div {...styles.grid()}>
24
+ <Surface>
25
+ <Surface.Header>
26
+ <Surface.Title>
27
+ <SwapHorizontal />
28
+ Routes
29
+ </Surface.Title>
30
+ </Surface.Header>
31
+ <Surface.Description>
32
+ Move stablecoins between Tempo and other networks.
33
+ </Surface.Description>
34
+ <Surface.Links>
35
+ <a href="#basic">Make a transfer</a>
36
+ <a href="#basic">Accept deposits</a>
37
+ <a href="#basic">Supported routes</a>
38
+ </Surface.Links>
39
+ </Surface>
40
+ </div>
41
+ )
42
+ }
43
+
44
+ namespace styles {
45
+ export const grid = style({
46
+ alignItems: 'start',
47
+ backgroundColor: 'background.primary',
48
+ display: 'grid',
49
+ gap: '12',
50
+ padding: '16',
51
+ gridTemplateColumns: 'repeat(auto-fill, minmax(14rem, 1fr)) !custom',
52
+ })
53
+ }
54
+ ```
55
+
56
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Surface/Basic.tsx)
57
+
58
+ ### Header
59
+
60
+ Place a `Surface.Title` and an optional action inside `Surface.Header`.
61
+
62
+ ```tsx
63
+ import { Button, style, Surface, TokenLogo } from '@tempoxyz/ds'
64
+
65
+ const balances = [
66
+ ['Bridged USDC (Stargate)', '0x20c000000000000000000000b9537d11c60e8b50', '$2.02'],
67
+ ['pathUSD', '0x20c0000000000000000000000000000000000000', '$0.12'],
68
+ ['USDT0', '0x20c00000000000000000000014f22ca97301eb73', '$0.10'],
69
+ ] as const
70
+
71
+ export function Demo() {
72
+ return (
73
+ <div {...styles.grid()}>
74
+ <Surface>
75
+ <Surface.Header>
76
+ <Surface.Title>Balances</Surface.Title>
77
+ <Button size="small" variant="tertiary">
78
+ View all
79
+ </Button>
80
+ </Surface.Header>
81
+ {balances.map(([name, address, amount]) => (
82
+ <div key={address} {...styles.balance()}>
83
+ <TokenLogo address={address} />
84
+ <span {...styles.name()}>{name}</span>
85
+ {amount}
86
+ </div>
87
+ ))}
88
+ </Surface>
89
+ </div>
90
+ )
91
+ }
92
+
93
+ namespace styles {
94
+ export const balance = style({
95
+ alignItems: 'center',
96
+ columnGap: '12',
97
+ display: 'flex',
98
+ paddingBlock: '8',
99
+ typography: 'body.b1Strong',
100
+ })
101
+
102
+ export const grid = style({
103
+ backgroundColor: 'background.primary',
104
+ display: 'grid',
105
+ padding: '16',
106
+ })
107
+
108
+ export const name = style({ flex: '1 !custom' })
109
+ }
110
+ ```
111
+
112
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Surface/Header.tsx)
113
+
114
+ ### List
115
+
116
+ A [ListGroup](list-group.md) inside a surface bleeds into its padding, so a row's hover fill reaches the edges of the surface. Each row is 44px, and a [Select](select.md) in a row hugs its value at the end of the row.
117
+
118
+ ```tsx
119
+ /** Renders a small surface whose list holds a network picker and a row of token logos, for the Surface docs. @module */
120
+ import { ListGroup, NetworkLogo, Select, style, Surface, TokenLogo } from '@tempoxyz/ds'
121
+
122
+ const networks = [
123
+ { available: true, id: 'tempo', name: 'Tempo' },
124
+ { available: false, id: 'ethereum', name: 'Ethereum' },
125
+ { available: false, id: 'base', name: 'Base' },
126
+ ] as const
127
+
128
+ const stablecoins = [
129
+ ['pathUSD', '0x20c0000000000000000000000000000000000000'],
130
+ ['Bridged USDC (Stargate)', '0x20c000000000000000000000b9537d11c60e8b50'],
131
+ ['USDT0', '0x20c00000000000000000000014f22ca97301eb73'],
132
+ ] as const
133
+
134
+ export function Demo() {
135
+ return (
136
+ <div {...styles.grid()}>
137
+ <Surface size="small">
138
+ <ListGroup>
139
+ <ListGroup.Row>
140
+ <ListGroup.Label id="surface-list-network">Network</ListGroup.Label>
141
+ <Select.Root value="tempo">
142
+ <Select.Trigger aria-labelledby="surface-list-network">
143
+ <Select.Value>
144
+ {() => (
145
+ <span {...styles.value()}>
146
+ <NetworkLogo network="tempo" size="medium" />
147
+ Tempo
148
+ </span>
149
+ )}
150
+ </Select.Value>
151
+ <Select.Icon />
152
+ </Select.Trigger>
153
+ <Select.Popup align="end">
154
+ {networks.map((network) => (
155
+ <Select.Item disabled={!network.available} key={network.id} value={network.id}>
156
+ <Select.ItemPrefix>
157
+ <NetworkLogo network={network.id} size="medium" />
158
+ </Select.ItemPrefix>
159
+ <Select.ItemText>{network.name}</Select.ItemText>
160
+ {network.available ? null : <Select.ItemSuffix>Coming soon</Select.ItemSuffix>}
161
+ </Select.Item>
162
+ ))}
163
+ </Select.Popup>
164
+ </Select.Root>
165
+ </ListGroup.Row>
166
+ <ListGroup.Row>
167
+ <ListGroup.Label>Supported stablecoins</ListGroup.Label>
168
+ <span {...styles.coins()}>
169
+ {stablecoins.map(([symbol, address]) => (
170
+ <TokenLogo address={address} alt={symbol} key={address} />
171
+ ))}
172
+ </span>
173
+ </ListGroup.Row>
174
+ </ListGroup>
175
+ </Surface>
176
+ </div>
177
+ )
178
+ }
179
+
180
+ namespace styles {
181
+ export const coins = style({ display: 'flex', gap: '4', marginInlineStart: 'auto !custom' })
182
+
183
+ export const grid = style({ display: 'grid', maxWidth: '25rem !custom', width: '100% !custom' })
184
+
185
+ export const value = style({ alignItems: 'center', display: 'flex', gap: '8' })
186
+ }
187
+ ```
188
+
189
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Surface/List.tsx)
190
+
191
+ ### Size
192
+
193
+ Set `size` to `small`, `medium`, or `large` (default).
194
+
195
+ ```tsx
196
+ import { style, Surface } from '@tempoxyz/ds'
197
+
198
+ export function Demo() {
199
+ return (
200
+ <div {...styles.grid()}>
201
+ {(['large', 'medium', 'small'] as const).map((size) => (
202
+ <Surface key={size} size={size}>
203
+ Size {size}
204
+ </Surface>
205
+ ))}
206
+ </div>
207
+ )
208
+ }
209
+
210
+ namespace styles {
211
+ // Surfaces keep their content height instead of stretching to the tallest one in a row.
212
+ export const grid = style({
213
+ alignItems: 'start',
214
+ backgroundColor: 'background.primary',
215
+ display: 'grid',
216
+ gap: '12',
217
+ padding: '16',
218
+ gridTemplateColumns: 'repeat(auto-fill, minmax(14rem, 1fr)) !custom',
219
+ })
220
+ }
221
+ ```
222
+
223
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Surface/Size.tsx)
224
+
225
+ ### Render
226
+
227
+ Pass a `button` or link to `render` for a pressable surface with hover, press, and focus styles.
228
+
229
+ ```tsx
230
+ import { style, Surface } from '@tempoxyz/ds'
231
+ import { SwapHorizontal } from '@tempoxyz/ds/icons'
232
+
233
+ export function Demo() {
234
+ return (
235
+ <div {...styles.grid()}>
236
+ <Surface render={<a href="#render" />}>
237
+ <Surface.Header>
238
+ <Surface.Title>
239
+ <SwapHorizontal />
240
+ Routes
241
+ </Surface.Title>
242
+ </Surface.Header>
243
+ <Surface.Description>
244
+ Move stablecoins between Tempo and other networks.
245
+ </Surface.Description>
246
+ </Surface>
247
+ <Surface render={<button type="button" />}>Interactive button</Surface>
248
+ <Surface render={<a href="#render" />}>Interactive link</Surface>
249
+ </div>
250
+ )
251
+ }
252
+
253
+ namespace styles {
254
+ // Surfaces keep their content height instead of stretching to the tallest one in a row.
255
+ export const grid = style({
256
+ alignItems: 'start',
257
+ backgroundColor: 'background.primary',
258
+ display: 'grid',
259
+ gap: '12',
260
+ padding: '16',
261
+ gridTemplateColumns: 'repeat(auto-fill, minmax(14rem, 1fr)) !custom',
262
+ })
263
+ }
264
+ ```
265
+
266
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Surface/Render.tsx)
267
+
268
+ ### Disabled
269
+
270
+ Set `disabled` on a pressable surface to block interaction.
271
+
272
+ ```tsx
273
+ import { style, Surface } from '@tempoxyz/ds'
274
+
275
+ export function Demo() {
276
+ return (
277
+ <div {...styles.grid()}>
278
+ <Surface disabled render={<button type="button" />}>
279
+ Disabled button
280
+ </Surface>
281
+ </div>
282
+ )
283
+ }
284
+
285
+ namespace styles {
286
+ export const grid = style({
287
+ alignItems: 'start',
288
+ backgroundColor: 'background.primary',
289
+ display: 'grid',
290
+ padding: '16',
291
+ gridTemplateColumns: 'repeat(auto-fill, minmax(14rem, 1fr)) !custom',
292
+ })
293
+ }
294
+ ```
295
+
296
+ [View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Surface/Disabled.tsx)
297
+
298
+ ## Anatomy
299
+
300
+ Import the component and assemble its parts.
301
+
302
+ ```tsx
303
+ import { Surface } from '@tempoxyz/ds'
304
+
305
+ <Surface>
306
+ <Surface.Header>
307
+ <Surface.Title />
308
+ </Surface.Header>
309
+ <Surface.Description />
310
+ <Surface.Links />
311
+ </Surface>
312
+ ```
313
+
314
+ ## Guidelines
315
+
316
+ ### When to Use
317
+
318
+ * Group related content into a card, such as a wallet's Balance, an Activity list, or an API key's details.
319
+ * Make a whole card pressable when it leads to one place, such as a project card that opens its dashboard.
320
+
321
+ ### When Not to Use
322
+
323
+ * Use [Alert](alert.md) for a message about a section, and [Banner](banner.md) for one about the page.
324
+ * Use [Dialog](dialog.md) or [Popover](popover.md) for content that opens over the page.
325
+ * Use [Stack](stack.md) or [Inset](inset.md) to space content without a visible container.
326
+ * Use [Frame](frame.md) inside a surface for a card with a footer of actions.
327
+
328
+ ### Name Each Card
329
+
330
+ Start a card with a `Surface.Header` that holds a `Surface.Title`. Put a card-level action at the end of the header, such as a `small` `tertiary` [Button](button.md).
331
+
332
+ **Do:** Name the card with a `Surface.Title`, and put its action at the end of the header.
333
+
334
+ ```tsx
335
+ /**
336
+ * Do example for "Name Each Card" on the Surface page.
337
+ * Name the card with a `Surface.Title`, and put its action at the end of the header.
338
+ * @module
339
+ */
340
+ import { Amount, Button, ListGroup, style, Surface } from '@tempoxyz/ds'
341
+
342
+ /** Renders the static preview, which the guideline card shows inert. */
343
+ export function Demo() {
344
+ return (
345
+ <div {...styles.canvas()}>
346
+ <Surface size="medium">
347
+ <Surface.Header>
348
+ <Surface.Title>Balances</Surface.Title>
349
+ <Button size="small" variant="tertiary">
350
+ View all
351
+ </Button>
352
+ </Surface.Header>
353
+ <ListGroup dividers={false}>
354
+ <ListGroup.Row>
355
+ <ListGroup.Label>USDC</ListGroup.Label>
356
+ <Amount value="1250.00" />
357
+ </ListGroup.Row>
358
+ <ListGroup.Row>
359
+ <ListGroup.Label>pathUSD</ListGroup.Label>
360
+ <Amount value="80.25" />
361
+ </ListGroup.Row>
362
+ </ListGroup>
363
+ </Surface>
364
+ </div>
365
+ )
366
+ }
367
+
368
+ namespace styles {
369
+ export const canvas = style({
370
+ backgroundColor: 'background.primary',
371
+ borderRadius: 'sm',
372
+ boxSizing: 'border-box',
373
+ padding: '12',
374
+ width: '100% !custom',
375
+ })
376
+ }
377
+ ```
378
+
379
+ **Don't:** Start a card with its content.
380
+
381
+ ```tsx
382
+ /** Don't example for "Name Each Card" on the Surface page. Don't start a card with its content. @module */
383
+ import { Amount, ListGroup, style, Surface } from '@tempoxyz/ds'
384
+
385
+ /** Renders the static preview, which the guideline card shows inert. */
386
+ export function Demo() {
387
+ return (
388
+ <div {...styles.canvas()}>
389
+ <Surface size="medium">
390
+ <ListGroup dividers={false}>
391
+ <ListGroup.Row>
392
+ <ListGroup.Label>USDC</ListGroup.Label>
393
+ <Amount value="1250.00" />
394
+ </ListGroup.Row>
395
+ <ListGroup.Row>
396
+ <ListGroup.Label>pathUSD</ListGroup.Label>
397
+ <Amount value="80.25" />
398
+ </ListGroup.Row>
399
+ </ListGroup>
400
+ </Surface>
401
+ </div>
402
+ )
403
+ }
404
+
405
+ namespace styles {
406
+ export const canvas = style({
407
+ backgroundColor: 'background.primary',
408
+ borderRadius: 'sm',
409
+ boxSizing: 'border-box',
410
+ padding: '12',
411
+ width: '100% !custom',
412
+ })
413
+ }
414
+ ```
415
+
416
+ ### Match Size to Density
417
+
418
+ * **Large (24px):** The default, for page cards such as Balances.
419
+ * **Medium (16px):** For dashboard tiles, such as TPS.
420
+ * **Small (12px):** For compact tiles, such as Block time.
421
+
422
+ Keep one size across cards that sit side by side.
423
+
424
+ ### Keep Pressable Cards Free of Other Controls
425
+
426
+ A surface rendered as a link or button is one target, and screen readers announce the whole card as one control.
427
+
428
+ **Do:** Make the whole card one link with a short title.
429
+
430
+ ```tsx
431
+ /**
432
+ * Do example for "Keep Pressable Cards Free of Other Controls" on the Surface page.
433
+ * Make the whole card one link with a short title.
434
+ * @module
435
+ */
436
+ import { style, Surface } from '@tempoxyz/ds'
437
+
438
+ /** Renders the static preview, which the guideline card shows inert. */
439
+ export function Demo() {
440
+ return (
441
+ <div {...styles.canvas()}>
442
+ <Surface render={<a href="#" />} size="medium">
443
+ <span {...styles.title()}>Production key</span>
444
+ <span {...styles.meta()}>Created 3 days ago</span>
445
+ </Surface>
446
+ </div>
447
+ )
448
+ }
449
+
450
+ namespace styles {
451
+ export const canvas = style({
452
+ backgroundColor: 'background.primary',
453
+ borderRadius: 'sm',
454
+ padding: '16',
455
+ width: '16rem !custom',
456
+ })
457
+
458
+ export const meta = style({ color: 'content.secondary', display: 'block', typography: 'body.b3' })
459
+
460
+ export const title = style({ display: 'block', typography: 'body.b1Strong' })
461
+ }
462
+ ```
463
+
464
+ **Don't:** Place a button inside a pressable card.
465
+
466
+ ```tsx
467
+ /**
468
+ * Don't example for "Keep Pressable Cards Free of Other Controls" on the Surface page.
469
+ * Don't place a button inside a pressable card.
470
+ * @module
471
+ */
472
+ import { Button, style, Surface } from '@tempoxyz/ds'
473
+
474
+ /** Renders the static preview, which the guideline card shows inert. */
475
+ export function Demo() {
476
+ return (
477
+ <div {...styles.canvas()}>
478
+ <Surface render={<a href="#" />} size="medium">
479
+ <span {...styles.title()}>Production key</span>
480
+ <span {...styles.meta()}>Created 3 days ago</span>
481
+ <Button size="small" {...styles.action()}>
482
+ Revoke key
483
+ </Button>
484
+ </Surface>
485
+ </div>
486
+ )
487
+ }
488
+
489
+ namespace styles {
490
+ export const action = style({ marginBlockStart: '12' })
491
+
492
+ export const canvas = style({
493
+ backgroundColor: 'background.primary',
494
+ borderRadius: 'sm',
495
+ padding: '16',
496
+ width: '16rem !custom',
497
+ })
498
+
499
+ export const meta = style({ color: 'content.secondary', display: 'block', typography: 'body.b3' })
500
+
501
+ export const title = style({ display: 'block', typography: 'body.b1Strong' })
502
+ }
503
+ ```
504
+
505
+ ### Don't Nest Surfaces
506
+
507
+ Divide the content of one surface with [ListGroup](list-group.md), a [Table](table.md), or a [Separator](separator.md). A table placed directly inside a surface bleeds 12px into its padding, so its rows end 12px inside the edges of a large surface and its text stays on the content edge. The surface draws no border around it.
508
+
509
+ **Do:** Divide one surface with ListGroup.
510
+
511
+ ```tsx
512
+ /** Do example for "Don't Nest Surfaces" on the Surface page: divide one surface with ListGroup. @module */
513
+ import { Amount, Hex, ListGroup, style, Surface } from '@tempoxyz/ds'
514
+
515
+ /** Renders the static preview, which the guideline card shows inert. */
516
+ export function Demo() {
517
+ return (
518
+ <div {...styles.canvas()}>
519
+ <Surface size="medium">
520
+ <ListGroup>
521
+ <ListGroup.Row>
522
+ <ListGroup.Label>Amount</ListGroup.Label>
523
+ <Amount symbol="USDC" value="48.50" />
524
+ </ListGroup.Row>
525
+ <ListGroup.Row>
526
+ <ListGroup.Label>Recipient</ListGroup.Label>
527
+ <Hex value="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" />
528
+ </ListGroup.Row>
529
+ </ListGroup>
530
+ </Surface>
531
+ </div>
532
+ )
533
+ }
534
+
535
+ namespace styles {
536
+ export const canvas = style({
537
+ backgroundColor: 'background.primary',
538
+ borderRadius: 'sm',
539
+ boxSizing: 'border-box',
540
+ padding: '12',
541
+ width: '100% !custom',
542
+ })
543
+ }
544
+ ```
545
+
546
+ **Don't:** Place surfaces inside a surface.
547
+
548
+ ```tsx
549
+ /** Don't example for "Don't Nest Surfaces" on the Surface page. Don't place surfaces inside a surface. @module */
550
+ import { Amount, Hex, style, Surface } from '@tempoxyz/ds'
551
+
552
+ /** Renders the static preview, which the guideline card shows inert. */
553
+ export function Demo() {
554
+ return (
555
+ <div {...styles.canvas()}>
556
+ <Surface size="medium" {...styles.outer()}>
557
+ <Surface size="small" {...styles.row()}>
558
+ <span>Amount</span>
559
+ <Amount symbol="USDC" value="48.50" />
560
+ </Surface>
561
+ <Surface size="small" {...styles.row()}>
562
+ <span>Recipient</span>
563
+ <Hex value="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" />
564
+ </Surface>
565
+ </Surface>
566
+ </div>
567
+ )
568
+ }
569
+
570
+ namespace styles {
571
+ export const canvas = style({
572
+ backgroundColor: 'background.primary',
573
+ borderRadius: 'sm',
574
+ boxSizing: 'border-box',
575
+ padding: '12',
576
+ width: '100% !custom',
577
+ })
578
+
579
+ export const outer = style({ display: 'flex', flexDirection: 'column', gap: '8' })
580
+
581
+ export const row = style({
582
+ alignItems: 'center',
583
+ backgroundColor: 'container.regular',
584
+ display: 'flex',
585
+ justifyContent: 'space-between',
586
+ })
587
+ }
588
+ ```
589
+
590
+ ## Content
591
+
592
+ * Write titles as short nouns, such as Balances, Activity, or Routes.
593
+ * Keep `Surface.Description` to one or two sentences.
594
+ * Use `Surface.Links` for two or three follow-up tasks, written as verbs, such as Make a transfer.
595
+
596
+ ## Accessibility
597
+
598
+ A surface takes its semantics from the element you render, such as a `section`, a `button`, or a link.
599
+
600
+ ### Semantics
601
+
602
+ * **Default Element (div):** Carries no role.
603
+ * **Surface.Title (h2):** Lets screen reader users find the card by heading.
604
+ * **Surface.Description (p):** A plain paragraph under the title.
605
+ * **Pressable Cards (button or link):** The whole card becomes one control, named by its text.
606
+ * **Disabled (aria-disabled):** Dims the card and drops pointer events. Only a button also stops keyboard activation.
607
+
608
+ ### Keyboard
609
+
610
+ For a pressable surface rendered as a button or link:
611
+
612
+ * **Move Focus to the Card (Tab):** Moves focus to the card.
613
+ * **Activate a Link or Button (Enter):** Activates a link or button card.
614
+ * **Activate a Button (Space):** Activates a button card.
615
+
616
+ ### Your Responsibilities
617
+
618
+ * **Name Regions (aria-labelledby):** If the card is a distinct region, render a section labelled by its title.
619
+ * **Fit the Outline (h2):** Place cards where their title's heading level fits the page outline.
620
+ * **Keep Pressable Text Short:** The card's full content becomes its accessible name, so keep its text short.
621
+ * **Disabling Link Cards (href):** A link can't be disabled. Remove its `href` when it must not work.
622
+
623
+ ## Related
624
+
625
+ [Frame](frame.md)
626
+
627
+ Use for a header, body, and footer inside a card.
628
+
629
+ [ListGroup](list-group.md)
630
+
631
+ Use for divided content in a card.
632
+
633
+ [Grid](grid.md)
634
+
635
+ Use for laying out several cards.
636
+
637
+ [Dashboards](../patterns/dashboards.md)
638
+
639
+ Covers metric tiles.