altitude-design 0.3.2 → 0.4.1

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 (294) hide show
  1. package/README.md +2 -0
  2. package/dist/cli/altitude.mjs +120 -20
  3. package/dist/guidance/README.md +4 -0
  4. package/dist/guidance/agent-setup.md +3 -2
  5. package/dist/guidance/components/AILabel/README.md +60 -0
  6. package/dist/guidance/components/Accordion/README.md +32 -0
  7. package/dist/guidance/components/AgentFleet/README.md +81 -0
  8. package/dist/guidance/components/AgentLanes/README.md +53 -0
  9. package/dist/guidance/components/AgentRequests/README.md +76 -0
  10. package/dist/guidance/components/Alert/README.md +71 -0
  11. package/dist/guidance/components/AltitudeProvider/README.md +111 -0
  12. package/dist/guidance/components/AppShell/README.md +121 -0
  13. package/dist/guidance/components/AreaChart/README.md +101 -0
  14. package/dist/guidance/components/Artifact/README.md +99 -0
  15. package/dist/guidance/components/Avatar/README.md +75 -0
  16. package/dist/guidance/components/Await/README.md +128 -0
  17. package/dist/guidance/components/Badge/README.md +66 -0
  18. package/dist/guidance/components/BarChart/README.md +109 -0
  19. package/dist/guidance/components/BarList/README.md +87 -0
  20. package/dist/guidance/components/Board/README.md +98 -0
  21. package/dist/guidance/components/Breadcrumb/README.md +66 -0
  22. package/dist/guidance/components/Button/README.md +58 -0
  23. package/dist/guidance/components/Card/README.md +52 -0
  24. package/dist/guidance/components/ChartBrush/README.md +98 -0
  25. package/dist/guidance/components/ChartContainer/README.md +229 -0
  26. package/dist/guidance/components/ChartLegend/README.md +78 -0
  27. package/dist/guidance/components/ChartReference/README.md +115 -0
  28. package/dist/guidance/components/ChartTooltip/README.md +101 -0
  29. package/dist/guidance/components/Checkbox/README.md +46 -0
  30. package/dist/guidance/components/Checklist/README.md +137 -0
  31. package/dist/guidance/components/CodeBlock/README.md +72 -0
  32. package/dist/guidance/components/ColorPicker/README.md +69 -0
  33. package/dist/guidance/components/Combobox/README.md +51 -0
  34. package/dist/guidance/components/CommandPalette/README.md +204 -0
  35. package/dist/guidance/components/CommentThread/README.md +81 -0
  36. package/dist/guidance/components/Confirmation/README.md +94 -0
  37. package/dist/guidance/components/ContextMenu/README.md +81 -0
  38. package/dist/guidance/components/Conversation/README.md +169 -0
  39. package/dist/guidance/components/CopyButton/README.md +54 -0
  40. package/dist/guidance/components/DataGrid/README.md +157 -0
  41. package/dist/guidance/components/DatePicker/README.md +116 -0
  42. package/dist/guidance/components/Dialog/README.md +204 -0
  43. package/dist/guidance/components/DiffView/README.md +107 -0
  44. package/dist/guidance/components/DotPlot/README.md +82 -0
  45. package/dist/guidance/components/Drilldown/README.md +43 -0
  46. package/dist/guidance/components/DropZone/README.md +71 -0
  47. package/dist/guidance/components/DropdownMenu/README.md +63 -0
  48. package/dist/guidance/components/EditRegion/README.md +263 -0
  49. package/dist/guidance/components/EmptyState/README.md +66 -0
  50. package/dist/guidance/components/FeatureGate/README.md +67 -0
  51. package/dist/guidance/components/Field/README.md +46 -0
  52. package/dist/guidance/components/FilterBar/README.md +132 -0
  53. package/dist/guidance/components/FormattedNumber/README.md +81 -0
  54. package/dist/guidance/components/Heatmap/README.md +116 -0
  55. package/dist/guidance/components/HoldButton/README.md +48 -0
  56. package/dist/guidance/components/HoverCard/README.md +71 -0
  57. package/dist/guidance/components/InlineCitation/README.md +56 -0
  58. package/dist/guidance/components/InlineEdit/README.md +379 -0
  59. package/dist/guidance/components/Input/README.md +63 -0
  60. package/dist/guidance/components/InputOTP/README.md +76 -0
  61. package/dist/guidance/components/ItemGroup/README.md +193 -0
  62. package/dist/guidance/components/Kbd/README.md +36 -0
  63. package/dist/guidance/components/LineChart/README.md +109 -0
  64. package/dist/guidance/components/Link/README.md +69 -0
  65. package/dist/guidance/components/Markdown/README.md +113 -0
  66. package/dist/guidance/components/Meter/README.md +81 -0
  67. package/dist/guidance/components/NotificationCenter/README.md +67 -0
  68. package/dist/guidance/components/NumberInput/README.md +66 -0
  69. package/dist/guidance/components/PageHeader/README.md +74 -0
  70. package/dist/guidance/components/Pagination/README.md +58 -0
  71. package/dist/guidance/components/PasswordInput/README.md +70 -0
  72. package/dist/guidance/components/PermissionMatrix/README.md +68 -0
  73. package/dist/guidance/components/Pile/README.md +54 -0
  74. package/dist/guidance/components/PlanPicker/README.md +62 -0
  75. package/dist/guidance/components/Popover/README.md +48 -0
  76. package/dist/guidance/components/Progress/README.md +41 -0
  77. package/dist/guidance/components/PromptInput/README.md +138 -0
  78. package/dist/guidance/components/PropertyList/README.md +137 -0
  79. package/dist/guidance/components/Question/README.md +81 -0
  80. package/dist/guidance/components/RadioGroup/README.md +47 -0
  81. package/dist/guidance/components/RelativeTime/README.md +73 -0
  82. package/dist/guidance/components/RemovalReceipt/README.md +111 -0
  83. package/dist/guidance/components/Resizable/README.md +65 -0
  84. package/dist/guidance/components/SaveBar/README.md +65 -0
  85. package/dist/guidance/components/SavedViews/README.md +82 -0
  86. package/dist/guidance/components/ScatterChart/README.md +104 -0
  87. package/dist/guidance/components/Schedule/README.md +142 -0
  88. package/dist/guidance/components/ScrollArea/README.md +35 -0
  89. package/dist/guidance/components/SecretField/README.md +74 -0
  90. package/dist/guidance/components/Select/README.md +97 -0
  91. package/dist/guidance/components/Separator/README.md +70 -0
  92. package/dist/guidance/components/Sheet/README.md +126 -0
  93. package/dist/guidance/components/Skeleton/README.md +50 -0
  94. package/dist/guidance/components/Slider/README.md +60 -0
  95. package/dist/guidance/components/SortableList/README.md +45 -0
  96. package/dist/guidance/components/Sparkline/README.md +87 -0
  97. package/dist/guidance/components/SplitButton/README.md +65 -0
  98. package/dist/guidance/components/Stat/README.md +92 -0
  99. package/dist/guidance/components/Stepper/README.md +90 -0
  100. package/dist/guidance/components/Suggestions/README.md +87 -0
  101. package/dist/guidance/components/Surface/README.md +48 -0
  102. package/dist/guidance/components/Switch/README.md +38 -0
  103. package/dist/guidance/components/SyncIndicator/README.md +78 -0
  104. package/dist/guidance/components/Table/README.md +138 -0
  105. package/dist/guidance/components/Tabs/README.md +73 -0
  106. package/dist/guidance/components/TagInput/README.md +116 -0
  107. package/dist/guidance/components/Terminal/README.md +69 -0
  108. package/dist/guidance/components/ThreadList/README.md +110 -0
  109. package/dist/guidance/components/TimeInput/README.md +63 -0
  110. package/dist/guidance/components/Timeline/README.md +87 -0
  111. package/dist/guidance/components/Toaster/README.md +54 -0
  112. package/dist/guidance/components/Toggle/README.md +85 -0
  113. package/dist/guidance/components/Toolbar/README.md +106 -0
  114. package/dist/guidance/components/Tooltip/README.md +41 -0
  115. package/dist/guidance/components/Tour/README.md +73 -0
  116. package/dist/guidance/components/Trace/README.md +129 -0
  117. package/dist/guidance/components/Tree/README.md +171 -0
  118. package/dist/guidance/evidence.json +18 -0
  119. package/dist/guidance/index.json +811 -7
  120. package/dist/guidance/llms.txt +153 -2
  121. package/dist/guidance/manifest.json +133 -12
  122. package/dist/guidance/patterns/screen-layout.md +1 -1
  123. package/dist/guidance/references/build/checks/agent-setup.mjs +7 -0
  124. package/dist/guidance/references/build/checks/guidance.mjs +8 -2
  125. package/dist/guidance/references/build/checks/source-check.mjs +101 -0
  126. package/dist/guidance/rules.json +155 -0
  127. package/dist/guidance/visual/ActionsInPlace.md +463 -0
  128. package/dist/guidance/visual/Charts.md +119 -0
  129. package/dist/guidance/visual/Distinctiveness.md +106 -0
  130. package/dist/guidance/visual/Elevation.md +1 -1
  131. package/dist/guidance/visual/Mobile.md +64 -0
  132. package/dist/guidance/visual/Motion.md +225 -0
  133. package/dist/guidance/visual/README.md +98 -0
  134. package/dist/guidance/visual/Research.md +1 -1
  135. package/dist/guidance/visual/Theming.md +349 -0
  136. package/dist/types/agent-fleet.d.ts +28 -0
  137. package/dist/types/ai-label.d.ts +7 -0
  138. package/dist/types/app-shell.d.ts +23 -0
  139. package/dist/types/area-chart.d.ts +8 -0
  140. package/dist/types/artifact.d.ts +14 -0
  141. package/dist/types/bar-chart.d.ts +6 -0
  142. package/dist/types/bar-list.d.ts +6 -0
  143. package/dist/types/breadcrumb.d.ts +6 -0
  144. package/dist/types/chart-brush.d.ts +6 -0
  145. package/dist/types/chart.d.ts +29 -1
  146. package/dist/types/checklist.d.ts +6 -0
  147. package/dist/types/code-block.d.ts +6 -0
  148. package/dist/types/collections.d.ts +15 -0
  149. package/dist/types/color-picker.d.ts +6 -0
  150. package/dist/types/command.d.ts +13 -0
  151. package/dist/types/comment-thread.d.ts +11 -0
  152. package/dist/types/confirmation.d.ts +8 -0
  153. package/dist/types/context-menu.d.ts +11 -0
  154. package/dist/types/controls.d.ts +174 -10
  155. package/dist/types/conversation.d.ts +21 -0
  156. package/dist/types/copy-button.d.ts +6 -0
  157. package/dist/types/core.d.ts +31 -0
  158. package/dist/types/data-grid.d.ts +25 -0
  159. package/dist/types/date-picker.d.ts +6 -0
  160. package/dist/types/diff-view.d.ts +8 -0
  161. package/dist/types/dot-plot.d.ts +6 -0
  162. package/dist/types/edit-region.d.ts +23 -0
  163. package/dist/types/empty.d.ts +9 -0
  164. package/dist/types/feature-gate.d.ts +8 -0
  165. package/dist/types/filter-bar.d.ts +8 -0
  166. package/dist/types/formatted-number.d.ts +6 -0
  167. package/dist/types/heatmap.d.ts +6 -0
  168. package/dist/types/inline-citation.d.ts +6 -0
  169. package/dist/types/inline-edit.d.ts +7 -0
  170. package/dist/types/input-otp.d.ts +11 -0
  171. package/dist/types/item-group.d.ts +29 -0
  172. package/dist/types/line-chart.d.ts +6 -0
  173. package/dist/types/link.d.ts +8 -1
  174. package/dist/types/markdown.d.ts +6 -0
  175. package/dist/types/meter.d.ts +6 -0
  176. package/dist/types/nav.d.ts +6 -0
  177. package/dist/types/notifications.d.ts +6 -0
  178. package/dist/types/number-input.d.ts +6 -0
  179. package/dist/types/overlays.d.ts +61 -0
  180. package/dist/types/page-header.d.ts +14 -0
  181. package/dist/types/pagination.d.ts +6 -0
  182. package/dist/types/password-input.d.ts +6 -0
  183. package/dist/types/permission-matrix.d.ts +7 -0
  184. package/dist/types/pile.d.ts +6 -0
  185. package/dist/types/plan-picker.d.ts +6 -0
  186. package/dist/types/prompt-input.d.ts +11 -0
  187. package/dist/types/property-list.d.ts +17 -0
  188. package/dist/types/question.d.ts +11 -0
  189. package/dist/types/relative-time.d.ts +8 -1
  190. package/dist/types/removal-receipt.d.ts +18 -1
  191. package/dist/types/save-bar.d.ts +6 -0
  192. package/dist/types/saved-views.d.ts +12 -0
  193. package/dist/types/scatter-chart.d.ts +8 -0
  194. package/dist/types/schedule.d.ts +21 -0
  195. package/dist/types/secret-field.d.ts +6 -0
  196. package/dist/types/select.d.ts +12 -0
  197. package/dist/types/separator.d.ts +8 -1
  198. package/dist/types/sheet.d.ts +19 -0
  199. package/dist/types/sparkline.d.ts +6 -0
  200. package/dist/types/split-button.d.ts +7 -0
  201. package/dist/types/stat.d.ts +7 -0
  202. package/dist/types/stepper.d.ts +12 -0
  203. package/dist/types/suggestions.d.ts +10 -0
  204. package/dist/types/sync-indicator.d.ts +8 -0
  205. package/dist/types/tag-input.d.ts +8 -0
  206. package/dist/types/terminal.d.ts +6 -0
  207. package/dist/types/thread-list.d.ts +16 -0
  208. package/dist/types/time-input.d.ts +6 -0
  209. package/dist/types/timeline.d.ts +9 -0
  210. package/dist/types/toggle.d.ts +6 -0
  211. package/dist/types/toolbar.d.ts +20 -0
  212. package/dist/types/tour.d.ts +10 -0
  213. package/dist/types/trace.d.ts +16 -0
  214. package/dist/types/tree.d.ts +21 -0
  215. package/dist/types-cjs/agent-fleet.d.cts +28 -0
  216. package/dist/types-cjs/ai-label.d.cts +7 -0
  217. package/dist/types-cjs/app-shell.d.cts +23 -0
  218. package/dist/types-cjs/area-chart.d.cts +8 -0
  219. package/dist/types-cjs/artifact.d.cts +14 -0
  220. package/dist/types-cjs/bar-chart.d.cts +6 -0
  221. package/dist/types-cjs/bar-list.d.cts +6 -0
  222. package/dist/types-cjs/breadcrumb.d.cts +6 -0
  223. package/dist/types-cjs/chart-brush.d.cts +6 -0
  224. package/dist/types-cjs/chart.d.cts +29 -1
  225. package/dist/types-cjs/checklist.d.cts +6 -0
  226. package/dist/types-cjs/code-block.d.cts +6 -0
  227. package/dist/types-cjs/collections.d.cts +15 -0
  228. package/dist/types-cjs/color-picker.d.cts +6 -0
  229. package/dist/types-cjs/command.d.cts +13 -0
  230. package/dist/types-cjs/comment-thread.d.cts +11 -0
  231. package/dist/types-cjs/confirmation.d.cts +8 -0
  232. package/dist/types-cjs/context-menu.d.cts +11 -0
  233. package/dist/types-cjs/controls.d.cts +174 -10
  234. package/dist/types-cjs/conversation.d.cts +21 -0
  235. package/dist/types-cjs/copy-button.d.cts +6 -0
  236. package/dist/types-cjs/core.d.cts +31 -0
  237. package/dist/types-cjs/data-grid.d.cts +25 -0
  238. package/dist/types-cjs/date-picker.d.cts +6 -0
  239. package/dist/types-cjs/diff-view.d.cts +8 -0
  240. package/dist/types-cjs/dot-plot.d.cts +6 -0
  241. package/dist/types-cjs/edit-region.d.cts +23 -0
  242. package/dist/types-cjs/empty.d.cts +9 -0
  243. package/dist/types-cjs/feature-gate.d.cts +8 -0
  244. package/dist/types-cjs/filter-bar.d.cts +8 -0
  245. package/dist/types-cjs/formatted-number.d.cts +6 -0
  246. package/dist/types-cjs/heatmap.d.cts +6 -0
  247. package/dist/types-cjs/inline-citation.d.cts +6 -0
  248. package/dist/types-cjs/inline-edit.d.cts +7 -0
  249. package/dist/types-cjs/input-otp.d.cts +11 -0
  250. package/dist/types-cjs/item-group.d.cts +29 -0
  251. package/dist/types-cjs/line-chart.d.cts +6 -0
  252. package/dist/types-cjs/link.d.cts +8 -1
  253. package/dist/types-cjs/markdown.d.cts +6 -0
  254. package/dist/types-cjs/meter.d.cts +6 -0
  255. package/dist/types-cjs/nav.d.cts +6 -0
  256. package/dist/types-cjs/notifications.d.cts +6 -0
  257. package/dist/types-cjs/number-input.d.cts +6 -0
  258. package/dist/types-cjs/overlays.d.cts +61 -0
  259. package/dist/types-cjs/page-header.d.cts +14 -0
  260. package/dist/types-cjs/pagination.d.cts +6 -0
  261. package/dist/types-cjs/password-input.d.cts +6 -0
  262. package/dist/types-cjs/permission-matrix.d.cts +7 -0
  263. package/dist/types-cjs/pile.d.cts +6 -0
  264. package/dist/types-cjs/plan-picker.d.cts +6 -0
  265. package/dist/types-cjs/prompt-input.d.cts +11 -0
  266. package/dist/types-cjs/property-list.d.cts +17 -0
  267. package/dist/types-cjs/question.d.cts +11 -0
  268. package/dist/types-cjs/relative-time.d.cts +8 -1
  269. package/dist/types-cjs/removal-receipt.d.cts +18 -1
  270. package/dist/types-cjs/save-bar.d.cts +6 -0
  271. package/dist/types-cjs/saved-views.d.cts +12 -0
  272. package/dist/types-cjs/scatter-chart.d.cts +8 -0
  273. package/dist/types-cjs/schedule.d.cts +21 -0
  274. package/dist/types-cjs/secret-field.d.cts +6 -0
  275. package/dist/types-cjs/select.d.cts +12 -0
  276. package/dist/types-cjs/separator.d.cts +8 -1
  277. package/dist/types-cjs/sheet.d.cts +19 -0
  278. package/dist/types-cjs/sparkline.d.cts +6 -0
  279. package/dist/types-cjs/split-button.d.cts +7 -0
  280. package/dist/types-cjs/stat.d.cts +7 -0
  281. package/dist/types-cjs/stepper.d.cts +12 -0
  282. package/dist/types-cjs/suggestions.d.cts +10 -0
  283. package/dist/types-cjs/sync-indicator.d.cts +8 -0
  284. package/dist/types-cjs/tag-input.d.cts +8 -0
  285. package/dist/types-cjs/terminal.d.cts +6 -0
  286. package/dist/types-cjs/thread-list.d.cts +16 -0
  287. package/dist/types-cjs/time-input.d.cts +6 -0
  288. package/dist/types-cjs/timeline.d.cts +9 -0
  289. package/dist/types-cjs/toggle.d.cts +6 -0
  290. package/dist/types-cjs/toolbar.d.cts +20 -0
  291. package/dist/types-cjs/tour.d.cts +10 -0
  292. package/dist/types-cjs/trace.d.cts +16 -0
  293. package/dist/types-cjs/tree.d.cts +21 -0
  294. package/package.json +1 -1
@@ -0,0 +1,81 @@
1
+ # FormattedNumber
2
+
3
+ A number in a sentence or a table cell, formatted once: invoices, usage ("4.5 GB of 10 GB"), latency ("128 ms"), seats, error rates. `formatNumber()` gives the same text as a string, for `DataTable` columns and chart formatters.
4
+
5
+ **Elevation.** A number is the record, so it lies flush in its line, in tabular figures, at no level. When the value changes, the old figure fades out over the new one (`dur-travel-2`) and the number takes a ground-level tint that decays over `dur-settle`. That's the afterglow without the lift, because a word in a line can't rise. It never counts up, as with `Stat`: counting delays the number for decoration.
6
+
7
+ **Presets** (`format`):
8
+
9
+ | `format` | value | shows |
10
+ |---|---|---|
11
+ | `number` (default) | any | `1,250` |
12
+ | `currency` | minor units (cents) by default, as payment APIs send them | `€49.00` for `4900`. `minorUnits={false}` takes whole units. A currency with no minor unit (JPY) isn't divided. |
13
+ | `bytes` | bytes | `4.5 GB`, in the largest unit that keeps it at 1 or more; `base={1024}` gives `4.2 GiB` |
14
+ | `duration` | `unit` (default milliseconds) | `128 ms`, `1.6 min`: the largest unit that keeps it at 1 or more |
15
+ | `percent` | a fraction | `1.2%` for `0.0123` with `maximumFractionDigits={1}` |
16
+ | `compact` | any | `4.2K` |
17
+
18
+ Every other `Intl.NumberFormat` option (`maximumFractionDigits`, `signDisplay`, `currencyDisplay`, …) passes through.
19
+
20
+ **Accessibility.** It's a `<data value>` element carrying the raw value. When the text rounds or abbreviates the value (`4.2K`, `4.5 GB`), the exact value ("4,213", "4,512,000,000 bytes") is its `title`. Units whose symbols are ambiguous read aloud are spoken in words ("4.5 gigabytes", "128 milliseconds"). Changes aren't announced: put the number in a live region yourself if a change is something to hear. Under reduced motion there's no cross-fade, but the tint remains (it's colour, not travel). Under forced colours the tint is a `Highlight` outline.
21
+
22
+ **Props:** `value`; `format`; `locale`; `currency`; `minorUnits`; `unit`; `base`; any `Intl.NumberFormat` option; `title`.
23
+
24
+ **You provide:** the raw number and what it is. Format in one place, not with `toFixed` and string concatenation.
25
+
26
+ ```tsx
27
+ <FormattedNumber value={4900} format="currency" currency="EUR" /> // €49.00
28
+ <FormattedNumber value={4_512_000_000} format="bytes" /> // 4.5 GB
29
+ <FormattedNumber value={128} format="duration" /> // 128 ms
30
+ <FormattedNumber value={0.123} format="percent" maximumFractionDigits={1} /> // 12.3%
31
+ formatNumber(4213, { format: 'compact' }) // "4.2K"
32
+ ```
33
+
34
+ - Do pass amounts of money in minor units, as your payment provider sends them, or set `minorUnits={false}`.
35
+ - Do use `formatNumber` for table columns and chart formatters, so a number reads the same everywhere.
36
+ - Don't animate digits or count up to a new value.
37
+ - Don't use it for a headline figure; that's a `Stat`.
38
+
39
+ <!-- example: generated from build/previews.txt by build/previews.mjs. Edit the preview, not this section. -->
40
+ ## Example
41
+
42
+ `FormattedNumber` as first used in its preview:
43
+
44
+ ```tsx
45
+ import { FormattedNumber } from 'altitude-design';
46
+
47
+ <FormattedNumber value={4900} format="currency" currency="EUR" locale="en-IE" />
48
+ ```
49
+
50
+ The full preview, as rendered in Storybook and checked in CI (`fn`, `cap` are the preview page's own layout classes, not Altitude's):
51
+
52
+ ```tsx
53
+ import * as React from 'react';
54
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, FormattedNumber } from 'altitude-design';
55
+
56
+ const usage = [4_212_000_000, 4_512_000_000, 5_030_000_000];
57
+ export default function App() {
58
+ const [i, setI] = React.useState(0);
59
+ React.useEffect(() => { const t = setInterval(() => setI((n) => (n + 1) % usage.length), 2600); return () => clearInterval(t); }, []);
60
+ return (
61
+ <div className="fn">
62
+ <dl>
63
+ <dt>Plan</dt><dd><FormattedNumber value={4900} format="currency" currency="EUR" locale="en-IE" /> a month</dd>
64
+ <dt>Storage</dt><dd><FormattedNumber value={4_512_000_000} format="bytes" /></dd>
65
+ <dt>Latency</dt><dd><FormattedNumber value={128} format="duration" /> · <FormattedNumber value={95_000} format="duration" /></dd>
66
+ <dt>Error rate</dt><dd><FormattedNumber value={0.0123} format="percent" maximumFractionDigits={1} /></dd>
67
+ <dt>Requests</dt><dd><FormattedNumber value={4213} format="compact" /></dd>
68
+ <dt>Seats</dt><dd><FormattedNumber value={1250} /></dd>
69
+ </dl>
70
+ <Card>
71
+ <CardHeader><CardTitle>Usage</CardTitle><CardDescription>Refreshes as files are uploaded</CardDescription></CardHeader>
72
+ <CardContent>
73
+ <p>You've used <FormattedNumber value={usage[i]} format="bytes" /> of <FormattedNumber value={10_000_000_000} format="bytes" />.</p>
74
+ <p className="cap">A changed value cross-fades and settles with a tint. It never counts up. Point at "4.2K" or a byte size for its exact value.</p>
75
+ </CardContent>
76
+ </Card>
77
+ </div>
78
+ );
79
+ }
80
+ ```
81
+ <!-- /example -->
@@ -0,0 +1,116 @@
1
+ # Heatmap
2
+
3
+ A value per cell across two dimensions: load by hour and weekday, error rate by service and region, or activity by day over a year (`variant="calendar"`, as in GitHub's contributions). It renders inside a [`ChartContainer`](../ChartContainer/README.md), which gives it the frame, the readout, the keyboard path, the table view, loading and empty states.
4
+
5
+ **Why it's flat.** The cells are the record, so they lie on the plot: flat fills, parted by a 2px gap of the plot's own colour and rounded at `radius-xs` (less on small cells, so a cell stays a square). No shadow, no wall, no sheen and no gradient. Amounts are carried by the **Amounts** signal's colour channel, the sequential ramp, never by height.
6
+
7
+ **Steps, not a gradient.** Values are binned into two to seven steps (`bins={[0, 1, 4, 10]}` gives "0", "1–3", "4–9", "10+"), spread over `data-seq-1` to `data-seq-7`, so each colour is a class you can name and find in the legend. Zero is the lightest step. Without `bins`, counts get a step of their own for zero and even steps above it, and other values five to seven even steps. `scale="diverging"` uses `data-div-*` around `data-div-mid` for which side of `midpoint` (default 0) a value is on; without `bins` that's seven steps on round numbers, the middle one within a step of the midpoint.
8
+
9
+ **No data.** A cell with no record, or a `null` value, has no fill and a 1px `line` outline, and says "No data". It isn't a well: it isn't waiting for anything.
10
+
11
+ **The legend** is the steps as swatches, each with its range in words, under the cells (`legend={false}` to leave it out). Ranges say their unit once ("−0.5 to +0.5 pts").
12
+
13
+ **Layout.** In the grid, columns fill the width and rows are as tall as a column is wide, up to 34px. In the calendar, a column is a week (`weekStart` 0, Sunday, or 1, Monday), months are named above the week each begins in, and Mon, Wed and Fri down the side. The plot is as tall as its cells need. Cells are at least 10px: narrower than that, the columns wrap into bands (a year into three at 360px; 24 hours into 00–11 and 12–23), each naming its rows and columns.
14
+
15
+ **Reading a cell.** There's no crosshair in a grid, so the cell under the readout wears a 2px `ink` outline. The readout sits beside it: the place ("Tue, 14"), then the value keyed by its step's colour.
16
+
17
+ **Without colour.** Under forced colours and in print, and with `patterns` on the container, each step also gets a pattern density (none, sparse dots, dense dots, hatching, crosshatch), so the ramp survives losing its colours; a diverging scale hatches its two sides in opposite directions. The values stay in the cell's name and the table view. With `contrast="more"` every cell has a 1px `ink` edge.
18
+
19
+ **Motion.** A value change cross-fades the cell's fill over `dur-travel-1`; a whole refresh is one change, so in a `live` container it lights the "Updated" caption, not every cell. Under reduced motion it's instant.
20
+
21
+ **Accessibility.** The keyboard path is one Tab stop; Enter goes from the summary straight to the cells (there's no series level), and Escape comes back. Arrows move cell to cell and stop at the edges; Home and End go to the start and end of the row, and with Ctrl (or Cmd) the grid's; Page Up and Page Down move a month in the calendar. Each cell is named by its row, its column, its value and its step: "Tuesday, 14:00, 312 requests, step 5 of 7." (rows and columns as `yFormat` and `xFormat` write them), or in the calendar "Thursday, Nov 27, 2025, 4 commits, step 3 of 4." A diverging cell also says its side ("below 0"). The focus ring is the cell's own box. Without a written `summary`, the generated one names the highest and lowest cells, how many have no data, and the steps. The table view has a row per cell with its step.
22
+
23
+ **Props:** `data`, `value`; `x` and `y` for the grid, or `variant="calendar"` and `date`; `bins`, `scale`, `midpoint`; `xFormat` and `yFormat` for column and row names; `weekStart`; `legend`; `tooltip`.
24
+
25
+ **Selecting and drilling.** `selected` and `onSelect` make cells a selection that cross-filters the rest of a dashboard; `drill` opens a level down inside a `Drilldown`. `selected` is the record or its id: `"14|Tue"` (x, then y) for a grid, `"2026-03-14"` for a calendar. The selected cell keeps its colour, the rest recede to 35%, and the frame says "Filtered to Tue, 14". See [ChartContainer](../ChartContainer/README.md), "Marks you can select or drill into".
26
+
27
+ **Filtering in place.** `relevance={(d) => 'match' | 'miss' | undefined}` recedes misses to 35% where they stand.
28
+
29
+ **You provide:** a `ChartContainer` whose `config` names the value key (its label and format), the records, and usually a `summary`.
30
+
31
+ ```tsx
32
+ <ChartContainer config={{ count: { label: 'Commits' } }} title="Commits">
33
+ <Heatmap variant="calendar" data={commits} date="day" value="count" bins={[0, 1, 4, 10]} />
34
+ </ChartContainer>
35
+
36
+ <ChartContainer config={{ requests: { label: 'Requests' } }} title="Requests by hour">
37
+ <Heatmap data={load} x="hour" y="weekday" value="requests" />
38
+ </ChartContainer>
39
+ ```
40
+
41
+ - Do use five to seven steps; more can't be told apart, especially in small cells.
42
+ - Do give zero its own step when zero means "nothing happened".
43
+ - Do use `scale="diverging"` only when the midpoint means something (no change, a target).
44
+ - Don't use a heatmap to compare a handful of values; that's `BarChart`.
45
+ - Don't encode a second measure in cell size or a glow; it's one value per cell.
46
+
47
+ <!-- example: generated from build/previews.txt by build/previews.mjs. Edit the preview, not this section. -->
48
+ ## Example
49
+
50
+ `Heatmap` as first used in its preview:
51
+
52
+ ```tsx
53
+ import { Heatmap } from 'altitude-design';
54
+
55
+ <Heatmap variant="calendar" data={commits} date="day" value="count" bins={[0, 1, 4, 10]} />
56
+ ```
57
+
58
+ The full preview, as rendered in Storybook and checked in CI (`hm`, `wide` are the preview page's own layout classes, not Altitude's):
59
+
60
+ ```tsx
61
+ import * as React from 'react';
62
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, ChartContainer, Heatmap } from 'altitude-design';
63
+
64
+ const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
65
+ // Requests per hour: a working-day hump, quieter weekends, and a Tuesday-afternoon peak.
66
+ const load = days.flatMap((weekday, w) => Array.from({ length: 24 }, (_, hour) => {
67
+ const day = Math.max(0, Math.sin(((hour - 6) / 15) * Math.PI));
68
+ const base = (w < 5 ? 300 : 110) * day + 20 + ((hour * 7 + w * 13) % 17);
69
+ return { weekday, hour, requests: Math.round(base + (w === 1 && hour >= 13 && hour <= 15 ? 160 : 0)) };
70
+ }));
71
+ // Commits per day for a year, with quiet weekends, a holiday gap and a few busy weeks.
72
+ const start = Date.UTC(2025, 9, 27);
73
+ const commits = Array.from({ length: 365 }, (_, i) => {
74
+ const t = start + i * 864e5, wd = new Date(t).getUTCDay(), r = (i * 37 + 11) % 23;
75
+ const busy = (i > 120 && i < 140) || (i > 300 && i < 312);
76
+ const n = wd === 0 || wd === 6 ? (r < 18 ? 0 : r - 17) : i > 56 && i < 68 ? 0 : busy ? 6 + (r % 9) : r < 5 ? 0 : Math.round(r / 3);
77
+ return { day: new Date(t).toISOString().slice(0, 10), count: n };
78
+ });
79
+ const services = ['Checkout', 'Search', 'Accounts', 'Media', 'Payments'];
80
+ const regions = ['US', 'EU', 'APAC', 'LATAM'];
81
+ // Error rate against last week, in points: below zero is better.
82
+ const change = services.flatMap((service, s) => regions.map((region, r) => ({ service, region, delta: s === 3 && r === 3 ? null : Math.round((Math.sin(s * 2.1 + r * 1.3) * 1.6 + (s === 4 && r === 1 ? 1.8 : 0)) * 10) / 10 })));
83
+ const pts = (v) => (v > 0 ? '+' : v < 0 ? '−' : '') + Math.abs(v).toFixed(1) + ' pts';
84
+ export default function App() {
85
+ const [cell, setCell] = React.useState(null);
86
+ return (
87
+ <div className="hm">
88
+ <Card className="wide">
89
+ <CardHeader><CardTitle id="h1">Commits</CardTitle><CardDescription>A year, a cell per day: zero is the lightest step, and each step says its range</CardDescription></CardHeader>
90
+ <CardContent>
91
+ <ChartContainer aria-labelledby="h1" config={{ count: { label: 'Commits' } }}>
92
+ <Heatmap variant="calendar" data={commits} date="day" value="count" bins={[0, 1, 4, 10]} />
93
+ </ChartContainer>
94
+ </CardContent>
95
+ </Card>
96
+ <Card>
97
+ <CardHeader><CardTitle id="h2">Requests by hour</CardTitle><CardDescription>Load by weekday and hour, with the table view</CardDescription></CardHeader>
98
+ <CardContent>
99
+ <ChartContainer aria-labelledby="h2" views config={{ requests: { label: 'Requests' } }} xLabel="Weekday">
100
+ <Heatmap data={load} x="hour" y="weekday" value="requests" xFormat={(h) => String(h).padStart(2, '0')} />
101
+ </ChartContainer>
102
+ </CardContent>
103
+ </Card>
104
+ <Card>
105
+ <CardHeader><CardTitle id="h3">Error rate against last week</CardTitle><CardDescription>{cell ? `${cell.service} in ${cell.region}: select it again to clear` : 'scale="diverging": better below zero. Select a cell'}</CardDescription></CardHeader>
106
+ <CardContent>
107
+ <ChartContainer aria-labelledby="h3" config={{ delta: { label: 'Change', format: pts } }}>
108
+ <Heatmap data={change} x="region" y="service" value="delta" scale="diverging" selected={cell} onSelect={setCell} />
109
+ </ChartContainer>
110
+ </CardContent>
111
+ </Card>
112
+ </div>
113
+ );
114
+ }
115
+ ```
116
+ <!-- /example -->
@@ -0,0 +1,48 @@
1
+ # HoldButton
2
+
3
+ Commits a consequential action by pushing it through the ground: hold until it sinks into a trench.
4
+
5
+ At rest it's a level-2 button (danger by default). While held, it sinks steadily from its wall into a `trench` over `dur-hold`, while a fuse along its bottom edge burns across in the label colour. Let go early and it springs back on `ease-settle`. A live region says "Keep holding to confirm".
6
+
7
+ **When the hold completes, it's final.** `onConfirm` is called once, the button settles flat on the ground, shows `doneLabel` and can't be pressed again: the action is now part of the record. It stays focusable (it uses `aria-disabled`, not `disabled`) so keyboard focus isn't lost. For actions that can be repeated, set `repeatable` and the button re-arms after a moment.
8
+
9
+ **It never changes width.** Its label, `holdingLabel` and `doneLabel` are laid out in the same place and only the current one shows, so the button is as wide as the longest of them from the start and nothing beside it moves when it completes.
10
+
11
+ This is a design friction: a small, deliberate obstacle in front of an action that's hard to undo, cheaper than a confirmation dialog and harder to trigger by accident than a click.
12
+
13
+ **You provide:** the label ("Hold to delete"), `onConfirm`, optional `holdingLabel` and `doneLabel` (say what happened: "Project deleted"), `variant` (`danger` or `primary`), `duration` in ms, `repeatable`.
14
+
15
+ - Use it for destructive or irreversible actions where the person already knows what will happen.
16
+ - Don't use it when the consequence needs explaining; that's a `Dialog`.
17
+
18
+ <!-- example: generated from build/previews.txt by build/previews.mjs. Edit the preview, not this section. -->
19
+ ## Example
20
+
21
+ `HoldButton` as first used in its preview:
22
+
23
+ ```tsx
24
+ import { HoldButton } from 'altitude-design';
25
+
26
+ <HoldButton onConfirm={() => {}} holdingLabel="Keep holding…" doneLabel="Project deleted">Hold to delete</HoldButton>
27
+ ```
28
+
29
+ The full preview, as rendered in Storybook and checked in CI (`col`, `row`, `cap` are the preview page's own layout classes, not Altitude's):
30
+
31
+ ```tsx
32
+ import * as React from 'react';
33
+ import { HoldButton } from 'altitude-design';
34
+
35
+ export default function App() {
36
+ const [n, setN] = React.useState(0);
37
+ return (
38
+ <div className="col">
39
+ <div className="row">
40
+ <HoldButton onConfirm={() => {}} holdingLabel="Keep holding…" doneLabel="Project deleted">Hold to delete</HoldButton>
41
+ <HoldButton variant="primary" duration={700} repeatable onConfirm={() => setN(n + 1)} doneLabel="Published">Hold to publish</HoldButton>
42
+ </div>
43
+ <p className="cap">Press and hold (or hold Space). The button sinks below the ground as the fuse burns; let go early and it springs back. Once done it lies flat and can't be pressed again, unless it's <code>repeatable</code> (published {n}×).</p>
44
+ </div>
45
+ );
46
+ }
47
+ ```
48
+ <!-- /example -->
@@ -0,0 +1,71 @@
1
+ # HoverCard
2
+
3
+ A richer preview of what a link or a face points to: who someone is, what a project holds. It rises from its trigger after the pointer rests on it.
4
+
5
+ **Elevation.** Level 3, like Popover: `surface-floating`, `elev-3`, rising 6px from 96% scale out of its trigger. It's something you glance at, above the page and gone as soon as you move on, which is what level 3 means. Unlike a Tooltip it can hold more than a label (an avatar, a sentence, a few numbers), so it's a card with `radius-lg` and `space-4` padding.
6
+
7
+ **Timing is the design.** It opens only after the pointer has rested on the trigger for 400ms (hover intent), so passing over a paragraph of names doesn't set off a string of cards. It waits 250ms after the pointer leaves, and an invisible bridge spans the gap between trigger and card, so you can move into it. It shares Tooltip's warm-up: once a card or tooltip has shown, a neighbour opens at once instead of waiting again. Only one card is open at a time; moving to a neighbour hands over. Under reduced motion it fades without travelling.
8
+
9
+ **Keyboard and touch.** Keyboard focus on the trigger opens it after the same pause; Tab continues into any links inside it; Escape closes it and leaves focus on the trigger. On touch there's no hover, so it never opens: a tap just follows the link.
10
+
11
+ **Supplementary, always.** Nothing may live only in a HoverCard. The trigger must work on its own (the link goes to the profile; the profile has everything the card showed), because touch users never see the card and screen readers aren't told about it. In forced colours it has the floating tier's 2px border.
12
+
13
+ **On a narrow screen.** It opens where its `side` and `align` put it, then shifts sideways to stay 8px inside the screen, and it's never wider than the screen less 16px.
14
+
15
+ **You provide:** a `trigger` (a link or an avatar with its own job) and the card's content: a heading line, one or two sentences, perhaps a few numbers. Optionally `side`, `align`, `openDelay` and `closeDelay`.
16
+
17
+ - Do keep it to a glance: if people need to act on it, it's a Popover (click to open) or a page.
18
+ - Don't put the only copy of anything in it, and don't put a form in it.
19
+
20
+ <!-- example: generated from build/previews.txt by build/previews.mjs. Edit the preview, not this section. -->
21
+ ## Example
22
+
23
+ `HoverCard` as first used in its preview:
24
+
25
+ ```tsx
26
+ import { HoverCard } from 'altitude-design';
27
+
28
+ <HoverCard defaultOpen={true} trigger={<a href="#mara">Mara Quist</a>}>
29
+ <Card p={people.mara} />
30
+ </HoverCard>
31
+ ```
32
+
33
+ The full preview, as rendered in Storybook and checked in CI (`who`, `bio`, `stats`, `col`, `para`, `cap` are the preview page's own layout classes, not Altitude's):
34
+
35
+ ```tsx
36
+ import { Avatar, HoverCard } from 'altitude-design';
37
+
38
+ const people = {
39
+ mara: { name: "Mara Quist", role: "Platform \xB7 Lisbon", bio: "Owns deploys and the edge runtime. Usually reviews within the hour.", s: [42, 6, 3] },
40
+ jon: { name: "Jon Reyes", role: "Docs \xB7 Lima", bio: "Writes the release notes and keeps the changelog honest.", s: [18, 2, 5] }
41
+ };
42
+ const Card = ({ p }) => <>
43
+ <div className="who">
44
+ <Avatar name={p.name} size={40} status="active" />
45
+ <div><b>{p.name}</b><span>{p.role}</span></div>
46
+ </div>
47
+ <p className="bio">{p.bio}</p>
48
+ <div className="stats">
49
+ <span><b>{p.s[0]}</b>{" merged"}</span>
50
+ <span><b>{p.s[1]}</b>{" open"}</span>
51
+ <span><b>{p.s[2]}</b>{" projects"}</span>
52
+ </div>
53
+ </>;
54
+ export default function App() {
55
+ return <div className="col" style={{ gap: 18 }}>
56
+ <p className="para">
57
+ {"Merged by "}
58
+ <HoverCard defaultOpen={true} trigger={<a href="#mara">Mara Quist</a>}>
59
+ <Card p={people.mara} />
60
+ </HoverCard>
61
+ {" two hours ago, after review from "}
62
+ <HoverCard trigger={<a href="#jon">Jon Reyes</a>}><Card p={people.jon} /></HoverCard>
63
+ .
64
+ </p>
65
+ <p className="cap" style={{ marginTop: 160 }}>
66
+ Rest the pointer on a name; once one card has shown, the other opens at once. Focus a link with Tab to open it from the keyboard; Escape closes it.
67
+ </p>
68
+ </div>;
69
+ }
70
+ ```
71
+ <!-- /example -->
@@ -0,0 +1,56 @@
1
+ # InlineCitation
2
+
3
+ Numbered source markers in a grounded answer ("…renews monthly [2]"), with a preview of each source on hover or focus, and `Sources`, the list at the end.
4
+
5
+ **Elevation: a citation is part of the record.**
6
+ - **The marker** is a small flush plate with a mono number, raised a little off the baseline like a superscript. It's `ChartAnnotation`'s build: a flush `Badge` plate, and only one that acts lifts. It acts, so it **lifts one level when pointed at**.
7
+ - **The preview** is a `HoverCard` at level 3: "Source 2 · example.com", the title (linked), and the excerpt the answer relied on.
8
+ - **Sources** is a flush ordered list under a heading. Each entry is a marker's destination, highlighted when you arrive.
9
+ - **An unverified source** keeps its plate, adding a `caution` mark and "Unverified source" in words.
10
+
11
+ **Accessibility.** The marker is a link named "Source 2: Billing FAQ", never "[2]". Tab reaches it, the preview opens on focus as well as hover, and Enter follows it (to its entry in Sources by default, or your `href`). Under forced colours the plate has a `LinkText` border. Under `contrast="more"` its border is `line-control`.
12
+
13
+ **Props:** `InlineCitation`: `index`, `source` (`{ title, url?, excerpt?, unverified? }`), `href`, `idPrefix`. `Sources`: `items`, `heading`, `idPrefix`.
14
+
15
+ **You provide:** the sources, numbered in the order the answer cites them. When there are several answers on a page, give each its own `idPrefix`.
16
+
17
+ ```tsx
18
+ <p>Plans renew monthly <InlineCitation index={2} source={{ title: 'Billing FAQ', url, excerpt }} />.</p>
19
+ <Sources items={sources} />
20
+ ```
21
+
22
+ - Do include the excerpt the answer relied on.
23
+ - Do mark sources you couldn't verify.
24
+ - Don't render citations as bare numbers or superscripts with no name.
25
+
26
+ <!-- example: generated from build/previews.txt by build/previews.mjs. Edit the preview, not this section. -->
27
+ ## Example
28
+
29
+ `InlineCitation` as first used in its preview:
30
+
31
+ ```tsx
32
+ import { InlineCitation } from 'altitude-design';
33
+
34
+ <InlineCitation index={1} source={sources[0]} />
35
+ ```
36
+
37
+ The full preview, as rendered in Storybook and checked in CI (`ic` is the preview page's own layout class, not Altitude's):
38
+
39
+ ```tsx
40
+ import { InlineCitation, Sources } from 'altitude-design';
41
+
42
+ const sources = [
43
+ { title: 'Billing FAQ', url: 'https://help.example.com/billing/faq', excerpt: 'Annual plans can be refunded in full within 30 days of purchase.' },
44
+ { title: 'Plans and pricing', url: 'https://example.com/pricing', excerpt: 'Monthly plans renew on the same day each month.' },
45
+ { title: 'Forum post: “Refunds after 30 days?”', url: 'https://community.example.com/t/4821', unverified: true },
46
+ ];
47
+ export default function App() {
48
+ return (
49
+ <div className="ic">
50
+ <p>Annual plans can be refunded in full within 30 days<InlineCitation index={1} source={sources[0]} />. Monthly plans renew on the same day each month<InlineCitation index={2} source={sources[1]} />, and some customers report partial refunds after that<InlineCitation index={3} source={sources[2]} />.</p>
51
+ <Sources items={sources} />
52
+ </div>
53
+ );
54
+ }
55
+ ```
56
+ <!-- /example -->