# Aura

Aura exports Cognite's UI components, styles, utilities, and ESLint guidance for preserving the design system in downstream apps.

## Using Aura in Fusion

[`DESIGN.md`](./DESIGN.md) describes visual identity, critical interaction rules, and UX guidance for feedback, disclosure, errors, layout, and accessibility. This section covers *how to use the package* in the Fusion monorepo and host shell.

### Package imports

Aura ships two flavours of component import. Both resolve through the package's `exports` map — never reach into `src/`.

**Per-component subpath (strongly preferred for app code)** keeps bundles small *and* keeps builds fast by only pulling in what each module actually needs:

```tsx
import { Button } from '@cognite/aura/components/button';
import { Card } from '@cognite/aura/components/card';
import { DatePicker } from '@cognite/aura/components/date-time-pickers';
```

**Aggregate barrel** is convenient for stories, prototypes, and code that already pulls in many components:

```tsx
import { Button, Card } from '@cognite/aura/components';
```

> ⚠️ **The barrel is not free at build time.** Even though the runtime output tree-shakes (the barrel is side-effect-free apart from `*.css`), a bundler must still *load and transform* every module the barrel re-exports before tree-shaking can drop the unused ones. That includes heavy graphs such as `shiki` (via `CodeBlock`) and `mermaid` + `streamdown` (via `Message`). For a small app this can mean transforming ~10k modules and exhausting the default Node heap (`JavaScript heap out of memory`). Reaching for a single component from the barrel (`import { Card } from '@cognite/aura/components'`) pays this whole cost. Use per-component subpaths in app code; reserve the barrel for stories/prototypes.

Lightweight components never pull the heavy graphs: `shiki` is only imported by `@cognite/aura/components/code-block`, and `mermaid`/`streamdown` only by `@cognite/aura/components/message`. Importing e.g. `@cognite/aura/components/card` (or the shared `@cognite/aura/utils` `cn` helper) pulls neither — the `cn` helper is deliberately kept in a module that has no path to `shiki`.

> The `highlightCode` helper (Shiki wrapper) previously lived on `@cognite/aura/utils`. It now has its own entry point, `@cognite/aura/highlight-code`, so that importing `cn` from `@cognite/aura/utils` never drags Shiki into your build graph.

**System icons** are provided by Tabler through Aura's icon entry point. Use named imports so application bundlers can tree-shake unused icons:

```tsx
import { IconSearch, IconSettings } from '@cognite/aura/icons';
```

Aura styles default Tabler icons to 16px with a 1.5px stroke. Override these defaults with Tailwind utilities, which take precedence over Aura's base styles:

```tsx
<IconSearch />
<IconSettings className="size-6 stroke-2" />
```

Use `size-*` and `stroke-*` utilities rather than Tabler's `size` and `stroke` props when Aura styles are loaded, because CSS takes precedence over SVG presentation attributes.

Stylesheets and tokens are imported the same way regardless of which component-import style you use:

```tsx
import '@cognite/aura/colors.css';
import '@cognite/aura/styles.css';
```

Canonical token sources in this repo: `src/colors.css` and `src/styles.source.css`. In consuming apps, import from the published package paths above — not from `src/` next to your app code.

Do not import Aura through relative paths from another project, such as `../../../libs/aura/src/components`. Fusion resolves Aura through its package exports, so use `@cognite/aura/components` (or a per-component subpath), `@cognite/aura/icons`, `@cognite/aura/colors.css`, and `@cognite/aura/styles.css`.

#### Adding a new component

Every Aura component must support **both** import styles. When you add a new component:

1. Place its source under `src/components/ui/core/<name>/<name>.tsx`, matching the kebab-case directory used by existing components.
2. Re-export it from the aggregate barrel in `src/components/index.ts` so `@cognite/aura/components` keeps working.
3. Register a per-component subpath export in `libs/aura/package.json` (alphabetical order):

   ```json
   "./components/<name>": {
     "@fusion/source": "./src/components/ui/core/<name>/<name>.tsx",
     "import": "./dist/components/ui/core/<name>/<name>.js",
     "types": "./dist/components/ui/core/<name>/<name>.d.ts"
   }
   ```

   Composite components that ship as a folder (such as `date-time-pickers`) point at the folder's `index.ts` instead.

The Vite build derives library entries directly from `package.json` (`entriesFromPackageJson: true`), so once both entry points are wired the dist output and types appear automatically. The two surfaces must stay in sync — consumers should be able to choose either style without missing exports.

Aura uses Tailwind v4 package CSS entry points. Consuming Fusion apps should not add a `tailwind.config.js` just to wire Aura tokens or content paths; import `@cognite/aura/styles.css` and let Aura's exported CSS carry the theme and source directives. `styles.css` is the public stylesheet entry point for product consumers; in published external packages it resolves to the built Tailwind CSS output produced by Aura's build.

When another Fusion library exposes Aura-styled components, give that library the same self-sourcing setup instead of pushing scan rules into every consumer:

- Export a package stylesheet, for example `@cognite/example-ui/styles.css`.
- In that stylesheet, import `@cognite/aura/styles.source.css` and source the library itself. `styles.source.css` is for package stylesheets that compose Aura's Tailwind theme/source directives before adding their own `@source` rules:

  ```css
  @import '@cognite/aura/styles.source.css';
  @source './';
  ```

- If the target app already relies on `!important` style precedence, for example through styled-components overrides or existing Cogs components, add Tailwind's import modifier so Aura utilities can match that setup when necessary:

  ```css
  @import '@cognite/aura/styles.source.css' important;
  @source './';
  ```

- If the library builds or previews that stylesheet directly, include `@tailwindcss/vite` in its Vite and Storybook setup.
- Consumers should import the library stylesheet, not Aura internals. For example, an app using `@cognite/atlas-ai-react-ui` should import `@cognite/atlas-ai-react-ui/styles.css`, which can pull in Aura internally.
- Do not add cross-project `@source "../../../libs/..."` directives or `tailwind.config.js` `content` entries for other Fusion libraries. In Tailwind v4 these app-level content arrays do not replace package-owned `@source` directives.

Prefer **CVA** variants and component APIs over overriding primitive styles. Prop names, `size` values, and subcomponents are defined in:

- [Aura Storybook](https://storybook-aura-23638.fusion-preview.preview.cogniteapp.com)
- [Aura design system docs](https://docs.cognite.com/aura-design-system/get-started)
- TypeScript types from `@cognite/aura/components`

### Fusion shell integration

The Fusion host shell owns global chrome that Aura does not ship: **Topbar**, **Sonner** toasts, **AlertDialog**, **Sheet** / **Drawer**, **Tabs**, **SegmentedControl**, and some patterns like **EmptyState**. These **must** still follow Aura tokens, [Interaction states](./DESIGN.md#interaction-states), and [Heuristics](./DESIGN.md#heuristics).

| Concern | Fusion convention |
| ------- | ----------------- |
| Primary navigation | One **Topbar**; avoid duplicating global nav in content |
| View switching | Shell **Tabs** / **SegmentedControl** when the product uses that pattern |
| Toasts | **Sonner**, bottom-right, ~4s auto-dismiss, themed with Aura tokens |
| Confirm destructive work | Shell **AlertDialog** or Aura **Dialog** with explicit copy |
| Narrow viewports | Prefer shell **Drawer** / **Dialog** over compressed multi-column chrome |

For local sub-app development against the live shell, use import map overrides — see the Fusion [subapp manual testing guide](../../.cursor/rules/subapp-manual-testing.mdc).

### Serve and test locally

```sh
pnpm nx serve aura          # Storybook
pnpm nx run aura:design-md-lint
```

## Optional peer dependencies

Some Aura entry points require optional peer dependencies that consumers must install themselves:

- `@cognite/aura/chart` requires `recharts >=3.7`. Add it to your app:

  ```sh
  pnpm add recharts
  ```

  Aura follows the [shadcn/ui Charts](https://ui.shadcn.com/docs/components/chart) pattern: import the shell and chrome from `@cognite/aura/chart`, and import Recharts primitives from `recharts`.

  ```tsx
  import { Bar, BarChart, XAxis } from 'recharts';
  import {
    ChartContainer,
    ChartTooltip,
    type ChartConfig,
  } from '@cognite/aura/chart';

  const config = {
    runs: { label: 'Runs', color: 'var(--color-chart-fjord-color-1)' },
  } satisfies ChartConfig;

  <ChartContainer config={config} aria-label="Runs by day">
    <BarChart data={data}>
      <XAxis dataKey="day" />
      <ChartTooltip />
      <Bar dataKey="runs" fill="var(--color-runs)" />
    </BarChart>
  </ChartContainer>
  ```

- `@cognite/aura/data-grid` requires `@tanstack/react-table >=8.7` and `@tanstack/react-virtual >=3.10`. Add them to your app:

  ```sh
  pnpm add @tanstack/react-table @tanstack/react-virtual
  ```

  The DataGrid is a virtualised table with client/server sorting, column pinning, and
  expandable rows. Pass `columns` and `data` from your own TanStack column definitions.
  Header chrome, pagination, selection, search, filters, and loading states are landing in
  follow-up PRs.

  ```tsx
  import type { ColumnDef } from '@tanstack/react-table';
  import { DataGrid } from '@cognite/aura/data-grid';

  type Row = { id: string; name: string };
  const columns: ColumnDef<Row>[] = [{ accessorKey: 'name', header: 'Name' }];

  <DataGrid
    data={rows}
    columns={columns}
    getRowId={(row) => row.id}
    enableSorting
    aria-label="Assets"
  />;
  ```

## Versioning

### Before releasing

Ensure all documentation is up to date before bumping the version:

- [`CHANGELOG.md`](./CHANGELOG.md) — summarise all consumer-facing changes since the last release.
- [`DESIGN.md`](./DESIGN.md) — reflect any new or updated components, tokens, or visual behaviour.
- Any agent skills in `.cursor/skills/` or `.claude/skills/` that reference Aura components or APIs.

### Release process

1. Create a release branch off the latest `master`.
2. Bump the version in `libs/aura/package.json` and prepend a new section to `CHANGELOG.md`.
3. Commit with `release(aura): <version>` and open a PR into `master`.
4. Once merged, CI publishes the package to the registry automatically.

### After publishing

Consumers can adopt the new version by updating their `package.json` manually, or by letting Renovate/Dependabot open a bump PR in their repo automatically. [The Custom Apps repo](https://github.com/cognitedata/dune) has this configured and is the primary critical consumer. 

## DESIGN.md

[`DESIGN.md`](./DESIGN.md) describes Aura's visual identity in the [Google design.md](https://github.com/google-labs-code/design.md) format — YAML design tokens in front matter plus markdown rationale for coding agents.

Validate structure, token references, and section order with [`@google/design.md`](https://www.npmjs.com/package/@google/design.md):

**Recommended (from the Fusion workspace root):**

```sh
pnpm nx run aura:design-md-lint
```

**Direct CLI (from `libs/aura`):**

```sh
npx --yes @google/design.md lint ./DESIGN.md
```

Exit code `0` means the file passed (no errors). Warnings surface issues such as orphaned tokens or out-of-order sections.

Published installs ship this spec at the package root; resolve it as `@cognite/aura/DESIGN.md` (for example with `import.meta.resolve` or your bundler's raw import).

## ESLint

Aura ships an ESLint plugin at `@cognite/aura/eslint`.

### What it does

The `aura/no-overriding-styles` rule warns when consumers pass visual Tailwind-style utilities to Aura or Aura Labs components via `className`.

It is intended to preserve Aura's out-of-the-box appearance while still allowing host apps to control layout and sizing.

Allowed examples:

- `w-full`
- `ml-auto`
- `hidden md:flex`
- `grid-cols-2`
- `max-w-[32rem]`

Warned examples:

- `bg-card`
- `text-xs`
- `rounded-lg`
- `shadow-none`
- `animate-pulse`

The rule also provides suggestions and autofix for simple static `className` values by removing disallowed classes and keeping layout-safe utilities.

### Usage

Add the Aura plugin to your ESLint config and enable the rule:

```js
import { auraEslintPlugin } from '@cognite/aura/eslint';

export default [
  {
    files: ['**/*.{ts,tsx,js,jsx}'],
    plugins: {
      aura: auraEslintPlugin,
    },
    rules: {
      'aura/no-overriding-styles': 'warn',
    },
  },
];
```

### Example

```tsx
import { Button } from '@cognite/aura/components';

export function Example() {
  return <Button className="w-full ml-auto bg-card rounded-lg" />;
}
```

The rule keeps the layout-safe classes and warns about the visual overrides:

- kept: `w-full`, `ml-auto`
- warned: `bg-card`, `rounded-lg`

Use Aura variants, props, or composition when you need to change the component's appearance.
