#0075DE carries links, focus and selection. The primary ramp steps from it at 500.
MINDER · GENERAL DESIGN SYSTEM
Minder Platform Design System
Live components, one set of tokens.
01
Foundation / Design Tokens
Every value here is what the stylesheet at the foot of the page ships.
Near-neutral greys, tint instead of rules, a neutral CTA, the system font.
Principles
the rules the values below followNear-black in light, near-white in dark. Blue never fills a button.
8% accent mixed into the neutral hover. One token; shows on menus, tabs, rows.
Primary / Brand
primary-50 → primary-900 · accent at 500#F2F8FEtint background#E0EFFCsoft fill#C2DEFA#8FC4F5#3B9BEC#0075DEaccent · link, focus, selection#005FB4hover / pressed#004A8C#003666#00243FNeutral / Gray
neutral-0 → neutral-1000 · ink at 1000#FFFFFFsurface · the main column#F9F9F9surface-secondary · sidebar, canvas#F3F3F3surface-tertiary · wells#EDEDEDsoft fill · resting chip#CDCDCD#AFAFAF#8F8F8Ftertiary text, disabled#5D5D5Dsecondary text#414141#303030#212121#181818the solid CTA#0D0D0Dink · never pure blackSemantic / Status
each ramp carries -light, -default, -dark#D9F4E4#00A240#00692A#FFE7D9#E25507#923B0F#FFD9D9#E02E2A#911E1B#E0EFFC#0075DE#004A8CBackground & Surface
surface · surface-secondary · surface-tertiary · overlay#FFFFFFthe main column, cards, menus#F9F9F9sidebar, page canvas#F3F3F3wells, code blocks, composer#FFFFFFsame white — the ring and shadow do the liftingrgba(13,13,13,0.40)scrim behind a modalText Colors
text-primary → text-link#0D0D0D#5D5D5D#8F8F8F#8F8F8F#FFFFFF#0075DEBorder & Divider
border-subtle · border-default · border-strong · border-focuscolor-mix(in oklab, #0D0D0D 5%, transparent)color-mix(in oklab, #0D0D0D 10%, transparent)color-mix(in oklab, #0D0D0D 15%, transparent)#0075DETypography
the platform system stack — no webfontWhat's on your mind today?
What should we work on?
Plugins in Minder
Display modes
Inline card
Visual design guidelines
The reading size for a long model response.
The default — conversation, prose, most UI copy.
Compact enough for tables, rows and metadata.
Workspace name
Supporting notes and timestamps.
BADGE
14px28px312px416px520px624px832px1040px1248px1664px2pxinline accents4pxsmall badges6pxchips, small buttons8pxdefault button, input10pxlarge button, select12pxalerts, menu, popover16pxcards, inline widgets20pxsheets, panels24pxthe composer, hero surfaces9999pxpill CTAs, avatars, send button≥ 380pxInline widget minimum — cards go single-column≥ 576pxCarousels show a second item; metadata returns≥ 768pxSidebar appears; two-up grids≥ 1024pxThree-up grids; fullscreen mode gets its inspector≥ 1280pxCentred reading column, ~768px, canvas either side≥ 1536pxColumn stays put; only the canvas grows02
Unique Component
The four pieces a re-vendor would overwrite.
Nav bar · outline trace
--sweep-intensity 1.00 · --sweep-cycle 18scomposed · ambient-sweepThe light rides the whole outline on a motion path, so it holds one speed the whole way round instead of tearing along the long edges the way a rotating gradient would. Drops onto .systemNav unchanged — --sweep-radius defaults to 0, which is the real bar’s square corner.
Button · hover
--primary-hover-* · --primary-hover-liftcomposed · globals.cssHover picks up a vertical gradient with a lit top edge and an outer glow. The gradient starts at --primary itself, so it can never drift from the resting state it grows out of. Geometry is untouched — only the surface changes.
composed · globals.cssA solid tint rather than a gradient, so the two never compete. Both skies are one set of tokens; only the values swap.
Toast · tilted sweep
--sweep-toast-tilt -30degcomposed · sonner + ambient-sweepA toast lives about four seconds, so the nav’s 18s cycle would never be seen on one: the light runs once, just after it settles. Status toasts sweep in their own colour — a green toast lit with brand blue would read as two unrelated systems.
State surfaces
lottie · vector, no raster assetscomposed · empty + lottie + skeletoncomposed · empty + lottie03
Form & Input
components/select · components-minder/search-select- A value in a settings row is a ghost dropdown: the value and a chevron, a grey pill on hover and while open.
- The list is a rounded card. The row under the pointer is neutral grey; the chosen value carries a check on the right.
- A list longer than a screen gets a search field and, where it has them, group headings.
- Form fields keep the bordered trigger below. On Chromium the native list is drawn the same way; elsewhere the platform draws it.
components/select · native-selectcomponents/calendar + popovercomponents/input[type=file]Shown to everyone in the workspace.
Control first, text beside it.
05
Feedback & Status
composed · empty + lottie + skeleton06
Data Display
composed · card + badge| Customer | Owner | Status | Progress |
|---|---|---|---|
| Acme Corp | Hung | Live | 100% |
| Northwind | Mai | Deploying | 62% |
| Globex | Trung | Blocked | 18% |
Updated 12 minutes ago
Running · 3 of 8 steps
composed · markerAn internal operations console.
07
Overlay / Interaction
Command Palette
Search for a command to run...
08
The stylesheet
Generated from tokens.ts.
/* ==========================================================================
Minder design system — design tokens
Generated from app/design-system/general/tokens.ts
========================================================================== */
:root {
/* Primary / brand */
--color-primary-50: #F2F8FE;
--color-primary-100: #E0EFFC;
--color-primary-200: #C2DEFA;
--color-primary-300: #8FC4F5;
--color-primary-400: #3B9BEC;
--color-primary-500: #0075DE;
--color-primary-600: #005FB4;
--color-primary-700: #004A8C;
--color-primary-800: #003666;
--color-primary-900: #00243F;
/* Neutral */
--color-neutral-0: #FFFFFF;
--color-neutral-50: #F9F9F9;
--color-neutral-75: #F3F3F3;
--color-neutral-100: #EDEDED;
--color-neutral-200: #CDCDCD;
--color-neutral-300: #AFAFAF;
--color-neutral-400: #8F8F8F;
--color-neutral-500: #5D5D5D;
--color-neutral-600: #414141;
--color-neutral-700: #303030;
--color-neutral-800: #212121;
--color-neutral-900: #181818;
--color-neutral-1000: #0D0D0D;
/* Semantic */
--color-success-light: #D9F4E4;
--color-success: #00A240;
--color-success-dark: #00692A;
--color-warning-light: #FFE7D9;
--color-warning: #E25507;
--color-warning-dark: #923B0F;
--color-error-light: #FFD9D9;
--color-error: #E02E2A;
--color-error-dark: #911E1B;
--color-info-light: #E0EFFC;
--color-info: #0075DE;
--color-info-dark: #004A8C;
/* Background & surface */
--surface: #FFFFFF;
--surface-secondary: #F9F9F9;
--surface-tertiary: #F3F3F3;
--surface-elevated: #FFFFFF;
--overlay: rgba(13,13,13,0.40);
/* Text */
--text-primary: #0D0D0D;
--text-secondary: #5D5D5D;
--text-tertiary: #8F8F8F;
--text-disabled: #8F8F8F;
--text-inverse: #FFFFFF;
--text-link: #0075DE;
/* Border & divider */
--border-subtle: color-mix(in oklab, #0D0D0D 5%, transparent);
--border-default: color-mix(in oklab, #0D0D0D 10%, transparent);
--border-strong: color-mix(in oklab, #0D0D0D 15%, transparent);
--border-focus: #0075DE;
/* Typography — the platform system stack — no webfont */
--font-sans: ui-sans-serif, -apple-system, system-ui, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
--text-display-1: 600 60px/60px var(--font-sans);
--tracking-display-1: -0.025em;
--text-display-2: 600 48px/48px var(--font-sans);
--tracking-display-2: -0.025em;
--text-heading-1: 600 36px/42px var(--font-sans);
--tracking-heading-1: -0.025em;
--text-heading-2: 600 32px/38px var(--font-sans);
--tracking-heading-2: -0.025em;
--text-heading-3: 600 24px/28px var(--font-sans);
--tracking-heading-3: 0;
--text-title: 600 20px/26px var(--font-sans);
--tracking-title: 0;
--text-body-lg: 400 18px/29px var(--font-sans);
--tracking-body-lg: 0;
--text-body-md: 400 16px/24px var(--font-sans);
--tracking-body-md: 0;
--text-body-sm: 400 14px/20px var(--font-sans);
--tracking-body-sm: 0;
--text-label: 500 14px/20px var(--font-sans);
--tracking-label: 0;
--text-caption: 400 12px/18px var(--font-sans);
--tracking-caption: 0.025em;
--text-micro: 400 10px/14px var(--font-sans);
--tracking-micro: 0.025em;
/* Spacing — 4px base unit, token = multiplier */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
/* Border radius */
--radius-2xs: 2px;
--radius-xs: 4px;
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 10px;
--radius-xl: 12px;
--radius-2xl: 16px;
--radius-3xl: 20px;
--radius-4xl: 24px;
--radius-full: 9999px;
/* Elevation */
--shadow-hairline: 0 0 0 1px rgb(0 0 0 / 8%);
--shadow-100: 0 1px 2px -1px rgb(0 0 0 / 8%);
--shadow-200: 0 2px 4px -1px rgb(0 0 0 / 8%);
--shadow-300: 0 4px 8px -2px rgb(0 0 0 / 10%);
--shadow-400: 0 8px 16px -4px rgb(0 0 0 / 12%);
/* Breakpoints */
/* xs: ≥ 380px — Inline widget minimum — cards go single-column */
/* sm: ≥ 576px — Carousels show a second item; metadata returns */
/* md: ≥ 768px — Sidebar appears; two-up grids */
/* lg: ≥ 1024px — Three-up grids; fullscreen mode gets its inspector */
/* xl: ≥ 1280px — Centred reading column, ~768px, canvas either side */
/* 2xl: ≥ 1536px — Column stays put; only the canvas grows */
}
/* --------------------------------------------------------------------------
Base
-------------------------------------------------------------------------- */
body {
background: var(--surface-secondary);
color: var(--text-primary);
font: var(--text-body-md);
}
a {
color: var(--text-link);
text-decoration: none;
}
a:hover { text-decoration: underline; }
:focus-visible {
outline: 2px solid var(--border-focus);
outline-offset: 2px;
}
.card {
border: 1px solid var(--border-default);
border-radius: var(--radius-2xl);
background: var(--surface);
padding: var(--space-6);
}
.card--elevated { border-color: transparent; box-shadow: var(--shadow-300); }