Tokens
Tokens & themes
Semantic tokens come from the app's own globals.css token layer; themes are imported from shared/themes.ts. Both are checked against the app by bun run check:sync.
Semantic tokens
Stored as bare HSL triples so Tailwind can compose alpha — hsl(var(--primary) / .9).
Surfaces & depth
Three layers. Depth comes from panels floating on a themed frame, not from borders between flush columns. Shown in the Classic theme.
theme.sidebarToolbar, rail and every gutter. One continuous ground; the toolbar is transparent on it.
theme.workspaceSidebarChannel list. Floats on the frame with an inset white/6% ring.
--backgroundMain canvas and thread. Floats on the frame with a soft 0 1px 3px shadow.
| Panel radius | 12px | rounded-xl · phone list 16px, phone chat 18px top corners only |
| Panel gap | 6px | between panels and to the frame edge · phone list 8px |
| Rail | 72px | 38px tiles, rounded-[10px], 11px bold labels |
| List row | 30px | rounded-[7px] · 44px on phone |
| Pane header | 54px | md and up: channel, DM, group DM, thread, profile, drafts, threads, user group panel, new message, and the list's workspace header · Activity and Saved have their own · phone bars are min 56px |
| Search pill | 32px | rounded-[9px], white/13% on the frame · shows ⌘J (Ctrl + J off Mac), which opens the quick switcher |
Theme accent
--theme-accent is the workspace theme's accent.light or accent.dark, resolved for the current mode. It is a hex, not an HSL triple, so read it as var(--theme-accent, hsl(var(--primary-accent))) and tint with color-mix rather than Tailwind's /alpha. --theme-badge is always the theme's pastel accent.dark, whatever the mode, and count pills put #16090e text on it.
workspace-shell.tsx sets both variables twice: inline on the shell root, and on <html> from an effect that removes them on unmount. Sheets, dialogs and popovers portal to <body>, outside the shell root, and only inherit the accent because it also lives on <html>.
Helpers in src/lib/accent.ts
Every class helper falls back to --primary-accent outside a workspace and is written as a full literal so Tailwind's scanner finds it. This site imports a verbatim copy, held to the app by check:sync.
| withAlpha(hex, alpha) | Appends an alpha byte to a theme hex, for inline styles where only the per-mode hex is at hand. Own reactions use withAlpha(accent, 0.12). |
| accentText | Accent-coloured text: reply counts, the NEW divider, thread bar, saved-state icon, underline tab labels. |
| accentTintBg | The accent tint, 8% light / 15% dark: the open thread's parent, file icons, the group-DM hero's name chip, a selected theme card or huddle invitee. Rendered @mentions use the same mix, written in globals.css. |
| accentBorder | Accent border: underline tabs, the selected mode button and theme card. |
| accentSelected | accentTintBg + the same tint on hover + accentText. The shared selected-row style; the tint holds under the pointer instead of flipping to the grey hover. |
Type scale
Lato, with a system stack behind it. Titles and sender names use 900, font-black; 700 stays for controls, labels and page chrome.
Workspace themes
17 palettes. The bar is each theme's rail colour; the two dots are its accent.light and accent.dark.
Each theme also defines a lighter workspaceSidebar for the channel list panel, so the frame and list read as two depths. Only the rail is shown here, and gradients are reduced to their first stop.