UI principles
The North component library, live
Licence updated for 3 users.
Calm, clear, in command
North products are used by people doing serious work, often for hours at a time. The interface should be quiet, predictable and fast, and it should always make clear what the AI is doing and what the person decides.
- Content first. Chrome is Midnight, white and Steel; colour is saved for actions, status and AI activity.
- One primary action per view. Everything else is secondary or tertiary.
- Humans approve. Consequential AI actions show a review step with clear consequences before anything changes.
- Every state is designed: empty, loading, partial, error, success, disabled, offline.
- Keyboard and screen reader first-class. Every component here is built on native elements with visible focus.
Every component in this section is implemented in north-components.css on top of the design tokens, and shown live with the hub's light/dark switch. Developers can use the CSS directly or rebuild it in Tailwind with the recipes.
The state model
Every interactive component supports the same states, in the same order of precedence. Design all of them, not just the default.
| State | Visual change | How it is set |
|---|---|---|
| Default | Resting style | — |
| Hover | Background or border one step stronger. Pointer devices only; never the only cue | :hover |
| Focus | 3px focus ring, 2px offset (Gulf 60 light, Oasis 30 dark) | :focus-visible |
| Pressed | 1px down shift, slightly darker | :active |
| Selected / current | Filled, underlined or checked, plus aria state | aria-selected, aria-current, aria-pressed, :checked |
| Disabled | 40% opacity, no pointer events, not focusable if possible. Explain why nearby | disabled, aria-disabled |
| Loading | Spinner replaces content; size does not change; double clicks are ignored | aria-busy="true" |
| Error | Red border and message below, with icon | aria-invalid="true" + aria-describedby |
| Read-only | Subtle background, normal text, selectable | readonly |
Sizes and density
Three control heights
On touch devices every target is at least 44px. If a control is visually smaller, enlarge its hit area with padding.
| Size | Height | Use |
|---|---|---|
| Small | 32px | Dense tables, toolbars, filters |
| Medium | 40px | Default for buttons, inputs, selects |
| Large | 48px | Marketing CTAs, touch-first forms, onboarding |
Density: comfortable is the default (16px gaps, 44px table rows). Compact (8px gaps, 32px rows) is for data-heavy operator tools such as NorthStar Admiral Console, and is a user setting, never a reason to shrink text below 13px.
Layering
| Layer | z-index token | Shadow | Examples |
|---|---|---|---|
| Base content | --n-z-base 0 | 0–1 | Pages, cards, tables |
| Raised | --n-z-raised 10 | 2 | Hovered cards, sticky table headers |
| Sticky chrome | --n-z-sticky 100 | — (blur) | App header, toolbars, sidebars |
| Overlay | --n-z-overlay 1000 | 3 | Menus, popovers, drawers, scrims |
| Modal | --n-z-modal 1100 | 4 | Dialogs, command palette |
| Toast | --n-z-toast 1200 | 3 | Toasts, tooltips |
AI in the interface
- Anything produced by AI carries an AI marker: the AI badge, the agent avatar, or the Oasis accent.
- Running agents show named steps and a soft Oasis pulse, never an endless spinner.
- Before an AI action changes data, sends a message or spends money, show an approval card with what will happen, to whom, and a clear primary action.
- Show where a model runs (on-premises or cloud) wherever the user chooses or sees model output.
Dos and don'ts
Do
- Use the component library and semantic tokens.
- Design every state, including empty and error.
- Keep one primary action per view.
- Label AI output and ask before AI acts.
Don't
- Invent new components for problems the library solves.
- Use colour as the only signal of state.
- Hide disabled reasons.
- Shrink text or targets to fit more in.
Last updated on 14 October 2026