


Dust Design System โ Sparkle
Source: Open source ยท [github.com/dust-tt/dust](http://github.com/dust-tt/dust) ยท /sparkle package
UI Stack \- Framework: Next.js (App Router + Pages Router) \- Styling: Tailwind CSS via @dust-tt/sparkle preset \- Component library: Sparkle (internal, open source) \- Dark mode: class-based (darkMode: "class"), every token has a -night variant
Typography \- Sans font: Geist (variable font) \- Mono font: Geist Mono \- Scale: xs 12px โ 9xl 80px, with negative letter-spacing at larger sizes \- Font weights: copy 400 ยท label 500 ยท heading-smโ3xl 550 ยท heading-4xl+ 450 \- Three type styles: copy-, label-, heading- (+ heading-mono-)
Color Philosophy \- Fully custom palette: gray, stone, blue, green, rose, golden, violet, red, orange, lime, emerald, pink \- Every shade has a mirrored -night sibling (light โ dark inversion) \- Semantic aliases: foreground, background, primary, highlight (blue), warning (rose), success (green), info (golden), border, muted, faint, hover, separator, ring \- Brand tokens: hunter-green, electric-blue, red-rose, orange-golden mapped to palette
Spacing & Layout \- Default Tailwind spacing scale \- Sidebar spacing: 0.75rem \- Conversation max-width: 48rem \- Breakpoints: xxs 384px ยท xs 512px ยท sm 640px ยท md 768px ยท lg 1024px ยท xl 1280px ยท 2xl 1536px \- Size scale additions: 100โ400px, 125โ500px, 150โ600px
Border Radius \- Tailwind defaults + 4xl: 2rem
Shadows \- Box shadows use gray-950 base with low opacity \- Scale: sm, DEFAULT, md, lg, xl, 2xl
Transitions \- Named durations: enter 200ms ยท exit 160ms ยท modal-enter 300ms ยท modal-exit 240ms \- Rich easing library: out-quad, out-expo, emphasized (cubic-bezier(0.23,1,0.32,1)), enter, move
:root { / TYPOGRAPHY / --font-family-base: 'Geist', sans-serif; --font-family-mono: 'Geist Mono', monospace; --font-weight-copy: 400; --font-weight-label: 500; --font-weight-heading: 550; --font-weight-heading-large: 450;
/ FONT SIZES / --text-xs: 12px; --leading-xs: 16px; --tracking-xs: normal; --text-sm: 14px; --leading-sm: 20px; --tracking-sm: -0.28px; --text-base: 16px; --leading-base: 24px; --tracking-base: -0.32px; --text-lg: 18px; --leading-lg: 26px; --tracking-lg: -0.36px; --text-xl: 20px; --leading-xl: 28px; --tracking-xl: -0.4px; --text-2xl: 24px; --leading-2xl: 30px; --tracking-2xl: -0.96px; --text-3xl: 32px; --leading-3xl: 36px; --tracking-3xl: -1.28px; --text-4xl: 40px; --leading-4xl: 42px; --tracking-4xl: -2.4px; --text-5xl: 48px; --leading-5xl: 52px; --tracking-5xl: -2.88px;
/ SPACING / --space-xs: 0.25rem; / 4px / --space-sm: 0.5rem; / 8px / --space-md: 1rem; / 16px / --space-lg: 1.5rem; / 24px / --space-xl: 2rem; / 32px / --space-2xl: 3rem; / 48px / --space-sidebar: 0.75rem;
/ COLORS โ Light mode / --color-background: #ffffff; --color-app-background: #FBFAF9; --color-foreground: #111418; --color-foreground-muted: #596170; --color-foreground-faint: #969CA5;
/ Primary (gray scale) / --color-primary: #2A3241; --color-primary-light: #596170; --color-primary-dark: #111418; --color-primary-muted: #7B818D;
/ Highlight (blue) / --color-highlight: #1C91FF; --color-highlight-light: #4BABFF; --color-highlight-dark: #137FE3;
/ Warning (rose) / --color-warning: #E14322; --color-warning-light: #ED756C; --color-warning-dark: #C93913;
/ Success (green) / --color-success: #6AA668; --color-success-light: #91C174; --color-success-dark: #418B5C;
/ Info (golden) / --color-info: #FFAA0D; --color-info-light: #FFBE2C; --color-info-dark: #FE9C1A;
/ Brand / --color-brand: #418B5C; --color-brand-electric-blue: #1C91FF; --color-brand-red-rose: #E14322; --color-brand-golden: #FE9C1A;
/ Borders & UI chrome / --color-border: #EEEEEF; --color-border-dark: #DFE0E2; --color-border-focus: #4BABFF; --color-separator: #EEEEEF; --color-hover: #EEEEEF; --color-muted-background: #F7F7F7; --color-ring: #9FDBFF;
/ BORDER RADIUS / --radius-sm: 0.125rem; / 2px / --radius-md: 0.375rem; / 6px / --radius-lg: 0.5rem; / 8px / --radius-xl: 0.75rem; / 12px / --radius-2xl: 1rem; / 16px / --radius-3xl: 1.5rem; / 24px / --radius-4xl: 2rem; / 32px / --radius-full: 9999px;
/ SHADOWS / --shadow-sm: 0 1px 2px rgba(17,20,24,0.05); --shadow-md: 0 2px 6px rgba(17,20,24,0.10); --shadow-lg: 0 4px 12px rgba(17,20,24,0.12); --shadow-xl: 0 10px 20px rgba(17,20,24,0.12); --shadow-2xl: 0 25px 50px rgba(17,20,24,0.12);
/ TRANSITIONS / --transition-default: all 200ms cubic-bezier(0.215, 0.61, 0.355, 1); --transition-enter: 200ms cubic-bezier(0.215, 0.61, 0.355, 1); --transition-exit: 160ms cubic-bezier(0.25, 0.46, 0.45, 0.94); --transition-modal-enter: 300ms cubic-bezier(0.23, 1, 0.32, 1); --transition-modal-exit: 240ms cubic-bezier(0.455, 0.03, 0.515, 0.955); --transition-emphasized: cubic-bezier(0.23, 1, 0.32, 1);
/ LAYOUT / --max-w-conversation: 48rem; --panel-height: var(--panel-height); }
/ Dark mode overrides / .dark { --color-background: #111418; --color-app-background: #1C222D; --color-foreground: #D3D5D9; --color-foreground-muted: #969CA5; --color-foreground-faint: #596170; --color-primary: #D3D5D9; --color-primary-light: #B2B6BD; --color-primary-dark: #EEEEEF; --color-border: #2A3241; --color-border-dark: #364153; --color-border-focus: #137FE3; --color-hover: #2A3241; --color-muted-background: #111418; --color-ring: #364153; }
Dust / Sparkle โ Design Tokens Reference
Color Tokens
| Token | Light | Dark (night) | Usage |
|---|---|---|---|
| background | #ffffff | #111418 | Page background |
| app-background | #FBFAF9 | #1C222D | App shell background |
| foreground | #111418 | #D3D5D9 | Primary text |
| muted.foreground | #596170 | #969CA5 | Secondary text |
| faint | #969CA5 | #596170 | Placeholder / disabled text |
| primary | #2A3241 | #D3D5D9 | Default UI color |
| primary.dark | #111418 | #EEEEEF | Emphasis |
| highlight | #1C91FF | #1C91FF | Interactive / links |
| highlight.dark | #137FE3 | #4BABFF | Hover state |
| warning | #E14322 | #E14322 | Errors / destructive |
| success | #6AA668 | #6AA668 | Positive states |
| info | #FFAA0D | #FFAA0D | Informational / golden |
| brand | #418B5C | #418B5C | Brand hunter-green |
| border | #EEEEEF | #2A3241 | Default border |
| border.dark | #DFE0E2 | #364153 | Prominent border |
| border.focus | #4BABFF | #137FE3 | Focus ring color |
| hover | #EEEEEF | #2A3241 | Hover background |
| separator | #EEEEEF | #2A3241 | Dividers |
| ring | #9FDBFF | #364153 | Focus ring |
| sidebar.primary | #292524 | #D6D3D1 | Sidebar text |
Palette Reference
| Name | 50 | 200 | 500 | 800 | 950 |
|---|---|---|---|---|---|
| gray | #F7F7F7 | #D3D5D9 | #7B818D | #2A3241 | #111418 |
| stone | #FBFAF9 | #E7E5E4 | #79716B | #292524 | #0C0A09 |
| blue | #E9F7FF | #9FDBFF | #1C91FF | #085092 | #041728 |
| green | #FEFFF0 | #E2F78C | #6AA668 | #105B2B | #04140A |
| rose | #FFF1F7 | #FFC3DF | #E14322 | #8C230D | #220A04 |
| golden | #FFFAE0 | #FFE262 | #FFAA0D | #AF5511 | #331606 |
| violet | #F5F3FF | #DDD6FE | #8B5CF6 | #5B21B6 | #2E1065 |
Typography Tokens
| Class | Size | Line Height | Letter Spacing | Weight |
|---|---|---|---|---|
| copy-xs | 12px | 16px | normal | 400 |
| copy-sm | 14px | 20px | -0.28px | 400 |
| copy-base | 16px | 24px | -0.32px | 400 |
| copy-lg | 18px | 26px | -0.36px | 400 |
| label-xs | 12px | 16px | normal | 500 |
| label-sm | 14px | 20px | -0.28px | 500 |
| label-base | 16px | 24px | -0.32px | 500 |
| heading-sm | 14px | 20px | -0.28px | 550 |
| heading-base | 16px | 24px | -0.32px | 550 |
| heading-xl | 20px | 28px | -0.4px | 550 |
| heading-3xl | 32px | 36px | -1.28px | 550 |
| heading-4xl | 40px | 42px | -2.4px | 450 |
| heading-6xl | 56px | 60px | -3.36px | 450 |
| heading-mono-2xl | 24px | 30px | -0.96px | 400 mono |
Spacing Tokens
| Token | Value | px equiv |
|---|---|---|
| space-1 | 0.25rem | 4px |
| space-2 | 0.5rem | 8px |
| space-3 | 0.75rem | 12px |
| space-4 | 1rem | 16px |
| space-6 | 1.5rem | 24px |
| space-8 | 2rem | 32px |
| space-12 | 3rem | 48px |
| space-16 | 4rem | 64px |
| sidebar-side-spacing | 0.75rem | 12px |
Border Radius
| Token | Value |
|---|---|
| rounded-sm | 2px |
| rounded | 4px |
| rounded-md | 6px |
| rounded-lg | 8px |
| rounded-xl | 12px |
| rounded-2xl | 16px |
| rounded-3xl | 24px |
| rounded-4xl | 32px |
| rounded-full | 9999px |
Shadows
| Token | Value |
|---|---|
| shadow-sm | 0 1px 2px gray-950/5% |
| shadow | 0 2px 6px gray-950/10% |
| shadow-md | 0 4px 12px gray-950/12% |
| shadow-lg | 0 10px 20px gray-950/12% |
| shadow-xl | 0 20px 25px gray-950/12% |
| shadow-2xl | 0 25px 50px gray-950/12% |
Breakpoints
| Name | Width |
|---|---|
| xxs | 384px |
| xs | 512px |
| sm | 640px |
| md | 768px |
| lg | 1024px |
| xl | 1280px |
| 2xl | 1536px |
Implementation Notes โ Dust Design System
Source \- Repository: [github.com/dust-tt/dust](http://github.com/dust-tt/dust) (fully open source, MIT) \- Design system package: /sparkle โ published as @dust-tt/sparkle on npm \- Data provenance: Extracted directly from sparkle/tailwind-preset.js and front/tailwind.config.js โ these are the ground-truth token files, not approximations
UI Framework \- Next.js (both App Router and Pages Router in use across the monorepo) \- Tailwind CSS via a custom preset (@dust-tt/sparkle/tailwind-preset) \- Component system: Sparkle (internal design system, open source) \- Tailwind plugins in use: @tailwindcss/forms, @tailwindcss/container-queries, tailwind-scrollbar-hide, tailwindcss-animate
Theme / Dark Mode \- Dark mode via darkMode: "class" โ a .dark class on or a parent element \- Every semantic color token has a paired -night value baked into the Tailwind config \- The color inversion strategy is explicit: light shade 100 โ dark shade 900, etc. \- No CSS custom property swap at runtime โ Tailwind generates both light and dark utility classes statically
Notable Patterns \- Typography classes are Tailwind components (addComponents), not utilities โ e.g. .heading-3xl, .copy-base, .label-sm \- Custom easing curves named out-expo, emphasized, enter, move โ richer than standard Tailwind \- Negative letter-spacing scales with size: all headings above sm use negative tracking for a premium editorial feel \- Geist font family (Vercel's open source font) used for both sans and mono \- Golden color replaces amber/yellow โ a warm amber with custom 12-stop scale (50โ950) \- Sidebar uses stone palette (warm gray) rather than cool gray, for visual differentiation \- Conversation max-width is hardcoded at 48rem โ a key layout constraint for the chat UI \- Animation conventions: spring-like cubic-bezier (0.34, 1.56, 0.64, 1) for entry animations, standard ease-out for exits \- Container queries are used (@tailwindcss/container-queries) with named sizes from xxs: 24rem to xl: 80rem