Design System
Bilko Design System
Source: Extracted from apps/web/tailwind.config.ts + brand identity spec
Design Language: Modern Balkan accounting SaaS — clean, professional, accessible
Token Architecture Overview
graph TD
TC["tailwind.config.ts\n(73 design tokens)"]
TC --> COLORS["Color Tokens"]
TC --> TYPE["Typography Tokens"]
TC --> SPACE["Spacing Tokens"]
TC --> RADIUS["Border Radius Tokens"]
TC --> SHADOW["Shadow Tokens"]
TC --> BP["Breakpoint Tokens"]
COLORS --> PRIMARY["Primary Brand\n#00E5A0 / #00B380 / #33EBB3"]
COLORS --> STATUS["Status Colors\nsuccess / warning / error / info"]
COLORS --> TEXT["Text Scale\nprimary / secondary / muted"]
COLORS --> BG["Backgrounds\nlight #FAFAFA / surface #FFF"]
COLORS --> SIDEBAR["Sidebar (Dark Theme)\nbg / text / text-muted / active / hover"]
COLORS --> CHART["Chart Colors\nrevenue / expense / profit / neutral"]
TYPE --> FONT["Inter (Google Fonts)\nxs 12px → 4xl 40px"]
TYPE --> WEIGHT["Weights\n400 / 500 / 600 / 700"]
SPACE --> GRID["8px Grid\nxs 4px → 3xl 64px"]
RADIUS --> SIZES["6px / 8px / 12px / full"]
SHADOW --> ELEV["card / modal / dropdown"]
BP --> SCREEN["640px / 768px / 1024px / 1280px"]
Color Palette
Primary Brand Colors
Primary: #00E5A0 (Vibrant teal-green — primary CTA, links, active states)
Primary Dark: #00B380 (Darker variant for hover states)
Primary Light: #33EBB3 (Lighter variant for backgrounds)
Status Colors
Success: #22C55E (Green — success states, paid invoices, positive metrics)
Warning: #F59E0B (Amber — warnings, pending items, aging invoices)
Error: #EF4444 (Red — errors, overdue invoices, negative actions)
Info: #3B82F6 (Blue — informational messages, neutral data)
Text Colors
Text Primary: #111113 (Near-black — body text, headings)
Text Secondary: #6B7280 (Gray-600 — secondary text, labels)
Text Muted: #888888 (Gray-500 — muted text, placeholders)
Background Colors
Background Light: #FAFAFA (Off-white — main content area background)
Background Surface: #FFFFFF (White — card backgrounds, modals)
Border Color
Border: #E5E7EB (Gray-200 — borders, dividers)
Chart Colors
Chart Revenue: #22C55E (Green — revenue bars/lines)
Chart Expense: #EF4444 (Red — expense bars/lines)
Chart Profit: #3B82F6 (Blue — profit bars/lines)
Chart Neutral: #6B7280 (Gray — neutral data points)
Sidebar Colors (Dark Theme)
Sidebar BG: #111113 (Near-black — sidebar background)
Sidebar Text: #FAFAFA (Off-white — sidebar text)
Sidebar Text Muted: #888888 (Gray — inactive menu items)
Sidebar Active: #00E5A0 (Primary green — active menu item)
Sidebar Hover: #1F1F23 (Slightly lighter black — hover state)
Usage:
Color Relationship Map
graph LR
subgraph BRAND["Brand Identity"]
P["Primary\n#00E5A0"]
PD["Primary Dark\n#00B380\n(hover)"]
PL["Primary Light\n#33EBB3\n(bg tint)"]
P --> PD
P --> PL
end
subgraph LAYOUT["Layout Zones"]
SBG["Sidebar BG\n#111113"]
SBG --> STEXT["Sidebar Text\n#FAFAFA"]
SBG --> SMUTED["Sidebar Muted\n#888888"]
SBG --> SACTIVE["Active Item\n#00E5A0"]
CBG["Content BG\n#FAFAFA"]
CBG --> SURF["Card Surface\n#FFFFFF"]
CBG --> BORDER["Border\n#E5E7EB"]
end
subgraph SEMANTIC["Semantic Status"]
SUCCESS["Success\n#22C55E\n(paid, positive)"]
WARN["Warning\n#F59E0B\n(pending, aging)"]
ERR["Error\n#EF4444\n(overdue, delete)"]
INFO["Info\n#3B82F6\n(neutral data)"]
end
subgraph TEXT_SCALE["Text Scale"]
TP["Text Primary\n#111113"]
TS["Text Secondary\n#6B7280"]
TM["Text Muted\n#888888"]
end
P -->|"active states"| SACTIVE
SUCCESS -->|"chart-revenue"| CR["Chart Revenue"]
ERR -->|"chart-expense"| CE["Chart Expense"]
INFO -->|"chart-profit"| CP["Chart Profit"]
Typography
Font Family
Sans Serif: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif
Source: Google Fonts Inter (variable font) Fallback: System UI fonts for performance
Font Sizes
xs: 12px (Small badges, captions)
sm: 14px (Table cells, secondary text, form labels)
base: 16px (Body text, default)
lg: 18px (Subheadings, emphasized text)
xl: 20px (Section titles)
2xl: 24px (Card titles, small headings)
3xl: 32px (Page headings)
4xl: 40px (Hero text, large numbers)
Font Weights
normal: 400 (Body text)
medium: 500 (Emphasis, table headers)
semibold: 600 (Subheadings, button text)
bold: 700 (Headings, metric numbers)
Type Scale Usage
- Headings:
- Page title:
text-3xl font-bold(32px, 700) - Section title:
text-2xl font-bold(24px, 700) - Card title:
text-base font-semibold(16px, 600)
- Page title:
- Body:
- Default:
text-base font-normal(16px, 400) - Table cells:
text-sm font-medium(14px, 500) - Muted text:
text-sm text-text-muted(14px, #888888)
- Default:
- Numbers:
- Metrics:
text-3xl font-bold(32px, 700) - Totals:
text-2xl font-bold(24px, 700) - Amounts:
text-base font-medium(16px, 500)
- Metrics:
Spacing System (8px Grid)
xs: 4px (Tight spacing, icon gaps)
sm: 8px (Input padding, small gaps)
md: 16px (Default spacing, card padding)
lg: 24px (Section spacing)
xl: 32px (Large section spacing)
2xl: 48px (Major section breaks)
3xl: 64px (Hero spacing)
Usage:
- Card padding:
p-6(24px) - Form field gap:
space-y-4(16px) - Section spacing:
space-y-6(24px) - Grid gap:
gap-6(24px)
Consistency: All spacing uses 8px increments (4px, 8px, 16px, 24px, 32px, 48px, 64px)
Border Radius
sm: 6px (Small elements, badges)
md: 8px (Buttons, inputs, cards)
lg: 12px (Modals, large cards)
full: 9999px (Circular elements, pills)
Usage:
- Cards:
rounded-md(8px) - Buttons:
rounded-md(8px) - Inputs:
rounded-md(8px) - Badges:
rounded-sm(6px) - User avatar:
rounded-full(circular)
Shadows
Card Shadow: 0 2px 8px rgba(0, 0, 0, 0.08) (Subtle card elevation)
Modal Shadow: 0 8px 24px rgba(0, 0, 0, 0.12) (Dialog/modal elevation)
Dropdown Shadow: 0 4px 16px rgba(0, 0, 0, 0.10) (Dropdown menu elevation)
Usage:
- Cards:
shadow-card - Modals/dialogs:
shadow-modal - Dropdown menus:
shadow-dropdown
Philosophy: Subtle shadows for depth, avoid heavy shadows (material design style)
Design Token Relationships
classDiagram
class ButtonTokens {
+height_default: 40px
+height_sm: 32px
+height_lg: 48px
+padding_x: 16px
+border_radius: 8px (md)
+font_size: 14px medium
+variant_default: primary-bg white-text
+variant_outline: border-only transparent
+variant_ghost: no-border no-bg
+variant_destructive: error-red white-text
}
class InputTokens {
+height: 40px
+padding_x: 12px
+border: 1px solid #E5E7EB
+border_radius: 8px (md)
+font_size: 14px normal
+focus_ring: 2px primary-color
}
class CardTokens {
+background: #FFFFFF
+border: 1px solid #E5E7EB
+border_radius: 8px (md)
+shadow: 0 2px 8px rgba-8pct
+padding: 24px
}
class BadgeTokens {
+padding: 4px 8px
+border_radius: 6px (sm)
+font_size: 12px medium
+variant_success: green-bg
+variant_warning: amber-bg
+variant_destructive: red-bg
+variant_secondary: light-gray-bg
}
class TableTokens {
+row_height: 48px
+cell_padding_x: 12px
+cell_padding_y: 16px
+border: 1px solid #E5E7EB
+hover: light-gray #FAFAFA
+header_weight: medium
+header_color: text-secondary
}
class ColorTokens {
+primary: #00E5A0
+primary_dark: #00B380
+success: #22C55E
+warning: #F59E0B
+error: #EF4444
+info: #3B82F6
+text_primary: #111113
+text_secondary: #6B7280
+border: #E5E7EB
+surface: #FFFFFF
+bg_light: #FAFAFA
}
ButtonTokens --> ColorTokens : uses primary, error
InputTokens --> ColorTokens : uses border, primary (focus)
CardTokens --> ColorTokens : uses surface, border
BadgeTokens --> ColorTokens : uses success, warning, error
TableTokens --> ColorTokens : uses border, bg-light (hover)
Breakpoints
sm: 640px (Small tablets, large phones)
md: 768px (Tablets)
lg: 1024px (Small desktops, large tablets)
xl: 1280px (Desktops)
Mobile-First Strategy:
- Base styles = mobile (< 640px)
sm:= small tablet (640px+)md:= tablet/desktop toggle (768px+)lg:= desktop layout (1024px+)xl:= wide desktop (1280px+)
Responsive Patterns:
- Grid:
grid-cols-1 md:grid-cols-2 lg:grid-cols-3 - Sidebar:
hidden md:block(hide on mobile) - Filters:
flex-col sm:flex-row(stack on mobile, row on tablet+)
Responsive Layout Behavior
graph TD
subgraph MOBILE["Mobile (< 640px)"]
M1["Sidebar: hidden\n(overlay when toggled)"]
M2["TopBar: shows hamburger + logo"]
M3["Grid: single column"]
M4["Filters: stacked vertically"]
M5["Tables: horizontal scroll"]
end
subgraph TABLET["Tablet (768px+)"]
T1["Sidebar: visible, persistent"]
T2["TopBar: shows search + user menu"]
T3["Grid: 2 columns"]
T4["Filters: row layout"]
T5["Tables: full width"]
end
subgraph DESKTOP["Desktop (1024px+)"]
D1["Sidebar: 256px fixed width"]
D2["TopBar: full bar"]
D3["Grid: 3 columns"]
D4["Settings: sidebar + content split"]
D5["Banking: full tab content"]
end
Component Tokens
Button
- Height: 40px (default), 32px (sm), 48px (lg), 40px (icon)
- Padding: 16px horizontal (default), 12px (sm), 20px (lg)
- Border Radius: 8px (md)
- Font: 14px medium (default), 12px (sm), 16px (lg)
- Variants:
- Default: Primary green background, white text
- Outline: Border only, transparent background
- Ghost: No border, no background, hover shows background
- Destructive: Error red background, white text
Input
- Height: 40px
- Padding: 12px horizontal
- Border: 1px solid #E5E7EB (border color)
- Border Radius: 8px (md)
- Font: 14px normal
- Focus: Primary color ring (2px)
Card
- Background: #FFFFFF (surface)
- Border: 1px solid #E5E7EB
- Border Radius: 8px (md)
- Shadow: 0 2px 8px rgba(0, 0, 0, 0.08)
- Padding: 24px (default content padding)
Badge
- Padding: 4px 8px
- Border Radius: 6px (sm)
- Font: 12px medium
- Variants:
- Default: Gray background
- Success: Green background
- Warning: Amber background
- Destructive: Red background
- Secondary: Light gray
Table
- Row Height: 48px (default)
- Cell Padding: 12px horizontal, 16px vertical
- Border: 1px solid #E5E7EB (between rows)
- Hover: Light gray background (#FAFAFA)
- Header: Medium font weight, secondary text color
Icon System
Library: Lucide React (v0.469.0)
Size: Consistent 16px (w-4 h-4) or 20px (w-5 h-5)
Usage:
Common Icons:
- Plus (add actions)
- Search (search inputs)
- Menu (mobile sidebar toggle)
- User (user menu)
- Bell (notifications)
- ChevronDown/Right (expandable sections)
- Check (success, reconciliation)
- X (close, delete)
- Download (export actions)
- Send (send email)
Chart Design Tokens
Chart Colors (Recharts)
Revenue: #22C55E (Green bars)
Expense: #EF4444 (Red bars)
Profit: #3B82F6 (Blue bars)
Neutral: #6B7280 (Gray — when no semantic meaning)
Chart Typography
- Axis Labels: 12px normal
- Tooltip: 14px medium
- Legend: 12px normal
Chart Layout
- Responsive Container: 100% width, fixed height (250px default)
- Cartesian Grid: Dashed, #E5E7EB stroke
- Tooltip Background: White with border
- Border Radius: 8px (md)
Accessibility
Color Contrast
- All text colors meet WCAG AA standards
- Primary text (#111113) on white = 16.17:1 (AAA)
- Secondary text (#6B7280) on white = 4.69:1 (AA)
- Primary green (#00E5A0) on white = 2.92:1 (fails — used for accents only, not body text)
Focus Indicators
- All interactive elements have visible focus ring
- Focus ring color: Primary green (#00E5A0)
- Focus ring width: 2px
Semantic HTML
- Proper heading hierarchy (h1 → h2 → h3)
- Form labels properly associated with inputs
- ARIA labels on icon-only buttons
- Table headers properly scoped
Design Principles
- Clarity over Decoration — Data-first, minimal ornamentation
- Consistent Spacing — 8px grid, predictable rhythm
- Accessible by Default — WCAG AA minimum, Radix UI primitives
- Mobile-First — Responsive from 375px+ (iPhone SE)
- Dark Sidebar + Light Content — Clear visual separation
- Primary Color as Accent — Green (#00E5A0) for actions, not backgrounds
- Subtle Shadows — Elevation without heaviness
- Data-Dense UI — Tables, charts, metrics — optimized for information density
Brand Identity Alignment
From ~/system/specs/bilko-brand-identity.md:
- Primary Color: #00E5A0 (implemented)
- Typography: Inter (implemented)
- Tone: Modern, professional, Balkan-focused (implemented)
- Dark Sidebar: #111113 (implemented)
- Logo Placement: Top left sidebar (implemented)
Future Tokens (Phase 2)
When implementing API integration:
- Loading States: Skeleton component colors
- Error States: Error message backgrounds (#FEF2F2, light red)
- Success States: Success message backgrounds (#F0FDF4, light green)
- Toast Notifications: Background, text, border colors
- Dark Mode: Full dark theme variant (optional)
No comments to display
No comments to display