@cognite/aura 0.1.6 → 0.1.7

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.
package/DESIGN.md ADDED
@@ -0,0 +1,1269 @@
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://cognitedata.github.io/aura/storybook)) 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://cognitedata.github.io/aura/storybook) 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))]`. See [Grids and layouts](#grids-and-layouts) and [Storybook grid patterns](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--grid-patterns-reference).
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
+ ---
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://cognitedata.github.io/aura/storybook)). **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
+
39
+ ---
40
+
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.
186
+
187
+ #### 3.2 Multi-step flows
188
+
189
+ **Applies when:** Three or more steps or grouped data entry.
190
+
191
+ **Aura components:** `Dialog`, `Progress`, `Button`, `Separator`
192
+
193
+ **Rules**
194
+
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.
198
+
199
+ #### 3.3 Contextual menus and secondary actions
200
+
201
+ **Applies when:** Per-row or per-object actions should stay out of the default chrome.
202
+
203
+ **Aura components:** `DropdownMenu`, `Button` (kebab trigger), `ButtonGroup`
204
+ **App:** `ContextMenu` — same grouping and token rules
205
+
206
+ **Rules**
207
+
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.
212
+
213
+ ---
214
+
215
+ ### 4. Error handling and prevention
216
+
217
+ Errors **should** be prevented; when they happen, users **must** understand cause and recovery.
218
+
219
+ #### 4.1 Destructive action prevention
220
+
221
+ **Applies when:** Delete, archive, reset, overwrite, disconnect, or other irreversible commits.
222
+
223
+ **Aura components:** `Dialog`, `Alert`, `Banner`, `Button` (`destructive`)
224
+ **App:** `AlertDialog` / confirm flow where supplied by shell
225
+
226
+ **Rules**
227
+
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.
233
+
234
+ #### 4.2 Form validation
235
+
236
+ **Applies when:** Any `Input`, `Textarea`, `Select`, or similar field.
237
+
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
256
+
257
+ **Rules**
258
+
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.
262
+
263
+ #### 4.4 Recovery and undo
264
+
265
+ **Applies when:** User mutates or removes content.
266
+
267
+ **Aura components:** `Dialog`
268
+ **App:** Sonner with undo
269
+
270
+ **Rules**
271
+
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).
275
+
276
+ ---
277
+
278
+ ### 5. Enabling power users
279
+
280
+ Experts **should** move faster without harming first-time clarity.
281
+
282
+ #### 5.1 Keyboard shortcuts
283
+
284
+ **Applies when:** High-frequency actions (save, search, command palette, AI trigger).
285
+
286
+ **Aura components:** `Command`, `CommandShortcut`, `DropdownMenuShortcut`, `Tooltip`
287
+
288
+ **Rules**
289
+
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.
294
+
295
+ #### 5.2 Bulk actions
296
+
297
+ **Applies when:** Lists or tables with repeated items.
298
+
299
+ **Aura components:** `DropdownMenuCheckboxItem`, `Button`, `ButtonGroup`, `Badge`, `Banner`
300
+ **App:** table selection, **ActionToolbar** pattern
301
+
302
+ **Rules**
303
+
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).
308
+
309
+ #### 5.3 Onboarding and learnability
310
+
311
+ **Applies when:** First-use, empty data, or role-gated features.
312
+
313
+ **Aura components:** `Card`, `Button`, `Tooltip`, `HelperText`, `Banner`, `Message`
314
+
315
+ **Rules**
316
+
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.
321
+
322
+ ---
323
+
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
369
+
370
+ **Applies when:** Viewport spans tablet / desktop / embedded shell widths.
371
+
372
+ **Aura components:** `Card`, `Dialog`, `DropdownMenu`
373
+ **Fusion shell:** `Topbar` overflow behavior
374
+
375
+ **Rules**
376
+
377
+ - **Should** verify layouts at common widths (e.g. 768 / 1024 / 1440px) when shipping responsive surfaces (see **[Grids and layouts](#grids-and-layouts)**).
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.
380
+
381
+ ---
382
+
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
399
+
400
+ **Applies when:** Text, icons, or controls on colored surfaces.
401
+
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**
425
+
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.
429
+
430
+ ### Common pitfalls (agent guidance)
431
+
432
+ These are the most frequent mistakes when generating or modifying Aura-based UI. Avoid all of them.
433
+
434
+ **Raw hex or hardcoded colors**
435
+
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.
437
+
438
+ **Overriding style tokens or component styles**
439
+
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.
441
+
442
+ **Duplicate or parallel navigation**
443
+
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.
445
+
446
+ **Overly dense card layouts**
447
+
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.
449
+
450
+ **Mixing chart, decorative, and semantic color tokens**
451
+
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.
453
+
454
+ **Icon-only controls without accessible names**
455
+
456
+ Every icon-only Button must have `aria-label` and a `Tooltip`. Do not rely on visual context alone.
457
+
458
+ **Disabled primary CTA with no resolution path**
459
+
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.
461
+
462
+ ---
463
+
464
+ ### For `llms.txt` / agent exports
465
+
466
+ When splitting or stripping this doc for agents:
467
+
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://cognitedata.github.io/aura/storybook). 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**.
475
+
476
+ ---
477
+
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-solid`, `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` | `rgba(2, 6, 23, 0.2)` | `rgba(226, 232, 240, 0.2)` | 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` | `#BBC0C4` | `#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-critical`, `ring-critical-shadow` 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` | `#E19E00` | `#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-{ramp}-background`, `decorative-{ramp}-background-hover`, `decorative-{ramp}-foreground`.
634
+
635
+ **Preference order for new work:**
636
+
637
+ | Priority | Ramp | Background | Foreground |
638
+ | :---: | :--- | :--- | :--- |
639
+ | 1 | Fjord | `decorative-fjord-background` | `decorative-fjord-foreground` |
640
+ | 2 | Nordic | `decorative-nordic-background` | `decorative-nordic-foreground` |
641
+ | 3 | Aurora | `decorative-aurora-background` | `decorative-aurora-foreground` |
642
+ | 4 | Dusk | `decorative-dusk-background` | `decorative-dusk-foreground` |
643
+ | 5 | Orange | `decorative-orange-background` | `decorative-orange-foreground` |
644
+ | 6 | Sky | `decorative-sky-background` | `decorative-sky-foreground` |
645
+ | 7 | Mountain | `decorative-mountain-background` | `decorative-mountain-foreground` |
646
+
647
+ Example (fjord ramp): light `decorative-fjord-background` → `#CCD5FA` (fjord-200), `decorative-fjord-foreground` → `#1234B6` (fjord-700); dark → `#AEBDF7` / `#0D2582` (fjord-300 / fjord-800). Every ramp resolves in [`src/colors.css`](./src/colors.css).
648
+
649
+ #### Chart tokens
650
+
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.
652
+
653
+ | Token | Use |
654
+ | :--- | :--- |
655
+ | `chart-fjord-solid` … `chart-orange-solid` | Solid series stroke / marker color |
656
+ | `chart-{ramp}-opacity-1` … `chart-{ramp}-opacity-5` | Area-fill opacity steps (lightest → strongest) |
657
+ | `chart-gridlines` | Grid lines |
658
+
659
+ Default series order: **fjord → nordic → aurora → dusk → orange**.
660
+
661
+ ---
662
+
663
+ ### Typography
664
+
665
+ Aura uses three **font families** (loaded in [`src/styles.source.css`](./src/styles.source.css)):
666
+
667
+ | Token | Font | Use |
668
+ | :--- | :--- | :--- |
669
+ | `--font-sans` / `--font-inter` | Inter | Default UI — copy, labels, dense UI |
670
+ | `--font-marketing` | Space Grotesk | Marketing / display headings only |
671
+ | `--font-mono` | Source Code Pro | Code, technical strings |
672
+
673
+ **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):
674
+
675
+ | Style | Font | Size | Weight | Line height | Letter spacing | Use |
676
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
677
+ | `display` | Space Grotesk | 36px (`text-5xl`) | 600 | 44px | -0.08px | Hero / marketing display |
678
+ | `h1` | Inter | 32px (`text-4xl`) | 600 | 40px | -0.08px | Page title |
679
+ | `h2` | Inter | 28px (`text-3xl`) | 600 | 32px | -0.08px | Section title |
680
+ | `h3` | Inter | 24px (`text-2xl`) | 600 | 28px | -0.04px | Subsection |
681
+ | `h4` | Inter | 20px (`text-xl`) | 500 | 24px | -0.04px | Group label |
682
+ | `body-md` | Inter | 16px (`text-base`) | 400 | 20px | -0.04px | Default body |
683
+ | `body-sm` | Inter | 14px (`text-sm`) | 400 | 18px | -0.04px | Secondary body |
684
+ | `label` | Inter | 12px (`text-xs`) | 500 | 14px | -0.04px | Form labels, compact UI |
685
+ | `code` | Source Code Pro | 14px (`text-sm`) | 400 | 20px | — | Monospace content |
686
+
687
+ ---
688
+
689
+ ### Size and dimensions
690
+
691
+ Aura aligns to a **4px base grid**. Spacing in components follows **Tailwind spacing** (`p-*`, `gap-*`, `m-*`): one unit = **4px** unless overridden. Common steps:
692
+
693
+ | Name | Value | Tailwind | Typical use |
694
+ | :--- | :--- | :--- | :--- |
695
+ | xs | 4px | `1` | Tight gaps, icon padding |
696
+ | sm | 8px | `2` | Inline controls, compact padding |
697
+ | md | 12px | `3` | Card / popover internal padding |
698
+ | lg | 16px | `4` | Related groups |
699
+ | xl | 20px | `5` | Sections |
700
+ | 2xl | 24px | `6` | Page regions |
701
+ | 3xl | 32px | `8` | Large layout gaps |
702
+
703
+ Layout helpers in theme: `--container-2xl` (40rem), `--container-8xl` (96rem), `--message-content-max-width` (80% for chat content).
704
+
705
+ #### Component heights
706
+
707
+ Heights are **not** always single CSS variables; primitives use Tailwind height utilities. Representative values from core components:
708
+
709
+ | Size | Height | Aura usage |
710
+ | :--- | :--- | :--- |
711
+ | xs | 20px (`h-5`) | Badge (default) |
712
+ | sm | 28px (`h-7`) | Button `sm`, compact rows |
713
+ | md | 36px (`h-9`) | Button default, Input, Select, many menu rows |
714
+ | lg | 40px (`h-10`) | Button `lg` |
715
+ | Icon button | 28 / 36 / 40px | `icon-sm` / default / `icon-lg` (`size-7`, `size-9`, `size-10`) |
716
+
717
+ **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.
718
+
719
+ ---
720
+
721
+ ### Corner radius
722
+
723
+ 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`**.
724
+
725
+ | Token | Value | Use |
726
+ | :--- | :--- | :--- |
727
+ | `--radius-none` | 0px | Dividers, full-bleed |
728
+ | `--radius-xs` | 2px | Tight inner chrome |
729
+ | `--radius-sm` | 4px | Small controls, badges |
730
+ | `--radius-md` / `--radius` | 6px | Maps to `rounded-md` — shared default in theme |
731
+ | `--radius-lg` | 8px | **Default** for many controls (Button, Input) via `rounded-lg` |
732
+ | `--radius-xl` | 12px | Dialogs, large cards, popovers |
733
+ | `--radius-2xl` | 16px | Extra-large surfaces |
734
+ | `--radius-3xl` | 24px | Marketing / hero panels |
735
+ | `--radius-4xl` | 32px | Largest marketing rounding |
736
+ | `--radius-full` | 9999px | Pills, avatars |
737
+
738
+ ---
739
+
740
+ ### Border
741
+
742
+ Aura is visually **flat**; surfaces, spacing, and typography do most structure. Add borders only when separation or affordance needs extra clarity.
743
+
744
+ **Rules**
745
+
746
+ - **Must** treat borders/strokes as structural signals (inputs, table boundaries, critical separators), not decoration.
747
+ - **Should** distinguish line items inside cards with spacing, alignment, and type hierarchy before adding dividers.
748
+ - **Should** prefer one outer container boundary over many nested per-row outlines in the same card.
749
+ - **Avoid** drawing borders around every item in a list/card just to create visual rhythm.
750
+ - **Avoid** decorative outline stacks (`border` + `ring` + inset strokes) when no state or interaction meaning is conveyed.
751
+
752
+ | Concept | Value | Use |
753
+ | :--- | :--- | :--- |
754
+ | Default width | **1px** | Tailwind `border` — tables, inputs, and occasional structural dividers |
755
+ | Emphasized width | **2px** | Stronger separation or invalid/critical state emphasis |
756
+ | Border color | `border`, `border-emphasized`, … | See **Base — Borders and focus** |
757
+ | Style | solid | Default |
758
+
759
+ ---
760
+
761
+ ### Effects
762
+
763
+ #### Shadows
764
+
765
+ `--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:
766
+
767
+ | Tailwind shadow | Built from `--effect-shadow-*` | Light (α) | Dark (α) | Use (per theme comments in CSS) |
768
+ | :--- | :--- | :--- | :--- | :--- |
769
+ | `shadow-sm` | `--effect-shadow-sm` | 0.04 | 0.2 | Tooltips, small floating containers |
770
+ | `shadow-default` | md + sm layers | 0.05 + 0.04 | 0.3 + 0.2 | Menus, popovers, hover cards |
771
+ | `shadow-md` | md + sm layers | 0.05 + 0.04 | 0.3 + 0.2 | Sonner toasts, temporary elevated elements |
772
+ | `shadow-lg` | lg + sm layers | 0.06 + 0.04 | 0.4 + 0.2 | Modals / dialogs **without** full backdrop overlay |
773
+ | `shadow-xl` | xl + lg layers | 0.10 + 0.06 | 0.6 + 0.4 | Modals / dialogs **with** backdrop overlay |
774
+
775
+ Exact pixel stacks: `--shadow-sm` … `--shadow-xl` in [`src/styles.source.css`](./src/styles.source.css).
776
+
777
+ #### Focus rings
778
+
779
+ Shadow-based (not `outline`) for consistent rendering:
780
+
781
+ | Token | Composition | Use |
782
+ | :--- | :--- | :--- |
783
+ | `--shadow-focus-ring` | `0 0 0 2px var(--ring), 0 0 0 4px var(--ring-muted)` | Default focus on interactive controls |
784
+ | `--shadow-focus-ring-destructive` | `0 0 0 2px var(--ring-critical), 0 0 0 4px var(--ring-critical-shadow)` | Destructive / invalid focus |
785
+
786
+ #### Opacity
787
+
788
+ | Token / concept | Value | Use |
789
+ | :--- | :--- | :--- |
790
+ | `--opacity-10` … `--opacity-80` (+ `*-inverted`) | rgba steps | Overlays, glass effects |
791
+ | Overlay scrim | via `overlay-background` | Modal backdrop (see color tables) |
792
+ | Chart fills | `chart-*-opacity-*` | See **Chart tokens** |
793
+
794
+ #### Motion (reference)
795
+
796
+ 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.
797
+
798
+ ---
799
+
800
+ ## Grids and layouts
801
+
802
+ **What this section is:** How to think about **width**, **reading measure**, **vertical rhythm**, and **responsive composition** when building with Aura’s Tailwind v4 theme. Visual grids, column spans, and compositions are maintained in Storybook; this section captures the **rules and links** agents and engineers should follow first.
803
+
804
+ ### Storybook layout reference
805
+
806
+ | Topic | Storybook |
807
+ | :--- | :--- |
808
+ | Layout overview (docs) | [Foundations / Layout — Docs](https://cognitedata.github.io/aura/storybook/?path=/docs/foundations-layout--docs) |
809
+ | **Column spans** | [Column spans](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--column-spans) |
810
+ | **Layout compositions** | [Compositions](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--compositions) |
811
+ | **Grid patterns** | [Grid patterns reference](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--grid-patterns-reference) |
812
+ | **Container queries** | [Container queries](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--container-queries) |
813
+ | **Breakpoints** | [Breakpoints](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--breakpoints) |
814
+
815
+ ### Copy-paste patterns (Tailwind)
816
+
817
+ Abbreviated recipes for local iteration when Storybook is not open — **[Grid patterns reference](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--grid-patterns-reference)** and related stories remain the source of truth; tune spans and gaps to match product templates.
818
+
819
+ **Dashboard main frame** (wide upper bound from **Width and max content**):
820
+
821
+ ```html
822
+ <div class="mx-auto w-full max-w-[min(100%,var(--container-8xl))] px-4 md:px-6">
823
+ <!-- page content -->
824
+ </div>
825
+ ```
826
+
827
+ **12-column metric row** (example tile shrinks from full width to quarter width at large breakpoints):
828
+
829
+ ```html
830
+ <div class="grid grid-cols-12 gap-4">
831
+ <section class="col-span-12 sm:col-span-6 lg:col-span-3">…</section>
832
+ <!-- repeat tiles -->
833
+ </div>
834
+ ```
835
+
836
+ **12-column dashboard tile row** (copy-pasteable baseline):
837
+
838
+ ```html
839
+ <div class="mx-auto w-full max-w-[min(100%,var(--container-8xl))] px-4 md:px-6">
840
+ <div class="grid grid-cols-12 gap-4 lg:gap-6">
841
+ <section class="col-span-12 sm:col-span-6 lg:col-span-3">…</section>
842
+ <section class="col-span-12 sm:col-span-6 lg:col-span-3">…</section>
843
+ <section class="col-span-12 sm:col-span-6 lg:col-span-3">…</section>
844
+ <section class="col-span-12 sm:col-span-6 lg:col-span-3">…</section>
845
+ </div>
846
+ </div>
847
+ ```
848
+
849
+ Adjust `col-span-*` values to match your content hierarchy. Always verify against [Storybook grid patterns](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--grid-patterns-reference).
850
+
851
+ **Numbers** in the tables below come from [`src/styles.source.css`](./src/styles.source.css) (`@theme inline` and `:root`) where applicable. **Gutters and gaps** use the same **4px-based** spacing scale as **[Tokens → Size and dimensions](#size-and-dimensions)**.
852
+
853
+ ### Body text reading width
854
+
855
+ - **Must** cap **continuous body text** (paragraphs, descriptions, long labels) at a **maximum width of 600px** for comfortable reading.
856
+ - **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.
857
+ - **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.
858
+
859
+ ### Width and max content
860
+
861
+ Aura adjusts Tailwind **container** breakpoints where the default scale is too wide or too narrow for Fusion-style surfaces:
862
+
863
+ | Token | Value | Role |
864
+ | :--- | :--- | :--- |
865
+ | `--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 |
866
+ | `--container-8xl` | 96rem (**1536px**) | Wide upper bound for dashboards and full-bleed marketing rows |
867
+
868
+ 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.
869
+
870
+ ### Column spans, compositions, and grids
871
+
872
+ - **Must** follow the **column span** and **composition** patterns from Storybook when laying out multi-column app and marketing surfaces — see [Column spans](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--column-spans) and [Compositions](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--compositions).
873
+ - **Must** align card grids, lists, and dashboard tiles to the **grid pattern** reference — see [Grid patterns reference](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--grid-patterns-reference).
874
+ - **Should** use **container queries** where a component’s layout should react to its **parent** width, not only the viewport — see [Container queries](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--container-queries).
875
+ - **Should** use the canonical **viewport breakpoints** for page-level reflow — see [Breakpoints](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--breakpoints).
876
+
877
+ ### Specialized layout variables
878
+
879
+ | Variable | Value | Use |
880
+ | :--- | :--- | :--- |
881
+ | `--message-content-max-width` | `80%` | Primary column for chat / assistant **Message** content in wide threads |
882
+ | `--drawer-max-height` | `80vh` | Maximum height for top/bottom drawer-style panels when the host implements them |
883
+ | `--alert-icon-width` | `calc(var(--spacing) * 4)` (typically **16px**) | Fixed icon column in the **Alert** grid so titles and descriptions align |
884
+
885
+ ### Grid and spacing usage
886
+
887
+ - **Must** use the **spacing scale** for padding, margin, and `gap` between layout regions (`gap-*`, `p-*`, `m-*`) — see **Tokens → Size and dimensions**.
888
+ - **Should** keep major block **padding** and **gap** on **4px** multiples so control heights, radii, and typography line up visually.
889
+ - **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**.
890
+ - **Avoid** one-off pixel gutters that ignore the scale unless matching a fixed graphic asset.
891
+
892
+ ### Responsive behavior
893
+
894
+ - **Should** treat viewport breakpoints as defined in Storybook — [Breakpoints](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--breakpoints) — and still sanity-check primary templates at about **768px**, **1024px**, and **1440px** in the Fusion shell or embedded contexts.
895
+ - **Should** use **container queries** for component-local layout where the preview shows it — [Container queries](https://cognitedata.github.io/aura/storybook/?path=/story/foundations-layout--container-queries).
896
+ - **Should** move secondary work into **Dialog** or a shell **Drawer** on narrow widths instead of compressing multi-column chrome.
897
+ - **Avoid** single-breakpoint layouts tuned only to a static design frame — use breakpoints, **container queries**, wrapping, and CSS grid `minmax` / `fr` where content must grow and shrink.
898
+
899
+ ### Shell vs content
900
+
901
+ **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.
902
+
903
+ ---
904
+
905
+ ## Assets
906
+
907
+ **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.
908
+
909
+ ### Illustrations
910
+
911
+ Illustrations add a human, expressive layer for **meaningful moments** — not general decoration. An illustration without a clear message is a distraction.
912
+
913
+ **Use for**
914
+
915
+ - Empty states — no content yet; user needs context or a clear next action
916
+ - Onboarding modals and product tours — first-use moments that should feel approachable
917
+ - Announcements — system-level messages that need more presence than copy alone
918
+ - Card visuals when photography or live data is not appropriate
919
+
920
+ **Do not use for**
921
+
922
+ - Decorative filler where the layout is already sufficient
923
+ - Stacking multiple illustrations in one context — **one illustration per context**
924
+ - Replacing copy — they **support** a message; they do not carry it alone
925
+
926
+ **Guidance**
927
+
928
+ - **Must** pair every illustration with supporting copy.
929
+ - **Must** use the asset variant that matches the active workspace theme (**light** or **dark**).
930
+ - **Must** preserve original aspect ratio — no non-uniform scaling or distortion.
931
+ - **Must** leave enough surrounding space so the asset reads clearly.
932
+ - **Must not** alter illustration artwork (cropping beyond safe bounds, filters, overlays, recolor).
933
+ - **Avoid** illustrations in dense data views or anywhere the primary task is scanning or acting on structured information.
934
+
935
+ **Accessibility**
936
+
937
+ - **Must** provide descriptive `alt` text on informative illustrations — describe the message, not every visual detail.
938
+ - Decorative illustrations that convey no extra information **should** use `alt=""` so assistive tech skips them.
939
+
940
+ ### Document icons
941
+
942
+ Document icons signal **file type** so users can scan lists, tables, uploads, and attachments quickly.
943
+
944
+ **Use for**
945
+
946
+ - File-type identification in lists, tables, and previews
947
+ - Upload flows and pickers where type recognition matters
948
+
949
+ **Guidance**
950
+
951
+ - **Must** use only approved sizes: **36px**, **40px**, or **44px** — no other sizes.
952
+ - **Must** center and vertically middle-align icons with adjacent text.
953
+ - **Must** keep shipped colors — do not recolor or theme-swizzle document icons outside the provided set.
954
+ - **Must not** edit artwork (shapes, backgrounds, proportions).
955
+
956
+ **Accessibility**
957
+
958
+ - **Must** use `alt` text that names the file type (e.g. `alt="PDF"`).
959
+
960
+ ### App icons
961
+
962
+ App icons identify **products, workspaces, or integrations** (launcher tiles, chrome, marketing surfaces). They are identity marks, not UI chrome.
963
+
964
+ **Guidance**
965
+
966
+ - **Must** use **official** Cognite or product marks from the brand system — no unofficial redraws.
967
+ - **Must** preserve clear space and minimum sizes defined by brand guidelines for each context (favicon, tile, splash).
968
+ - **Must not** distort, rotate for effect, add badges, or combine marks with decorative illustrations in the same glyph.
969
+
970
+ **Accessibility**
971
+
972
+ - Treat launcher and header marks as **informative** where they disambiguate apps; use `alt` or adjacent text consistent with the surface (e.g. app name next to the tile).
973
+
974
+ ### System icons
975
+
976
+ System icons are **functional** shorthand for actions, state, and navigation. Aura standardizes on **Tabler Icons** (`@tabler/icons-react` in the library). Names describe intent — **do not repurpose** an icon for an unrelated meaning.
977
+
978
+ **Sizes**
979
+
980
+ - **Default / recommended:** 16×16px
981
+ - **Accepted in UI components:** 12×12px, 14×14px, 16×16px (match the component’s density; Aura primitives often default to **16px** via `size-4` classes on icons)
982
+
983
+ **Guidance**
984
+
985
+ - **Must** use **filled** variants where brand or application chrome calls for weight (e.g. persistent app strip); use **outlined** variants for in-product actions and navigation unless a specific Aura component specifies otherwise.
986
+ - **Must not** edit, merge, or warp glyphs; icons stay **single-color** (typically `currentColor` so **Tokens** foreground colors apply). Exceptions: **branded** marks supplied as dedicated assets (see below).
987
+ - **Must not** hang hover, active, or focus styling on the raw icon — those states belong on the **control** (button, link, menu item).
988
+ - **Should** limit how many distinct icons compete on one view so each stays recognizable.
989
+ - **Avoid** icon-only interactive targets without a **Tooltip** or visible label (see accessibility).
990
+
991
+ **Branded icons**
992
+
993
+ Rare exceptions (third-party or Cognite logos inside a cell) use **provided SVGs only** — same rules as app icons for distortion and clear space; color may be multi-hue **only** when the asset is the official brand mark.
994
+
995
+ **Accessibility**
996
+
997
+ - **Must** meet **4.5:1** contrast against the icon’s background (same bar as body text when the icon communicates meaning).
998
+ - **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.
999
+ - Icons that only repeat the meaning of adjacent visible text **should** be `aria-hidden="true"`.
1000
+
1001
+ ---
1002
+
1003
+ ## Interaction states
1004
+
1005
+ **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.
1006
+
1007
+ 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.
1008
+
1009
+ | Concept | Meaning |
1010
+ | :--- | :--- |
1011
+ | **Affordance** | A property that makes an action possible (e.g. a control can be activated). |
1012
+ | **Signifier** | A visible cue that communicates that affordance (shape, label, shadow, state styling). |
1013
+
1014
+ Aura primitives ship these states by default; the rules below describe the **design contract** and apply when extending Aura or building one-off interactives.
1015
+
1016
+ ### Default (enabled)
1017
+
1018
+ The **resting** state: the element is available without shouting over neighboring content. Weight follows importance — a **primary** action reads stronger than a **table row** or **list item**. Match prominence to the action’s priority (see **Tokens** for `primary-background`, `muted-background`, `accent-background`, etc.).
1019
+
1020
+ ### Hover
1021
+
1022
+ The pointer is over the element; hover confirms interactivity before commitment.
1023
+
1024
+ **Guidance**
1025
+
1026
+ - **Must** change visibly from default — usually a background shift (`accent-background`, `primary-background-hover`, `secondary-background-hover`) or stroke emphasis (`border-emphasized` on outlines).
1027
+ - **Should** feel immediate (no intentional lag on hover feedback).
1028
+ - **Must not** be the **only** cue for something critical — hover is absent on many touch and reduced-motion contexts.
1029
+ - **May** add elevation (`shadow-*`) on hover for objects that already read as “cards” or panels — **sparingly**, only where elevation matches the metaphor.
1030
+
1031
+ ### Pressed
1032
+
1033
+ Pointer or finger is **down** on the control; confirms input was received.
1034
+
1035
+ **Guidance**
1036
+
1037
+ - **Must** read clearly **stronger or “deeper”** than hover (darker/lighter fill step, or subtle scale / inset — within the same token family, not a new ad-hoc color).
1038
+ - **Should** appear within about **one frame** of the gesture; duration is short and ends on release.
1039
+
1040
+ ### Focused
1041
+
1042
+ Keyboard or assistive tech has moved focus to the element. This is the main non-pointer signal for “where am I?” and is required for accessibility.
1043
+
1044
+ **Guidance**
1045
+
1046
+ - **Must** show a **visible** focus indicator on every interactive control. Do not remove focus styling without replacing it with an equivalent that meets contrast rules.
1047
+ - **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**.
1048
+ - **Must** meet **WCAG AA** for the focus indicator against its immediate background.
1049
+ - **Should** use **`:focus-visible`** (or library equivalents) so pointers do not get a keyboard ring on every click, while keyboard users always see one.
1050
+ - **Invalid inputs:** on focus, use the **destructive** focus ring token pair above (see **Tokens → Effects → Focus rings**).
1051
+
1052
+ ### Disabled
1053
+
1054
+ The control is present but **not** actionable in the current context; it does not respond to hover, press, or activation.
1055
+
1056
+ **Guidance**
1057
+
1058
+ - **Must** use **`disabled-background`** and **`disabled-foreground`** — not generic opacity on top of default colors unless a component API explicitly documents that pattern.
1059
+ - **Must not** show hover, pressed, or focus styling that implies activation (disabled is inert).
1060
+ - **Should** pair unexplained disabled controls with a **Tooltip** or inline hint (“Complete required fields to continue”) so users know how to re-enable.
1061
+ - **Avoid** using disabled as the main pattern for “not yet allowed” flows — prefer hiding the action, an inline message, or a clear path to fix the blocker.
1062
+ - **Avoid** disabling the **primary** CTA without a visible way to resolve the blocking condition.
1063
+
1064
+ ### Selected (toggled)
1065
+
1066
+ Persistent **on/off**, **selected**, **active filter**, or **applied setting** until the user changes it.
1067
+
1068
+ **Guidance**
1069
+
1070
+ - **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.
1071
+ - **Must not** rely on **color alone** — combine fill with icon, checkmark, label, or border treatment where the pattern is ambiguous.
1072
+ - **Must** implement **hover**, **pressed**, and **focus** for the **selected** variant as well as the default variant when both exist.
1073
+ - **Must not** show “selected” visuals for controls that are not actually in a selected state.
1074
+
1075
+ ### Loading
1076
+
1077
+ Work is **in progress**; the control or region may be temporarily inert or show progress.
1078
+
1079
+ **Guidance**
1080
+
1081
+ - **Must** expose busy state accessibly where appropriate (`aria-busy`, progress semantics, or an accessible name that includes “Loading”).
1082
+ - **Should** use Aura **Loader** / **Skeleton** / **Shimmer** (or documented equivalents) instead of ad-hoc spinners that ignore motion and contrast tokens.
1083
+ - **Should** read differently from **disabled** when the user can still cancel, navigate away, or understand wait time — disabled means “you cannot act here”; loading means “wait or observe progress.”
1084
+
1085
+ ---
1086
+
1087
+ ## Content
1088
+
1089
+ **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.
1090
+
1091
+ **Who:** Designers, product writers, engineers, and agents generating microcopy.
1092
+
1093
+ **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.
1094
+
1095
+ ---
1096
+
1097
+ ### Action labels
1098
+
1099
+ Users predict behavior from **consistent verbs**. Action labels use **sentence case** (e.g. “Edit model”).
1100
+
1101
+ **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.
1102
+
1103
+ **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.
1104
+
1105
+ | Label | Use |
1106
+ | :--- | :--- |
1107
+ | **Add** | Attach an existing object to a new context (e.g. add to canvas). |
1108
+ | **Apply** | Commit filters or settings so they drive subsequent behavior. |
1109
+ | **Approve** | User agrees; in workflows, usually advances the process. |
1110
+ | **Back** | Previous step in a sequence or hierarchy. |
1111
+ | **Browse** | Structured scanning (categories, menus, filters). |
1112
+ | **Cancel** | Stop the current action and dismiss the surface; warn if stopping risks data loss. |
1113
+ | **Clear (all)** | Clear fields or selections; restore default where a control always has a value (e.g. radio). |
1114
+ | **Close** | Close a page, pane, or window (often icon-only). |
1115
+ | **Collapse** / **Expand** | Hide or show a panel (often icon-only). |
1116
+ | **Copy** | Copy to clipboard for use elsewhere. |
1117
+ | **Create** | New object from nothing (vs **Add** / **Duplicate**). |
1118
+ | **Delete** | Permanently remove the object. |
1119
+ | **Discard** | Abandon unsaved draft or edits. |
1120
+ | **Download** / **Upload** | Transfer file remote → local / local → remote. |
1121
+ | **Duplicate** | Copy in the same location as the original. |
1122
+ | **Edit** | Change data or values. |
1123
+ | **Explore** | Open-ended discovery without a fixed goal. |
1124
+ | **Export** | Save in an external format (often via a secondary step for type and destination). |
1125
+ | **Finish** | Complete a multi-step flow (e.g. wizard). |
1126
+ | **Hide** / **Show** | Toggle visibility in the UI only (not delete). |
1127
+ | **Import** | Bring data in from an external source. |
1128
+ | **Insert** | Place at a position in an ordered structure (e.g. table row). |
1129
+ | **Next** | Advance one step in a sequence. |
1130
+ | **Open** | **Internal:** drawer, modal, or in-app route (support open-in-new-tab where appropriate). **External:** new tab/window for external URLs. |
1131
+ | **Publish** / **Unpublish** | Make content available to intended audiences / remove from public view without deleting. |
1132
+ | **Query** | Request specific data from a store or service. |
1133
+ | **Redo** / **Undo** | Redo reverses undo; undo steps back through user edits (not all actions are undoable). |
1134
+ | **Refresh** | Reload when the view may be stale. |
1135
+ | **Register** | Create an account or enroll a user (prefer over “Sign up” where it could be confused with **Sign in**). |
1136
+ | **Reject** | User does not approve; in workflows, usually blocks progression. |
1137
+ | **Remove** | Remove from current context without destroying the object. |
1138
+ | **Reset** | Revert to last saved or default values. |
1139
+ | **Restore** | Revert to last saved version. |
1140
+ | **Save** | Persist changes without closing the surface. |
1141
+ | **Search** | Goal-oriented lookup. |
1142
+ | **Select** | Pick from a set of options. |
1143
+ | **Sign in** / **Sign out** | Authenticate / end session. |
1144
+ | **View** | Show details or properties (read-heavy). |
1145
+
1146
+ ---
1147
+
1148
+ ### Date and time formatting
1149
+
1150
+ **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.
1151
+
1152
+ **Dimensions**
1153
+
1154
+ | Concept | Meaning |
1155
+ | :--- | :--- |
1156
+ | **Read-only vs input** | Read-only is display-only; input uses pickers/fields — both should stay consistent within a feature. |
1157
+ | **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. |
1158
+ | **Absolute vs relative** | Absolute = calendar date/time of the event; relative = “32 min ago”. |
1159
+
1160
+ **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).
1161
+
1162
+ **Time**
1163
+
1164
+ - **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`).
1165
+ - **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.
1166
+
1167
+ **Dates and combined date-time**
1168
+
1169
+ - **Must** include the **year** unless context makes it obvious (e.g. chart titled by year).
1170
+ - **Must not** use **ordinal** day forms (“1st”, “23rd”) in UI dates.
1171
+ - If numeric dates are required, **should** use **`/`** separators, zero-pad single-digit days/months, and include the year; stay consistent across the feature.
1172
+ - For combined date + time in prose, **should** separate with **“at”** or an unambiguous pattern; **must** keep date and time ordering consistent.
1173
+
1174
+ **Ranges**
1175
+
1176
+ - **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).
1177
+ - **Date range:** consistent formatting; **avoid** dense numeric ranges that are hard to parse.
1178
+ - **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.
1179
+
1180
+ **Duration** (elapsed length, not a clock range)
1181
+
1182
+ - **Should** express duration when elapsed length matters more than endpoints.
1183
+ - No “relative” phrasing for duration lists.
1184
+ - **Should** use a **space** between number and unit in body text and tables (`3 seconds`); compact controls may omit the space per component spec.
1185
+ - **Should** avoid commas between compound units (`10 minutes 3 seconds` not `10 minutes, 3 seconds`).
1186
+ - For sub-second precision, **should** use decimals (`2.5 seconds`) or round to a meaningful whole unit to reduce noise.
1187
+
1188
+ **Abbreviations** (lowercase units except proper nouns like **Jan**, **Mon**; no periods on abbreviations)
1189
+
1190
+ | Full (examples) | Abbreviated |
1191
+ | :--- | :--- |
1192
+ | millisecond(s), second(s), minute(s), hour(s) | ms, s, min, hr |
1193
+ | day(s), week(s), month(s), year(s) | d, wk, mo, yr |
1194
+
1195
+ Days and months: **Monday** → **Mon**, **January** → **Jan**, etc.; capitalize; allow width for **four-letter** abbreviations where internationalization may need it.
1196
+
1197
+ **Scheduled automation:** use **cron** expressions where users define recurring runs.
1198
+
1199
+ ---
1200
+
1201
+ ### Grammar and style
1202
+
1203
+ **Must** use **American English** in UI (`color`, `center`, `organization`, …). **Must** use **sentence case** for UI phrases; **must not** use **ALL CAPS** for body labels.
1204
+
1205
+ **Should** prefer **active voice**; use passive only for objectivity or legal emphasis.
1206
+
1207
+ **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.
1208
+
1209
+ **Abbreviations:** spell out when possible; **avoid** Latin shortcuts (“e.g.”, “etc.”) — use “for example”, “and more”, or recast the sentence.
1210
+
1211
+ **Punctuation**
1212
+
1213
+ - **Avoid** terminal periods on short labels, tooltips, and single-line list items.
1214
+ - **Must** use periods for **multi-sentence** blocks and dense prose.
1215
+ - **Avoid** exclamation marks in default UI; use **ellipses** sparingly for in-progress or truncated text.
1216
+ - **Should** use the **Oxford comma** in lists.
1217
+ - **Avoid** ampersands (`&`) in translatable UI — use **and**.
1218
+
1219
+ **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).
1220
+
1221
+ **Plural forms:** **avoid** “(s)” or “(es)” in labels — use separate strings or unambiguous copy per locale.
1222
+
1223
+ ---
1224
+
1225
+ ### Localization
1226
+
1227
+ Strings ship through translation workflows (e.g. **Locize**); follow platform developer documentation for keys and context.
1228
+
1229
+ **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.
1230
+
1231
+ ---
1232
+
1233
+ ### Voice and tone
1234
+
1235
+ **Voice** stays consistent; **tone** shifts with context (onboarding vs error vs success).
1236
+
1237
+ **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).
1238
+
1239
+ **Should** acknowledge friction honestly where UX is rough; keep disclaimers minimal.
1240
+
1241
+ | Scenario | Tone | Example |
1242
+ | :--- | :--- | :--- |
1243
+ | First-time onboarding | Friendly, welcoming | “Let’s get started — you’re ready when you are.” |
1244
+ | Technical flows | Clear, direct | “Configure your endpoint and authenticate with your API key.” |
1245
+ | Errors | Empathetic, constructive | “Something went wrong. Try refreshing or check your connection.” |
1246
+ | Success | Brief, positive | “Your data is now flowing.” |
1247
+ | Tours / help | Conversational | “Want a quick tour? We’ll cover the essentials in under two minutes.” |
1248
+
1249
+ Align microcopy with the same **product terminology** glossary referenced in **Grammar and style**.
1250
+
1251
+ ---
1252
+
1253
+ ### Writing for accessibility
1254
+
1255
+ Structural accessibility (focus, contrast, semantics, targets) lives in **Heuristics §7** and **Interaction states**. This subsection is **copy-specific**.
1256
+
1257
+ **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.
1258
+
1259
+ **Must** make **link text** describe the destination or outcome (“Learn about pricing”), not “click here” or bare “read more”.
1260
+
1261
+ **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.
1262
+
1263
+ **Should** avoid **this** / **that** without a clear noun referent.
1264
+
1265
+ **Should** describe **data trends** in words when the UI relies on charts or color alone.
1266
+
1267
+ **Must** use **Select** (or “choose”, “turn on”) rather than **Click** in instructions — not all users use a pointer.
1268
+
1269
+ ---