init
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
# Topbar Implementation
|
||||
|
||||
Install, theme-hook wiring, and composition for `@aura/topbar`. Run the interview ([INTERVIEW.md](INTERVIEW.md)) first.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Install
|
||||
|
||||
**Installation is mandatory.** If `@aura/topbar` cannot be installed, stop and surface the blocker. Do not build a custom component or any workaround.
|
||||
|
||||
### 3a — Check if already installed
|
||||
|
||||
Check `package.json` for `@aura/topbar`. If present, skip to Step 3d.
|
||||
|
||||
### 3b — Determine install method
|
||||
|
||||
`@aura/topbar` is a **shadcn registry component** — not on npm. The only valid install path is the shadcn CLI (`pnpm dlx shadcn@latest add`). Do not use `npm install`, `pnpm add`, or `yarn add`.
|
||||
|
||||
Before running the install:
|
||||
|
||||
1. **Ensure `components.json` has the `@aura` registry.** If absent or missing the entry, add:
|
||||
|
||||
```json
|
||||
{
|
||||
"registries": {
|
||||
"@aura": "https://cognitedata.github.io/aura/r/{name}.json"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If `components.json` does not exist at all, run `pnpm dlx shadcn@latest init` first, then add the entry.
|
||||
|
||||
2. **Detect the package manager:**
|
||||
- `pnpm-lock.yaml` → pnpm
|
||||
- `yarn.lock` → yarn
|
||||
- `package-lock.json` → npm
|
||||
|
||||
### 3c — Install
|
||||
|
||||
```bash
|
||||
pnpm dlx shadcn@latest add @aura/topbar
|
||||
```
|
||||
|
||||
> **If this fails**, stop. Tell the user exactly what failed and ask them to resolve the blocker. Do not proceed with a workaround.
|
||||
|
||||
### 3d — Tailwind check
|
||||
|
||||
Confirm `tailwind.config` has `darkMode: 'class'`. Add it if missing.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Dark mode hook
|
||||
|
||||
Always implement theme switching (light / dark). Check for an existing theme system first:
|
||||
|
||||
- Search for `useDarkMode`, `useTheme`, `useColorScheme`, or a `ThemeProvider` in `src/`
|
||||
- If found, wire into it and skip creating a new hook.
|
||||
|
||||
If none exists, create `src/hooks/use-theme-mode.ts` (or extend your existing hook) so the Topbar menu can **set** light or dark explicitly:
|
||||
|
||||
```ts
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export type ThemeMode = 'light' | 'dark';
|
||||
|
||||
export function useThemeMode() {
|
||||
const [mode, setMode] = useState<ThemeMode>(() => {
|
||||
const stored = localStorage.getItem('theme');
|
||||
if (stored === 'dark' || stored === 'light') return stored;
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const isDark = mode === 'dark';
|
||||
document.documentElement.classList.toggle('dark', isDark);
|
||||
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
||||
}, [mode]);
|
||||
|
||||
return {
|
||||
mode,
|
||||
isDark: mode === 'dark',
|
||||
setTheme: (next: ThemeMode) => setMode(next),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Apply the initial class on page load in `main.tsx` / `index.tsx`:
|
||||
|
||||
```ts
|
||||
const stored = localStorage.getItem('theme');
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
if (stored === 'dark' || (!stored && prefersDark)) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
```
|
||||
|
||||
The Topbar **theme** trigger should open a **Menu** whose items call `setTheme('light')` and `setTheme('dark')` and show a **checkmark** on the active row.
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Implement the Topbar
|
||||
|
||||
**Always check Storybook for exact prop names before writing code.** The names below are illustrative — verify against the current `@aura/topbar` package.
|
||||
|
||||
```tsx
|
||||
import { Topbar } from '@aura/topbar';
|
||||
import { Breadcrumb, BreadcrumbItem } from '@aura/topbar'; // adjust to actual exports
|
||||
// App + user Avatar: import from the Aura package / path Storybook documents for Topbar.
|
||||
import { useThemeMode } from '@/hooks/use-theme-mode';
|
||||
|
||||
export function AppShell({ children }: { children: React.ReactNode }) {
|
||||
const { mode, setTheme } = useThemeMode();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Topbar
|
||||
// Left — application mark: Avatar small, fjord (verify Storybook props)
|
||||
applicationIcon={
|
||||
<Avatar size="small" colorway="fjord" src={appMarkSrc} alt="" />
|
||||
}
|
||||
breadcrumbs={
|
||||
<Breadcrumb>
|
||||
<BreadcrumbItem label="Application Name" href="/" />
|
||||
{/* <BreadcrumbItem label={objectName} ... dropdown ... /> */}
|
||||
</Breadcrumb>
|
||||
}
|
||||
|
||||
// Inline metadata — optional string immediately after breadcrumb, left-aligned only
|
||||
// breadcrumbMetadata="Updated 3 hours ago"
|
||||
|
||||
// Middle — optional Tabs (routes) OR Segmented control (modes); size small; omit if unused
|
||||
centerSlot={
|
||||
null
|
||||
// Example Tabs: <Tabs size="sm" ... />
|
||||
// Example Segmented: <SegmentedControl size="sm" ... />
|
||||
}
|
||||
|
||||
// Right strip — fixed order when each is visible: share → notifications → theme → atlas → avatar
|
||||
// Theme: sun when light, moon when dark; Menu with Light mode / Dark mode + checkmark on active
|
||||
// Storybook may still call this darkMode or split props differently — map menu choice to setTheme('light'|'dark').
|
||||
trailingSlot={null}
|
||||
systemActions={{
|
||||
share: { visible: true },
|
||||
notifications: { visible: true },
|
||||
darkMode: {
|
||||
visible: true,
|
||||
mode, // 'light' | 'dark' — illustrative; use whatever resolvedTheme API Aura exposes
|
||||
onSelectLight: () => setTheme('light'),
|
||||
onSelectDark: () => setTheme('dark'),
|
||||
},
|
||||
atlas: { visible: true },
|
||||
avatar: { visible: true, src: userPhotoSrc, alt: userName },
|
||||
}}
|
||||
/>
|
||||
<main>{children}</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Layout wrapper:** The parent element must allow the Topbar to be full-width and sticky:
|
||||
|
||||
```tsx
|
||||
<div className="flex min-h-screen flex-col">
|
||||
<AppShell>
|
||||
{/* page content — primary actions for the current screen live here */}
|
||||
</AppShell>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional resources
|
||||
|
||||
- Full Topbar architecture rules: [RULES.md](RULES.md)
|
||||
- Aura Topbar Storybook: https://cognitedata.github.io/aura/storybook/?path=/docs/primitives-topbar--docs
|
||||
- Aura Breadcrumb Storybook: https://cognitedata.github.io/aura/storybook/?path=/docs/primitives-breadcrumb--docs
|
||||
- Aura Button Storybook: https://cognitedata.github.io/aura/storybook/?path=/docs/primitives-button--docs
|
||||
- Aura colors / dark mode tokens: https://cognitedata.github.io/aura/storybook/?path=/docs/foundations-colors--docs
|
||||
@@ -0,0 +1,178 @@
|
||||
# Topbar Configuration Interview
|
||||
|
||||
**Complete this interview before writing any implementation code.** Do not skip, shorten, or defer it. If completing it mid-task feels disruptive, pause the task, run the interview, then resume.
|
||||
|
||||
Ask **one question at a time** and wait for the answer. Skip only questions that the pre-flight read (Step 1 in [SKILL.md](SKILL.md)) already answered definitively.
|
||||
|
||||
---
|
||||
|
||||
## Topbar layout reference
|
||||
|
||||
Use this diagram to orient yourself and the user throughout the interview:
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ [App Avatar] [App] > [Object▾] metadata… │ (optional) Tabs or Segmented — sm │ Share Bell Theme Atlas User │
|
||||
│ ←── Left: fjord Avatar + breadcrumb + metadata (left-aligned, not centered) ──→ │ ←── Middle ──→ │ ←── Right strip (fixed order) ──→ │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Left section — breadcrumb states:**
|
||||
|
||||
```
|
||||
No object open: [App Avatar] My App
|
||||
Object open: [App Avatar] My App > Root Cause Analysis ▾
|
||||
With inline metadata: [App Avatar] My App > Root Cause Analysis ▾ Updated 3 hours ago
|
||||
```
|
||||
|
||||
- Metadata always continues **on the left**, immediately after the breadcrumb — it is **never** centered in the Topbar.
|
||||
- App name clicking navigates to the app's home/root route — but only when an object is open. If no object is open, the app name is not a link.
|
||||
- Object name is clickable only when it acts as a dropdown trigger (▾). Each breadcrumb segment is an interactive link that navigates to its route.
|
||||
|
||||
**Middle section — Tabs or Segmented control (optional):**
|
||||
|
||||
```
|
||||
Tabs (routes): [Overview] [Well analysis] [Settings]
|
||||
Segmented (modes): [Canvas view] [Code view]
|
||||
```
|
||||
|
||||
- **Tabs** — mutually exclusive **page-level** views (routes).
|
||||
- **Segmented control** — **mode** or layout switching (e.g. canvas vs code) when that fits better than route tabs.
|
||||
- **Always `size="sm"`** (or Aura's equivalent **small** size for these primitives).
|
||||
- Omit entirely if the app has no global navigation or only one view.
|
||||
- **Do not** put app-specific **primary** actions here — those belong **below** the Topbar.
|
||||
|
||||
**Right section — utility strip (fixed order when each control is shown):**
|
||||
|
||||
```
|
||||
Share (ghost, sm) Notifications (ghost, sm) Theme (ghost, sm) Atlas (secondary, sm) User Avatar (sm)
|
||||
optional optional optional optional optional*
|
||||
```
|
||||
|
||||
\*Theme and user Avatar are **typically on**; turn off only when the API and product policy allow.
|
||||
|
||||
**Theme control:**
|
||||
|
||||
- **Light mode** → **sun** icon on the trigger; **dark mode** → **moon** icon.
|
||||
- Clicking opens a **Menu** with **Light mode** and **Dark mode** rows; a **checkmark** shows the current selection; only **one** row is active at a time.
|
||||
|
||||
If Storybook exposes extra right-slot entries (e.g. legacy agent), follow the **current** Aura API and [RULES.md §3.3](RULES.md).
|
||||
|
||||
---
|
||||
|
||||
## Left section
|
||||
|
||||
**Q1 — Application mark (Avatar)**
|
||||
|
||||
> "At the far left we use a small Aura Avatar in the fjord colorway for the app mark. Does your app already have branding or an image in config, or should we use the default fjord Avatar treatment from Aura?"
|
||||
|
||||
- Prefer assets from Flows/Fusion app config when present.
|
||||
- Compose with Aura **`Avatar`**, **`size="small"`**, **`fjord`** (exact props from Storybook).
|
||||
|
||||
**Q2 — App name**
|
||||
|
||||
> "What is the name of your application? It will appear as the first breadcrumb and always be visible."
|
||||
|
||||
- If already defined in app config (`displayName`, `name`), apply it and skip.
|
||||
|
||||
**Q3 — App structure and breadcrumbs**
|
||||
|
||||
> "Referring to the breadcrumb states above — which best describes your app: single app name only (no objects), or does the app let users open specific named items like a canvas, report, or document?"
|
||||
|
||||
- **No objects** → only the app name appears in the breadcrumb. The app name is not a link (there is nowhere to navigate back to).
|
||||
- **Named objects** → app name always visible; object name added as the last segment only when an object is open. If yes: "What do you call these items? (e.g. Canvas, Report, Dashboard)"
|
||||
|
||||
**Breadcrumb interactivity rules (non-negotiable):**
|
||||
- All breadcrumb segments are **interactive links** — they must navigate to their corresponding route, not be plain text.
|
||||
- When an object is open, clicking the **app name** navigates back to the app's home/root (e.g. the object list or landing page).
|
||||
- When no object is open, the app name segment is **not** a link (it is the current location).
|
||||
- Do not render breadcrumbs as static/non-interactive text.
|
||||
|
||||
**Q4 — Object actions dropdown** _(ask only if Q3 identified named objects)_
|
||||
|
||||
> "When a user has a specific [object type] open, would you like a dropdown menu on its name in the breadcrumb for object-level actions — like rename, duplicate, export, or delete?"
|
||||
|
||||
- This dropdown appears **only on the object name** (the last breadcrumb segment), and **only when an object is currently open**.
|
||||
- **There is no dropdown on the app name.** If users need app-level settings (e.g. manage permissions, configure defaults), place entry points in the **content area below the Topbar** (or another approved pattern), not inside the object dropdown.
|
||||
- All actions in the object dropdown must apply **only to the currently open object** — do not mix in app-level or global actions.
|
||||
- Examples: "Rename this canvas", "Duplicate this report", "Export this document", "Delete this item".
|
||||
- If yes: "What object-specific actions should appear in the menu?"
|
||||
|
||||
---
|
||||
|
||||
## Left section — inline metadata
|
||||
|
||||
**Q5 — Inline metadata** _(optional)_
|
||||
|
||||
> "Would you like a short status string directly after the breadcrumb on the **left** — things like 'Updated 3 hours ago' or 'Read-only'? It stays in the left cluster with the breadcrumb, never centered in the bar."
|
||||
|
||||
- If yes: "What text should appear there?"
|
||||
- **String only** — no links, icons, or interactive elements.
|
||||
- Omit entirely if unused — do not add a placeholder.
|
||||
- Typical use: last-modified time, read-only state, a status label tied to the current object or page.
|
||||
|
||||
---
|
||||
|
||||
## Middle section — navigation
|
||||
|
||||
**Q6 — Global navigation (Tabs or Segmented)** _(optional)_
|
||||
|
||||
> "Does your app need global navigation in the center of the Topbar — either **Tabs** for mutually exclusive pages/routes, or a **Segmented control** for modes like canvas vs code?"
|
||||
|
||||
- **Tabs** — primary app sections as routes (e.g. Overview → `/overview`, Settings → `/settings`).
|
||||
- **Segmented control** — switching **views or modes** within the app without changing the top-level route model, when that fits better.
|
||||
- **Always small** size to match the rest of the Topbar.
|
||||
- **Never use a sidebar for primary navigation.** If the app needs additional internal navigation beyond this slot, it must live within the content area — not as a sidebar.
|
||||
- Only include controls that are relevant globally. Page-specific sub-navigation belongs in the content area.
|
||||
- If yes: "Which pattern (Tabs vs Segmented), what are the labels, and where does each choice lead?"
|
||||
- **Default:** leave the center empty and keep **primary actions below the Topbar**.
|
||||
|
||||
---
|
||||
|
||||
## Right section — utility strip
|
||||
|
||||
**Q7 — Primary actions in the Topbar** _(reframe as guidance, not a button inventory)_
|
||||
|
||||
> "We no longer place app-specific primary CTAs in the Topbar — those should live in the content area below it. Are you comfortable leaving the Topbar without '+ Create' / 'Export' style buttons, or is there a rare, truly app-wide control you still need next to the utility icons?"
|
||||
|
||||
- **Default:** no extra action buttons in the Topbar shell.
|
||||
- If something is proposed, apply the test: does it apply to the **entire app on every screen**? If not, it belongs **below** the Topbar.
|
||||
- When in doubt, omit it from the Topbar.
|
||||
|
||||
**Q8 — Right-strip controls** _(ask each sub-question separately)_
|
||||
|
||||
> "The right side is a fixed-order strip; you can turn each control on or off depending on capabilities. I'll ask about each one."
|
||||
|
||||
Ask each separately (in this order for consistency with the bar):
|
||||
|
||||
- **Share:** "Do users need share? Should the Share icon (ghost, small) appear?"
|
||||
- **Notifications:** "Does this app surface notifications? Should the bell appear?"
|
||||
- **Theme menu:** "Should users switch light/dark theme from the Topbar (sun/moon trigger + menu with checkmarked Light/Dark rows)?"
|
||||
- **Atlas:** "Does this app use Atlas? Should the secondary Atlas button (leading icon + label) appear?"
|
||||
- **User Avatar:** "Should the signed-in user Avatar appear on the far right?"
|
||||
|
||||
Fixed order when visible (left → right): **Share → Notifications → Theme → Atlas → user Avatar**.
|
||||
|
||||
Apps **must not** reorder these items; styling follows Aura. If Aura documents additional optional controls, align with Storybook.
|
||||
|
||||
---
|
||||
|
||||
## Omissions
|
||||
|
||||
**Q9 — Excluded routes**
|
||||
|
||||
> "Are there any screens where the top bar should NOT appear? Common exceptions: login/auth screens, fullscreen flows, onboarding. Default is to show it everywhere."
|
||||
|
||||
---
|
||||
|
||||
## Closing
|
||||
|
||||
Before implementing, summarize the configuration in five bullets or fewer:
|
||||
|
||||
- left (fjord `Avatar` + breadcrumb pattern + inline metadata if any)
|
||||
- middle (Tabs, Segmented control, or none)
|
||||
- primary actions (confirm they live **below** the Topbar)
|
||||
- right strip (which of Share / Notifications / Theme / Atlas / Avatar are on)
|
||||
- excluded routes
|
||||
|
||||
Then proceed to install and implement (see [IMPLEMENTATION.md](IMPLEMENTATION.md)).
|
||||
@@ -0,0 +1,205 @@
|
||||
# Topbar Rules — Full Reference (Aura)
|
||||
|
||||
Detailed architecture and usage rules for the Topbar across Flows and Fusion applications. Read this file when you need the full rule set beyond the quick reference in `SKILL.md`.
|
||||
|
||||
**Storybook:** https://cognitedata.github.io/aura/storybook/?path=/docs/primitives-topbar--docs
|
||||
**Install:** `pnpm dlx shadcn@latest add @aura/topbar` — registry component only; do not use `npm install` / `pnpm add` / `yarn add`
|
||||
|
||||
---
|
||||
|
||||
## 1. Non-negotiables
|
||||
|
||||
1. Every authenticated app view must render exactly **one** Topbar, composed only from Aura Topbar primitives and `@aura/topbar` documented APIs.
|
||||
2. Do **not** implement a custom top bar, duplicate header, or alternate app chrome that replaces or shadows the Topbar.
|
||||
3. Do **not** render **multiple** Topbars on a single page (including embedded views or nested frames).
|
||||
4. Styling and behavior must follow Aura: **token-level theming only**. No ad-hoc overrides that break Aura semantics.
|
||||
|
||||
---
|
||||
|
||||
## 2. Where Topbar is omitted
|
||||
|
||||
The Topbar **may** be omitted only on:
|
||||
|
||||
- Login / auth-only screens
|
||||
- Fullscreen modal or fullscreen flows that hide global chrome by design
|
||||
- Other explicit shell exceptions documented by the platform team
|
||||
|
||||
If unsure whether a route qualifies, **default to including the Topbar**.
|
||||
|
||||
---
|
||||
|
||||
## 3. Layout contract (three regions)
|
||||
|
||||
### 3.1 Left section (required)
|
||||
|
||||
Order (left → right), all in one **left-aligned cluster** (metadata is never centered in the bar):
|
||||
|
||||
1. **Application mark** — Aura **`Avatar`**, **`size="small"`**, **`fjord`** colorway. Use the app image or branding supplied by app config / Aura Topbar API when available. Confirm props and slots in Storybook.
|
||||
2. **Breadcrumbs** — Aura Breadcrumb component. All segments are **interactive links** that navigate to their corresponding route. Do not render breadcrumbs as static/non-interactive text.
|
||||
3. **Inline metadata** _(optional)_ — immediately to the right of the breadcrumb, still in the left cluster (e.g. "Updated 3 hours ago", "Read-only"). String only; no links, icons, or interactive elements. Omit entirely when unused.
|
||||
|
||||
Breadcrumb rules:
|
||||
|
||||
- Application name is always the **first** segment.
|
||||
- When an object is open, clicking the app name navigates back to the app's home/root route.
|
||||
- When no object is open, the app name is **not** a link (it is the current location).
|
||||
- Current object name appears in the **last** segment **only** when a specific object is open; otherwise omit.
|
||||
|
||||
Object dropdown:
|
||||
|
||||
- The object name may act as the **sole** trigger for an object-level dropdown **only when an object is open**.
|
||||
- **No dropdown on the app name.** If app-level settings are needed, surface them in the **content area below the Topbar** (or another approved shell pattern), not in the object dropdown.
|
||||
- All dropdown actions must apply **only to the currently open object** (rename, duplicate, export, delete, etc.). Do not mix in app-level or global actions.
|
||||
- Use Aura components for the trigger, menu, and items only.
|
||||
|
||||
### 3.2 Middle section — global navigation (optional)
|
||||
|
||||
- **Optional slot** for **global** navigation only: controls that apply across the app shell, not page-local toolbars.
|
||||
- **Tabs** — preferred for **mutually exclusive page-level** views (routes): one tab = one primary destination.
|
||||
- **Segmented control** — alternative when the user switches **modes or layouts** within the app (e.g. canvas view vs code view) rather than top-level routes.
|
||||
- **Size** — always **small** to match other Topbar controls.
|
||||
- **Do not** place app-specific **primary** actions or a **primary CTA** in the Topbar. Those belong in the **content region below the Topbar** unless Aura documents a dedicated exception.
|
||||
- **Never use a sidebar** for primary app navigation. If additional sub-navigation is needed beyond this slot, it must live within the content area.
|
||||
- If the app has no global navigation or only one view, leave this section empty entirely.
|
||||
|
||||
### 3.3 Right section — utility strip (component API, app visibility)
|
||||
|
||||
The right area is defined by `@aura/topbar` and exposed as **one ordered strip**. Apps choose **which controls are visible** based on capabilities and product policy; **order is fixed** when a control is shown.
|
||||
|
||||
Fixed order (left → right within the strip):
|
||||
|
||||
1. **Share** — icon button, **`size="sm"`**, **`variant` / styling: ghost**.
|
||||
2. **Notifications** — bell icon button, **`size="sm"`**, **ghost**.
|
||||
3. **Theme** — icon button, **`size="sm"`**, **ghost**:
|
||||
- **Light mode** → show **sun** icon; **dark mode** → show **moon** icon.
|
||||
- On click: open an Aura **Menu** with two items, **Light mode** and **Dark mode**. Exactly **one** is selected at a time; a **checkmark** indicates the current theme. Choosing an item sets that theme (radio-like behavior, not a blind toggle).
|
||||
4. **Atlas** — **`size="sm"`**, **secondary** button, **leading icon** + label **"Atlas"**.
|
||||
5. **User** — **`Avatar`**, **`size="small"`**.
|
||||
|
||||
Rules:
|
||||
|
||||
- Visibility of Share, Notifications, Theme, Atlas, and user Avatar is **configurable** per app where the Aura API allows — enable only what the product needs.
|
||||
- Theme and user Avatar are **typically always on** for authenticated apps; hide them only when the Aura/shell API and product policy explicitly allow.
|
||||
- **Do not reorder** items; **do not** override Aura styling or behavior for these controls.
|
||||
- If Storybook documents additional entries (e.g. a separate agent affordance), follow the **current** `@aura/topbar` API — this document lists the canonical Flows/Fusion strip above.
|
||||
|
||||
---
|
||||
|
||||
## 4. Sizing
|
||||
|
||||
All Topbar interactive elements use **small** size unless Aura Topbar documentation explicitly prescribes otherwise. (Avatar application mark and user Avatar use **`size="small"`** as in Aura docs.)
|
||||
|
||||
---
|
||||
|
||||
## 5. Responsive behavior
|
||||
|
||||
- Follow Aura Topbar default responsive behavior.
|
||||
- If an app fills the center slot or right strip densely, the app must handle overflow (prioritization, fewer items, progressive disclosure). This is an **app responsibility** when content is dense.
|
||||
|
||||
---
|
||||
|
||||
## 6. Accessibility & keyboard
|
||||
|
||||
- Tab / focus order follows **visual** order: **left section** → **middle** (if any) → **right strip** in the order defined in §3.3.
|
||||
- No extra skip link or focus management requirements beyond Aura defaults at this time.
|
||||
|
||||
---
|
||||
|
||||
## 7. Loading & long labels
|
||||
|
||||
- Truncation, ellipsis, tooltips, loading states: follow Aura default behavior for Topbar and related primitives. Do not invent one-off patterns.
|
||||
|
||||
---
|
||||
|
||||
## 8. Configuration model
|
||||
|
||||
| Concern | Who controls | Notes |
|
||||
|---------|-------------|-------|
|
||||
| Topbar presence & single instance | App + shell | One per page; no duplicates |
|
||||
| Left: application mark | App (via Aura API) | `Avatar`, `size="small"`, `fjord` colorway |
|
||||
| Left: breadcrumbs | App (via Aura API) | Interactive links; app name navigates to home only when object is open |
|
||||
| Left: inline metadata | App | Optional plain string **after breadcrumb**, left cluster only; never centered; no interactive elements |
|
||||
| Object dropdown | App (items), platform/Aura (presentation) | Object name only, object-scoped actions only; no app-level dropdown |
|
||||
| Middle: Tabs or Segmented control | App | Optional; **small**; global routes (Tabs) or global modes (Segmented); never a sidebar; no primary CTAs here |
|
||||
| Right: Share, Notifications, Theme menu, Atlas, user Avatar | App + Aura API | Fixed **order** when shown; each visibility toggled per capability/policy; theme uses sun/moon icons and menu with checkmarked selection |
|
||||
| Theming | Aura tokens only | No arbitrary CSS |
|
||||
|
||||
**Open items (to be finalized):**
|
||||
|
||||
- System-level configuration matrix (tenant vs build-time vs runtime) per control.
|
||||
- Telemetry/analytics for notifications, share, Atlas.
|
||||
- Shell responsibility details (single mount point vs per-app composition).
|
||||
- Lint rules and automated checks for Topbar compliance.
|
||||
- Automated binding of app config / Fusion config to pre-fill Atlas answers.
|
||||
|
||||
---
|
||||
|
||||
## 9. Configuration interview protocol
|
||||
|
||||
The full interview is defined in `SKILL.md §2` (Step 2, pre-flight through closing summary). Run it before implementing or changing any Topbar wiring.
|
||||
|
||||
---
|
||||
|
||||
## 10. Composition & API guidance
|
||||
|
||||
- Prefer the Aura Topbar API as documented in Storybook. Use documented props and slots for each region.
|
||||
- Structured data (names, breadcrumb items, menu definitions) is easier to validate than arbitrary JSX.
|
||||
- Where Aura exposes slots, only place Aura-approved components inside each slot.
|
||||
- Do **not** bypass the Topbar by injecting a second header row or fake breadcrumbs outside the Topbar.
|
||||
- Always fetch actual component names, props, and slot names from the current Aura package and Storybook before writing code — the pseudo-code in this document is illustrative only.
|
||||
|
||||
---
|
||||
|
||||
## 11. Do / Don't
|
||||
|
||||
**Do**
|
||||
|
||||
- Use `@aura/topbar` and compose Topbar exactly as Aura documents.
|
||||
- Keep **one** Topbar per page.
|
||||
- Use **`Avatar`**, **`size="small"`**, **`fjord`** for the application mark at the far left.
|
||||
- Keep inline metadata in the **left cluster**, **after** the breadcrumb — **never** centered in the bar.
|
||||
- Make breadcrumb segments interactive links that navigate to their routes.
|
||||
- Add the app name link to home/root only when an object is currently open.
|
||||
- Put object dropdown only on the object name; scope all actions to that object only.
|
||||
- Use the middle section for **Tabs** (page views) or **Segmented control** (mode views), **size small**, when global navigation is needed.
|
||||
- Put **app-specific primary actions** in the **content area below the Topbar**, not in the Topbar.
|
||||
- Use **small** size for Topbar controls; use **ghost** icon buttons for Share, Notifications, and Theme; **secondary** for Atlas.
|
||||
- Implement theme as **sun** in light mode, **moon** in dark mode, with a **menu** and **checkmark** on the active **Light mode** / **Dark mode** row.
|
||||
- Respect fixed **order** and Aura styling for the right strip.
|
||||
|
||||
**Don't**
|
||||
|
||||
- Don't build a custom top bar or duplicate global chrome.
|
||||
- Don't use multiple Topbars or a second header in embedded views.
|
||||
- Don't use a sidebar for navigation — ever. Use middle Tabs/Segmented control or content-area navigation instead.
|
||||
- Don't put page-specific or app-primary CTAs in the Topbar — they belong below it.
|
||||
- Don't add a dropdown to the app name — use patterns **below the Topbar** for app-level settings.
|
||||
- Don't mix app-level and object-level actions in the object dropdown.
|
||||
- Don't render breadcrumbs as static/non-interactive text.
|
||||
- Don't use a filled Tabler icon stack in place of the **fjord Avatar** application mark unless Aura docs explicitly allow an alternative.
|
||||
- Don't override right-strip appearance or behavior outside Aura options.
|
||||
- Don't use non-token styling on Topbar or its children.
|
||||
- Don't use `@cognite/dune-industrial-components/navigation` (deprecated — use `@aura/topbar`).
|
||||
|
||||
---
|
||||
|
||||
## 12. Enforcement
|
||||
|
||||
1. Verify `@aura/topbar` is the only top-level app chrome; reject any parallel header implementation.
|
||||
2. Check left section: **`Avatar` (small, fjord)** → breadcrumbs (interactive links) → optional inline metadata (string only, left-aligned after breadcrumb).
|
||||
3. Check breadcrumb behavior: app name links to home only when object is open; object dropdown (if any) is on the object name only and contains only object-scoped actions.
|
||||
4. Check middle section: **Tabs** or **Segmented control** at **small** if present; no sidebar; no primary CTA in the bar.
|
||||
5. Check app actions: primary / app-specific actions live **below** the Topbar, not in the middle or as an extra ad-hoc header row.
|
||||
6. Check right strip: when present, order is Share → Notifications → Theme → Atlas → user Avatar; ghost icon buttons for Share, Notifications, Theme; theme shows **sun** in light / **moon** in dark and a **menu** with checkmarked **Light mode** / **Dark mode**; Atlas **secondary** with leading icon + "Atlas"; **`Avatar` small** for user.
|
||||
7. Confirm the configuration interview (`SKILL.md §2`) was completed for new Topbar work.
|
||||
|
||||
---
|
||||
|
||||
## 13. Revision history intent
|
||||
|
||||
Update `RULES.md` when:
|
||||
|
||||
- Aura Topbar API or package name changes.
|
||||
- Platform finalizes configuration, telemetry, shell mount, or lint rules.
|
||||
- New controls are added to the right strip or center slot contract changes.
|
||||
- Flows/Fusion config paths or fields used for pre-flight are standardized.
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
name: use-topbar
|
||||
description: >-
|
||||
Wires the Aura Topbar (@aura/topbar) into Flows/Fusion apps as the single top
|
||||
navigation bar — breadcrumbs, optional center Tabs or Segmented control, right
|
||||
utility strip (Share, notifications, theme menu, Atlas, user Avatar), and
|
||||
light/dark theme switching. Use when adding a topbar, app header, navigation
|
||||
bar, breadcrumbs, or theme switcher to a Flows or Fusion app, or when
|
||||
scaffolding a new Flows/Fusion application.
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Bash
|
||||
---
|
||||
|
||||
# Topbar
|
||||
|
||||
`@aura/topbar` is the single, compliant top navigation bar for every authenticated Flows/Fusion app. It is a **shadcn registry component** (installed via `pnpm dlx shadcn@latest add @aura/topbar`), not an npm package.
|
||||
|
||||
- **Storybook:** https://cognitedata.github.io/aura/storybook/?path=/docs/primitives-topbar--docs
|
||||
- **Full rules:** [RULES.md](RULES.md) · **Interview:** [INTERVIEW.md](INTERVIEW.md) · **Install + code:** [IMPLEMENTATION.md](IMPLEMENTATION.md)
|
||||
|
||||
> **Non-negotiables:** Exactly one Topbar per page, composed only from `@aura/topbar` primitives, installed via the shadcn CLI only. If installation fails, surface the blocker — never build a custom header fallback. See [RULES.md §1, §11, §12](RULES.md).
|
||||
|
||||
---
|
||||
|
||||
## Step 0 — Auto-prompt hook setup
|
||||
|
||||
Ensure the topbar interview is triggered at the start of every future Cursor session in this project.
|
||||
|
||||
1. Check whether `.cursor/hooks.json` exists in the project root.
|
||||
2. If it does not exist, create it:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"hooks": {
|
||||
"sessionStart": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "This is a Flows/Fusion application. Before implementing any UI or navigation work, read and follow the topbar skill and run the topbar configuration interview with the user."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. If `.cursor/hooks.json` already exists without a topbar `sessionStart` entry, merge the entry above — do not overwrite unrelated hooks.
|
||||
4. Confirm to the user, then continue.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Pre-flight: read the app
|
||||
|
||||
Before asking any questions, read:
|
||||
|
||||
- `package.json` — package manager, existing UI deps, existing `@aura/topbar`
|
||||
- `src/App.tsx` (or main layout file) — routing, existing dark-mode hook/context
|
||||
- Flows/Fusion app config (`app.config.ts`, `fusion.config.ts`, manifest) — `displayName`, `name`, app mark / branding
|
||||
|
||||
Apply any found defaults and skip the corresponding interview questions. State what was inferred.
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Configuration interview (mandatory)
|
||||
|
||||
Run the full Q1–Q9 interview in [INTERVIEW.md](INTERVIEW.md) before writing any implementation code. Ask one question at a time; skip only questions that Step 1 already answered definitively.
|
||||
|
||||
---
|
||||
|
||||
## Steps 3–5 — Install, theme hook, implement
|
||||
|
||||
See [IMPLEMENTATION.md](IMPLEMENTATION.md) for:
|
||||
|
||||
- Installing `@aura/topbar` via the shadcn CLI (mandatory, no workarounds)
|
||||
- `useThemeMode` hook wiring for light/dark switching
|
||||
- Topbar component composition example and layout wrapper
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Compliance checklist
|
||||
|
||||
Verify before finishing (see [RULES.md §12](RULES.md) for the full enforcement checklist):
|
||||
|
||||
- [ ] Exactly **one** Topbar per page
|
||||
- [ ] Left: `Avatar` application mark (**small**, **fjord**) → app name breadcrumb → object name breadcrumb (only when an object is open)
|
||||
- [ ] Breadcrumb segments are interactive links — not static text
|
||||
- [ ] Object dropdown (if present) only on the object name segment; actions are object-scoped only
|
||||
- [ ] Inline metadata (if present) is a plain string, left-aligned after the breadcrumb — not centered
|
||||
- [ ] Middle: **Tabs** or **Segmented control** at **small** if present; no sidebar; no primary CTA in the Topbar
|
||||
- [ ] **Primary / app-specific actions** live in the content area **below** the Topbar
|
||||
- [ ] Right strip order when used: **Share → Notifications → Theme → Atlas → user Avatar**; Share/Notifications/Theme as **ghost small**, Atlas as **secondary small** with leading icon + "Atlas"
|
||||
- [ ] Theme: **sun** in light mode, **moon** in dark mode; Menu with Light/Dark rows + checkmark on active; wired to `document.documentElement`
|
||||
- [ ] `tailwind.config` has `darkMode: 'class'`
|
||||
Reference in New Issue
Block a user