@cognite/aura 0.2.0 → 0.3.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 (239) hide show
  1. package/DESIGN.md +869 -870
  2. package/README.md +143 -9
  3. package/dist/colors.css +30 -0
  4. package/dist/components/index.d.ts +7 -36
  5. package/dist/components/index.js +319 -350
  6. package/dist/components/ui/core/accordion/accordion.d.ts +7 -7
  7. package/dist/components/ui/core/accordion/accordion.js +49 -47
  8. package/dist/components/ui/core/action-toolbar/action-toolbar.d.ts +41 -0
  9. package/dist/components/ui/core/action-toolbar/action-toolbar.js +176 -0
  10. package/dist/components/ui/core/alert/alert.d.ts +23 -12
  11. package/dist/components/ui/core/alert/alert.js +123 -120
  12. package/dist/components/ui/core/avatar/avatar.d.ts +12 -8
  13. package/dist/components/ui/core/badge/badge.d.ts +11 -8
  14. package/dist/components/ui/core/banner/banner.d.ts +18 -28
  15. package/dist/components/ui/core/breadcrumb/breadcrumb.d.ts +10 -9
  16. package/dist/components/ui/core/breadcrumb/breadcrumb.js +98 -88
  17. package/dist/components/ui/core/button/button.d.ts +8 -5
  18. package/dist/components/ui/core/button/button.js +22 -19
  19. package/dist/components/ui/core/button-group/button-group.d.ts +7 -6
  20. package/dist/components/ui/core/card/card.d.ts +17 -16
  21. package/dist/components/ui/core/chart/chart.d.ts +69 -0
  22. package/dist/components/ui/core/chart/chart.js +215 -0
  23. package/dist/components/ui/core/chart/index.d.ts +2 -0
  24. package/dist/components/ui/core/chart/index.js +8 -0
  25. package/dist/components/ui/core/checkbox/checkbox.d.ts +13 -9
  26. package/dist/components/ui/core/checkbox/checkbox.js +32 -28
  27. package/dist/components/ui/core/code-block/code-block.d.ts +6 -9
  28. package/dist/components/ui/core/code-block/code-block.js +48 -44
  29. package/dist/components/ui/core/collapsible/collapsible.d.ts +5 -3
  30. package/dist/components/ui/core/combobox/combobox.d.ts +2 -2
  31. package/dist/components/ui/core/command/command.d.ts +11 -78
  32. package/dist/components/ui/core/command/command.js +53 -52
  33. package/dist/components/ui/core/count/count.d.ts +7 -6
  34. package/dist/components/ui/core/date-time-pickers/date-picker/date-picker.d.ts +15 -0
  35. package/dist/components/ui/core/date-time-pickers/date-picker/date-picker.js +84 -0
  36. package/dist/components/ui/core/date-time-pickers/date-picker/index.d.ts +3 -0
  37. package/dist/components/ui/core/date-time-pickers/date-picker/types.d.ts +18 -0
  38. package/dist/components/ui/core/date-time-pickers/date-picker/use-date-picker.d.ts +3 -0
  39. package/dist/components/ui/core/date-time-pickers/date-picker/use-date-picker.js +63 -0
  40. package/dist/components/ui/core/date-time-pickers/date-range-picker/date-range-picker.d.ts +15 -0
  41. package/dist/components/ui/core/date-time-pickers/date-range-picker/date-range-picker.js +99 -0
  42. package/dist/components/ui/core/date-time-pickers/date-range-picker/index.d.ts +3 -0
  43. package/dist/components/ui/core/date-time-pickers/date-range-picker/types.d.ts +25 -0
  44. package/dist/components/ui/core/date-time-pickers/date-range-picker/use-date-range-picker.d.ts +4 -0
  45. package/dist/components/ui/core/date-time-pickers/date-range-picker/use-date-range-picker.js +82 -0
  46. package/dist/components/ui/core/date-time-pickers/date-time-range-picker/date-time-range-picker.d.ts +17 -0
  47. package/dist/components/ui/core/date-time-pickers/date-time-range-picker/date-time-range-picker.js +190 -0
  48. package/dist/components/ui/core/date-time-pickers/date-time-range-picker/index.d.ts +3 -0
  49. package/dist/components/ui/core/date-time-pickers/date-time-range-picker/types.d.ts +42 -0
  50. package/dist/components/ui/core/date-time-pickers/date-time-range-picker/use-date-time-range-picker.d.ts +3 -0
  51. package/dist/components/ui/core/date-time-pickers/date-time-range-picker/use-date-time-range-picker.js +161 -0
  52. package/dist/components/ui/core/date-time-pickers/index.d.ts +8 -0
  53. package/dist/components/ui/core/date-time-pickers/index.js +8 -0
  54. package/dist/components/ui/core/date-time-pickers/shared/am-pm-scroll/am-pm-scroll.d.ts +7 -0
  55. package/dist/components/ui/core/date-time-pickers/shared/am-pm-scroll/am-pm-scroll.js +57 -0
  56. package/dist/components/ui/core/date-time-pickers/shared/calendar/calendar.d.ts +13 -0
  57. package/dist/components/ui/core/date-time-pickers/shared/calendar/calendar.js +119 -0
  58. package/dist/components/ui/core/date-time-pickers/shared/calendar-header/calendar-header.d.ts +10 -0
  59. package/dist/components/ui/core/date-time-pickers/shared/calendar-header/calendar-header.js +93 -0
  60. package/dist/components/ui/core/date-time-pickers/shared/constants.d.ts +20 -0
  61. package/dist/components/ui/core/date-time-pickers/shared/constants.js +14 -0
  62. package/dist/components/ui/core/date-time-pickers/shared/date-time-input/date-time-input.d.ts +19 -0
  63. package/dist/components/ui/core/date-time-pickers/shared/date-time-input/date-time-input.js +99 -0
  64. package/dist/components/ui/core/date-time-pickers/shared/date-time-input/range-input-display.d.ts +12 -0
  65. package/dist/components/ui/core/date-time-pickers/shared/date-time-input/range-input-display.js +68 -0
  66. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-popover-state.d.ts +12 -0
  67. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-popover-state.js +40 -0
  68. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-range-date-state.d.ts +29 -0
  69. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-range-date-state.js +63 -0
  70. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-range-step-manager.d.ts +8 -0
  71. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-range-step-manager.js +19 -0
  72. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-single-date-state.d.ts +23 -0
  73. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-single-date-state.js +32 -0
  74. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-time-state.d.ts +17 -0
  75. package/dist/components/ui/core/date-time-pickers/shared/hooks/use-time-state.js +34 -0
  76. package/dist/components/ui/core/date-time-pickers/shared/scroll-cell-classes.d.ts +8 -0
  77. package/dist/components/ui/core/date-time-pickers/shared/scroll-cell-classes.js +7 -0
  78. package/dist/components/ui/core/date-time-pickers/shared/shortcuts-panel/shortcuts-panel.d.ts +13 -0
  79. package/dist/components/ui/core/date-time-pickers/shared/shortcuts-panel/shortcuts-panel.js +31 -0
  80. package/dist/components/ui/core/date-time-pickers/shared/time-picker-scroll/time-picker-scroll.d.ts +10 -0
  81. package/dist/components/ui/core/date-time-pickers/shared/time-picker-scroll/time-picker-scroll.js +52 -0
  82. package/dist/components/ui/core/date-time-pickers/utils/calendar-utils.d.ts +48 -0
  83. package/dist/components/ui/core/date-time-pickers/utils/calendar-utils.js +52 -0
  84. package/dist/components/ui/core/date-time-pickers/utils/date-range-utils.d.ts +26 -0
  85. package/dist/components/ui/core/date-time-pickers/utils/format-utils.d.ts +37 -0
  86. package/dist/components/ui/core/date-time-pickers/utils/segment-utils.d.ts +34 -0
  87. package/dist/components/ui/core/date-time-pickers/utils/time-utils.d.ts +43 -0
  88. package/dist/components/ui/core/date-time-pickers/utils/time-utils.js +15 -0
  89. package/dist/components/ui/core/date-time-pickers/utils/time-validation.d.ts +23 -0
  90. package/dist/components/ui/core/dialog/dialog.d.ts +10 -10
  91. package/dist/components/ui/core/dialog/dialog.js +12 -3
  92. package/dist/components/ui/core/dropdown-menu/dropdown-menu.d.ts +24 -47
  93. package/dist/components/ui/core/dropdown-menu/dropdown-menu.js +125 -123
  94. package/dist/components/ui/core/empty-state/empty-state.context.d.ts +10 -0
  95. package/dist/components/ui/core/empty-state/empty-state.context.js +8 -0
  96. package/dist/components/ui/core/empty-state/empty-state.d.ts +18 -0
  97. package/dist/components/ui/core/empty-state/empty-state.js +139 -0
  98. package/dist/components/ui/core/helper-text/helper-text.d.ts +7 -5
  99. package/dist/components/ui/core/hover-card/hover-card.d.ts +5 -7
  100. package/dist/components/ui/core/hover-card/hover-card.js +23 -22
  101. package/dist/components/ui/core/inline-citation/inline-citation.d.ts +10 -10
  102. package/dist/components/ui/core/inline-citation/inline-citation.js +57 -49
  103. package/dist/components/ui/core/input/input.d.ts +2 -1
  104. package/dist/components/ui/core/input/input.js +1 -1
  105. package/dist/components/ui/core/input-group/input-group.d.ts +17 -13
  106. package/dist/components/ui/core/input-group/input-group.js +35 -36
  107. package/dist/components/ui/core/kbd/kbd.d.ts +3 -2
  108. package/dist/components/ui/core/label/label.d.ts +3 -2
  109. package/dist/components/ui/core/loader/loader.d.ts +2 -2
  110. package/dist/components/ui/core/message/message.d.ts +18 -17
  111. package/dist/components/ui/core/message/message.js +387 -99
  112. package/dist/components/ui/core/pagination/pagination-size-context.d.ts +5 -0
  113. package/dist/components/ui/core/pagination/pagination-size-context.js +6 -0
  114. package/dist/components/ui/core/pagination/pagination-teleport.d.ts +11 -0
  115. package/dist/components/ui/core/pagination/pagination-teleport.js +108 -0
  116. package/dist/components/ui/core/pagination/pagination-teleport.utils.d.ts +1 -0
  117. package/dist/components/ui/core/pagination/pagination-teleport.utils.js +7 -0
  118. package/dist/components/ui/core/pagination/pagination.d.ts +41 -0
  119. package/dist/components/ui/core/pagination/pagination.js +337 -0
  120. package/dist/components/ui/core/popover/popover.d.ts +12 -16
  121. package/dist/components/ui/core/popover/popover.js +52 -51
  122. package/dist/components/ui/core/progress/progress.d.ts +7 -4
  123. package/dist/components/ui/core/prompt-input/prompt-input.d.ts +36 -103
  124. package/dist/components/ui/core/prompt-input/prompt-input.js +180 -167
  125. package/dist/components/ui/core/radio-group/radio-group.d.ts +12 -8
  126. package/dist/components/ui/core/radio-group/radio-group.js +56 -53
  127. package/dist/components/ui/core/reasoning/reasoning.d.ts +5 -5
  128. package/dist/components/ui/core/scroll-area/scroll-area.d.ts +4 -2
  129. package/dist/components/ui/core/search/search.d.ts +10 -0
  130. package/dist/components/ui/core/search/search.js +99 -0
  131. package/dist/components/ui/core/segmented-control/segmented-control.d.ts +15 -11
  132. package/dist/components/ui/core/segmented-control/segmented-control.js +4 -1
  133. package/dist/components/ui/core/select/select.d.ts +15 -14
  134. package/dist/components/ui/core/select/select.js +135 -108
  135. package/dist/components/ui/core/separator/separator.d.ts +2 -4
  136. package/dist/components/ui/core/separator/separator.js +4 -5
  137. package/dist/components/ui/core/shimmer/shimmer.d.ts +5 -5
  138. package/dist/components/ui/core/shimmer/shimmer.js +91 -52
  139. package/dist/components/ui/core/skeleton/skeleton.d.ts +2 -1
  140. package/dist/components/ui/core/sonner-toast/sonner-toast.d.ts +2 -1
  141. package/dist/components/ui/core/sources/sources.d.ts +3 -3
  142. package/dist/components/ui/core/sources/sources.js +6 -1
  143. package/dist/components/ui/core/switch/switch.d.ts +11 -0
  144. package/dist/components/ui/core/{button/button.metadata.d.ts → switch/switch.metadata.d.ts} +1 -1
  145. package/dist/components/ui/core/tabs/tabs.d.ts +21 -17
  146. package/dist/components/ui/core/tabs/tabs.js +11 -9
  147. package/dist/components/ui/core/textarea/textarea.d.ts +2 -1
  148. package/dist/components/ui/core/textarea/textarea.js +20 -18
  149. package/dist/components/ui/core/toggle/toggle.d.ts +15 -0
  150. package/dist/components/ui/core/toggle/toggle.js +74 -0
  151. package/dist/components/ui/core/tool/tool.d.ts +7 -6
  152. package/dist/components/ui/core/tool/tool.js +47 -43
  153. package/dist/components/ui/core/tooltip/tooltip.d.ts +6 -5
  154. package/dist/components/ui/core/tooltip/tooltip.js +10 -8
  155. package/dist/components/ui/core/topbar/topbar.d.ts +11 -13
  156. package/dist/eslint/index.d.ts +2 -1
  157. package/dist/index.d.ts +1 -1
  158. package/dist/lib/portal-container-context.d.ts +2 -1
  159. package/dist/lib/portal-container-context.js +3 -5
  160. package/dist/lib/utils.d.ts +1 -1
  161. package/dist/lib/utils.js +7 -7
  162. package/dist/styles.css +1 -1
  163. package/dist/styles.source.css +12 -1
  164. package/package.json +217 -14
  165. package/dist/components/ui/core/accordion/accordion.metadata.d.ts +0 -2
  166. package/dist/components/ui/core/accordion/accordion.metadata.js +0 -9
  167. package/dist/components/ui/core/alert/alert.metadata.d.ts +0 -2
  168. package/dist/components/ui/core/alert/alert.metadata.js +0 -9
  169. package/dist/components/ui/core/avatar/avatar.metadata.d.ts +0 -8
  170. package/dist/components/ui/core/avatar/avatar.metadata.js +0 -9
  171. package/dist/components/ui/core/badge/badge.metadata.d.ts +0 -2
  172. package/dist/components/ui/core/badge/badge.metadata.js +0 -8
  173. package/dist/components/ui/core/banner/banner.metadata.d.ts +0 -2
  174. package/dist/components/ui/core/banner/banner.metadata.js +0 -9
  175. package/dist/components/ui/core/breadcrumb/breadcrumb.metadata.d.ts +0 -2
  176. package/dist/components/ui/core/breadcrumb/breadcrumb.metadata.js +0 -9
  177. package/dist/components/ui/core/button/button.metadata.js +0 -9
  178. package/dist/components/ui/core/button-group/button-group.metadata.d.ts +0 -2
  179. package/dist/components/ui/core/button-group/button-group.metadata.js +0 -8
  180. package/dist/components/ui/core/card/card.metadata.d.ts +0 -8
  181. package/dist/components/ui/core/card/card.metadata.js +0 -9
  182. package/dist/components/ui/core/code-block/code-block.metadata.d.ts +0 -2
  183. package/dist/components/ui/core/code-block/code-block.metadata.js +0 -8
  184. package/dist/components/ui/core/collapsible/collapsible.metadata.d.ts +0 -2
  185. package/dist/components/ui/core/collapsible/collapsible.metadata.js +0 -9
  186. package/dist/components/ui/core/combobox/combobox.metadata.d.ts +0 -2
  187. package/dist/components/ui/core/command/command.metadata.d.ts +0 -2
  188. package/dist/components/ui/core/command/command.metadata.js +0 -9
  189. package/dist/components/ui/core/dialog/dialog.metadata.d.ts +0 -2
  190. package/dist/components/ui/core/dialog/dialog.metadata.js +0 -9
  191. package/dist/components/ui/core/dropdown-menu/dropdown-menu.metadata.d.ts +0 -2
  192. package/dist/components/ui/core/dropdown-menu/dropdown-menu.metadata.js +0 -9
  193. package/dist/components/ui/core/helper-text/helper-text.metadata.d.ts +0 -2
  194. package/dist/components/ui/core/helper-text/helper-text.metadata.js +0 -9
  195. package/dist/components/ui/core/hover-card/hover-card.metadata.d.ts +0 -2
  196. package/dist/components/ui/core/hover-card/hover-card.metadata.js +0 -8
  197. package/dist/components/ui/core/inline-citation/inline-citation.metadata.d.ts +0 -2
  198. package/dist/components/ui/core/inline-citation/inline-citation.metadata.js +0 -8
  199. package/dist/components/ui/core/input/input.metadata.d.ts +0 -2
  200. package/dist/components/ui/core/input/input.metadata.js +0 -9
  201. package/dist/components/ui/core/input-group/input-group.metadata.d.ts +0 -2
  202. package/dist/components/ui/core/input-group/input-group.metadata.js +0 -9
  203. package/dist/components/ui/core/kbd/kbd.metadata.d.ts +0 -2
  204. package/dist/components/ui/core/kbd/kbd.metadata.js +0 -9
  205. package/dist/components/ui/core/label/label.metadata.d.ts +0 -2
  206. package/dist/components/ui/core/label/label.metadata.js +0 -9
  207. package/dist/components/ui/core/loader/loader.metadata.d.ts +0 -2
  208. package/dist/components/ui/core/loader/loader.metadata.js +0 -9
  209. package/dist/components/ui/core/message/message.metadata.d.ts +0 -2
  210. package/dist/components/ui/core/popover/popover.metadata.d.ts +0 -2
  211. package/dist/components/ui/core/popover/popover.metadata.js +0 -9
  212. package/dist/components/ui/core/progress/progress.metadata.d.ts +0 -2
  213. package/dist/components/ui/core/progress/progress.metadata.js +0 -9
  214. package/dist/components/ui/core/prompt-input/prompt-input.metadata.d.ts +0 -2
  215. package/dist/components/ui/core/prompt-input/prompt-input.metadata.js +0 -9
  216. package/dist/components/ui/core/radio-group/radio-group.metadata.d.ts +0 -2
  217. package/dist/components/ui/core/radio-group/radio-group.metadata.js +0 -9
  218. package/dist/components/ui/core/reasoning/reasoning.metadata.d.ts +0 -2
  219. package/dist/components/ui/core/reasoning/reasoning.metadata.js +0 -8
  220. package/dist/components/ui/core/scroll-area/scroll-area.metadata.d.ts +0 -2
  221. package/dist/components/ui/core/scroll-area/scroll-area.metadata.js +0 -9
  222. package/dist/components/ui/core/select/select.metadata.d.ts +0 -2
  223. package/dist/components/ui/core/select/select.metadata.js +0 -9
  224. package/dist/components/ui/core/separator/separator.metadata.d.ts +0 -2
  225. package/dist/components/ui/core/separator/separator.metadata.js +0 -8
  226. package/dist/components/ui/core/shimmer/shimmer.metadata.d.ts +0 -2
  227. package/dist/components/ui/core/shimmer/shimmer.metadata.js +0 -9
  228. package/dist/components/ui/core/skeleton/skeleton.metadata.d.ts +0 -2
  229. package/dist/components/ui/core/skeleton/skeleton.metadata.js +0 -9
  230. package/dist/components/ui/core/sonner-toast/sonner-toast.metadata.d.ts +0 -2
  231. package/dist/components/ui/core/sonner-toast/sonner-toast.metadata.js +0 -9
  232. package/dist/components/ui/core/sources/sources.metadata.d.ts +0 -2
  233. package/dist/components/ui/core/textarea/textarea.metadata.d.ts +0 -2
  234. package/dist/components/ui/core/textarea/textarea.metadata.js +0 -9
  235. package/dist/components/ui/core/tool/tool.metadata.d.ts +0 -2
  236. package/dist/components/ui/core/tool/tool.metadata.js +0 -8
  237. package/dist/components/ui/core/tooltip/tooltip.metadata.d.ts +0 -8
  238. package/dist/components/ui/core/tooltip/tooltip.metadata.js +0 -9
  239. package/dist/index.js +0 -342
package/DESIGN.md CHANGED
@@ -1,742 +1,575 @@
1
- ## Overview
2
-
3
- Aura is the design system for Cognite Data Fusion experiences: composable UI primitives (buttons, inputs, overlays, AI/chat surfaces), Tailwind v4 theme extensions, and **Base**, **Decorative**, and **Semantic** tokens. Interfaces should feel **clear, layered without clutter, and trustworthy** — mountain neutrals for structure, fjord for links and focus, and restrained decorative ramps for accents, charts, and status.
4
-
5
- **What belongs in this file:** identity, token *names*, *roles*, and *resolved reference values* so humans and agents choose the right variable or Tailwind color/shadow/radius utility; **[Content](#content)** for UI copy (action labels, dates, grammar, localization, voice, accessible writing). **How** to wire themes, run Figma sync, or verify in CI belongs in Aura engineering / agent skills, not here.
6
-
7
- **Where the CSS sources live**
8
-
9
- The canonical token files (`colors.css`, `styles.source.css`) live in the Aura library repo under `src/`. In a consuming app they are available through the published package — import from `@cognite/aura/colors.css` and `@cognite/aura/styles.css`. Do not look for `src/colors.css` next to your app code; resolve token names via your IDE's autocomplete on `@cognite/aura`, or consult the tables in [Tokens](#tokens) below.
10
-
11
- **Code:** In Fusion / host apps (example convention), ship UI from Aura exports (`@cognite/aura/components`, [Storybook](https://storybook-aura-23638.fusion-preview.preview.cogniteapp.com)) under e.g. `src/components/ui`; prefer **CVA** variants. **[Interaction states](#interaction-states)**, **[Heuristics](#heuristics)**, and **[Content](#content)** define how to use primitives — prefer component APIs over reimplementing or overriding internals when a variant already matches intent. **Prop names, `size` values, and subcomponents** are **not** duplicated here; use [Storybook](https://storybook-aura-23638.fusion-preview.preview.cogniteapp.com), the [Aura design system documentation](https://docs.cognite.com/aura-design-system/get-started) (foundations, primitives, installation), and TypeScript types from `@cognite/aura/components` as the source of truth. For color in product UI, use tokens — not raw `hex` / `rgb` / `hsl` when a semantic or base token exists; details under **[Tokens](#tokens)**.
12
-
13
- ## Dashboard quick start (agent checklist)
14
-
15
- For pages with data-heavy layouts — cards, charts, metric tiles — work through these steps before writing component code.
16
-
17
- - [ ] **Tokens** — confirm all colors use semantic or chart tokens, no raw hex. Metric tiles: `decorative-*`. Data series: `chart-*`. Status: `info-*`, `success-*`, `warning-*`, `destructive-*`. See [Tokens → Color](#color).
18
- - [ ] **Layout** — use a 12-column grid with `gap-4` or `gap-6`. Tile widths: `col-span-12 sm:col-span-6 lg:col-span-3`. Cap the page frame with `max-w-[min(100%,var(--container-8xl))]`.
19
- - [ ] **Cards** — use the `Card` component with title, description, and a primary action. Do not stack unrelated actions in the same card. See [Heuristics §6.1](#61-grouping-and-proximity).
20
- - [ ] **Loading states** — every data region must show `Shimmer` (known layout) or `Loader` (unknown layout) while fetching. See [Heuristics §1.1](#11-loading-states).
21
- - [ ] **Status signals** — default to **Badge** or compact status cards for repeated states; keep **Alert** to one page-level inline instance unless multiple independent incidents each need separate action. See [Alert vs Banner vs Badge vs Sonner](#alert-vs-banner-vs-badge-vs-sonner).
22
- - [ ] **Navigation** — one Topbar, no sidebar. Chart sub-navigation lives in the content area. See [Heuristics §3.3](#33-contextual-menus-and-secondary-actions).
23
- - [ ] **Accessibility** — every chart must have a text summary of key insights. Icon-only controls must have `aria-label` and a `Tooltip`. See [Heuristics §7](#7-accessibility-and-inclusive-design).
24
-
25
1
  ---
26
-
27
- ## Heuristics
28
-
29
- **What this section is:** Interaction-quality, disclosure, error, power-user, layout, and accessibility heuristics for **Aura-based** UIs. **Severity:** **Must** / **must not** — breaks usability, a11y, or system conformance; **Should** — strong default, deviate only with intent; **Avoid** — known failure mode. Component **names** and composition patterns are specified here; **props and enums** live in Storybook and package types (see **Overview**).
30
-
31
- **Who:** Designers reviewing UI, engineers implementing features, agents generating or auditing code.
32
-
33
- **Scope — two layers**
34
-
35
- - **`@cognite/aura`:** primitives exported from this library ([Storybook](https://storybook-aura-23638.fusion-preview.preview.cogniteapp.com)). **Components:** lines below name Aura exports where they exist.
36
- - **Fusion / app shell:** patterns such as global **Topbar**, **Sonner** toasts, **AlertDialog**, **Sheet** / **Drawer**, **Tabs**, **SegmentedControl**, **Checkbox** / **Radio** / **Switch**, **ContextMenu**, or **EmptyState** may live **outside** this package — **Must** still follow the same **Tokens**, **Interaction states**, and severity rules using your shell’s components or Radix-style primitives themed with Aura.
37
- - **Minimal or standalone apps** (no Fusion shell): apply the **same tokens** and **interaction rules** with Aura primitives and your stack’s equivalents. **Must** rules that name shell-only components (**Topbar**, **Sonner**, **AlertDialog**, **Sheet**, …) apply **when that capability exists** — treat them as **Should** / **when available** and substitute with the closest Aura or Radix pattern; wire **TooltipProvider** (or your tooltip root) at app root wherever **Tooltip** is used. Do not invent a fake shell just to satisfy a checklist.
38
-
2
+ version: alpha
3
+ name: Aura
4
+ description: Cognite's design system for composable UI primitives in data-heavy industrial software.
5
+ colors:
6
+ primary: '#212426'
7
+ secondary: '#E4E6E8'
8
+ tertiary: '#486AED'
9
+ neutral: '#F1F2F3'
10
+ background: '#FFFFFF'
11
+ foreground: '#191B1D'
12
+ alternate-background: '#F9FAFA'
13
+ card-background: '#F9FAFA'
14
+ muted-background: '#F1F2F3'
15
+ muted-foreground: '#6D767E'
16
+ primary-background-hover: '#40464A'
17
+ secondary-background-hover: '#D4D7D9'
18
+ foreground-on-primary: '#F1F2F3'
19
+ secondary-foreground: '#40464A'
20
+ link-foreground: '#486AED'
21
+ border: '#E4E6E8'
22
+ border-emphasized: '#D4D7D9'
23
+ ring: '#7081C7'
24
+ ring-muted: '#B5BEE2'
25
+ info-background: '#D0D6ED'
26
+ info-foreground-on-info: '#32417F'
27
+ success-background: '#BBF3D0'
28
+ success-foreground-on-success: '#0F5026'
29
+ warning-background: '#FFE3A2'
30
+ warning-foreground-on-warning: '#755200'
31
+ destructive-background: '#FCCAD2'
32
+ destructive-foreground-on-critical: '#8D081F'
33
+ overlay-background: '#7C868E80'
34
+ typography:
35
+ display:
36
+ fontFamily: Space Grotesk
37
+ fontSize: 36px
38
+ fontWeight: 600
39
+ lineHeight: 44px
40
+ letterSpacing: -0.08px
41
+ h1:
42
+ fontFamily: Inter
43
+ fontSize: 32px
44
+ fontWeight: 600
45
+ lineHeight: 40px
46
+ letterSpacing: -0.08px
47
+ h2:
48
+ fontFamily: Inter
49
+ fontSize: 28px
50
+ fontWeight: 600
51
+ lineHeight: 32px
52
+ letterSpacing: -0.08px
53
+ h3:
54
+ fontFamily: Inter
55
+ fontSize: 24px
56
+ fontWeight: 600
57
+ lineHeight: 28px
58
+ letterSpacing: -0.04px
59
+ h4:
60
+ fontFamily: Inter
61
+ fontSize: 20px
62
+ fontWeight: 500
63
+ lineHeight: 24px
64
+ letterSpacing: -0.04px
65
+ body-md:
66
+ fontFamily: Inter
67
+ fontSize: 16px
68
+ fontWeight: 400
69
+ lineHeight: 20px
70
+ letterSpacing: -0.04px
71
+ body-sm:
72
+ fontFamily: Inter
73
+ fontSize: 14px
74
+ fontWeight: 400
75
+ lineHeight: 18px
76
+ letterSpacing: -0.04px
77
+ label:
78
+ fontFamily: Inter
79
+ fontSize: 12px
80
+ fontWeight: 500
81
+ lineHeight: 14px
82
+ letterSpacing: -0.04px
83
+ code:
84
+ fontFamily: Source Code Pro
85
+ fontSize: 14px
86
+ fontWeight: 400
87
+ lineHeight: 20px
88
+ rounded:
89
+ none: 0px
90
+ xs: 2px
91
+ sm: 4px
92
+ md: 6px
93
+ lg: 8px
94
+ xl: 12px
95
+ 2xl: 16px
96
+ 3xl: 24px
97
+ 4xl: 32px
98
+ full: 9999px
99
+ spacing:
100
+ base: 4px
101
+ xs: 4px
102
+ sm: 8px
103
+ md: 12px
104
+ lg: 16px
105
+ xl: 20px
106
+ 2xl: 24px
107
+ 3xl: 32px
108
+ prose-max: 600px
109
+ container-2xl: 640px
110
+ container-8xl: 1536px
111
+ components:
112
+ button-primary:
113
+ backgroundColor: '{colors.primary}'
114
+ textColor: '{colors.foreground-on-primary}'
115
+ rounded: '{rounded.lg}'
116
+ padding: '{spacing.md}'
117
+ height: 36px
118
+ button-primary-hover:
119
+ backgroundColor: '{colors.primary-background-hover}'
120
+ button-secondary:
121
+ backgroundColor: '{colors.secondary}'
122
+ textColor: '{colors.foreground}'
123
+ rounded: '{rounded.lg}'
124
+ padding: '{spacing.md}'
125
+ height: 36px
126
+ button-destructive:
127
+ backgroundColor: '{colors.destructive-background}'
128
+ textColor: '{colors.destructive-foreground-on-critical}'
129
+ rounded: '{rounded.lg}'
130
+ height: 36px
131
+ button-sm:
132
+ height: 28px
133
+ rounded: '{rounded.lg}'
134
+ button-lg:
135
+ height: 40px
136
+ rounded: '{rounded.lg}'
137
+ button-secondary-hover:
138
+ backgroundColor: '{colors.secondary-background-hover}'
139
+ input-default:
140
+ backgroundColor: '{colors.background}'
141
+ textColor: '{colors.foreground}'
142
+ rounded: '{rounded.lg}'
143
+ height: 36px
144
+ input-muted:
145
+ backgroundColor: '{colors.muted-background}'
146
+ textColor: '{colors.muted-foreground}'
147
+ rounded: '{rounded.lg}'
148
+ height: 36px
149
+ dialog-overlay:
150
+ backgroundColor: '{colors.overlay-background}'
151
+ divider-default:
152
+ backgroundColor: '{colors.border}'
153
+ divider-emphasized:
154
+ backgroundColor: '{colors.border-emphasized}'
155
+ badge-neutral:
156
+ backgroundColor: '{colors.neutral}'
157
+ textColor: '{colors.secondary-foreground}'
158
+ rounded: '{rounded.sm}'
159
+ panel-alternate:
160
+ backgroundColor: '{colors.alternate-background}'
161
+ textColor: '{colors.foreground}'
162
+ card-default:
163
+ backgroundColor: '{colors.card-background}'
164
+ textColor: '{colors.foreground}'
165
+ rounded: '{rounded.xl}'
166
+ padding: '{spacing.lg}'
167
+ link-default:
168
+ textColor: '{colors.link-foreground}'
169
+ typography: '{typography.body-md}'
170
+ badge-xs:
171
+ height: 20px
172
+ rounded: '{rounded.sm}'
173
+ alert-info:
174
+ backgroundColor: '{colors.info-background}'
175
+ textColor: '{colors.info-foreground-on-info}'
176
+ rounded: '{rounded.lg}'
177
+ alert-success:
178
+ backgroundColor: '{colors.success-background}'
179
+ textColor: '{colors.success-foreground-on-success}'
180
+ rounded: '{rounded.lg}'
181
+ alert-warning:
182
+ backgroundColor: '{colors.warning-background}'
183
+ textColor: '{colors.warning-foreground-on-warning}'
184
+ rounded: '{rounded.lg}'
185
+ alert-destructive:
186
+ backgroundColor: '{colors.destructive-background}'
187
+ textColor: '{colors.destructive-foreground-on-critical}'
188
+ rounded: '{rounded.lg}'
39
189
  ---
40
190
 
41
- ### 1. Feedback and system status
42
-
43
- Users **must** always know what changed: loading, success, failure, or background work needs a visible signal.
44
-
45
- #### 1.1 Loading states
46
-
47
- **Applies when:** Data fetch, async work, route transition, or slow AI step blocks meaningful UI.
48
-
49
- **Aura components:** `Shimmer`, `Loader`, `Progress`, `Skeleton`
50
-
51
- **Rules**
52
-
53
- - **Must** show loading for any wait the user is expected to sit through.
54
- - **Must** use **Shimmer** when the layout of incoming content is known (list rows, cards, table skeleton).
55
- - **Must** use **Loader** for compact inline waits (e.g. inside a **Button** or card header).
56
- - **Must** use a **full-surface** pattern (centered **Loader**, **Skeleton** layout, or app **PageLoader**) for full-page or high-latency transitions including long AI operations.
57
- - **Should** use **Progress** when completion is measurable (upload %, stepped flow).
58
- - **Avoid** blank content areas with no indicator.
59
- - **Avoid** using only a tiny spinner for large unknown layouts — prefer **Shimmer** / **Skeleton**.
60
-
61
- #### 1.2 Action confirmation
62
-
63
- **Applies when:** User actions mutate state (save, submit, delete, copy, send).
64
-
65
- **Aura components:** `Dialog` (+ destructive **Button**), `Alert`, `Tooltip`, `Banner`
66
- **App / shell:** Sonner (or equivalent toast), dedicated confirm **AlertDialog** where the shell provides it
67
-
68
- **Rules**
69
-
70
- - **Must** acknowledge user-triggered mutations with a visible signal.
71
- - **Must** use **transient toast** (e.g. Sonner, bottom-right, ~4s auto-dismiss) for low-stakes confirmations (“Saved”, “Copied”) — theme with Aura tokens.
72
- - **Must** use **Dialog** (or shell **AlertDialog**) with explicit copy **before** irreversible actions — not only after the fact.
73
- - **Should** offer **Undo** in the toast when the action is reversible and undo is cheap.
74
- - **Should** use **Tooltip** (“Copied!”) for copy on small icon targets.
75
- - **Avoid** `alert()` and other native blocking dialogs for product UX.
76
- - **Avoid** stacking multiple toasts for a single user gesture.
77
-
78
- #### 1.3 System status visibility
79
-
80
- **Applies when:** **Persistent** problems with **user-visible workflow impact** — degraded mode, auth expiry, data stale beyond policy, or API health that blocks or misleads work — not routine connection handshakes or background connectivity that users do not need to monitor continuously.
81
-
82
- **Aura components:** `Alert`, `Badge`, `Banner`, `Loader` (see §1.1)
83
- **App:** `Sonner` for ephemeral global notices
84
-
85
- **Rules**
86
-
87
- - **Must** surface problems that stay **until dismissed or resolved** and **scope to a region** with **Banner** at the top of that region — when the issue is **persistent** and **not** low-salience ambient state.
88
- - **Must** use **Alert** for inline, page-scoped status that needs awareness but not always immediate action, and keep it to **one page-level Alert per view** in standard dashboards.
89
- - **Should** use **Badge** semantic variants (`warning`, `destructive`, …) on entities carrying that state.
90
- - **Should** represent repeated or list-level status (many assets, tasks, signals) with **Badge**, metric/status cards, or concise icon+text rows — not repeated Alert stacks.
91
- - **Should** use **Loader** (inline or full-surface per §1.1) for transient waits such as host handshake or reconnect; use **Banner** only when the degraded state **remains** after loading settles.
92
- - **Should** use a short **Sonner** or **inline Alert** for **optional** or **intermittent** connection notices instead of permanent chrome.
93
- - **Avoid** hiding workflow-critical status **only** behind hover.
94
- - **Avoid** dedicating **Banner** or other persistent strip space to connection state when users **do not** need that signal continuously — prefer compact indicators (**Badge**, toolbar dot, footer text) or nothing until failure.
95
- - **Avoid** treating routine “connecting / connected” or handshake flows as the default **Banner** channel — same rationale as **Avoid** using **Banner** for long onboarding when critical alerts need that channel (§5.3).
96
- - **Avoid** stacking multiple Alerts inside one card or page section to enumerate line items; aggregate the message and push per-item state to badges or compact status rows.
97
-
98
- ### Alert vs Banner vs Badge vs Sonner
99
-
100
- Use this matrix to pick the right feedback component. Priority is defined by whether the message requires immediate action and how long it needs to persist.
101
-
102
- | Priority | When | Components | Notes |
103
- | :--- | :--- | :--- | :--- |
104
- | **Low** | Non-disruptive updates, minor status, validation hints | `Badge`, notification dot, inline `HelperText` | Does not interrupt the user. Badge for entity state; HelperText for field-level feedback. |
105
- | **Medium** | Informative, occasionally actionable, not urgent | `Sonner` (toast), `Alert` | Sonner for transient confirmations (~4 s, bottom-right). Alert for inline, page-scoped status that needs awareness but not immediate action (typically one per page section/view). |
106
- | **High** | Requires immediate attention or action; may interrupt task flow | `Banner` (system errors), `Dialog` / `AlertDialog`, full-page error state | Banner for persistent, region-scoped degraded states. Dialog for irreversible actions. Never use Sonner as the sole safety net for destructive work. |
107
-
108
- **Rules**
109
-
110
- - **Must not** use Banner for low-priority or transient notices — it occupies persistent chrome and dilutes high-priority signals.
111
- - **Must not** use Sonner for errors that require user action — it auto-dismisses.
112
- - **Must not** use repeated Alerts as a list visualization pattern; one Alert communicates the grouped situation, while item-level status belongs in Badge/status-card patterns.
113
- - **Should** use `Badge` semantic variants (`warning`, `destructive`, `success`) on entities that carry that state, not as page-level alerts.
114
- - **Avoid** stacking multiple Sonner toasts for a single user gesture.
115
-
116
- **Industrial / operational states**
117
-
118
- The matrix above covers standard cases. For domain-specific states (e.g. sensor offline, process limit breach, control system degraded), apply the same priority logic: does the user need to act now? -> Banner or Dialog. Informational? -> Alert or Badge on the asset. Transient confirmation? -> Sonner. When many entities share similar state, summarize once (Alert/Banner) and show per-entity state with Badge or status cards.
119
-
120
- ---
121
-
122
- ### 2. Affordance and discoverability
123
-
124
- Controls **must** read as interactive; users **should** not guess what is clickable, expandable, or editable.
125
-
126
- #### 2.1 Interactive signifiers
127
-
128
- **Applies when:** Click, drag, expand, or edit.
129
-
130
- **Aura components:** `Button`, `DropdownMenu`, `Collapsible`, `Accordion`, `Select`, `Command`
131
-
132
- **Rules**
133
-
134
- - **Must** use **Button** for discrete actions — not `div`/`span` with `onClick` styled as buttons.
135
- - **Must** match **Button** `variant` to prominence: `default` = primary CTA, `secondary` / `outline` / `ghost` for supporting actions, `destructive` for irreversible commit.
136
- - **Must** use a **chevron-down** (or equivalent) on controls that open menus or expandable regions, consistent with **DropdownMenu** / **Collapsible** / **Accordion** patterns.
137
- - **Should** keep **`pointer`** cursor on interactive surfaces — Aura sets this; do not override without cause.
138
- - **Avoid** custom “clickable text” that looks identical to body copy.
139
-
140
- #### 2.2 Labels and recognizable patterns
141
-
142
- **Applies when:** Forms, navigation, empty views, search.
143
-
144
- **Aura components:** `Label`, `Input`, `Textarea`, `Select`, `Card`, `Command` / `CommandInput`
145
-
146
- **Rules**
147
-
148
- - **Must** pair every field with a visible **Label** — placeholders are not labels.
149
- - **Must** use recognizable patterns (search field + magnifier icon, menu trigger + chevron).
150
- - **Should** use **Card** + title/description + **Button** for first-use empty views — not a bare white panel.
151
- - **Avoid** ambiguous icon-only controls without **Tooltip** + accessible name (see §2.3).
152
-
153
- #### 2.3 Contextual help
154
-
155
- **Applies when:** Non-obvious behavior, format rules, or icon-only controls.
156
-
157
- **Aura components:** `Tooltip`, `Popover`, `HelperText`, `HoverCard`
158
-
159
- **Rules**
160
-
161
- - **Must** put **Tooltip** on icon-only **Button**s with no visible label.
162
- - **Must** use **HelperText** under fields for format and constraints **before** error.
163
- - **Should** use **Popover** / **HoverCard** when help needs paragraphs or links.
164
- - **Avoid** **Tooltip** as the **only** place for information users must have on touch-first flows.
165
-
166
- ---
167
-
168
- ### 3. Progressive disclosure
169
-
170
- Introduce complexity only when needed; default views **should** stay scannable.
171
-
172
- #### 3.1 Collapsible content
173
-
174
- **Applies when:** Secondary detail, advanced settings, or optional blocks.
175
-
176
- **Aura components:** `Accordion`, `Collapsible`, `Dialog`, `Popover`
177
- **App:** `Sheet`, `Drawer` where the shell provides them — still use Aura tokens
178
-
179
- **Rules**
180
-
181
- - **Must** use **Accordion** for stacked, independent sections (FAQ, settings groups).
182
- - **Must** use **Collapsible** for a single inline expandable block.
183
- - **Must** use **Drawer** / **Sheet** (shell) for edge panels or lightweight overlays that should not replace the whole page; otherwise **Dialog** for modal tasks.
184
- - **Should** default **Accordion** / **Collapsible** to collapsed unless the section is the main purpose of the view.
185
- - **Avoid** nesting **Accordion** more than one level.
191
+ ## Overview
186
192
 
187
- #### 3.2 Multi-step flows
193
+ Aura is the official design system for Cognite experiences: composable UI primitives for data-heavy industrial software.
188
194
 
189
- **Applies when:** Three or more steps or grouped data entry.
195
+ Aura should feel like an **industrial control room**: quiet surfaces, stable hierarchy, immediate status signals, and controls that stay out of the operator's way until action is needed. The interface is engineered, not decorated. It gives dense operational data enough structure to scan quickly, reserves color for meaning, and makes interaction states predictable under pressure.
190
196
 
191
- **Aura components:** `Dialog`, `Progress`, `Button`, `Separator`
197
+ Light and dark themes share the same semantic roles; fixed tokens support persistent shell chrome.
192
198
 
193
- **Rules**
199
+ **Tokens:** Reference values live in the YAML front matter at the top of this file. They provide context for agents and humans — the prose sections below carry design intent, constraints, and reasoning. Reference tokens in prose as `{colors.<name>}`, `{spacing.<name>}`, `{typography.<name>}`, `{rounded.<name>}`, and `{components.<name>}`.
194
200
 
195
- - **Must** split into discrete steps with visible progress (step label, **Progress**, or stepper UI).
196
- - **Must** let users return to earlier steps unless that causes data loss.
197
- - **Avoid** multiple irreversible **primary** decisions in one step.
201
+ **Implementation:** Package imports, component APIs, and host-shell integration live in the Aura [README](./README.md) — not in this file.
198
202
 
199
- #### 3.3 Contextual menus and secondary actions
203
+ ### For agents: how to read this file
200
204
 
201
- **Applies when:** Per-row or per-object actions should stay out of the default chrome.
205
+ Before editing or generating from this file, read Google's [DESIGN.md Philosophy](https://github.com/google-labs-code/design.md/blob/main/PHILOSOPHY.md). The philosophy applies directly to how Aura's spec should be used:
202
206
 
203
- **Aura components:** `DropdownMenu`, `Button` (kebab trigger), `ButtonGroup`
204
- **App:** `ContextMenu` — same grouping and token rules
207
+ 1. **Start with prose, not tokens.** The quality of generated UI depends more on understanding _intent_ than on copying hex values. Read **Overview**, **Do's and Don'ts**, **Heuristics**, **Interaction states**, and **Content** before implementing from the YAML block. Use **Heuristics** for detailed feedback, disclosure, error, layout, and accessibility decisions.
208
+ 2. **Tokens are context, not rendering instructions.** YAML values anchor names and approximate light-theme references. Runtime styling comes from `@cognite/aura/colors.css`, `@cognite/aura/styles.css`, and component APIs — not from reimplementing token literals in product code.
209
+ 3. **Prefer specific constraints over adjectives.** Aura targets data-heavy industrial software: flat hierarchy, semantic color only for status and feedback, predictable interaction states, and calm surfaces. When prose and a token disagree, follow the prose rationale.
210
+ 4. **Negative constraints matter.** **Do's and Don'ts** and the **Avoid** / **Must not** rules in Heuristics define character as much as the palette.
211
+ 5. **Extension sections are intentional.** Sections beyond the core design.md spec order — **Assets & Motion**, **Heuristics**, **Interaction states**, **Content** — extend the format for Aura. UX playbook guidance lives in this file.
205
212
 
206
- **Rules**
213
+ ### Alignment with Google design.md
207
214
 
208
- - **Must** use **DropdownMenu** for action lists anchored to a trigger (e.g. “More”).
209
- - **Must** scope menu items to the entity they affect — do not mix unrelated global actions into an item menu.
210
- - **Should** use **ButtonGroup** for a small persistent contextual action cluster.
211
- - **Avoid** long flat menus of **more than ~7** items without **DropdownMenuGroup** / separators / submenus.
215
+ | Philosophy principle | Aura approach |
216
+ | ------------------------------------- | -------------------------------------------------------------------------------------------------------- |
217
+ | Prose carries design intent | Overview, colors, interaction states, content, and do's/don'ts are the primary identity guidance |
218
+ | Tokens referenced in prose | Key roles use `{colors.*}`, `{spacing.*}`, etc. inline; full ramps stay in tables and CSS |
219
+ | Specific reference > vague adjectives | Overview names data-heavy industrial UI; heuristic rules carry constraints |
220
+ | Do's and don'ts as guardrails | Dedicated **Do's and Don'ts** section plus compact severity-rated heuristics |
221
+ | Format extends beyond the spec | Motion, iconography, elevation, copy, accessibility, and extended UX guidance live in extension sections |
212
222
 
213
223
  ---
214
224
 
215
- ### 4. Error handling and prevention
225
+ ## Colors
216
226
 
217
- Errors **should** be prevented; when they happen, users **must** understand cause and recovery.
227
+ Aura color behaves like instrumentation in a control room. Most of the interface is neutral structure; important changes appear as clear signals; decorative color is rare and never competes with status. A screen should still make sense when color is removed, but color should make state faster to recognize.
218
228
 
219
- #### 4.1 Destructive action prevention
229
+ Use **Base** color for the operating surface: page backgrounds, cards, text, borders, focus, and persistent chrome. This is ~80–90% of the UI.
220
230
 
221
- **Applies when:** Delete, archive, reset, overwrite, disconnect, or other irreversible commits.
231
+ Use **Semantic** color only for status and feedback: info, success, warning, destructive, validation, and operational state. This is ~5–10% of the UI.
222
232
 
223
- **Aura components:** `Dialog`, `Alert`, `Banner`, `Button` (`destructive`)
224
- **App:** `AlertDialog` / confirm flow where supplied by shell
233
+ Use **Decorative** color only for non-status differentiation: accents, avatars, illustrations, and small visual markers that do not imply system health. This is ~5–10% of the UI.
225
234
 
226
- **Rules**
235
+ Light-theme reference values for key roles are defined as `colors.*` tokens in the YAML front matter (referenced in tables as `{colors.<name>}`); full ramps and dark-theme values are in the tables below.
227
236
 
228
- - **Must** confirm high-impact destructive actions in a **Dialog** (or **AlertDialog**) **before** execution.
229
- - **Must** name what will be destroyed — not generic “Are you sure?”.
230
- - **Must** label the confirm action with a **specific verb** (“Delete report”), not “OK”.
231
- - **Should** use **Button** `variant="destructive"` for the confirming destructive action.
232
- - **Avoid** toast as the **only** safety net for irreversible work.
237
+ Do not hardcode hex, font sizes, or shadow strings in product UI when a token exists.
233
238
 
234
- #### 4.2 Form validation
239
+ Aura supports **light** (`:root`) and **dark** (`.dark` / `prefers-color-scheme: dark` per library setup). Semantic and base tokens **resolve to different ramps** per theme. **`background-fixed-dark`**, **`background-fixed-light`**, **`foreground-fixed-*`**, and related **fixed** tokens keep the same appearance in both themes (persistent chrome such as sidebars). Always verify contrast in both themes before shipping.
235
240
 
236
- **Applies when:** Any `Input`, `Textarea`, `Select`, or similar field.
241
+ Reference tokens by **full CSS name** or Tailwind token. Never use raw `hex` / `rgb` / `hsl` in product code. If no semantic token fits, use a documented **base** token; **step colors** on ramps (`mountain/*`, `fjord/*`, …) are only for custom, branding, or marketing surfaces where no semantic token exists yet.
237
242
 
238
- **Aura components:** `Input`, `Textarea`, `Select`, `InputGroup`, `HelperText`, `Label`
239
-
240
- **Rules**
241
-
242
- - **Must** show errors inline with **HelperText** (or documented `aria-invalid` pattern) on the affected field.
243
- - **Must** say what is wrong and how to fix it — not only “Invalid”.
244
- - **Must** gate “next step” until blocking errors are resolved.
245
- - **Must** use component **`error`** / invalid props where **Input** / **Select** expose them — do not invent parallel red borders.
246
- - **Should** validate on **blur** when the value is incomplete mid-typing.
247
- - **Should** validate live when rules are cheap (length, pattern).
248
- - **Avoid** revealing every error only on final submit with no prior field feedback.
249
-
250
- #### 4.3 Auto-save and data loss prevention
251
-
252
- **Applies when:** Edits would be lost on navigation or timeout.
253
-
254
- **Aura components:** `Banner`, `Badge`, `Dialog`
255
- **App:** Sonner for “Saved” pulse
243
+ ### Common Tailwind mappings
256
244
 
257
- **Rules**
245
+ Tables in this section use **CSS role names** (e.g. `link-foreground`, `card-background`). Each role maps to a `--color-{role}` custom property and Tailwind v4 utilities (`text-{role}`, `bg-{role}`, `border-{role}`, and `ring-{role}` where applicable). Prefer these utilities over raw `var(--…)` when the theme wire-up matches.
246
+
247
+ | Role (suffix after `text-` / `bg-` / `border-`) | Typical utilities | Notes |
248
+ | ----------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------- |
249
+ | `background` | `bg-background` | Page base |
250
+ | `foreground` | `text-foreground` | Primary text |
251
+ | `muted-foreground` | `text-muted-foreground` | Tertiary copy |
252
+ | `card-background` | `bg-card-background` | Cards (see **Card** component) |
253
+ | `muted-background` | `bg-muted-background` | Static fills, inputs, secondary chrome |
254
+ | `border` | `border-border` | Default strokes |
255
+ | `link-foreground` (`{colors.link-foreground}`) | `text-link-foreground` | Text links — same value as `{colors.tertiary}` |
256
+ | `primary-background` | `bg-primary-background`, `text-foreground-on-primary` | Default **Button** (`variant="default"`) pattern |
257
+ | `destructive-background` | `bg-destructive-background`, `text-destructive-foreground-on-critical` (on surface) | Destructive actions — pairings in **Semantic colors** |
258
+ | `info-background`, `success-background`, … | `bg-info-background`, `text-info-foreground`, … | Full names match **Semantic colors** token columns |
259
+
260
+ Semantic utilities use the **full token name** as the Tailwind segment (e.g. `bg-info-background`, not `bg-info`). For **charts**, utilities follow the **Chart tokens** names (`bg-chart-fjord-color-1`, `bg-chart-gridlines`, …).
261
+
262
+ Tables below list **light-theme** values as `{colors.<name>}` token references in the YAML front matter and **dark-theme** resolved values in the second column; the published `colors.css` is the runtime source of truth (some entries are `rgba()`).
263
+
264
+ ### Base — Background
265
+
266
+ | Token | Light (reference) | Dark (reference) | Use |
267
+ | ------------------------------- | ------------------------------------- | ---------------- | ------------------------------------------------------------------ |
268
+ | `background` | `{colors.background}` | `#191B1D` | Primary surface — lowest layer |
269
+ | `alternate-background` | `{colors.alternate-background}` | `#111213` | Distinct layer or block separate from `background` |
270
+ | `card-background` | `{colors.card-background}` | `#212426` | Cards without drop shadow on `background` / `alternate-background` |
271
+ | `muted-background` | `{colors.muted-background}` | `#2D3134` | Static fills for controls, rows, segmented controls |
272
+ | `primary-background` | `{colors.primary}` | `#F9FAFA` | Primary actions (default button); use sparingly |
273
+ | `primary-background-hover` | `{colors.primary-background-hover}` | `#E4E6E8` | Hover on `primary-background` |
274
+ | `secondary-background` | `#E4E6E8` | `#40464A` | Secondary actions, switch track |
275
+ | `secondary-background-hover` | `{colors.secondary-background-hover}` | `#5E666D` | Hover on `secondary-background` |
276
+ | `accent-background` | `#F1F2F3` | `#2D3134` | Neutral hover on `background` / `card-background` (e.g. tabs) |
277
+ | `accent-background-strong` | `#E4E6E8` | `#40464A` | Neutral hover on `muted-background` / `active-muted-background` |
278
+ | `highlight-background` | `#F1F2F3` | `#2D3134` | Focused / active fields (inputs, selects, comboboxes) |
279
+ | `highlight-background-strong` | `#E4E6E8` | `#40464A` | Stronger focused / active field fill |
280
+ | `active-background` | `#191B1D` | `#F9FAFA` | High-contrast “on” (switch, checkbox, radio) |
281
+ | `active-background-hover` | `#2D3134` | `#F1F2F3` | Hover on `active-background` |
282
+ | `active-muted-background` | `#F1F2F3` | `#2D3134` | Lower-contrast selected (e.g. tabs) |
283
+ | `active-muted-background-hover` | `#E4E6E8` | `#40464A` | Hover on `active-muted-background` |
284
+ | `popover-background` | `#FFFFFF` | `#212426` | Top-layer surfaces with shadow (dialogs, popovers) |
285
+ | `raised-background` | `#2D3134` | `#40464A` | Tooltips, Sonner toasts — floats above page |
286
+ | `disabled-background` | `#F1F2F3` | `#2D3134` | Disabled inputs and controls |
287
+ | `overlay-background` | `{colors.overlay-background}` | `#7C868E80` | Scrim behind modals |
288
+ | `background-fixed-dark` | `#212426` | `#212426` | Must stay **dark** in both themes |
289
+ | `background-fixed-light` | `#FFFFFF` | `#FFFFFF` | Must stay **light** in both themes |
290
+ | `accent-background-fixed-dark` | `#2D3134` | `#2D3134` | Persistent dark accent chrome (e.g. sidebar) |
291
+
292
+ ### Base — Foreground
293
+
294
+ | Token | Light (reference) | Dark (reference) | Use |
295
+ | ---------------------------------- | -------------------------------- | ---------------- | ------------------------------ |
296
+ | `foreground` | `{colors.foreground}` | `#F1F2F3` | Primary text and icons |
297
+ | `secondary-foreground` | `{colors.secondary-foreground}` | `#D4D7D9` | Supporting text and icons |
298
+ | `muted-foreground` | `{colors.muted-foreground}` | `#A5ABB1` | Tertiary / low emphasis |
299
+ | `disabled-foreground` | `#D4D7D9` | `#5E666D` | Disabled text and icons |
300
+ | `link-foreground` | `{colors.link-foreground}` | `#1742E7` | Text links |
301
+ | `foreground-on-primary` | `{colors.foreground-on-primary}` | `#191B1D` | On `primary-background` |
302
+ | `foreground-on-active` | `#F1F2F3` | `#191B1D` | On `active-background` |
303
+ | `active-foreground` | `#191B1D` | `#F1F2F3` | On `active-muted-background` |
304
+ | `foreground-fixed-dark` | `#191B1D` | `#191B1D` | Must stay dark in both themes |
305
+ | `foreground-fixed-light` | `#FFFFFF` | `#FFFFFF` | Must stay light in both themes |
306
+ | `foreground-secondary-fixed-dark` | `#40464A` | `#40464A` | Secondary copy, always dark |
307
+ | `secondary-foreground-fixed-light` | `#D4D7D9` | `#D4D7D9` | Secondary copy, always light |
308
+ | `muted-foreground-fixed-light` | `#BBC0C4` | `#BBC0C4` | Muted copy, always light |
309
+
310
+ ### Base — Borders and focus
311
+
312
+ | Token | Light (reference) | Dark (reference) | Use |
313
+ | ------------------- | ---------------------------- | ---------------- | ------------------------------------------------ |
314
+ | `border` | `{colors.border}` | `#2D3134` | Default strokes |
315
+ | `border-emphasized` | `{colors.border-emphasized}` | `#40464A` | Stronger separation |
316
+ | `border-on-dark` | `#2D3134` | `#2D3134` | Strokes on dark chrome (both themes) |
317
+ | `border-active` | `#191B1D` | `#F9FAFA` | Active / toggled outlines |
318
+ | `ring` | `{colors.ring}` | `#7081C7` | Focus ring outer (maps to `--shadow-focus-ring`) |
319
+ | `ring-muted` | `{colors.ring-muted}` | `#B5BEE2` | Focus ring inner companion |
258
320
 
259
- - **Must** auto-save when feasible; when not, show persistent unsaved state (**Badge** / **Banner** / shell slot).
260
- - **Must** warn before discard navigation (**Dialog** confirm) when changes are unsaved.
261
- - **Should** show “Saved” / timestamp feedback (toast or inline) after auto-save.
321
+ Also generated: `ring-destructive`, `ring-destructive-muted` for destructive / invalid focus (see **Effects — Focus rings**).
262
322
 
263
- #### 4.4 Recovery and undo
323
+ ### Semantic colors
264
324
 
265
- **Applies when:** User mutates or removes content.
325
+ Semantic tokens are **only** for status and system feedback (Alert, Banner, Sonner, badge status variants, validation). Do not use them as generic fills or decoration.
266
326
 
267
- **Aura components:** `Dialog`
268
- **App:** Sonner with undo
327
+ Each family has **default** pairings (theme-switching surfaces) and **muted** pairings (blocks on **persistent dark chrome**). On muted surfaces, use the same `*-foreground-on-*` token names with the muted background; verify contrast in context.
269
328
 
270
- **Rules**
329
+ **Info**
271
330
 
272
- - **Should** provide **Undo** in toast for reversible destructive actions.
273
- - **Must** keep undo inside the same session without deep navigation gymnastics.
274
- - **Avoid** relying on undo alone for high-stakes actions — still confirm where appropriate (§4.1).
331
+ | Token | Light (reference) | Dark (reference) | Use |
332
+ | ------------------------- | ---------------------------------- | ---------------- | ----------------------------------------------------------------------------- |
333
+ | `info-background` | `{colors.info-background}` | `#B5BEE2` | Info surface |
334
+ | `info-background-hover` | `#B5BEE2` | `#D0D6ED` | Hover on `info-background` |
335
+ | `info-foreground` | `#4A5FB8` | `#9DA9D9` | Text near info context on standard surfaces |
336
+ | `info-foreground-on-info` | `{colors.info-foreground-on-info}` | `#1A2242` | Text **on** `info-background` |
337
+ | `info-muted-background` | `#F0F2F9` | `#2D3134` | Info tint on dark chrome |
338
+ | _(pairing)_ | — | — | On `info-muted-background`, use `info-foreground-on-info` for on-surface copy |
275
339
 
276
- ---
340
+ **Success**
277
341
 
278
- ### 5. Enabling power users
342
+ | Token | Light (reference) | Dark (reference) | Use |
343
+ | ------------------------------- | ---------------------------------------- | ---------------- | ------------------------------------------------------------------ |
344
+ | `success-background` | `{colors.success-background}` | `#8BDEAE` | Success surface |
345
+ | `success-background-hover` | `#8BDEAE` | `#BBF3D0` | Hover on `success-background` |
346
+ | `success-foreground` | `#1C984A` | `#24C45E` | Text near success on standard surfaces |
347
+ | `success-foreground-on-success` | `{colors.success-foreground-on-success}` | `#0A381C` | Text **on** `success-background` |
348
+ | `success-muted-background` | `#DDF9E7` | `#2D3134` | Success on dark chrome |
349
+ | _(pairing)_ | — | — | On `success-muted-background`, use `success-foreground-on-success` |
279
350
 
280
- Experts **should** move faster without harming first-time clarity.
351
+ **Warning**
281
352
 
282
- #### 5.1 Keyboard shortcuts
353
+ | Token | Light (reference) | Dark (reference) | Use |
354
+ | ------------------------------- | ---------------------------------------- | ---------------- | -------------------------------------- |
355
+ | `warning-background` | `{colors.warning-background}` | `#FFE3A2` | Warning surface |
356
+ | `warning-background-hover` | `#FFD062` | `#FFF1D0` | Hover on `warning-background` |
357
+ | `warning-foreground` | `#C18800` | `#D8BF00` | Text near warning on standard surfaces |
358
+ | `warning-foreground-on-warning` | `{colors.warning-foreground-on-warning}` | `#5B4000` | Text **on** `warning-background` |
359
+ | `warning-muted-background` | `#FFF1D0` | `#2D3134` | Warning on dark chrome |
283
360
 
284
- **Applies when:** High-frequency actions (save, search, command palette, AI trigger).
361
+ **Destructive**
285
362
 
286
- **Aura components:** `Command`, `CommandShortcut`, `DropdownMenuShortcut`, `Tooltip`
363
+ | Token | Light (reference) | Dark (reference) | Use |
364
+ | ------------------------------------ | --------------------------------------------- | ---------------- | -------------------------------------------------- |
365
+ | `destructive-background` | `{colors.destructive-background}` | `#FAA9B7` | Error / destructive surface |
366
+ | `destructive-background-hover` | `#FAA9B7` | `#FCCAD2` | Hover on `destructive-background` |
367
+ | `destructive-foreground` | `#CB0B2C` | `#F65E78` | Text near destructive context on standard surfaces |
368
+ | `destructive-foreground-on-critical` | `{colors.destructive-foreground-on-critical}` | `#8D081F` | Text **on** `destructive-background` |
369
+ | `destructive-muted-background` | `#FDDEE4` | `#2D3134` | Destructive on dark chrome |
370
+ | `destructive-muted-background-hover` | `#FCCAD2` | `#40464A` | Hover on `destructive-muted-background` |
287
371
 
288
- **Rules**
372
+ **Neutral** (status: draft, archived — not “semantic calm” in the same sense as info/success)
289
373
 
290
- - **Should** ship shortcuts for the top few actions per surface.
291
- - **Must** render shortcut glyphs with **CommandShortcut** / **DropdownMenuShortcut** — not bespoke styled `<kbd>`.
292
- - **Should** align with platform norms (e.g. ⌘/Ctrl+S, ⌘/Ctrl+K) where they do not fight the browser.
293
- - **Avoid** stealing OS or browser reserved shortcuts.
374
+ | Token | Light (reference) | Dark (reference) | Use |
375
+ | ------------------------------- | ----------------- | ---------------- | -------------------------------- |
376
+ | `neutral-background` | `#E4E6E8` | `#D4D7D9` | Neutral status surface |
377
+ | `neutral-background-hover` | `#D4D7D9` | `#E4E6E8` | Hover on `neutral-background` |
378
+ | `neutral-foreground` | `#52595F` | `#A5ABB1` | Text near neutral status |
379
+ | `neutral-foreground-on-neutral` | `#40464A` | `#2D3134` | Text **on** `neutral-background` |
380
+ | `neutral-muted-background` | `#F1F2F3` | `#2D3134` | Neutral on dark chrome |
294
381
 
295
- #### 5.2 Bulk actions
382
+ **Naming:** CSS uses full role names (`info-foreground-on-info`, `neutral-foreground-on-neutral`, `destructive-foreground-on-critical`). There is no shortened alias in the theme.
296
383
 
297
- **Applies when:** Lists or tables with repeated items.
384
+ ### Decorative colors
298
385
 
299
- **Aura components:** `DropdownMenuCheckboxItem`, `Button`, `ButtonGroup`, `Badge`, `Banner`
300
- **App:** table selection, **ActionToolbar** pattern
386
+ For **small accents** (badges, avatars, empty states) where color differentiates but does **not** signal status — use **Chart tokens** for plot colors, not this ramp, unless a design explicitly maps a tile to a series color. Pattern: `decorative-background-{ramp}`, `decorative-background-{ramp}-hover`, `decorative-foreground-{ramp}`.
301
387
 
302
- **Rules**
388
+ **Preference order for new work:**
303
389
 
304
- - **Must** support multi-select in list/table UIs that offer per-row destructive or batch actions (shell table + **DropdownMenuCheckboxItem** or equivalent).
305
- - **Must** show bulk **ButtonGroup** / toolbar only when selection is non-empty; show selected count.
306
- - **Should** support select-all for the current page or filter.
307
- - **Avoid** bulk destructive work without **Dialog** confirmation (§4.1).
390
+ | Priority | Ramp | Background | Foreground |
391
+ | -------- | -------- | -------------------------------- | -------------------------------- |
392
+ | 1 | Fjord | `decorative-background-fjord` | `decorative-foreground-fjord` |
393
+ | 2 | Nordic | `decorative-background-nordic` | `decorative-foreground-nordic` |
394
+ | 3 | Aurora | `decorative-background-aurora` | `decorative-foreground-aurora` |
395
+ | 4 | Dusk | `decorative-background-dusk` | `decorative-foreground-dusk` |
396
+ | 5 | Orange | `decorative-background-orange` | `decorative-foreground-orange` |
397
+ | 6 | Sky | `decorative-background-sky` | `decorative-foreground-sky` |
398
+ | 7 | Mountain | `decorative-background-mountain` | `decorative-foreground-mountain` |
308
399
 
309
- #### 5.3 Onboarding and learnability
400
+ Example (fjord ramp): light `decorative-background-fjord` → `#CCD5FA` (fjord-200), `decorative-foreground-fjord` → `#1234B6` (fjord-700); dark → `#AEBDF7` / `#0D2582` (fjord-300 / fjord-800).
310
401
 
311
- **Applies when:** First-use, empty data, or role-gated features.
402
+ ### Chart tokens
312
403
 
313
- **Aura components:** `Card`, `Button`, `Tooltip`, `HelperText`, `Banner`, `Message`
404
+ **Priority rule:** use `chart-*` for any data plotted on axes or series; use `decorative-*` for non-data visual differentiation (tiles, avatars, accents); use semantic tokens (`info-*`, `success-*`, `warning-*`, `destructive-*`) for operational status and feedback only. Never swap between these groups.
314
405
 
315
- **Rules**
406
+ | Token | Use |
407
+ | ----------------------------------------------- | ----------------------------------------------------------- |
408
+ | `chart-{ramp}-color-1` … `chart-{ramp}-color-6` | Alpha-based series / area-fill steps (strongest → lightest) |
409
+ | `chart-gridlines` | Grid lines |
316
410
 
317
- - **Must** use a structured empty pattern (**Card** + explanation + primary **Button**), not a blank canvas.
318
- - **Should** explain what the view is for and how to populate it.
319
- - **Should** use **HelperText** / **Tooltip** for compact role- or context-specific hints.
320
- - **Avoid** using **Banner** for long onboarding tours if **Banner** is already the channel for critical system alerts — mixed priority dilutes both.
411
+ Default series order: **fjord → nordic → aurora → dusk → orange**.
321
412
 
322
413
  ---
323
414
 
324
- ### 6. Layout and hierarchy
325
-
326
- Information **must** be scannable and oriented before action.
327
-
328
- #### 6.1 Grouping and proximity
329
-
330
- **Applies when:** Forms, settings, detail layouts.
331
-
332
- **Aura components:** `Card`, `InputGroup`, `Accordion`, `Separator`, `Label`
333
-
334
- **Rules**
335
-
336
- - **Must** group related fields in one **Card** or labeled section.
337
- - **Must** use **Separator** between unrelated groups in the same container.
338
- - **Must** use **InputGroup** when addons and input share one logical value.
339
- - **Should** use **Accordion** for distinct sub-topics in long settings.
340
- - **Avoid** unrelated primary actions in the same **Card** as sensitive fields without hierarchy.
341
-
342
- #### 6.2 Persistent actions and navigation
343
-
344
- **Applies when:** Global vs page-local actions.
345
-
346
- **Aura components:** `Button`, `DropdownMenu`
347
- **Fusion shell:** `Topbar`, `Tabs`, `SegmentedControl` — follow shell **SKILL** / **RULES** where your repo defines them
348
-
349
- **Rules**
350
-
351
- - **Must** keep **one** clear **primary** CTA per view in content; put global-only actions in shell chrome, page actions in page header/toolbar.
352
- - **Must** use shell **Tabs** / **SegmentedControl** for primary view switching when the product uses that pattern — do not duplicate the same navigation inline without reason.
353
- - **Avoid** duplicating shell navigation inside content.
354
-
355
- #### 6.3 Visual hierarchy
356
-
357
- **Applies when:** Any view with competing focal points.
358
-
359
- **Aura components:** `Button`, `Badge`, `Alert`, `Label`
360
-
361
- **Rules**
362
-
363
- - **Must** limit **primary** (`default` **Button**) to one obvious main action per view.
364
- - **Must** use **semantic tokens** for status (**Tokens** § Semantic) — no arbitrary hex.
365
- - **Must not** use **Button** `destructive` for non-destructive actions.
366
- - **Should** use type scale, weight, and spacing (**Tokens** § Typography / spacing) to lead attention.
367
-
368
- #### 6.4 Responsive behaviour
415
+ ## Typography
369
416
 
370
- **Applies when:** Viewport spans tablet / desktop / embedded shell widths.
417
+ Aura uses **Inter** for product UI, **Space Grotesk** for marketing display, and **Source Code Pro** for monospace. The type scale balances density for data interfaces with readable body copy at `{typography.body-md.fontSize}`.
371
418
 
372
- **Aura components:** `Card`, `Dialog`, `DropdownMenu`
373
- **Fusion shell:** `Topbar` overflow behavior
419
+ | Token | Font | Use |
420
+ | ------------------------------ | --------------- | ----------------------------------- |
421
+ | `--font-sans` / `--font-inter` | Inter | Default UI — copy, labels, dense UI |
422
+ | `--font-marketing` | Space Grotesk | Marketing / display headings only |
423
+ | `--font-mono` | Source Code Pro | Code, technical strings |
374
424
 
375
- **Rules**
425
+ **Type scale** — values live in the YAML `typography` tokens. Typical **semantic styles** map as follows:
376
426
 
377
- - **Should** verify layouts at common widths (e.g. 768 / 1024 / 1440px) when shipping responsive surfaces.
378
- - **Should** prefer **Dialog** / shell **Drawer** for secondary tasks on narrow viewports instead of cramming wide panels.
379
- - **Avoid** hard-coded pixel widths that bypass Tailwind and Aura layout tokens.
427
+ | Style | Token | Tailwind class | Use |
428
+ | --------- | ---------------------- | -------------- | ------------------------ |
429
+ | `display` | `{typography.display}` | `text-5xl` | Hero / marketing display |
430
+ | `h1` | `{typography.h1}` | `text-4xl` | Page title |
431
+ | `h2` | `{typography.h2}` | `text-3xl` | Section title |
432
+ | `h3` | `{typography.h3}` | `text-2xl` | Subsection |
433
+ | `h4` | `{typography.h4}` | `text-xl` | Group label |
434
+ | `body-md` | `{typography.body-md}` | `text-base` | Default body |
435
+ | `body-sm` | `{typography.body-sm}` | `text-sm` | Secondary body |
436
+ | `label` | `{typography.label}` | `text-xs` | Form labels, compact UI |
437
+ | `code` | `{typography.code}` | `text-sm` | Monospace content |
380
438
 
381
439
  ---
382
440
 
383
- ### 7. Accessibility and inclusive design
384
-
385
- Aura targets **WCAG AA** for primitives — usage must preserve that.
386
-
387
- #### 7.1 Keyboard accessibility
388
-
389
- **Applies when:** Any interactive **Aura** component or custom control.
390
-
391
- **Rules**
392
-
393
- - **Must** complete every task path with keyboard alone — do not break Radix / Base focus traps or `Tab` order.
394
- - **Must** keep a visible **focus** treatment per **Interaction states** — never `outline-none` / `ring-0` **without** Aura’s `shadow-focus-ring` equivalent.
395
- - **Must** expose **DropdownMenu**, **Dialog**, and other overlays via keyboard, not pointer-only triggers.
396
- - **Avoid** critical behavior on `onMouseEnter` / `onMouseLeave` without a keyboard-accessible path.
397
-
398
- #### 7.2 Color contrast and readability
441
+ ## Layout
399
442
 
400
- **Applies when:** Text, icons, or controls on colored surfaces.
443
+ ### Dashboard quick start (agent checklist)
401
444
 
402
- **Rules**
403
-
404
- - **Must** use **Tokens** for color — no stray hex / arbitrary Tailwind color literals.
405
- - **Must not** override colors in ways that drop below **4.5:1** for normal text (or **3:1** for large text) against its background.
406
- - **Must not** encode meaning with **color alone** — pair with icon, **HelperText**, or label.
407
- - **Avoid** `muted-foreground` for text the user must read to complete a task.
408
-
409
- #### 7.3 ARIA and semantic markup
410
-
411
- **Applies when:** Composing Aura primitives or wrapping native elements.
412
-
413
- **Rules**
414
-
415
- - **Must** use each primitive for its intended role — not **Button** as navigation that should be `<a>`.
416
- - **Must** name icon-only controls (`aria-label` / `aria-labelledby`) and supply **Tooltip** where design hides text.
417
- - **Should** use landmark elements (`main`, `nav`, `header`) at page level alongside Aura layout.
418
- - **Avoid** stripping default ARIA from primitives without an equivalent.
419
-
420
- #### 7.4 Touch and click targets
421
-
422
- **Applies when:** Touch or motor accessibility matters.
423
-
424
- **Rules**
445
+ For pages with data-heavy layouts — cards, charts, metric tiles — work through these steps before writing component code.
425
446
 
426
- - **Must** meet **WCAG 2.5** target-size expectations — do not ship tappable UI smaller than the primitive’s documented interactive box without an invisible hit-area expansion.
427
- - **Should** keep comfortable spacing between adjacent tap targets (use spacing tokens, not zero gap).
428
- - **Avoid** sub-24px icon hit zones without expansion in dense tables.
447
+ - [ ] **Tokens** — confirm all colors use semantic or chart tokens, no raw hex. Metric tiles: `decorative-*`. Data series: `chart-*`. Status: `info-*`, `success-*`, `warning-*`, `destructive-*`. See [Colors](#colors).
448
+ - [ ] **Layout** — use a 12-column grid with `gap-4` or `gap-6`. Tile widths: `col-span-12 sm:col-span-6 lg:col-span-3`. Cap the page frame with `max-w-[min(100%,var(--container-8xl))]`.
449
+ - [ ] **Cards** — use the `Card` component with title, description, and a primary action. Do not stack unrelated actions in the same card. See [Layout and hierarchy](#6-layout-and-hierarchy).
450
+ - [ ] **Loading states** — every data region must show `Shimmer` (known layout) or `Loader` (unknown layout) while fetching. See [Feedback and system status](#1-feedback-and-system-status).
451
+ - [ ] **Status signals** — default to **Badge** or compact status cards for repeated states; keep **Alert** to one page-level inline instance unless multiple independent incidents each need separate action. See [Alert vs Banner vs Badge vs Sonner](#alert-vs-banner-vs-badge-vs-sonner).
452
+ - [ ] **Navigation** — one primary app chrome; avoid duplicating global navigation inside content. See [Layout and hierarchy](#6-layout-and-hierarchy).
453
+ - [ ] **Accessibility** — every chart must have a text summary of key insights. Icon-only controls must have `aria-label` and a `Tooltip`. See [Accessibility and inclusive design](#7-accessibility-and-inclusive-design).
429
454
 
430
- ### Common pitfalls (agent guidance)
455
+ ### Layout and spacing
431
456
 
432
- These are the most frequent mistakes when generating or modifying Aura-based UI. Avoid all of them.
457
+ Width and spacing values in this subsection follow the **`{spacing.base}`-based** spacing scale in **[Layout → Size and dimensions](#size-and-dimensions)**.
433
458
 
434
- **Raw hex or hardcoded colors**
459
+ **Body text reading width**
435
460
 
436
- Do not write `#486AED`, `rgb(...)`, or arbitrary Tailwind color literals like `text-blue-600`. Always use a semantic, base, or chart token. If no token fits the intent, choose the closest documented base token. Using raw values breaks dark mode and makes token-level theming impossible.
461
+ - **Must** cap **continuous body text** (paragraphs, descriptions, long labels) at a **maximum width of `{spacing.prose-max}`** for comfortable reading.
462
+ - **Must** apply that limit to the **text column only** — companion UI (icons, thumbnails, side metadata, charts, code blocks) **may** sit outside that `{spacing.prose-max}` band in the same row or card; do not shrink the text measure to absorb those elements.
463
+ - **Should** implement the cap with `max-w-[{spacing.prose-max}]` / `max-w-[37.5rem]` (or an equivalent layout wrapper) on the text block, not by stretching typography alone inside an arbitrarily wide container.
437
464
 
438
- **Overriding style tokens or component styles**
465
+ ### Size and dimensions
439
466
 
440
- Do not add `style={{ color: '...' }}`, override Tailwind utilities that shadow Aura tokens, or patch component internals with ad-hoc CSS. The ESLint `className-override` rule will flag LLM-generated style overrides for this reason. If a component does not support a needed variant, raise it — do not work around it.
467
+ Aura aligns to a **`{spacing.base}` base grid**. Spacing in components follows **Tailwind spacing** (`p-*`, `gap-*`, `m-*`): one unit = **`{spacing.base}`** unless overridden. Common steps:
441
468
 
442
- **Duplicate or parallel navigation**
469
+ | Name | Token | Tailwind | Typical use |
470
+ | ---- | --------------- | -------- | -------------------------------- |
471
+ | xs | `{spacing.xs}` | `1` | Tight gaps, icon padding |
472
+ | sm | `{spacing.sm}` | `2` | Inline controls, compact padding |
473
+ | md | `{spacing.md}` | `3` | Card / popover internal padding |
474
+ | lg | `{spacing.lg}` | `4` | Related groups |
475
+ | xl | `{spacing.xl}` | `5` | Sections |
476
+ | 2xl | `{spacing.2xl}` | `6` | Page regions |
477
+ | 3xl | `{spacing.3xl}` | `8` | Large layout gaps |
443
478
 
444
- Every app has exactly one Topbar. Do not render a second header, a sidebar for primary navigation, or duplicate breadcrumbs outside the Topbar. Page-specific sub-navigation belongs in the content area.
479
+ Layout helpers in theme: `--container-2xl` (`{spacing.container-2xl}`), `--container-8xl` (`{spacing.container-8xl}`), `--message-content-max-width` (80% for chat content).
445
480
 
446
- **Overly dense card layouts**
481
+ ### Width and max content
447
482
 
448
- Do not stack unrelated actions or data types in a single Card, and do not reduce spacing below the 4 px grid scale. Cards should group one related concern with clear hierarchy: title, supporting content, one primary action.
483
+ Aura adjusts Tailwind **container** breakpoints where the default scale is too wide or too narrow for data-dense product surfaces:
449
484
 
450
- **Mixing chart, decorative, and semantic color tokens**
485
+ | Token | Value | Role |
486
+ | ----------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
487
+ | `--container-2xl` | `{spacing.container-2xl}` | Narrower than Tailwind’s default `2xl` container — useful outer bound for regions; **body copy** inside can still follow the **`{spacing.prose-max}`** reading rule above |
488
+ | `--container-8xl` | `{spacing.container-8xl}` | Wide upper bound for dashboards and full-bleed marketing rows |
451
489
 
452
- `chart-*` is for data series and plot areas only. `decorative-*` is for non-data differentiation (metric tile accents, avatars). `semantic-*` (`info-*`, `success-*`, etc.) is for operational status and feedback. Do not use chart or decorative tokens to imply system health or validation state.
490
+ Prefer **`max-w-*`** (and other width utilities) tied to the theme over ad-hoc pixel `max-width` on wrappers. **Global frame** width (host chrome) is defined by the **host application**; **inside** the frame, combine these tokens with responsive utilities so regions reflow predictably.
453
491
 
454
- **Icon-only controls without accessible names**
492
+ ### Specialized variables
455
493
 
456
- Every icon-only Button must have `aria-label` and a `Tooltip`. Do not rely on visual context alone.
494
+ | Variable | Value | Use |
495
+ | ----------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------- |
496
+ | `--message-content-max-width` | `80%` | Primary column for chat / assistant **Message** content in wide threads |
497
+ | `--drawer-max-height` | `80vh` | Maximum height for top/bottom drawer-style panels when the host implements them |
498
+ | `--alert-icon-width` | `calc(var(--spacing) * 4)` (typically **16px**) | Fixed icon column in the **Alert** layout so titles and descriptions align |
457
499
 
458
- **Disabled primary CTA with no resolution path**
500
+ ### Regional spacing
459
501
 
460
- Do not disable the main action without showing the user how to re-enable it. Pair a disabled CTA with a `HelperText` or `Tooltip` explaining the blocker.
502
+ - **Must** use the **spacing scale** for padding, margin, and `gap` between regions (`gap-*`, `p-*`, `m-*`) — see **Layout → Size and dimensions**.
503
+ - **Should** keep major block **padding** and **gap** on **`{spacing.base}`** multiples so control heights, radii, and typography line up visually.
504
+ - **Should** group related regions in **Card** (and **Separator** when two unrelated groups share a container) before mixing unrelated actions into the same band — see [Layout and hierarchy](#6-layout-and-hierarchy).
505
+ - **Avoid** one-off pixel gutters that ignore the scale unless matching a fixed graphic asset.
461
506
 
462
- ---
507
+ ### Responsive behavior
463
508
 
464
- ### For `llms.txt` / agent exports
509
+ - **Should** move secondary work into **Dialog** or a shell **Drawer** on narrow widths instead of compressing multi-column chrome.
510
+ - **Avoid** single-breakpoint layouts tuned only to a static design frame — use breakpoints, wrapping, and flexible sizing utilities where content must grow and shrink.
465
511
 
466
- When splitting or stripping this doc for agents:
512
+ ### Shell vs content
467
513
 
468
- - Drop decorative emoji or ornamental Unicode if any appear in future edits.
469
- - Keep **Must** / **Should** / **Avoid** / **must not** wording — severity is the routing signal.
470
- - Keep each **Applies when:** line — it tells the agent which subsection fires.
471
- - Keep **Aura components:** lines aligned with [`src/components/index.ts`](./src/components/index.ts) exports (public entry for `@cognite/aura/components`); treat **App / Fusion shell** lines as integration responsibilities, not as Aura package exports.
472
- - Preserve links: [Aura Storybook](https://storybook-aura-23638.fusion-preview.preview.cogniteapp.com); [Aura documentation](https://docs.cognite.com/aura-design-system/get-started) for published guides. Fetch current prop names from Storybook or source before codegen.
473
- - If you split by section (§1–§7), repeat the **Severity** and **Scope** bullets at the top of each file so standalone chunks stay interpretable.
474
- - Preserve **[Content](#content)** for action verbs, date/time rules, and tone; agents generating strings should follow it alongside **Heuristics**.
514
+ **Global chrome** (workspace switcher, app-level navigation) is implemented by the **host application shell**, not the Aura component library. **Must** still theme that chrome with Aura **tokens** so shell and in-app surfaces feel continuous. **In-app content** should rely on Aura primitives (**Card**, **Banner**, **Dialog**, forms) plus the width and spacing rules above.
475
515
 
476
516
  ---
477
517
 
478
- ## Tokens
479
-
480
- **What this section is:** The token reference for Aura — color (base, semantic, decorative), typography, spacing, radii, borders, and effects. Consume tokens via **CSS variables** (e.g. `var(--background)`) or **Tailwind theme** utilities (e.g. `bg-background`, `text-muted-foreground`, `shadow-default`, `rounded-lg`). Do not hardcode hex, font sizes, or shadow strings in product UI when a token exists.
481
-
482
- **Theming:** Aura supports **light** (`:root`) and **dark** (`.dark` / `prefers-color-scheme: dark` per library setup). Semantic and base tokens **resolve to different ramps** per theme. **`background-fixed-dark`**, **`background-fixed-light`**, **`foreground-fixed-*`**, and related **fixed** tokens keep the same appearance in both themes (persistent chrome such as sidebars). Always verify contrast in both themes in Storybook or the consuming app.
483
-
484
- **Agents:** Reference tokens by **full CSS name** or Tailwind token. Never use raw `hex` / `rgb` / `hsl` in product code. If no semantic token fits, use a documented **base** token; **step colors** on ramps (`mountain/*`, `fjord/*`, …) are only for custom, branding, or marketing surfaces where no semantic token exists yet.
485
-
486
- ### Common Tailwind mappings
487
-
488
- Tables in this section use **CSS role names** (e.g. `link-foreground`, `card-background`). Aura registers each role as `--color-{role}` in `@theme inline` in [`src/colors.css`](./src/colors.css); Tailwind v4 exposes utilities **`text-{role}`**, **`bg-{role}`**, **`border-{role}`** (and **`ring-{role}`** / **`shadow-*`** where documented in **Effects**). Prefer these utilities in components over raw `var(--…)` when the theme wire-up matches.
489
-
490
- | Role (suffix after `text-` / `bg-` / `border-`) | Typical utilities | Notes |
491
- | :--- | :--- | :--- |
492
- | `background` | `bg-background` | Page base |
493
- | `foreground` | `text-foreground` | Primary text |
494
- | `muted-foreground` | `text-muted-foreground` | Tertiary copy |
495
- | `card-background` | `bg-card-background` | Cards (see **Card** component) |
496
- | `muted-background` | `bg-muted-background` | Static fills, inputs, secondary chrome |
497
- | `border` | `border-border` | Default strokes |
498
- | `link-foreground` | `text-link-foreground` | Text links |
499
- | `primary-background` | `bg-primary-background`, `text-foreground-on-primary` | Default **Button** (`variant="default"`) pattern |
500
- | `destructive-background` | `bg-destructive-background`, `text-destructive-foreground-on-critical` (on surface) | Destructive actions — pairings in **Semantic colors** |
501
- | `info-background`, `success-background`, … | `bg-info-background`, `text-info-foreground`, … | Full names match **Semantic colors** token columns |
502
-
503
- Semantic utilities use the **full token name** as the Tailwind segment (e.g. `bg-info-background`, not `bg-info`). For **charts**, utilities follow the **Chart tokens** names (`bg-chart-fjord-color-1`, `bg-chart-gridlines`, …). For exhaustive coverage, use [`src/colors.css`](./src/colors.css) or your IDE on `@cognite/aura`.
504
-
505
- Tables below list **approximate hex** resolved from [`src/colors.css`](./src/colors.css) at build time; the source of truth is the synced file (some entries are `rgba()`).
506
-
507
- ### Color
508
-
509
- Aura groups color into **Base** (~80–90% of UI), **Semantic** (status and feedback, ~5–10%), and **Decorative** (accents and illustration, ~5–10%) so color carries **meaning** and stays calm.
510
-
511
- #### Base — Background
512
-
513
- | Token | Light (reference) | Dark (reference) | Use |
514
- | :--- | :--- | :--- | :--- |
515
- | `background` | `#FFFFFF` | `#191B1D` | Primary surface — lowest layer |
516
- | `alternate-background` | `#F9FAFA` | `#111213` | Distinct layer or block separate from `background` |
517
- | `card-background` | `#F9FAFA` | `#212426` | Cards without drop shadow on `background` / `alternate-background` |
518
- | `muted-background` | `#F1F2F3` | `#2D3134` | Static fills for controls, rows, segmented controls |
519
- | `primary-background` | `#212426` | `#F9FAFA` | Primary actions (default button); use sparingly |
520
- | `primary-background-hover` | `#40464A` | `#E4E6E8` | Hover on `primary-background` |
521
- | `secondary-background` | `#E4E6E8` | `#40464A` | Secondary actions, switch track |
522
- | `secondary-background-hover` | `#D4D7D9` | `#5E666D` | Hover on `secondary-background` |
523
- | `accent-background` | `#F1F2F3` | `#2D3134` | Neutral hover on `background` / `card-background` (e.g. tabs) |
524
- | `accent-background-strong` | `#E4E6E8` | `#40464A` | Neutral hover on `muted-background` / `active-muted-background` |
525
- | `highlight-background` | `#F1F2F3` | `#2D3134` | Focused / active fields (inputs, selects, comboboxes) |
526
- | `highlight-background-strong` | `#E4E6E8` | `#40464A` | Stronger focused / active field fill |
527
- | `active-background` | `#191B1D` | `#F9FAFA` | High-contrast “on” (switch, checkbox, radio) |
528
- | `active-background-hover` | `#2D3134` | `#F1F2F3` | Hover on `active-background` |
529
- | `active-muted-background` | `#F1F2F3` | `#2D3134` | Lower-contrast selected (e.g. tabs) |
530
- | `active-muted-background-hover` | `#E4E6E8` | `#40464A` | Hover on `active-muted-background` |
531
- | `popover-background` | `#FFFFFF` | `#212426` | Top-layer surfaces with shadow (dialogs, popovers) |
532
- | `raised-background` | `#2D3134` | `#40464A` | Tooltips, Sonner toasts — floats above page |
533
- | `disabled-background` | `#F1F2F3` | `#2D3134` | Disabled inputs and controls |
534
- | `overlay-background` | `#7C868E80` | `#7C868E80` | Scrim behind modals |
535
- | `background-fixed-dark` | `#212426` | `#212426` | Must stay **dark** in both themes |
536
- | `background-fixed-light` | `#FFFFFF` | `#FFFFFF` | Must stay **light** in both themes |
537
- | `accent-background-fixed-dark` | `#2D3134` | `#2D3134` | Persistent dark accent chrome (e.g. sidebar) |
538
-
539
- #### Base — Foreground
540
-
541
- | Token | Light (reference) | Dark (reference) | Use |
542
- | :--- | :--- | :--- | :--- |
543
- | `foreground` | `#191B1D` | `#F1F2F3` | Primary text and icons |
544
- | `secondary-foreground` | `#40464A` | `#D4D7D9` | Supporting text and icons |
545
- | `muted-foreground` | `#6D767E` | `#A5ABB1` | Tertiary / low emphasis |
546
- | `disabled-foreground` | `#D4D7D9` | `#5E666D` | Disabled text and icons |
547
- | `link-foreground` | `#486AED` | `#1742E7` | Text links |
548
- | `foreground-on-primary` | `#F1F2F3` | `#191B1D` | On `primary-background` |
549
- | `foreground-on-active` | `#F1F2F3` | `#191B1D` | On `active-background` |
550
- | `active-foreground` | `#191B1D` | `#F1F2F3` | On `active-muted-background` |
551
- | `foreground-fixed-dark` | `#191B1D` | `#191B1D` | Must stay dark in both themes |
552
- | `foreground-fixed-light` | `#FFFFFF` | `#FFFFFF` | Must stay light in both themes |
553
- | `foreground-secondary-fixed-dark` | `#40464A` | `#40464A` | Secondary copy, always dark |
554
- | `secondary-foreground-fixed-light` | `#D4D7D9` | `#D4D7D9` | Secondary copy, always light |
555
- | `muted-foreground-fixed-light` | `#BBC0C4` | `#BBC0C4` | Muted copy, always light |
556
-
557
- #### Base — Borders and focus
558
-
559
- | Token | Light (reference) | Dark (reference) | Use |
560
- | :--- | :--- | :--- | :--- |
561
- | `border` | `#E4E6E8` | `#2D3134` | Default strokes |
562
- | `border-emphasized` | `#D4D7D9` | `#40464A` | Stronger separation |
563
- | `border-on-dark` | `#2D3134` | `#2D3134` | Strokes on dark chrome (both themes) |
564
- | `border-active` | `#191B1D` | `#F9FAFA` | Active / toggled outlines |
565
- | `ring` | `#7081C7` | `#7081C7` | Focus ring outer (maps to `--shadow-focus-ring`) |
566
- | `ring-muted` | `#B5BEE2` | `#B5BEE2` | Focus ring inner companion |
567
-
568
- Also generated: `ring-destructive`, `ring-destructive-muted` for destructive / invalid focus (see **Effects — Focus rings**).
569
-
570
- #### Semantic colors
571
-
572
- Semantic tokens are **only** for status and system feedback (Alert, Banner, Sonner, badge status variants, validation). Do not use them as generic fills or decoration.
573
-
574
- Each family has **default** pairings (theme-switching surfaces) and **muted** pairings (blocks on **persistent dark chrome**). On muted surfaces, use the same `*-foreground-on-*` token names with the muted background; verify contrast in context.
575
-
576
- **Info**
577
-
578
- | Token | Light (reference) | Dark (reference) | Use |
579
- | :--- | :--- | :--- | :--- |
580
- | `info-background` | `#D0D6ED` | `#B5BEE2` | Info surface |
581
- | `info-background-hover` | `#B5BEE2` | `#D0D6ED` | Hover on `info-background` |
582
- | `info-foreground` | `#4A5FB8` | `#9DA9D9` | Text near info context on standard surfaces |
583
- | `info-foreground-on-info` | `#32417F` | `#1A2242` | Text **on** `info-background` |
584
- | `info-muted-background` | `#F0F2F9` | `#2D3134` | Info tint on dark chrome |
585
- | *(pairing)* | — | — | On `info-muted-background`, use `info-foreground-on-info` for on-surface copy |
586
-
587
- **Success**
588
-
589
- | Token | Light (reference) | Dark (reference) | Use |
590
- | :--- | :--- | :--- | :--- |
591
- | `success-background` | `#BBF3D0` | `#8BDEAE` | Success surface |
592
- | `success-background-hover` | `#8BDEAE` | `#BBF3D0` | Hover on `success-background` |
593
- | `success-foreground` | `#1C984A` | `#24C45E` | Text near success on standard surfaces |
594
- | `success-foreground-on-success` | `#0F5026` | `#0A381C` | Text **on** `success-background` |
595
- | `success-muted-background` | `#DDF9E7` | `#2D3134` | Success on dark chrome |
596
- | *(pairing)* | — | — | On `success-muted-background`, use `success-foreground-on-success` |
597
-
598
- **Warning**
599
-
600
- | Token | Light (reference) | Dark (reference) | Use |
601
- | :--- | :--- | :--- | :--- |
602
- | `warning-background` | `#FFE3A2` | `#FFE3A2` | Warning surface |
603
- | `warning-background-hover` | `#FFD062` | `#FFF1D0` | Hover on `warning-background` |
604
- | `warning-foreground` | `#C18800` | `#D8BF00` | Text near warning on standard surfaces |
605
- | `warning-foreground-on-warning` | `#755200` | `#5B4000` | Text **on** `warning-background` |
606
- | `warning-muted-background` | `#FFF1D0` | `#2D3134` | Warning on dark chrome |
607
-
608
- **Destructive**
609
-
610
- | Token | Light (reference) | Dark (reference) | Use |
611
- | :--- | :--- | :--- | :--- |
612
- | `destructive-background` | `#FCCAD2` | `#FAA9B7` | Error / destructive surface |
613
- | `destructive-background-hover` | `#FAA9B7` | `#FCCAD2` | Hover on `destructive-background` |
614
- | `destructive-foreground` | `#CB0B2C` | `#F65E78` | Text near destructive context on standard surfaces |
615
- | `destructive-foreground-on-critical` | `#8D081F` | `#8D081F` | Text **on** `destructive-background` |
616
- | `destructive-muted-background` | `#FDDEE4` | `#2D3134` | Destructive on dark chrome |
617
- | `destructive-muted-background-hover` | `#FCCAD2` | `#40464A` | Hover on `destructive-muted-background` |
618
-
619
- **Neutral** (status: draft, archived — not “semantic calm” in the same sense as info/success)
620
-
621
- | Token | Light (reference) | Dark (reference) | Use |
622
- | :--- | :--- | :--- | :--- |
623
- | `neutral-background` | `#E4E6E8` | `#D4D7D9` | Neutral status surface |
624
- | `neutral-background-hover` | `#D4D7D9` | `#E4E6E8` | Hover on `neutral-background` |
625
- | `neutral-foreground` | `#52595F` | `#A5ABB1` | Text near neutral status |
626
- | `neutral-foreground-on-neutral` | `#40464A` | `#2D3134` | Text **on** `neutral-background` |
627
- | `neutral-muted-background` | `#F1F2F3` | `#2D3134` | Neutral on dark chrome |
628
-
629
- **Naming:** CSS uses full role names (`info-foreground-on-info`, `neutral-foreground-on-neutral`, `destructive-foreground-on-critical`). There is no shortened alias in the theme.
630
-
631
- #### Decorative colors
632
-
633
- For **small accents** (badges, avatars, empty states) where color differentiates but does **not** signal status — use **Chart tokens** for plot colors, not this ramp, unless a design explicitly maps a tile to a series color. Pattern: `decorative-background-{ramp}`, `decorative-background-{ramp}-hover`, `decorative-foreground-{ramp}`.
634
-
635
- **Preference order for new work:**
636
-
637
- | Priority | Ramp | Background | Foreground |
638
- | :---: | :--- | :--- | :--- |
639
- | 1 | Fjord | `decorative-background-fjord` | `decorative-foreground-fjord` |
640
- | 2 | Nordic | `decorative-background-nordic` | `decorative-foreground-nordic` |
641
- | 3 | Aurora | `decorative-background-aurora` | `decorative-foreground-aurora` |
642
- | 4 | Dusk | `decorative-background-dusk` | `decorative-foreground-dusk` |
643
- | 5 | Orange | `decorative-background-orange` | `decorative-foreground-orange` |
644
- | 6 | Sky | `decorative-background-sky` | `decorative-foreground-sky` |
645
- | 7 | Mountain | `decorative-background-mountain` | `decorative-foreground-mountain` |
646
-
647
- Example (fjord ramp): light `decorative-background-fjord` → `#CCD5FA` (fjord-200), `decorative-foreground-fjord` → `#1234B6` (fjord-700); dark → `#AEBDF7` / `#0D2582` (fjord-300 / fjord-800). Every ramp resolves in [`src/colors.css`](./src/colors.css).
648
-
649
- #### Chart tokens
518
+ ## Elevation & Depth
650
519
 
651
- **Priority rule:** use `chart-*` for any data plotted on axes or series; use `decorative-*` for non-data visual differentiation (tiles, avatars, accents); use semantic tokens (`info-*`, `success-*`, `warning-*`, `destructive-*`) for operational status and feedback only. Never swap between these groups.
520
+ ### Shadows
652
521
 
653
- | Token | Use |
654
- | :--- | :--- |
655
- | `chart-{ramp}-color-1` … `chart-{ramp}-color-6` | Alpha-based series / area-fill steps (strongest → lightest) |
656
- | `chart-gridlines` | Grid lines |
522
+ `--effect-shadow-sm` through `--effect-shadow-xl` are **alpha blacks** tuned per theme. Tailwind shadow utilities compose layered stacks from these tokens:
657
523
 
658
- Default series order: **fjord → nordic → aurora → dusk → orange**.
524
+ | Tailwind shadow | Built from `--effect-shadow-*` | Light (α) | Dark (α) | Use (per theme comments in CSS) |
525
+ | ---------------- | ------------------------------ | ----------- | ----------- | -------------------------------------------------- |
526
+ | `shadow-sm` | `--effect-shadow-sm` | 0.04 | 0.2 | Tooltips, small floating containers |
527
+ | `shadow-default` | md + sm layers | 0.05 + 0.04 | 0.302 + 0.2 | Menus, popovers, hover cards |
528
+ | `shadow-md` | lg + md layers | 0.06 + 0.05 | 0.4 + 0.302 | Sonner toasts, temporary elevated elements |
529
+ | `shadow-lg` | xl + lg layers | 0.10 + 0.06 | 0.6 + 0.4 | Modals / dialogs **without** full backdrop overlay |
530
+ | `shadow-xl` | xl + lg layers | 0.10 + 0.06 | 0.6 + 0.4 | Modals / dialogs **with** backdrop overlay |
659
531
 
660
- ---
532
+ Exact pixel stacks are defined in the theme CSS alongside `--shadow-sm` … `--shadow-xl`.
661
533
 
662
- ### Typography
534
+ ### Focus rings
663
535
 
664
- Aura uses three **font families** (loaded in [`src/styles.source.css`](./src/styles.source.css)):
536
+ Shadow-based (not `outline`) for consistent rendering:
665
537
 
666
- | Token | Font | Use |
667
- | :--- | :--- | :--- |
668
- | `--font-sans` / `--font-inter` | Inter | Default UI — copy, labels, dense UI |
669
- | `--font-marketing` | Space Grotesk | Marketing / display headings only |
670
- | `--font-mono` | Source Code Pro | Code, technical strings |
538
+ | Token | Composition | Use |
539
+ | --------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------- |
540
+ | `--shadow-focus-ring` | `0 0 0 1px var(--ring)` (`{colors.ring}`), `0 0 0 3px var(--ring-muted)` (`{colors.ring-muted}`) | Default focus on interactive controls |
541
+ | `--shadow-focus-ring-destructive` | `0 0 0 1px var(--ring-destructive), 0 0 0 3px var(--ring-destructive-muted)` | Destructive / invalid focus |
671
542
 
672
- **Type scale** — sizes and line heights are driven by Tailwind v4 theme overrides (`--text-*`, `--text-*--line-height`) and tracking tokens (`--tracking-tight`, `--tracking-tighter`, `--tracking-tightest`). Typical **semantic styles** map as follows (use Storybook / product patterns for exact classes):
543
+ ### Opacity
673
544
 
674
- | Style | Font | Size | Weight | Line height | Letter spacing | Use |
675
- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
676
- | `display` | Space Grotesk | 36px (`text-5xl`) | 600 | 44px | -0.08px | Hero / marketing display |
677
- | `h1` | Inter | 32px (`text-4xl`) | 600 | 40px | -0.08px | Page title |
678
- | `h2` | Inter | 28px (`text-3xl`) | 600 | 32px | -0.08px | Section title |
679
- | `h3` | Inter | 24px (`text-2xl`) | 600 | 28px | -0.04px | Subsection |
680
- | `h4` | Inter | 20px (`text-xl`) | 500 | 24px | -0.04px | Group label |
681
- | `body-md` | Inter | 16px (`text-base`) | 400 | 20px | -0.04px | Default body |
682
- | `body-sm` | Inter | 14px (`text-sm`) | 400 | 18px | -0.04px | Secondary body |
683
- | `label` | Inter | 12px (`text-xs`) | 500 | 14px | -0.04px | Form labels, compact UI |
684
- | `code` | Source Code Pro | 14px (`text-sm`) | 400 | 20px | — | Monospace content |
545
+ | Token / concept | Value | Use |
546
+ | ------------------------------------------------ | ------------------------ | --------------------------------- |
547
+ | `--opacity-10` … `--opacity-80` (+ `*-inverted`) | rgba steps | Overlays, glass effects |
548
+ | Overlay scrim | via `overlay-background` | Modal backdrop (see color tables) |
549
+ | Chart fills | `chart-*-color-*` | See **Chart tokens** |
685
550
 
686
551
  ---
687
552
 
688
- ### Size and dimensions
689
-
690
- Aura aligns to a **4px base grid**. Spacing in components follows **Tailwind spacing** (`p-*`, `gap-*`, `m-*`): one unit = **4px** unless overridden. Common steps:
691
-
692
- | Name | Value | Tailwind | Typical use |
693
- | :--- | :--- | :--- | :--- |
694
- | xs | 4px | `1` | Tight gaps, icon padding |
695
- | sm | 8px | `2` | Inline controls, compact padding |
696
- | md | 12px | `3` | Card / popover internal padding |
697
- | lg | 16px | `4` | Related groups |
698
- | xl | 20px | `5` | Sections |
699
- | 2xl | 24px | `6` | Page regions |
700
- | 3xl | 32px | `8` | Large layout gaps |
701
-
702
- Layout helpers in theme: `--container-2xl` (40rem), `--container-8xl` (96rem), `--message-content-max-width` (80% for chat content).
703
-
704
- #### Component heights
705
-
706
- Heights are **not** always single CSS variables; primitives use Tailwind height utilities. Representative values from core components:
707
-
708
- | Size | Height | Aura usage |
709
- | :--- | :--- | :--- |
710
- | xs | 20px (`h-5`) | Badge (default) |
711
- | sm | 28px (`h-7`) | Button `sm`, compact rows |
712
- | md | 36px (`h-9`) | Button default, Input, Select, many menu rows |
713
- | lg | 40px (`h-10`) | Button `lg` |
714
- | Icon button | 28 / 36 / 40px | `icon-sm` / default / `icon-lg` (`size-7`, `size-9`, `size-10`) |
715
-
716
- **Topbar** height is **application-defined** (not a single Aura token). **Table / list row** density varies by product; menu and command patterns often use **36px** (`h-9`) rows.
717
-
718
- ---
553
+ ## Shapes
719
554
 
720
555
  ### Corner radius
721
556
 
722
- Defined in [`src/styles.source.css`](./src/styles.source.css). Default interactive radius in components is often **`rounded-lg` (8px)** for buttons/inputs; cards and overlays use **`rounded-lg`**–**`rounded-xl`**.
723
-
724
- | Token | Value | Use |
725
- | :--- | :--- | :--- |
726
- | `--radius-none` | 0px | Dividers, full-bleed |
727
- | `--radius-xs` | 2px | Tight inner chrome |
728
- | `--radius-sm` | 4px | Small controls, badges |
729
- | `--radius-md` / `--radius` | 6px | Maps to `rounded-md` — shared default in theme |
730
- | `--radius-lg` | 8px | **Default** for many controls (Button, Input) via `rounded-lg` |
731
- | `--radius-xl` | 12px | Dialogs, large cards, popovers |
732
- | `--radius-2xl` | 16px | Extra-large surfaces |
733
- | `--radius-3xl` | 24px | Marketing / hero panels |
734
- | `--radius-4xl` | 32px | Largest marketing rounding |
735
- | `--radius-full` | 9999px | Pills, avatars |
557
+ Defined in the theme. Default interactive radius in components is often **`rounded-lg`** (`{rounded.lg}`) for buttons/inputs; cards and overlays use **`rounded-lg`**–**`rounded-xl`** (`{rounded.lg}`–`{rounded.xl}`).
736
558
 
737
- ---
559
+ | CSS variable | Token | Use |
560
+ | -------------------------- | ---------------- | -------------------------------------------------------------- |
561
+ | `--radius-none` | `{rounded.none}` | Dividers, full-bleed |
562
+ | `--radius-xs` | `{rounded.xs}` | Tight inner chrome |
563
+ | `--radius-sm` | `{rounded.sm}` | Small controls, badges |
564
+ | `--radius-md` / `--radius` | `{rounded.md}` | Maps to `rounded-md` — shared default in theme |
565
+ | `--radius-lg` | `{rounded.lg}` | **Default** for many controls (Button, Input) via `rounded-lg` |
566
+ | `--radius-xl` | `{rounded.xl}` | Dialogs, large cards, popovers |
567
+ | `--radius-2xl` | `{rounded.2xl}` | Extra-large surfaces |
568
+ | `--radius-3xl` | `{rounded.3xl}` | Marketing / hero panels |
569
+ | `--radius-4xl` | `{rounded.4xl}` | Largest marketing rounding |
570
+ | `--radius-full` | `{rounded.full}` | Pills, avatars |
738
571
 
739
- ### Border
572
+ ### Borders
740
573
 
741
574
  Aura is visually **flat**; surfaces, spacing, and typography do most structure. Add borders only when separation or affordance needs extra clarity.
742
575
 
@@ -748,105 +581,65 @@ Aura is visually **flat**; surfaces, spacing, and typography do most structure.
748
581
  - **Avoid** drawing borders around every item in a list/card just to create visual rhythm.
749
582
  - **Avoid** decorative outline stacks (`border` + `ring` + inset strokes) when no state or interaction meaning is conveyed.
750
583
 
751
- | Concept | Value | Use |
752
- | :--- | :--- | :--- |
753
- | Default width | **1px** | Tailwind `border` — tables, inputs, and occasional structural dividers |
754
- | Emphasized width | **2px** | Stronger separation or invalid/critical state emphasis |
755
- | Border color | `border`, `border-emphasized`, … | See **Base — Borders and focus** |
756
- | Style | solid | Default |
584
+ | Concept | Value | Use |
585
+ | ---------------- | -------------------------------- | ---------------------------------------------------------------------- |
586
+ | Default width | **1px** | Tailwind `border` — tables, inputs, and occasional structural dividers |
587
+ | Emphasized width | **2px** | Stronger separation or invalid/critical state emphasis |
588
+ | Border color | `border`, `border-emphasized`, … | See **Base — Borders and focus** |
589
+ | Style | solid | Default |
757
590
 
758
591
  ---
759
592
 
760
- ### Effects
761
-
762
- #### Shadows
593
+ ## Components
763
594
 
764
- `--effect-shadow-sm` through `--effect-shadow-xl` are **alpha blacks** (tuned per theme in [`src/colors.css`](./src/colors.css)). [`src/styles.source.css`](./src/styles.source.css) composes Tailwind shadows:
595
+ ### Component heights
765
596
 
766
- | Tailwind shadow | Built from `--effect-shadow-*` | Light (α) | Dark (α) | Use (per theme comments in CSS) |
767
- | :--- | :--- | :--- | :--- | :--- |
768
- | `shadow-sm` | `--effect-shadow-sm` | 0.04 | 0.2 | Tooltips, small floating containers |
769
- | `shadow-default` | md + sm layers | 0.05 + 0.04 | 0.302 + 0.2 | Menus, popovers, hover cards |
770
- | `shadow-md` | lg + md layers | 0.06 + 0.05 | 0.4 + 0.302 | Sonner toasts, temporary elevated elements |
771
- | `shadow-lg` | xl + lg layers | 0.10 + 0.06 | 0.6 + 0.4 | Modals / dialogs **without** full backdrop overlay |
772
- | `shadow-xl` | xl + lg layers | 0.10 + 0.06 | 0.6 + 0.4 | Modals / dialogs **with** backdrop overlay |
773
-
774
- Exact pixel stacks: `--shadow-sm` … `--shadow-xl` in [`src/styles.source.css`](./src/styles.source.css).
775
-
776
- #### Focus rings
777
-
778
- Shadow-based (not `outline`) for consistent rendering:
779
-
780
- | Token | Composition | Use |
781
- | :--- | :--- | :--- |
782
- | `--shadow-focus-ring` | `0 0 0 1px var(--ring), 0 0 0 3px var(--ring-muted)` | Default focus on interactive controls |
783
- | `--shadow-focus-ring-destructive` | `0 0 0 1px var(--ring-destructive), 0 0 0 3px var(--ring-destructive-muted)` | Destructive / invalid focus |
784
-
785
- #### Opacity
786
-
787
- | Token / concept | Value | Use |
788
- | :--- | :--- | :--- |
789
- | `--opacity-10` … `--opacity-80` (+ `*-inverted`) | rgba steps | Overlays, glass effects |
790
- | Overlay scrim | via `overlay-background` | Modal backdrop (see color tables) |
791
- | Chart fills | `chart-*-color-*` | See **Chart tokens** |
597
+ Heights are **not** always single CSS variables; primitives use Tailwind height utilities. Representative values from core components:
792
598
 
793
- #### Motion (reference)
599
+ | Size | Component token | Height | Aura usage |
600
+ | ----------- | ----------------------------- | -------------- | --------------------------------------------- |
601
+ | xs | `{components.badge-xs}` | 20px (`h-5`) | Badge (default) |
602
+ | sm | `{components.button-sm}` | 28px (`h-7`) | Button `sm`, compact rows |
603
+ | md | `{components.button-primary}` | 36px (`h-9`) | Button default, Input, Select, many menu rows |
604
+ | lg | `{components.button-lg}` | 40px (`h-10`) | Button `lg` |
605
+ | Icon button | sm / md / lg tokens | 28 / 36 / 40px | `icon-sm` / default / `icon-lg` |
794
606
 
795
- Short UI motion (e.g. accordion height) uses **~0.2s ease-out** in utilities; there is no separate “motion duration” token table in Aura today — follow component and `tw-animate-css` patterns.
607
+ **Topbar** height is **application-defined** (not a single Aura token). **Table / list row** density varies by product; menu and command patterns often use **`{components.button-primary.height}`** (`h-9`) rows.
796
608
 
797
609
  ---
798
610
 
799
- ### Layout and spacing
800
-
801
- Width and spacing values in this subsection come from [`src/styles.source.css`](./src/styles.source.css) (`@theme inline` and `:root`) where noted. **Gutters and gaps** use the same **4px-based** spacing scale as **[Tokens → Size and dimensions](#size-and-dimensions)**.
802
-
803
- **Body text reading width**
804
-
805
- - **Must** cap **continuous body text** (paragraphs, descriptions, long labels) at a **maximum width of 600px** for comfortable reading.
806
- - **Must** apply that limit to the **text column only** — companion UI (icons, thumbnails, side metadata, charts, code blocks) **may** sit outside that 600px band in the same row or card; do not shrink the text measure to absorb those elements.
807
- - **Should** implement the cap with `max-w-[600px]` / `max-w-[37.5rem]` (or an equivalent layout wrapper) on the text block, not by stretching typography alone inside an arbitrarily wide container.
808
-
809
- ### Width and max content
810
-
811
- Aura adjusts Tailwind **container** breakpoints where the default scale is too wide or too narrow for Fusion-style surfaces:
812
-
813
- | Token | Value | Role |
814
- | :--- | :--- | :--- |
815
- | `--container-2xl` | 40rem (**640px**) | Narrower than Tailwind’s default `2xl` container — useful outer bound for regions; **body copy** inside can still follow the **600px** reading rule above |
816
- | `--container-8xl` | 96rem (**1536px**) | Wide upper bound for dashboards and full-bleed marketing rows |
611
+ ## Do's and Don'ts
817
612
 
818
- Prefer **`max-w-*`** (and other width utilities) tied to the theme over ad-hoc pixel `max-width` on wrappers. **Global frame** width (shell chrome) is defined by the **Fusion / product** host; **inside** the frame, combine these tokens with responsive utilities so regions reflow predictably.
613
+ Practical guardrails for Aura-based UI. For full rationale, see [Heuristics](#heuristics), [Interaction states](#interaction-states), and [Content](#content).
819
614
 
615
+ ### Do
820
616
 
821
- ### Specialized variables
822
-
823
- | Variable | Value | Use |
824
- | :--- | :--- | :--- |
825
- | `--message-content-max-width` | `80%` | Primary column for chat / assistant **Message** content in wide threads |
826
- | `--drawer-max-height` | `80vh` | Maximum height for top/bottom drawer-style panels when the host implements them |
827
- | `--alert-icon-width` | `calc(var(--spacing) * 4)` (typically **16px**) | Fixed icon column in the **Alert** layout so titles and descriptions align |
828
-
829
- ### Regional spacing
617
+ - Use semantic or base **color tokens** — never raw hex, rgb, or hsl when a token exists.
618
+ - Prefer Aura component **variants and APIs** over overriding styles with visual Tailwind utilities on primitives.
619
+ - Show **loading feedback** (`Shimmer`, `Loader`, `Skeleton`) for any wait the user is expected to sit through.
620
+ - Provide a **visible focus ring** on every interactive control (`shadow-focus-ring` / `shadow-focus-ring-destructive` on `:focus-visible`).
621
+ - Cap continuous **body text** at `{spacing.prose-max}` width; keep companion UI outside that measure.
622
+ - Use the **`{spacing.base}` spacing scale** for padding, margin, and gaps.
623
+ - Pair **icon-only controls** with `aria-label` and a `Tooltip`.
624
+ - Use **sentence case** for all UI copy; write action labels as verb + object ("Save changes", "Delete pipeline").
625
+ - Verify **contrast in both light and dark themes** before shipping.
830
626
 
831
- - **Must** use the **spacing scale** for padding, margin, and `gap` between regions (`gap-*`, `p-*`, `m-*`) — see **Tokens → Size and dimensions**.
832
- - **Should** keep major block **padding** and **gap** on **4px** multiples so control heights, radii, and typography line up visually.
833
- - **Should** group related regions in **Card** (and **Separator** when two unrelated groups share a container) before mixing unrelated actions into the same band — see **Heuristics §6**.
834
- - **Avoid** one-off pixel gutters that ignore the scale unless matching a fixed graphic asset.
627
+ ### Don't
835
628
 
836
- ### Responsive behavior
837
-
838
- - **Should** move secondary work into **Dialog** or a shell **Drawer** on narrow widths instead of compressing multi-column chrome.
839
- - **Avoid** single-breakpoint layouts tuned only to a static design frame — use breakpoints, wrapping, and flexible sizing utilities where content must grow and shrink.
840
-
841
- ### Shell vs content
842
-
843
- **Global chrome** (workspace switcher, app-level navigation) is implemented by the **product shell**, not `@cognite/aura`. **Must** still theme that chrome with Aura **Tokens** so shell and in-app surfaces feel continuous. **In-app content** should rely on Aura primitives (**Card**, **Banner**, **Dialog**, forms) plus the width and spacing rules above.
629
+ - Don't use semantic status colors (`info-*`, `success-*`, `warning-*`, `destructive-*`) as generic decoration or toggled selection fills.
630
+ - Don't remove focus styling or use `outline-none` / `ring-0` without an equivalent token-based focus ring.
631
+ - Don't stack multiple **Alerts** or **toasts** for a single user gesture.
632
+ - Don't use `alert()` or other native blocking dialogs for product UX.
633
+ - Don't hardcode **font sizes, shadows, or border radii** when theme tokens exist.
634
+ - Don't use icon-only targets without an accessible name and tooltip.
635
+ - Don't mix **chart**, **decorative**, and **semantic** color groups interchangeably.
636
+ - Don't override Aura primitive appearance with visual `className` utilities — use variants instead.
844
637
 
845
638
  ---
846
639
 
847
- ## Assets
640
+ ## Assets & Motion
848
641
 
849
- **What this section is:** Rules for **illustrations**, **document icons**, **app icons**, and **system icons** in Aura-based products. Each type has a distinct job; mixing types or bending the rules adds noise and weakens trust. Visual execution (where files live, export pipelines) belongs in brand tooling and engineering skills, not here.
642
+ **What this section is:** Rules for **illustrations**, **document icons**, **app icons**, and **system icons** in Aura-based products. It also includes rules and guidance for motion design. Each type has a distinct job; mixing types or bending the rules adds noise and weakens trust. Visual execution (where files live, export pipelines) belongs in brand tooling and engineering skills, not here.
850
643
 
851
644
  ### Illustrations
852
645
 
@@ -940,18 +733,156 @@ Rare exceptions (third-party or Cognite logos inside a cell) use **provided SVGs
940
733
  - **Must** give icon-only controls an accessible name (`aria-label` / `aria-labelledby`) **and** a **Tooltip** on hover/focus where the design hides the text label.
941
734
  - Icons that only repeat the meaning of adjacent visible text **should** be `aria-hidden="true"`.
942
735
 
736
+ ### Motion (reference)
737
+
738
+ Short UI motion (e.g. accordion height) uses **~0.2s ease-out** in utilities; there is no separate “motion duration” token table in Aura today — follow component and `tw-animate-css` patterns.
739
+
740
+ ---
741
+
742
+ ## Heuristics
743
+
744
+ **What this section is:** The short interaction contract for Aura-based UIs. It keeps the design identity usable by agents and reviewers without turning this file into a full UX playbook.
745
+
746
+ This section contains Aura's decision rules, component selection guidance, and common failure modes. Severity terms carry specific meaning: **Must** / **must not** breaks usability, accessibility, or system conformance; **Should** is the strong default; **Avoid** is a known failure mode.
747
+
748
+ These rules apply to Aura primitives, host-shell components themed with Aura tokens, and standalone apps using Aura. Component props and enum names live in the component APIs, not in this spec.
749
+
750
+ ---
751
+
752
+ ### 1. Feedback and system status
753
+
754
+ Users must always know whether the system is waiting, succeeded, failed, or needs action.
755
+
756
+ - **Must** show loading for any wait the user is expected to sit through. Use **Shimmer** or **Skeleton** when the incoming layout is known, **Loader** for compact waits, and **Progress** when completion is measurable.
757
+ - **Must** acknowledge user-triggered mutations with visible feedback. Use a transient toast for low-stakes confirmations, inline feedback for scoped changes, and **Dialog** / shell **AlertDialog** before irreversible actions.
758
+ - **Must** surface persistent workflow-impacting problems until dismissed or resolved. Use **Banner** for high-priority degraded states, **Alert** for page-scoped awareness, and **Badge** or compact status rows for repeated entity state.
759
+ - **Avoid** blank loading areas, stacked toasts for one gesture, repeated Alert lists, and using **Banner** for routine connection handshakes.
760
+
761
+ ### Alert vs Banner vs Badge vs Sonner
762
+
763
+ Use this matrix to pick the right feedback component. Priority is defined by whether the message requires immediate action and how long it needs to persist.
764
+
765
+ | Priority | When | Components | Notes |
766
+ | ---------- | --------------------------------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
767
+ | **Low** | Non-disruptive updates, minor status, validation hints | `Badge`, notification dot, inline `HelperText` | Does not interrupt the user. Badge for entity state; HelperText for field-level feedback. |
768
+ | **Medium** | Informative, occasionally actionable, not urgent | `Sonner` (toast), `Alert` | Sonner for transient confirmations (~4 s, bottom-right). Alert for inline, page-scoped status that needs awareness but not immediate action (typically one per page section/view). |
769
+ | **High** | Requires immediate attention or action; may interrupt task flow | `Banner` (system errors), `Dialog` / `AlertDialog`, full-page error state | Banner for persistent, region-scoped degraded states. Dialog for irreversible actions. Never use Sonner as the sole safety net for destructive work. |
770
+
771
+ **Rules**
772
+
773
+ - **Must not** use Banner for low-priority or transient notices — it occupies persistent chrome and dilutes high-priority signals.
774
+ - **Must not** use Sonner for errors that require user action — it auto-dismisses.
775
+ - **Must not** use repeated Alerts as a list visualization pattern; one Alert communicates the grouped situation, while item-level status belongs in Badge/status-card patterns.
776
+ - **Should** use `Badge` semantic variants (`warning`, `destructive`, `success`) on entities that carry that state, not as page-level alerts.
777
+ - **Avoid** stacking multiple Sonner toasts for a single user gesture.
778
+
779
+ **Industrial / operational states**
780
+
781
+ The matrix above covers standard cases. For domain-specific states (e.g. sensor offline, process limit breach, control system degraded), apply the same priority logic: does the user need to act now? -> Banner or Dialog. Informational? -> Alert or Badge on the asset. Transient confirmation? -> Sonner. When many entities share similar state, summarize once (Alert/Banner) and show per-entity state with Badge or status cards.
782
+
783
+ ---
784
+
785
+ ### 2. Affordance and discoverability
786
+
787
+ Controls must read as interactive; users should not guess what is clickable, expandable, editable, or destructive.
788
+
789
+ - **Must** use semantic controls for actions, links, form fields, menus, and disclosure. Do not make generic elements behave like buttons.
790
+ - **Must** match component variant to intent: primary for one main action, secondary or ghost for support, destructive only for irreversible work.
791
+ - **Must** pair every field with a visible **Label**. Placeholder text is not a label.
792
+ - **Must** give icon-only controls both an accessible name and a **Tooltip**.
793
+ - **Should** use recognizable signifiers: chevrons for menus and disclosure, magnifier icons for search, helper text for constraints, and empty-state cards with an explanation plus a next action.
794
+ - **Avoid** clickable text that looks identical to body copy or help that exists only in hover on touch-first flows.
795
+
796
+ ---
797
+
798
+ ### 3. Progressive disclosure
799
+
800
+ Introduce complexity only when needed; default views should stay scannable.
801
+
802
+ - **Must** use **Accordion** for stacked independent sections and **Collapsible** for one inline expandable block.
803
+ - **Must** use **Dialog** for modal tasks and shell **Drawer** / **Sheet** for secondary edge panels where the host provides them.
804
+ - **Must** split flows with 3 or more steps into discrete steps with visible progress.
805
+ - **Must** scope menu items to the entity they affect. Do not mix row actions, page actions, and global actions in one menu.
806
+ - **Should** keep advanced settings, rare metadata, and secondary actions behind disclosure when they are not needed for the main task.
807
+ - **Avoid** deeply nested accordions, long flat menus, and multiple irreversible primary decisions in one step.
808
+
809
+ ---
810
+
811
+ ### 4. Error handling and prevention
812
+
813
+ Prevent errors where possible. When errors happen, users must understand what failed, why it matters, and how to recover.
814
+
815
+ - **Must** confirm high-impact destructive actions before execution. Name the object and consequence; do not ask only "Are you sure?".
816
+ - **Must** label destructive confirmation with the specific action, such as "Delete report", not "OK" or "Confirm".
817
+ - **Must** show form errors inline on the affected field and explain how to fix them.
818
+ - **Must** protect unsaved work with auto-save where feasible, persistent unsaved state where not, and a discard warning before navigation.
819
+ - **Should** offer **Undo** for reversible destructive actions when recovery is cheap and contained in the same session.
820
+ - **Avoid** using toast as the only safety net for irreversible work or revealing every validation error only on final submit.
821
+
822
+ ---
823
+
824
+ ### 5. Enabling power users
825
+
826
+ Experts should move faster without harming first-time clarity.
827
+
828
+ - **Should** provide shortcuts for the top few high-frequency actions and render them with Aura shortcut components.
829
+ - **Should** align shortcuts with platform norms where they do not fight the browser or operating system.
830
+ - **Must** support multi-select in list or table UIs that offer per-row destructive or batch actions.
831
+ - **Must** show bulk action controls only when selection is non-empty, with selected count.
832
+ - **Must** use structured empty states for first use or no data: title, explanation, and one clear next action.
833
+ - **Avoid** bulk destructive work without confirmation, stealing reserved shortcuts, or using **Banner** for long onboarding tours.
834
+
835
+ ---
836
+
837
+ ### 6. Layout and hierarchy
838
+
839
+ Information must be scannable and oriented before action.
840
+
841
+ - **Must** group related fields and content in one **Card** or labeled section.
842
+ - **Must** separate unrelated groups with spacing, section labels, or **Separator** before adding nested borders.
843
+ - **Must** keep one clear primary CTA per view. Global actions belong in shell chrome; page actions belong in the page header or toolbar.
844
+ - **Must** use shell **Tabs** / **SegmentedControl** for primary view switching where the product uses that pattern; do not duplicate global navigation in content.
845
+ - **Should** use type scale, weight, and spacing to lead attention before using color or elevation.
846
+ - **Avoid** unrelated actions in the same card, hard-coded pixel widths, duplicated navigation, and destructive styling for non-destructive actions.
847
+
848
+ ---
849
+
850
+ ### 7. Accessibility and inclusive design
851
+
852
+ Aura targets **WCAG AA** for primitives — usage must preserve that.
853
+
854
+ - **Must** complete every task path with keyboard alone.
855
+ - **Must** keep visible focus treatment on every interactive control. Never use `outline-none` or `ring-0` without an equivalent Aura focus ring.
856
+ - **Must** preserve primitive roles and ARIA behavior when composing or wrapping Aura components.
857
+ - **Must** name icon-only controls and pair them with a **Tooltip**.
858
+ - **Must not** encode meaning with color alone. Pair color with text, icon, helper text, or label.
859
+ - **Must** meet contrast and target-size requirements for the shipped context.
860
+ - **Avoid** pointer-only behavior, unreadable `muted-foreground` copy for required tasks, and sub-24px icon hit zones without expansion.
861
+
862
+ ### Common pitfalls (agent guidance)
863
+
864
+ These are the most frequent mistakes when generating or modifying Aura-based UI. Avoid all of them.
865
+
866
+ - Raw hex, `rgb(...)`, or arbitrary Tailwind colors in product UI.
867
+ - Visual `className` overrides that bypass Aura variants, props, or tokens.
868
+ - Duplicate shell navigation inside content.
869
+ - Cards that mix unrelated actions, unrelated data, and dense nested borders.
870
+ - Semantic, decorative, and chart colors used interchangeably.
871
+ - Icon-only controls without accessible names and tooltips.
872
+ - Disabled primary CTAs with no visible path to resolve the blocker.
873
+
943
874
  ---
944
875
 
945
876
  ## Interaction states
946
877
 
947
- **What this section is:** What each interaction state *means* for users, which **Tokens** and patterns Aura uses, and rules for custom controls built outside the library. **How** to wire `focus-visible`, CVA variants, or component props belongs in code and engineering skills.
878
+ **What this section is:** What each interaction state _means_ for users, which **Tokens** and patterns Aura uses, and rules for custom controls built outside the library. **How** to wire `focus-visible`, CVA variants, or component props belongs in code and engineering skills.
948
879
 
949
- Every interactive control signals what is possible, what is happening, and what the system registered. **States are signifiers** — visual cues for affordances (what the element *can* do). Using them consistently builds trust and keeps keyboard and assistive-tech use predictable.
880
+ Every interactive control signals what is possible, what is happening, and what the system registered. **States are signifiers** — visual cues for affordances (what the element _can_ do). Using them consistently builds trust and keeps keyboard and assistive-tech use predictable.
950
881
 
951
- | Concept | Meaning |
952
- | :--- | :--- |
953
- | **Affordance** | A property that makes an action possible (e.g. a control can be activated). |
954
- | **Signifier** | A visible cue that communicates that affordance (shape, label, shadow, state styling). |
882
+ | Concept | Meaning |
883
+ | -------------- | -------------------------------------------------------------------------------------- |
884
+ | **Affordance** | A property that makes an action possible (e.g. a control can be activated). |
885
+ | **Signifier** | A visible cue that communicates that affordance (shape, label, shadow, state styling). |
955
886
 
956
887
  Aura primitives ship these states by default; the rules below describe the **design contract** and apply when extending Aura or building one-off interactives.
957
888
 
@@ -989,7 +920,7 @@ Keyboard or assistive tech has moved focus to the element. This is the main non-
989
920
  - **Must** use Aura’s **token-based focus ring** — `shadow-focus-ring` (CSS variable `--shadow-focus-ring`, composed from `ring` + `ring-muted` tokens) for default controls, and **`shadow-focus-ring-destructive`** / `--shadow-focus-ring-destructive` for invalid or destructive fields. Shared utilities in the library pair `outline-none` **with** these rings on `:focus-visible` — never `outline-none` or `ring-0` **alone**.
990
921
  - **Must** meet **WCAG AA** for the focus indicator against its immediate background.
991
922
  - **Should** use **`:focus-visible`** (or library equivalents) so pointers do not get a keyboard ring on every click, while keyboard users always see one.
992
- - **Invalid inputs:** on focus, use the **destructive** focus ring token pair above (see **Tokens → Effects → Focus rings**).
923
+ - **Invalid inputs:** on focus, use the **destructive** focus ring token pair above (see **Elevation & Depth → Focus rings**).
993
924
 
994
925
  ### Disabled
995
926
 
@@ -1009,7 +940,7 @@ Persistent **on/off**, **selected**, **active filter**, or **applied setting** u
1009
940
 
1010
941
  **Guidance**
1011
942
 
1012
- - **Must** use **`active-background`** / **`active-background-hover`** or **`active-muted-background`** / **`active-muted-background-hover`** (and matching foreground tokens such as **`foreground-on-active`**, **`active-foreground`**) — **not** semantic status colors (`info-*`, `success-*`, …) for generic toggles.
943
+ - **Must** use **`active-background`** / **`active-background-hover`** or **`active-muted-background`** / **`active-muted-background-hover`** (and matching foreground tokens such as **`foreground-on-active`**, **`active-foreground`**) — **not** semantic status colors (`info-`*, `success-`*, …) for generic toggles.
1013
944
  - **Must not** rely on **color alone** — combine fill with icon, checkmark, label, or border treatment where the pattern is ambiguous.
1014
945
  - **Must** implement **hover**, **pressed**, and **focus** for the **selected** variant as well as the default variant when both exist.
1015
946
  - **Must not** show “selected” visuals for controls that are not actually in a selected state.
@@ -1028,184 +959,252 @@ Work is **in progress**; the control or region may be temporarily inert or show
1028
959
 
1029
960
  ## Content
1030
961
 
1031
- **What this section is:** Conventions for **UI copy** — standardized action labels, date and time presentation, grammar and style, localization, voice and tone, and writing that supports accessibility. Use it with **Heuristics** (especially feedback, labels, and §7 accessibility) when designing or implementing strings in Aura-based surfaces.
962
+ **What this section is:** Conventions for **Fusion monorepo UI copy** in Aura-based surfaces: action labels, date and time presentation, grammar and style, localization, voice and tone, and writing that supports accessibility. Use it with **Heuristics** and **Interaction states** when designing or implementing strings.
1032
963
 
1033
964
  **Who:** Designers, product writers, engineers, and agents generating microcopy.
1034
965
 
1035
- **Scope:** English product UI for Cognite Data Fusion experiences unless a feature explicitly ships localized strings; numeric date order and clocks follow user or tenant preferences via the platform **dateTime** configuration. For **customer-visible** strings, follow the approved **product terminology** glossary (do not use internal codenames in place of customer-facing names). UI microcopy should **avoid** spelling out “Cognite Data Fusion” where products may be white-labeled — use neutral terms (“the application”, feature names) when context allows.
1036
-
1037
- ---
1038
-
1039
- ### Action labels
1040
-
1041
- Users predict behavior from **consistent verbs**. Action labels use **sentence case** (e.g. “Edit model”).
1042
-
1043
- **Must not** use **Confirm** as the primary action — name the outcome (**Delete**, **Save**, **Send**, …). **Must** use **Sign in** and **Sign out**; **must not** use “Log in” / “Log out” in UI.
1044
-
1045
- **Avoid** a labeled **Close** action **alongside** **Cancel** or a **Confirm**-labeled button in the same surface — use **Cancel** to abandon without applying, the **outcome verb** for commit, and/or icon-only dismiss per pattern library.
1046
-
1047
- | Label | Use |
1048
- | :--- | :--- |
1049
- | **Add** | Attach an existing object to a new context (e.g. add to canvas). |
1050
- | **Apply** | Commit filters or settings so they drive subsequent behavior. |
1051
- | **Approve** | User agrees; in workflows, usually advances the process. |
1052
- | **Back** | Previous step in a sequence or hierarchy. |
1053
- | **Browse** | Structured scanning (categories, menus, filters). |
1054
- | **Cancel** | Stop the current action and dismiss the surface; warn if stopping risks data loss. |
1055
- | **Clear (all)** | Clear fields or selections; restore default where a control always has a value (e.g. radio). |
1056
- | **Close** | Close a page, pane, or window (often icon-only). |
1057
- | **Collapse** / **Expand** | Hide or show a panel (often icon-only). |
1058
- | **Copy** | Copy to clipboard for use elsewhere. |
1059
- | **Create** | New object from nothing (vs **Add** / **Duplicate**). |
1060
- | **Delete** | Permanently remove the object. |
1061
- | **Discard** | Abandon unsaved draft or edits. |
1062
- | **Download** / **Upload** | Transfer file remote → local / local → remote. |
1063
- | **Duplicate** | Copy in the same location as the original. |
1064
- | **Edit** | Change data or values. |
1065
- | **Explore** | Open-ended discovery without a fixed goal. |
1066
- | **Export** | Save in an external format (often via a secondary step for type and destination). |
1067
- | **Finish** | Complete a multi-step flow (e.g. wizard). |
1068
- | **Hide** / **Show** | Toggle visibility in the UI only (not delete). |
1069
- | **Import** | Bring data in from an external source. |
1070
- | **Insert** | Place at a position in an ordered structure (e.g. table row). |
1071
- | **Next** | Advance one step in a sequence. |
1072
- | **Open** | **Internal:** drawer, modal, or in-app route (support open-in-new-tab where appropriate). **External:** new tab/window for external URLs. |
1073
- | **Publish** / **Unpublish** | Make content available to intended audiences / remove from public view without deleting. |
1074
- | **Query** | Request specific data from a store or service. |
1075
- | **Redo** / **Undo** | Redo reverses undo; undo steps back through user edits (not all actions are undoable). |
1076
- | **Refresh** | Reload when the view may be stale. |
1077
- | **Register** | Create an account or enroll a user (prefer over “Sign up” where it could be confused with **Sign in**). |
1078
- | **Reject** | User does not approve; in workflows, usually blocks progression. |
1079
- | **Remove** | Remove from current context without destroying the object. |
1080
- | **Reset** | Revert to last saved or default values. |
1081
- | **Restore** | Revert to last saved version. |
1082
- | **Save** | Persist changes without closing the surface. |
1083
- | **Search** | Goal-oriented lookup. |
1084
- | **Select** | Pick from a set of options. |
1085
- | **Sign in** / **Sign out** | Authenticate / end session. |
1086
- | **View** | Show details or properties (read-heavy). |
1087
-
1088
- ---
1089
-
1090
- ### Date and time formatting
1091
-
1092
- **Defaults:** Respect user or product **dateTime** configuration (CDF preferences where applicable). **Read-only** stamps (lists, headers, audit) follow these guidelines; **input** fields and pickers follow component behavior and the same provider unless an exceptional case is documented.
1093
-
1094
- **Dimensions**
1095
-
1096
- | Concept | Meaning |
1097
- | :--- | :--- |
1098
- | **Read-only vs input** | Read-only is display-only; input uses pickers/fields — both should stay consistent within a feature. |
1099
- | **Full vs abbreviated** | Full (“2 January 2023”, “6 hours 7 minutes”) vs short (“2 Jan 2023”, “6 hr 7 min”). Prefer abbreviated only when space is tight. |
1100
- | **Absolute vs relative** | Absolute = calendar date/time of the event; relative = “32 min ago”. |
1101
-
1102
- **Must** prefer **written** month forms over numeric dates when readability matters across locales. **Must** stay consistent within the same feature for format style. **Must** use **absolute** timestamps when the event is **more than 24 hours** in the past or future; **should** use **relative** timestamps within **24 hours** before/after “now” (either can be full or abbreviated).
966
+ **Scope:** English UI strings authored in the Fusion monorepo unless a feature explicitly ships localized strings. Numeric date order and clocks follow the host platform `dateTime` configuration. Product naming, white-labeling policy, and market-facing terminology are owned by product documentation and brand guidance; this section covers in-product microcopy patterns that Aura surfaces should follow.
1103
967
 
1104
- **Time**
968
+ ### Role
1105
969
 
1106
- - **Must** follow user preference for **12-** vs **24-hour** clock; 12-hour **must** include **AM** / **PM** (uppercase, no periods, space before suffix: `3:00 PM`).
1107
- - **Must** use **UTC** (not GMT) when a zone label is required; do not spell out “UTC” unless prose clarity needs it. **Must not** ask users to hand-convert zones — the application converts.
970
+ You are writing interface copy for Fusion applications. Every string must be purposeful, concise, conversational, and clear. Identify the target audience persona before writing; the persona determines reading level, technical vocabulary, and tone.
1108
971
 
1109
- **Dates and combined date-time**
972
+ For code-level accessibility (keyboard navigation, ARIA, focus, headings, live regions), see `handling-states.md`.
1110
973
 
1111
- - **Must** include the **year** unless context makes it obvious (e.g. chart titled by year).
1112
- - **Must not** use **ordinal** day forms (“1st”, “23rd”) in UI dates.
1113
- - If numeric dates are required, **should** use **`/`** separators, zero-pad single-digit days/months, and include the year; stay consistent across the feature.
1114
- - For combined date + time in prose, **should** separate with **“at”** or an unambiguous pattern; **must** keep date and time ordering consistent.
974
+ ### Audience personas
1115
975
 
1116
- **Ranges**
976
+ Canonical persona definitions live in the cogdocs repository (`cogdocs/cogdocs-metadata.mdx`, **Audience** section). This summary covers what matters for microcopy decisions.
1117
977
 
1118
- - **Time range:** same style at start and end; on 12-hour clocks, repeat **AM**/**PM** only when needed for clarity (single meridiem can use one suffix; cross-midnight or long ranges may need both date and meridiem on each end).
1119
- - **Date range:** consistent formatting; **avoid** dense numeric ranges that are hard to parse.
1120
- - **Date-time range:** date first, then time; include year unless context suffices; for 12-hour + range, **must** label **AM**/**PM** clearly on both ends when ambiguity is likely.
978
+ | Persona | Technical level | UX copy implication |
979
+ | ----------------------- | --------------- | ------------------------------------------------------------------------------- |
980
+ | `businessUser` | Low | Plain language; outcomes over features; domain terms OK, avoid platform jargon |
981
+ | `businessDecisionMaker` | Low | Plain language; ROI, business value, strategic impact; minimal technical detail |
982
+ | `appMaker` | Mid | Configuration, automation, outcomes; avoid deep code/API detail |
983
+ | `dataAnalyst` | Mid | Analytics, insights, dashboards; data terms OK, keep explanations clear |
984
+ | `partner` | Mid–high | Precise; balance technical accuracy with clarity |
985
+ | `administrator` | High | Technical terms OK; reliability, security, compliance, access; be precise |
986
+ | `dataEngineer` | High | Technical terms OK; pipelines, ingestion, transformation |
987
+ | `developer` | High | Technical terms OK; APIs, SDKs, integrations; precise and concise |
988
+ | `aiEngineer` | High | Technical terms OK; ML/AI, models, automation |
989
+ | `dataScientist` | High | Technical terms OK; experiments, models, analytics |
990
+ | `securityEngineer` | High | Technical terms OK; IAM, threats, compliance |
991
+ | `solutionArchitect` | High | Technical terms OK; integration, strategy, best practices |
992
+ | `internal` | Varies | Can use Cognite-internal jargon; match internal conventions |
1121
993
 
1122
- **Duration** (elapsed length, not a clock range)
994
+ **Reading level:** Low = 7th–8th grade; Mid = 9th–10th grade; High = 10th–11th grade.
1123
995
 
1124
- - **Should** express duration when elapsed length matters more than endpoints.
1125
- - No “relative” phrasing for duration lists.
1126
- - **Should** use a **space** between number and unit in body text and tables (`3 seconds`); compact controls may omit the space per component spec.
1127
- - **Should** avoid commas between compound units (`10 minutes 3 seconds` not `10 minutes, 3 seconds`).
1128
- - For sub-second precision, **should** use decimals (`2.5 seconds`) or round to a meaningful whole unit to reduce noise.
996
+ When the persona is unknown, default to plain language and outcomes.
1129
997
 
1130
- **Abbreviations** (lowercase units except proper nouns like **Jan**, **Mon**; no periods on abbreviations)
1131
-
1132
- | Full (examples) | Abbreviated |
1133
- | :--- | :--- |
1134
- | millisecond(s), second(s), minute(s), hour(s) | ms, s, min, hr |
1135
- | day(s), week(s), month(s), year(s) | d, wk, mo, yr |
1136
-
1137
- Days and months: **Monday** → **Mon**, **January** → **Jan**, etc.; capitalize; allow width for **four-letter** abbreviations where internationalization may need it.
998
+ ### Voice and tone
1138
999
 
1139
- **Scheduled automation:** use **cron** expressions where users define recurring runs.
1000
+ Voice is consistent; tone adapts to the user's emotional state.
1140
1001
 
1141
- ---
1002
+ | Scenario | Tone | Example |
1003
+ | ----------------------- | ------------------------- | ------------------------------------------------------------------------------ |
1004
+ | First-time onboarding | Friendly, welcoming | "Let's get started. Your workspace is ready when you are." |
1005
+ | Technical documentation | Clear, direct, supportive | "Configure your endpoint and authenticate using your API key." |
1006
+ | Error messages | Empathetic, constructive | "Something went wrong. Try refreshing, or check your connection." |
1007
+ | Success states | Encouraging, concise | "Your data is now flowing." |
1008
+ | Product tours / help | Conversational, helpful | "Want a quick tour? We'll walk you through the essentials in under 2 minutes." |
1009
+ | High-stakes actions | Serious, transparent | "Delete pipeline? All history will be permanently removed." |
1142
1010
 
1143
1011
  ### Grammar and style
1144
1012
 
1145
- **Must** use **American English** in UI (`color`, `center`, `organization`, …). **Must** use **sentence case** for UI phrases; **must not** use **ALL CAPS** for body labels.
1146
-
1147
- **Should** prefer **active voice**; use passive only for objectivity or legal emphasis.
1148
-
1149
- **Numbers:** use **numerals** for all magnitudes in UI (`6 queries per second`, `50 Mbps`). **Should** use a **non-breaking space** between a number and its unit where line breaks would confuse.
1013
+ #### Language and capitalization
1150
1014
 
1151
- **Abbreviations:** spell out when possible; **avoid** Latin shortcuts (“e.g.”, “etc.”) — use “for example”, “and more”, or recast the sentence.
1015
+ - **American English**: color, center, organization, modeling
1016
+ - **Sentence case everywhere**: "Create data model" — not "Create Data Model". No exceptions for UI text. Only proper nouns and product names are capitalized: Fusion, OPC-UA, Aura.
1017
+ - **No all-caps**
1018
+ - **No internal codenames** in customer-facing UI copy; use the feature or resource name users recognize.
1152
1019
 
1153
- **Punctuation**
1020
+ #### Numbers and units
1154
1021
 
1155
- - **Avoid** terminal periods on short labels, tooltips, and single-line list items.
1156
- - **Must** use periods for **multi-sentence** blocks and dense prose.
1157
- - **Avoid** exclamation marks in default UI; use **ellipses** sparingly for in-progress or truncated text.
1158
- - **Should** use the **Oxford comma** in lists.
1159
- - **Avoid** ampersands (`&`) in translatable UI — use **and**.
1022
+ - **Numerals for all numbers**, including those under 10: "6 queries", "3 items", "1 result"
1023
+ - Non-breaking space between number and unit: "50 Mbps"
1024
+ - Don't use "(s)" or "(es)" — choose singular or plural based on context
1160
1025
 
1161
- **Pronouns and point of view:** **must not** mix **my** and **your** in the same flow; **should** minimize “we” / “I” for the product voice — prefer the user’s perspective and **should** align with the approved product glossary (e.g. “My data” vs neutral labels).
1026
+ #### Abbreviations and punctuation
1162
1027
 
1163
- **Plural forms:** **avoid** “(s)” or “(es)” in labels — use separate strings or unambiguous copy per locale.
1028
+ - No Latin abbreviations: use "for example" not "e.g.", "and more" not "etc."
1029
+ - Define acronyms and technical terms when first used (unless writing for technical personas)
1030
+ - No ampersands (&): use "and" — including in headings
1031
+ - **Oxford comma**: "apples, oranges, and pears"
1032
+ - No exclamation marks in UI copy
1033
+ - No period after labels, tooltip text, or single-sentence bulleted list items; use periods for multiple/complex sentences
1034
+ - Ellipsis (…): only for ongoing processes or truncated text — use sparingly
1164
1035
 
1165
- ---
1166
-
1167
- ### Localization
1036
+ #### Pronouns
1168
1037
 
1169
- Strings ship through translation workflows (e.g. **Locize**); follow platform developer documentation for keys and context.
1170
-
1171
- **Must** ship source English without spelling or grammar errors. **Should** use **short**, simple sentences (one idea per sentence) and **consistent** word order and capitalization for easier translation. **Should** include “small grammar words” (**a**, **the**, **is**) in prose; labels may omit them only when space is critical.
1172
-
1173
- ---
1038
+ - Don't mix "my" and "your" in the same context
1039
+ - **"My [resource]"** for app-owned items: "My data", "My assets"
1040
+ - Minimize "I" and "we" representing the application; focus on the user's perspective
1041
+ - Avoid ambiguous pronouns ("this", "that") without an explicit referent — name the thing
1174
1042
 
1175
- ### Voice and tone
1176
-
1177
- **Voice** stays consistent; **tone** shifts with context (onboarding vs error vs success).
1178
-
1179
- **Should** lead with the user’s **intent** and **task**; use **plain**, customer vocabulary; stay **concise** and **scannable** (headings first, steps chunked; prefer visuals over long notes).
1180
-
1181
- **Should** acknowledge friction honestly where UX is rough; keep disclaimers minimal.
1182
-
1183
- | Scenario | Tone | Example |
1184
- | :--- | :--- | :--- |
1185
- | First-time onboarding | Friendly, welcoming | “Let’s get started — you’re ready when you are.” |
1186
- | Technical flows | Clear, direct | “Configure your endpoint and authenticate with your API key.” |
1187
- | Errors | Empathetic, constructive | “Something went wrong. Try refreshing or check your connection.” |
1188
- | Success | Brief, positive | “Your data is now flowing.” |
1189
- | Tours / help | Conversational | “Want a quick tour? We’ll cover the essentials in under two minutes.” |
1190
-
1191
- Align microcopy with the same **product terminology** glossary referenced in **Grammar and style**.
1043
+ ### Action labels
1192
1044
 
1193
- ---
1045
+ Use sentence case with an object: "Edit model", "Delete asset".
1194
1046
 
1195
- ### Writing for accessibility
1047
+ #### Approved labels
1196
1048
 
1197
- Structural accessibility (focus, contrast, semantics, targets) lives in **Heuristics §7** and **Interaction states**. This subsection is **copy-specific**.
1049
+ | Label | Use when |
1050
+ | ------------------ | --------------------------------------------------------------------------- |
1051
+ | Add | Taking an existing object into a new context ("Add to canvas") |
1052
+ | Apply | Setting filtered values that affect subsequent system behavior |
1053
+ | Approve | User agrees; initiates next step in a business process |
1054
+ | Back | Returning to the previous step in a sequence or hierarchy |
1055
+ | Cancel | Stopping the current action or closing a modal — warn of data loss |
1056
+ | Clear | Clearing all fields/selections; restores defaults |
1057
+ | Close | Closing a page, panel, or secondary window — often icon-only |
1058
+ | Copy | Copying an object to the clipboard |
1059
+ | Create | Making a new object from scratch |
1060
+ | Delete | Permanently destroying an object |
1061
+ | Discard | Discarding unsaved changes during create/edit |
1062
+ | Download | Transferring a file from remote to local |
1063
+ | Duplicate | Creating a copy in the same location as the original |
1064
+ | Edit | Changing data/values of an existing object |
1065
+ | Export | Saving data in an external format; typically opens a dialog |
1066
+ | Import | Bringing data from an external source; typically opens a dialog |
1067
+ | Next | Advancing to the next step in a wizard |
1068
+ | Finish | Completing a multi-step wizard |
1069
+ | Open | Opening a drawer, modal, or new page within current context |
1070
+ | Publish | Making content available to intended users |
1071
+ | Refresh | Reloading a view that is out of sync with the source |
1072
+ | Register | Creating a new user account |
1073
+ | Remove | Removing an object from the current context without destroying it |
1074
+ | Reset | Reverting to last saved or default state |
1075
+ | Save | Saving pending changes without closing the window/panel |
1076
+ | Search | Goal-oriented action to find precise information |
1077
+ | Select | Choosing one or more options from a list |
1078
+ | Show / Hide | Revealing or removing an element from view without deleting — use as a pair |
1079
+ | Sign in / Sign out | Entering or exiting the application |
1080
+ | Undo / Redo | Reversing or re-applying the most recent action |
1081
+ | Upload | Transferring a file from local to remote |
1082
+ | View | Presenting additional information or properties for an object |
1083
+
1084
+ #### Labels to avoid
1085
+
1086
+ | Avoid | Use instead | Reason |
1087
+ | --------------------- | ------------------------------------------- | -------------------------------- |
1088
+ | Confirm | The specific action verb ("Delete", "Send") | Too vague |
1089
+ | Log in / Log out | Sign in / Sign out | "Log" is technical jargon |
1090
+ | Sign up | Register | Avoids confusion with "Sign in" |
1091
+ | Submit, OK, Yes | The specific outcome verb | Generic; tell users what happens |
1092
+ | Click here, Read more | Descriptive link text | Inaccessible; not input-agnostic |
1093
+
1094
+ ### UI text patterns
1095
+
1096
+ #### Titles
1097
+
1098
+ Noun phrases, sentence case. Examples: "Asset overview", "Pipeline runs", "Configure integration"
1099
+
1100
+ #### Buttons and CTAs
1101
+
1102
+ Active imperative verb + object. 2–4 words target, 6 max. Examples: "Save changes", "Delete pipeline", "View details"
1103
+
1104
+ #### Error messages
1105
+
1106
+ Pattern: `[What failed]. [Why/context if known]. [What to do].`
1107
+ Examples:
1108
+
1109
+ - "Ingestion failed. Check your extractor configuration and try again."
1110
+ - "Couldn't save changes. Connection lost. Reconnect and retry."
1111
+ Avoid: blame language, dead ends with no recovery path
1112
+
1113
+ #### Success messages
1114
+
1115
+ Past tense, specific, brief. Pattern: `[Action] [result]`
1116
+ Avoid "successfully"; that's implied in the pattern
1117
+ Examples: "Changes saved", "Pipeline started", "Integration configured"
1118
+
1119
+ #### Empty states
1120
+
1121
+ Explanation + CTA. Example: "No assets yet. Connect a data source to start exploring."
1122
+
1123
+ #### Tooltips
1124
+
1125
+ One to two sentences, present tense. Pattern: `[What it is]. [What it does or why it matters].`
1126
+ Examples:
1127
+
1128
+ - "Asset ID. The unique identifier for this asset."
1129
+ - "Time granularity. Controls how data points are aggregated in the chart."
1130
+ Never repeat the label. Never write more than 2 sentences.
1131
+
1132
+ #### Confirmation dialogs
1133
+
1134
+ State the consequence, not just the action. Pattern: `[What will be lost or affected]. [Reversibility]. [Specific action].`
1135
+
1136
+ - Primary CTA: match the specific action ("Delete pipeline", not "Confirm")
1137
+ - Secondary CTA: always provide a clear exit ("Cancel")
1138
+ Examples:
1139
+ - "Delete pipeline? All runs and history will be permanently removed. This can't be undone."
1140
+ - "Remove team member? They'll lose access to all shared resources immediately."
1141
+ Avoid: "Are you sure?", manipulative phrasing
1142
+
1143
+ #### Form fields
1144
+
1145
+ - **Labels**: Clear noun phrases ("Time series ID", "Email address")
1146
+ - **Placeholder text**: Use sparingly, only for standard formats like "[name@example.com](mailto:name@example.com)"
1147
+ - **Helper text**: Verb-first; explain why the information is needed
1148
+
1149
+ #### Notifications
1150
+
1151
+ Verb-first title + contextual description. 10–15 words total.
1152
+ Example: "Extractor disconnected. Check your network and reconnect."
1153
+
1154
+ ### Accessibility
1155
+
1156
+ - Use **"Select"** not "Click" — input-agnostic: mouse, keyboard, touch, voice
1157
+ - Avoid ambiguous pronouns — screen readers lose surrounding context
1158
+ - Write descriptive link text: "Read pricing details" not "Click here"
1159
+ - Alt text by image type:
1160
+ - Icon → describes function: "Download PDF" not "download icon"
1161
+ - Link image → describes destination: "Contact support" not "question mark"
1162
+ - Chart/diagram → summarizes meaning: "Bar chart showing pipeline throughput declining 20% in Q3"
1163
+ - Decorative image → empty alt text (`alt=""`)
1164
+ - Never write "image of" or "photo of"
1165
+ - For charts and metrics, describe key trends or values in adjacent text — don't rely on visual encoding alone
1166
+ - Target 8–14 words per sentence (8 = 100% comprehension, 14 = 90%)
1167
+ - Pair visual indicators with text: "Error: field required" alongside a red icon
1198
1168
 
1199
- **Must** write **icon** `alt` / accessible names that state **intent** (“Download PDF”), not appearance (“disk icon”). **Must** provide **alt text** for informative images; **must** use empty alt for **decorative** images only.
1169
+ ### Date and time formatting
1200
1170
 
1201
- **Must** make **link text** describe the destination or outcome (“Learn about pricing”), not “click here” or bare “read more”.
1171
+ - **Prefer written dates**: "2 January 2023" not "02/01/2023"
1172
+ - **Relative vs absolute**: ≤24 h from now → relative ("32 min ago"); >24 h → absolute ("2 Jan 2023")
1173
+ - Always include the year unless obvious from context
1174
+ - No ordinal numbers: "2 January" not "2nd January"
1175
+ - Separate date and time with "at": "2 Jan 2023 at 10:00 AM" — no comma
1176
+ - **12-hour time**: uppercase AM/PM, no periods, space before: "10:00 AM"
1177
+ - **Time zone**: UTC only; spell out "UTC" in text-only contexts
1178
+ - Never make the user convert time zones — handle in code
1179
+ - Ranges: consistent format across start and end; for ongoing processes use absolute start + "ongoing" until complete
1180
+ - Duration: no comma between units ("10 minutes 3 seconds"); space between number and unit in running text ("3 min"); no space in controls ("3min")
1202
1181
 
1203
- **Should** use **headings** and **lists** so screen reader users can skim; for **charts** or complex figures, repeat key insights in adjacent text, not only in the graphic.
1182
+ **Time unit abbreviations** (no periods; same form singular/plural):
1183
+ ms, s, min, hr, d, wk, mo, yr
1204
1184
 
1205
- **Should** avoid **this** / **that** without a clear noun referent.
1185
+ **Day abbreviations** (3 chars for i18n):
1186
+ Mon, Tue, Wed, Thu, Fri, Sat, Sun
1206
1187
 
1207
- **Should** describe **data trends** in words when the UI relies on charts or color alone.
1188
+ **Month abbreviations** (4 chars for i18n):
1189
+ Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
1208
1190
 
1209
- **Must** use **Select** (or “choose”, “turn on”) rather than **Click** in instructions — not all users use a pointer.
1191
+ ### Localization
1210
1192
 
1211
- ---
1193
+ - Keep sentences short with the subject near the start — compound clauses increase translation cost
1194
+ - Maintain consistent terminology and capitalization across strings (critical for translation memory)
1195
+ - No Latin abbreviations in translatable strings: "for example" not "e.g.", "and more" not "etc."
1196
+ - Avoid idioms and cultural references
1197
+ - No ampersands: use "and"
1198
+ - Small words (a, the, that, is): include in prose; may omit only in space-constrained labels and CTAs
1199
+
1200
+ ### Benchmarks
1201
+
1202
+ | Element | Target | Maximum |
1203
+ | -------------- | ------------------------ | ------------- |
1204
+ | Buttons / CTAs | 2–4 words | 6 words |
1205
+ | Titles | 3–6 words, 40 characters | — |
1206
+ | Tooltips | 10–20 words | 2 sentences |
1207
+ | Error messages | 12–18 words | — |
1208
+ | Instructions | 14 words | 20 words |
1209
+ | Notifications | 10–15 words total | — |
1210
+ | Line length | 40–60 characters | 70 characters |