199 lines
8.8 KiB
Markdown
199 lines
8.8 KiB
Markdown
# Fluksio design guidelines
|
||
|
||
UI reference for the app, its dashboard editor and documentation site.
|
||
Paths below are relative to this repository.
|
||
|
||
## Design language
|
||
|
||
Use neutral white and near-black surfaces with a slate-blue primary accent.
|
||
Reserve terracotta for one secondary action per view. `--card` is the main
|
||
surface. Separate surfaces with borders and elevation. Controls are pills;
|
||
cards and panels use a 16px radius.
|
||
|
||
## Colour tokens
|
||
|
||
| Token | Light | Dark | Use |
|
||
|---|---|---|---|
|
||
| `--background` | `#ffffff` | `#0a0a0a` | page |
|
||
| `--foreground` | `#333232` | `#f5f5f5` | body text |
|
||
| `--card` / `--popover` | `#ffffff` | `#1a1a1a` | dominant surface; dark lifts above the page |
|
||
| `--card-foreground` / `--popover-foreground` | `#333232` | `#f5f5f5` | text on those surfaces |
|
||
| `--primary` | `#4a7189` | `#7ba3b8` | primary fills, active state, focus ring |
|
||
| `--primary-foreground` | `#ffffff` | `#0a0a0a` | text on `--primary` |
|
||
| `--primary-nested` | `#152128` | `#345160` | a reading drawn inside a `--primary` fill |
|
||
| `--brand-secondary` | `#de8f6e` | `#e5a184` | the one secondary call-to-action per view |
|
||
| `--brand-secondary-foreground` | `#333232` | `#0a0a0a` | text on `--brand-secondary` |
|
||
| `--secondary` / `--muted` | `#f2f2f2` | `#232323` | recessed surfaces |
|
||
| `--secondary-foreground` | `#333232` | `#f5f5f5` | text on those |
|
||
| `--muted-foreground` | `#6b6b6b` | `#a3a3a3` | secondary text, section headers |
|
||
| `--accent` | `#f5f5f5` | `#262626` | hover / selected surface |
|
||
| `--accent-foreground` | `#333232` | `#f5f5f5` | text on `--accent` |
|
||
| `--destructive` | `#b94d4d` | `#cf6666` | destructive actions, failing nodes |
|
||
| `--status-success` | `#5e8b6d` | `#87b596` | a node's last run succeeded |
|
||
| `--status-warning` | `#b45309` | `#e8a33d` | a node that works, but degraded, such as a device that is offline |
|
||
| `--chart-1` … `--chart-8` | see [Chart palette](#chart-palette) | | chart series, in slot order |
|
||
| `--border` / `--input` | `#e4e4e4` | `#2a2a2a` | hairlines, field borders |
|
||
| `--ring` | `#4a7189` | `#7ba3b8` | focus ring; always equals `--primary` |
|
||
| `--sidebar*` | mirrors card / accent / primary | | sidebar surface set |
|
||
|
||
The identity blue `#59849b` stays in the wordmark. Use `--primary` for controls
|
||
so text on primary fills meets contrast requirements. `--primary-nested` is
|
||
for stacked readings inside a primary fill, separated by a gutter.
|
||
|
||
- Use tokens in UI components. Custom SVG glyphs may use `currentColor`.
|
||
- Keep `--sidebar-accent` equal to `--accent`.
|
||
- Use one `--brand-secondary` action per view.
|
||
- Name every status in text. Running uses `--primary`, success
|
||
`--status-success`, failure `--destructive`, and degraded
|
||
`--status-warning`. Idle has no indicator.
|
||
- Home's brain graph uses primary discs as its identity. Its outer ring uses
|
||
`--foreground` for runnable nodes and terracotta for flow faults. Failed
|
||
nodes keep a terracotta disc until acknowledged. Persistent faults keep
|
||
their labels visible.
|
||
|
||
### Chart palette
|
||
|
||
| Slot | Hue | Light | Dark |
|
||
|---|---|---|---|
|
||
| 1 | `--primary` | `#4a7189` | `#7ba3b8` |
|
||
| 2 | orange | `#e26f00` | `#d26600` |
|
||
| 3 | violet | `#6f49ca` | `#8d71e6` |
|
||
| 4 | green | `#00721b` | `#55c15e` |
|
||
| 5 | orchid | `#c66ae1` | `#dd8bf6` |
|
||
| 6 | ochre | `#966a00` | `#ae7c00` |
|
||
| 7 | teal | `#00a093` | `#00c0b1` |
|
||
| 8 | magenta | `#b32474` | `#bf4483` |
|
||
|
||
Take colours in slot order. Line charts stop at five series and show a legend
|
||
when there is more than one. Reserve red, sage green and amber for status.
|
||
The terminal UI uses the terminal's named ANSI colours instead.
|
||
|
||
## The dashboard is exempt
|
||
|
||
User-defined dashboards can choose `fluksio`, `material` or `glass` under
|
||
`frontend/src/components/Dashboard/ui/`. The default `fluksio` look follows
|
||
these guidelines. Other looks may change surfaces and motion.
|
||
|
||
Behavior, keyboard handling and accessibility stay in `ui/core/`.
|
||
A dashboard palette overrides tokens on its own canvas, with colours assigned
|
||
by position. It must preserve contrast, named status, 44px touch targets and
|
||
reduced-motion behavior. Fault and success colours keep their meanings.
|
||
Widgets use container queries to follow their tile size.
|
||
|
||
Dashboard motion presets live in `ui/core/motion.ts`; the app shell uses
|
||
`frontend/src/lib/motion.ts`.
|
||
|
||
## Typography
|
||
|
||
Use the self-hosted Inter variable font at
|
||
`frontend/public/fonts/inter-latin-variable.woff2` for body text, headings and
|
||
wordmarks. `.font-display` selects it for display text. Use the system
|
||
monospace stack through `font-mono` for code, message names and payloads.
|
||
|
||
Use Tailwind's size scale. Arbitrary `text-[…]` sizes are banned and checked
|
||
by the `no-arbitrary-font-size` hook.
|
||
|
||
Section headers use:
|
||
|
||
```text
|
||
text-xs font-medium uppercase tracking-[0.5px] text-muted-foreground
|
||
```
|
||
|
||
## Radius
|
||
|
||
| Utility | Value | Use |
|
||
|---|---|---|
|
||
| `rounded-full` | pill | buttons, inputs, toggles, chips, badges |
|
||
| `rounded-sm` | 8px | checkboxes, small chips, nested items |
|
||
| `rounded-md` | 12px | menus, popovers, tooltips, textareas |
|
||
| `rounded-lg` | 16px | cards, panels, dialogs, alerts, sidebar |
|
||
| `rounded-xl` | 28px | large containers |
|
||
|
||
## Elevation
|
||
|
||
Use `shadow-e1` for resting cards, `shadow-e2` for floating surfaces, and
|
||
`shadow-e3` for modals. Avoid arbitrary or stock shadow utilities on surfaces.
|
||
Borders use `border border-border`, or `border-input` on fields.
|
||
|
||
## Motion
|
||
|
||
Use the `motion` package with presets from `frontend/src/lib/motion.ts`.
|
||
Keep JavaScript timings aligned with the CSS easing and duration tokens.
|
||
|
||
- Easing is `emphasized` for entering or expressive movement, `standard` for
|
||
neutral transitions.
|
||
- Durations are 150, 200 and 300 ms. One-shot activity feedback uses 500 ms.
|
||
- Variants are `fadeIn`, `scaleIn`, `slideUp`, `overlayFade` and `listStagger`.
|
||
- Wrap the app in `<MotionConfig reducedMotion="user">`.
|
||
|
||
## Microcopy
|
||
|
||
Keep captions short. Put explanations in `InfoTip`, `PanelSection.help` or
|
||
`FieldLabel.help`. A tooltip holds one or two sentences; longer instructions
|
||
belong in the docs. Help must work by tap as well as hover.
|
||
|
||
Visible supporting text describes state, such as an empty list, a stopped
|
||
flow or an error. A page may have one descriptive line below its heading.
|
||
Say what a control does. Keep design rationale in repository documentation.
|
||
|
||
Avoid em dashes in UI strings. Empty-value placeholders and structural
|
||
separators are allowed. The `no-em-dash` hook checks these rules, with
|
||
separators listed in `frontend/scripts/no-em-dash.allow.json`.
|
||
|
||
## Iconography
|
||
|
||
Use Lucide. Custom glyphs belong in `frontend/src/components/icons/` as 24×24
|
||
SVGs with no fill, `currentColor` strokes, weight 2 and round caps.
|
||
|
||
## Shells
|
||
|
||
The authenticated app uses a `bg-card` region with a floating translucent
|
||
sidebar. The flow editor floats its controls over the node canvas. Both use
|
||
`bg-card/80 backdrop-blur-md`, a token border and `shadow-e2`.
|
||
|
||
## Responsive
|
||
|
||
Use `md` at 768px as the mobile boundary. Keep `useIsMobile()` and Tailwind's
|
||
`md:` usage aligned, with stock breakpoints.
|
||
|
||
1. Keep the page within the viewport. Give wide tables and charts their own
|
||
`overflow-x-auto` region. Use `min-w-0` on flex and grid children when
|
||
content could stretch the page. `frontend/tests/mobile.spec.ts` checks this.
|
||
2. Cap floating controls with `max-w-[calc(100vw-2rem)]` and allow wrapping.
|
||
3. Use 44px touch targets below `md`, 32px above. Use `icon-touch`, `sm-touch`
|
||
or matching responsive utilities.
|
||
4. Turn floating panels into full-screen sheets on phones with the shared
|
||
`Flow/SidePanel`. Gate canvas side insets behind `md:`.
|
||
5. Provide tap or visible alternatives to hover actions.
|
||
6. Keep dragging, placing and resizing on desktop. Flow layout is automatic,
|
||
left-to-right on desktop and top-to-bottom on phones. Rectangular dashboard
|
||
grids stack to one column on phones.
|
||
|
||
Use `grid gap-* sm:grid-cols-2 lg:grid-cols-N` for card grids and
|
||
`p-4 sm:p-6 md:p-8` for page gutters.
|
||
|
||
## Overlay surfaces & content chips
|
||
|
||
Floating surfaces use `bg-card/80 backdrop-blur-md`, a token border and
|
||
`shadow-e2`. Use token alpha for translucency; panel opacity also fades text.
|
||
|
||
Content chips are transparent at rest and fill on hover or selection.
|
||
Use `hover:bg-accent/50` where hover and selection need distinct states.
|
||
Segmented controls use one bordered pill with no dividers, transparent
|
||
segments and `bg-accent` for the selected segment.
|
||
|
||
## UI configuration
|
||
|
||
`frontend/components.json` uses shadcn style `new-york`, CSS variables and
|
||
Lucide icons. Components under `frontend/src/components/ui/` are owned by
|
||
this repository. Update token definitions, component usage and this reference
|
||
together when changing the design.
|
||
|
||
## UX
|
||
|
||
- Keep common actions easy to reach without context menus.
|
||
- Apply theme through the `.dark` class on `<html>` and the pre-paint theme
|
||
script so the first frame uses the chosen theme.
|
||
- A dashboard subtree can use `.theme-light` or `.theme-dark` independently.
|
||
Menus and tooltips rendered outside it must carry that theme class too.
|