Files
eatme/docs/frontend/design-system.md
Michal Pemcak 94933cac5c Update OKF docs bundle, README, and CLAUDE.md for today's features
Documents the shift planning and closure/payroll modules (new tables,
routes, stores), the dark redesign, and the docker-compose-broken-host
workaround. Adds CLAUDE.md pointing agents at docs/. Translates README to
English and keeps host-specific infrastructure details out of the repo.
2026-08-16 18:41:11 +02:00

4.9 KiB

type, title, description, resource, tags, timestamp
type title description resource tags timestamp
Design Language Dark modern design system How EatMe's dark, sharp-edged, amber-accent design system is implemented in frontend/src/styles/theme.css. frontend/src/styles/theme.css
frontend
design
css
2026-08-16T00:00:00Z

Dark modern design system

Replaced the original light monochrome TUI style (mono font, ~/doc/concepts/ui/light-mono-tui.md) on 2026-08-16, on explicit request — the TUI look read as dated to the app's actual end users. All tokens and component classes live in frontend/src/styles/theme.css (was tui.css — renamed since "TUI" stopped being an accurate description).

Rules this design follows

  • Dark background, sharp corners. --radius-lg/--radius/--radius-sm are all 0 — deliberately, per explicit user preference against rounded corners even in an otherwise "modern SaaS" direction.
  • One accent color, used sparingly. --accent (warm amber, #f2a93b) marks state, not decoration: the active tab, "this shift is mine", today's calendar cell, focus rings. It is not used as a per-card or per-row accent border.
  • No colored border-left/border-right accent stripes. Explicitly rejected during design — a common AI-generated-UI tic. Emphasis instead comes from filled backgrounds (.badge-solid, .tab.active, .calendar-slot.is-mine) or a full inset ring around the whole element (.month-calendar-cell.is-today, .month-calendar-day-btn.is-selected), never a single colored edge.
  • System sans-serif for body text, --font-mono reserved for numbers/ timestamps that benefit from tabular alignment (.stat-value, calendar time chips, the bar chart's axis labels) — a common dashboard convention (Linear, Vercel), not an all-monospace TUI throwback.
  • Neutral hairline dividers, not colored ones. .list/.row, .stat-grid, and the calendar grid all use a 1px --border-colored gap/border for internal separators.
  • color-scheme: dark is set globally so native form controls (date/ time pickers, number spinners) render dark by default — otherwise bare <input type="date"> etc. render as light-mode browser chrome floating in an otherwise-dark page, which is what a generic input, select base rule plus this fixes.

Tokens

--bg, --surface (panels), --surface-hover, --surface-2 (nested/ input backgrounds), --border, --border-strong, --fg, --muted, --muted-2, --accent, --accent-strong, --accent-fg (text color for content sitting on the accent), --radius-lg/--radius/--radius-sm (all 0), --shadow-sm/--shadow-md, --font, --font-mono.

Component classes

Same class names as the previous TUI stylesheet — this was a pure CSS rewrite, no component file needed to change: .tabs/.tab, .btn/.btn-block/.btn-ghost, .panel, .field-row, .list/.row, .badge (-solid, -dashed — both restyled as pills, no more literal dashed border), .stat-grid/.stat-tile, .login-card, .month-calendar-*, .calendar-slot/.calendar-chip. .badge-double (from the old TUI system) was dropped — it had no remaining usages.

There's intentionally only one .btn visual style (no .btn-primary) — introducing a primary/secondary distinction would have meant touching every component that renders a button to classify its actions, which was out of scope for a CSS-only redesign pass.

App-specific additions

  • .bar-chart-* (frontend/src/components/BarChart.tsx) — bars are --accent-filled with a rounded top edge only, y-axis and day labels in --font-mono; day-of-month labels render in a separate flex row below the fixed-height bar track (not nested inside each bar's percentage- height column) specifically to avoid the bars visually overlapping the labels.
  • .month-nav (frontend/src/components/MonthNav.tsx) — [<] label [>] segmented-control strip. Placed inside the panel it controls (employee detail chart, shift calendar, closure card), not as a page-level control — an earlier version put it at the top of the whole admin stats page, which tested as confusing since it was visually disconnected from what it affected.
  • .month-calendar-* (frontend/src/components/MonthCalendar.tsx) — shared 7-column Monday-first grid used by both ShiftPlanning (employee) and ShiftPlanManager (admin), via a renderDay(dateStr, dayNumber) render-prop rather than two separate calendar implementations. The employee view renders interactive slot buttons directly in each cell; the admin view renders compact read-only chips and a day-select button, since full slot editing (capacity, notes, assign dropdown) doesn't fit in a calendar cell — clicking a day opens a detail panel below the grid instead.

Related