Minder

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 follow
Blue is the accent

#0075DE carries links, focus and selection. The primary ramp steps from it at 500.

The CTA stays neutral

Near-black in light, near-white in dark. Blue never fills a button.

Selection is tinted

8% accent mixed into the neutral hover. One token; shows on menus, tabs, rows.

Primary / Brand

primary-50 → primary-900 · accent at 500
primary-50#F2F8FEtint background
primary-100#E0EFFCsoft fill
primary-200#C2DEFA
primary-300#8FC4F5
primary-400#3B9BEC
primary-500#0075DEaccent · link, focus, selection
primary-600#005FB4hover / pressed
primary-700#004A8C
primary-800#003666
primary-900#00243F

Neutral / Gray

neutral-0 → neutral-1000 · ink at 1000
neutral-0#FFFFFFsurface · the main column
neutral-50#F9F9F9surface-secondary · sidebar, canvas
neutral-75#F3F3F3surface-tertiary · wells
neutral-100#EDEDEDsoft fill · resting chip
neutral-200#CDCDCD
neutral-300#AFAFAF
neutral-400#8F8F8Ftertiary text, disabled
neutral-500#5D5D5Dsecondary text
neutral-600#414141
neutral-700#303030
neutral-800#212121
neutral-900#181818the solid CTA
neutral-1000#0D0D0Dink · never pure black

Semantic / Status

each ramp carries -light, -default, -dark
successCompleted, verified
lightdefaultdark
#D9F4E4#00A240#00692A
warningNeeds attention
lightdefaultdark
#FFE7D9#E25507#923B0F
errorFailure, destructive
lightdefaultdark
#FFD9D9#E02E2A#911E1B
infoNeutral information
lightdefaultdark
#E0EFFC#0075DE#004A8C

Background & Surface

surface · surface-secondary · surface-tertiary · overlay
surface#FFFFFFthe main column, cards, menus
surface-secondary#F9F9F9sidebar, page canvas
surface-tertiary#F3F3F3wells, code blocks, composer
surface-elevated#FFFFFFsame white — the ring and shadow do the lifting
overlayrgba(13,13,13,0.40)scrim behind a modal

Text Colors

text-primary → text-link
Agtext-primary#0D0D0D
Agtext-secondary#5D5D5D
Agtext-tertiary#8F8F8F
Agtext-disabled#8F8F8F
Agtext-inverse#FFFFFF
Agtext-link#0075DE

Border & Divider

border-subtle · border-default · border-strong · border-focus
border-subtlecolor-mix(in oklab, #0D0D0D 5%, transparent)
border-defaultcolor-mix(in oklab, #0D0D0D 10%, transparent)
border-strongcolor-mix(in oklab, #0D0D0D 15%, transparent)
border-focus#0075DE

Typography

the platform system stack — no webfont
display-160 / 60 · 600 · -0.025em

What's on your mind today?

display-248 / 48 · 600 · -0.025em

What should we work on?

heading-136 / 42 · 600 · -0.025em

Plugins in Minder

heading-232 / 38 · 600 · -0.025em

Display modes

heading-324 / 28 · 600 · 0

Inline card

title20 / 26 · 600 · 0

Visual design guidelines

body-lg18 / 29 · 400 · 0

The reading size for a long model response.

body-md16 / 24 · 400 · 0

The default — conversation, prose, most UI copy.

body-sm14 / 20 · 400 · 0

Compact enough for tables, rows and metadata.

label14 / 20 · 500 · 0

Workspace name

caption12 / 18 · 400 · 0.025em

Supporting notes and timestamps.

micro10 / 14 · 400 · 0.025em

BADGE

Spacing — 4px base unit, token = multiplier
14px
28px
312px
416px
520px
624px
832px
1040px
1248px
1664px
Border radius
2xs2pxinline accents
xs4pxsmall badges
sm6pxchips, small buttons
md8pxdefault button, input
lg10pxlarge button, select
xl12pxalerts, menu, popover
2xl16pxcards, inline widgets
3xl20pxsheets, panels
4xl24pxthe composer, hero surfaces
full9999pxpill CTAs, avatars, send button
Elevation & depth
hairlinethe ring on any raised surface
100resting card
200hovered card
300menu, popover
400modal, sheet
Grid & breakpoints
xs≥ 380pxInline widget minimum — cards go single-column
sm≥ 576pxCarousels show a second item; metadata returns
md≥ 768pxSidebar appears; two-up grids
lg≥ 1024pxThree-up grids; fullscreen mode gets its inspector
xl≥ 1280pxCentred reading column, ~768px, canvas either side
2xl≥ 1536pxColumn stays put; only the canvas grows

02

Unique Component

The four pieces a re-vendor would overwrite.

Nav bar · outline trace

--sweep-intensity 1.00 · --sweep-cycle 18s
A · Outline tracecomposed · ambient-sweep
MinderGeneralDashboardAI chatLibraryGet global.css
One lap every 18s; ~3s to cross.

The 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-lift
Primarycomposed · globals.css

Hover 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.

Secondarycomposed · globals.css

A 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 -30deg
Toast / Notificationcomposed · sonner + ambient-sweep

A 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 assets
Loading statecomposed · empty + lottie + skeleton
Loading deployments
Fetching the latest rollout history.
Empty statecomposed · empty + lottie
No deployments yet
Kick off the first rollout to see it here.

03

Form & Input

Button
Text input
Textarea
Dropdown · settings rowscomponents/select · components-minder/search-select
Details
Runs in
Frequency
Repeat
Time
Notifications
  • 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.
Select / Dropdown · fieldcomponents/select · native-select
Checkbox
Radio button
Switch / Toggle
Slider / Range
Date pickercomponents/calendar + popover
Search input
File uploadcomponents/input[type=file]
Label, helper text, error

Shown to everyone in the workspace.

Horizontal field

Control first, text beside it.

05

Feedback & Status

Alert / Banner
Toast / Notification
Modal / Dialog
Popover
Tooltip
Progress bar
Spinner / Loading
Skeleton loader
Loading statecomposed · empty + lottie + skeleton
Loading deployments
Fetching the latest rollout history.
Empty state
No deployments yet
Kick off the first rollout to see it here.
Badge / Tag / Chip
DefaultSecondaryOutlineDestructive Needs review

06

Data Display

Card
Deploy the kit
Roll it out to a new customer.
New
Eight steps, tracked end to end.
Stat / KPI cardcomposed · card + badge
Total visitors
84,392
+12.8%
Active workspaces
1,284
+8.4%
Table / Data grid
Recent kit deployments.
CustomerOwnerStatusProgress
Acme CorpHungLive100%
NorthwindMaiDeploying62%
GlobexTrungBlocked18%
List
Customer tracker

Updated 12 minutes ago

Kit sync

Running · 3 of 8 steps

Avatar
MOHN
HNMTTL
+3
Accordion / Collapse

Yes. It follows the WAI-ARIA disclosure pattern.

Timelinecomposed · marker
Kit generated 09:12
Environment provisioned 09:24
Data migrated 09:51
Live 10:04
Carousel
1
2
3
4
5
Divider
Minder Ops

An internal operations console.

Blog
Docs
Source

07

Overlay / Interaction

Dropdown menu
Context menu
Right-click here
Command palette

Command Palette

Search for a command to run...

Confirmation dialog

08

The stylesheet

Generated from tokens.ts.

CSSminder-tokens.css
/* ==========================================================================
   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); }