# xBid Design System & Style Guide
A reference for the visual language, component patterns, and design principles used in xBid so that future apps can maintain the same look and feel.
---
## 1. Core Principles
- **Dark-first**: The app is permanently dark mode (`className="dark"` on ``). There is no light/dark toggle.
- **Minimal chrome**: Surfaces are dark zinc grays with amber as the single accent colour. No gradients, no heavy decoration.
- **Dense but readable**: Data-heavy UI uses compact sizing (`text-xs`, `text-sm`) with generous whitespace in page-level padding.
- **Amber accent, zinc foundation**: Brand colour is amber (`#f59e0b` / `amber-500`). All structural surfaces use the zinc palette.
---
## 2. Typography
### Font Family
- **Primary (body & UI)**: **Inter** — loaded via `next/font/google`, subset `latin`.
- **Mono**: Geist Mono (via `--font-geist-mono` CSS variable from shadcn).
- Applied globally: `font-sans` on ``.
### Scale (Tailwind defaults, used in practice)
| Usage | Class(es) | Notes |
|---|---|---|
| Page title | `text-3xl font-bold text-white` | e.g. Dashboard h1 |
| Section title | `text-xl font-semibold text-white` | e.g. "Recent Jobs" h2 |
| Detail page title | `text-xl font-bold text-white` | Truncated with `truncate` |
| Card title | `text-base font-medium` (via `CardTitle`) | |
| Body / default | `text-sm` | |
| Captions / meta | `text-sm text-zinc-400` or `text-zinc-500` | |
| Table headers | `text-xs uppercase tracking-wider text-zinc-500` | |
| Table cells | `text-xs` or `text-sm` | |
| Error messages | `text-xs text-red-400` | Form validation |
| Stat value | `text-3xl font-bold text-white` | Dashboard stat cards |
---
## 3. Colour Palette
The app uses **Tailwind CSS v4 with OKLCH CSS variables**. All semantic tokens map to zinc grays in dark mode.
### Brand / Accent
| Token | Tailwind class | Hex approx | Usage |
|---|---|---|---|
| Brand amber | `amber-500` | `#f59e0b` | Logo bg, icon colour |
| Active nav highlight | `amber-500/10` bg + `amber-400` text | — | Active nav item |
| Amber text | `text-amber-400` | `#fbbf24` | Active nav, stat icons |
| Amber text bold | `text-amber-500` | `#f59e0b` | Logo "Bid" wordmark |
### Surface / Layout
| Purpose | Tailwind class | Notes |
|---|---|---|
| Page background | `bg-zinc-950` | Top bar, outermost bg |
| Sidebar & card bg | `bg-zinc-900` | Primary surface |
| Hover / secondary surface | `bg-zinc-800` | Hover states, secondary card |
| Input fields | `bg-zinc-900 border-zinc-700` | Form inputs override |
| Borders | `border-zinc-800` | Dividers, card outlines |
| Input borders | `border-zinc-700` | Slightly lighter than surface borders |
### Text
| Purpose | Tailwind class | Hex approx |
|---|---|---|
| Primary / headings | `text-white` | `#ffffff` |
| Secondary / labels | `text-zinc-400` | `#a1a1aa` |
| Tertiary / placeholders | `text-zinc-500` | `#71717a` |
| Disabled / subtle | `text-zinc-600` | `#52525b` |
| Bright secondary | `text-zinc-300` | `#d4d4d8` |
### Semantic / Status Badges
These appear on `Job` and `Invoice` status badges. Pattern: coloured bg at low opacity + matching light text.
| Status | Classes |
|---|---|
| DRAFT | `bg-zinc-700 text-zinc-300` |
| SENT | `bg-blue-900/60 text-blue-300` |
| APPROVED / PAID | `bg-green-900/60 text-green-300` |
| REJECTED / OVERDUE | `bg-red-900/60 text-red-300` |
| ARCHIVED | `bg-yellow-900/60 text-yellow-300` |
| VIEWED | `bg-purple-900/60 text-purple-300` |
| PARTIALLY_PAID | `bg-orange-900/60 text-orange-300` |
| CANCELLED | `bg-zinc-800 text-zinc-500` |
### Icon Colours (Dashboard Stats)
| Metric | Icon colour |
|---|---|
| Jobs / Total | `text-amber-400` |
| Clients | `text-blue-400` |
| Drafts | `text-zinc-400` |
| Sent / Pending | `text-yellow-400` |
| Approved | `text-green-400` |
---
## 4. Spacing & Layout
### App Shell
```
┌─────────────────────────────────────────┐
│ Sidebar (w-60 / w-16 collapsed) │ Main content (flex-1 overflow-y-auto)
│ bg-zinc-900 │ p-8 on page content
│ border-r border-zinc-800 │
└─────────────────────────────────────────┘
```
- Root: `flex h-full overflow-hidden`
- Sidebar: `flex flex-col bg-zinc-900 border-r border-zinc-800 transition-all duration-200`
- Main: `flex-1 overflow-y-auto`
- Page padding: `p-8`
### Page Header pattern
```tsx
Page Title
Subtitle / description.
```
### Detail Page Top Bar
```tsx
{/* back arrow + title + meta + actions */}
```
### Grid layouts
| Pattern | Class |
|---|---|
| Stat cards | `grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-5` |
| Form fields | `grid grid-cols-1 sm:grid-cols-2 gap-5` |
| Form field spacing | `space-y-1.5` (label + input) |
| Form section spacing | `space-y-6` |
---
## 5. Border Radius
Defined by CSS variable `--radius: 0.625rem` (10px).
| Token | Size | Tailwind class |
|---|---|---|
| sm | ~6px | `rounded-sm` / `rounded` |
| md | ~8px | `rounded-md` |
| lg | 10px (base) | `rounded-lg` |
| xl | ~14px | `rounded-xl` |
| 4xl (badges) | ~26px | `rounded-4xl` |
**In practice**: `rounded-lg` is the default for buttons, inputs, cards, nav items. Cards use `rounded-xl`. Badges use `rounded-4xl` (pill shape).
---
## 6. Component Patterns
### Sidebar Navigation
- Container: `bg-zinc-900 border-r border-zinc-800`
- Logo area: `px-4 py-5 border-b border-zinc-800`
- Icon: `w-8 h-8 rounded-lg bg-amber-500 flex items-center justify-center` with black icon inside
- Wordmark: `font-bold text-lg tracking-tight text-white` — "x" white, "Bid" amber
- Nav item inactive: `text-zinc-400 hover:text-white hover:bg-zinc-800 px-3 py-2.5 rounded-lg text-sm font-medium`
- Nav item active: `bg-amber-500/10 text-amber-400`
- Icon size: `h-4 w-4`
### Cards
```tsx
…
…
…
```
- Card has `ring-1 ring-foreground/10` and `rounded-xl` by default via shadcn base-nova.
- Override bg/border on dark surfaces: `bg-zinc-900 border-zinc-800`.
### Buttons
Variants from shadcn `buttonVariants`:
| Variant | Appearance |
|---|---|
| `default` | Dark bg (`primary`), light text — effectively `bg-zinc-900 text-white` in dark mode |
| `outline` | Border, transparent bg, hover muted |
| `secondary` | Muted bg |
| `ghost` | No border, hover muted |
| `destructive` | Red tinted bg, red text |
| `link` | Underline on hover |
Sizes: `xs`, `sm`, `default` (h-8), `lg`, `icon`, `icon-xs`, `icon-sm`, `icon-lg`.
### Badges / Status Pills
```tsx
Approved
```
- Custom status colours applied via `className` override (see §3 Semantic/Status Badges).
- Default shape: pill (`rounded-4xl`), `h-5`, `text-xs`.
### Form Fields
```tsx
{error &&
{error.message}
}
```
- Input base: `h-8 rounded-lg border border-input bg-transparent` — always override with `bg-zinc-900 border-zinc-700` for dark surface visibility.
- Textarea, Select follow the same pattern.
### Tables
Line-item tables are custom `` elements styled with:
- `text-xs w-full`
- Header row: `border-b border-zinc-800 text-zinc-500 uppercase tracking-wider`
- Cells: `px-4 py-2 text-left`
- Alternating/hover rows: use `hover:bg-zinc-800/50`
shadcn `` component uses `text-sm` and standard `border-b` between rows.
### Tabs
```tsx
Label
…
```
- `TabsList` bg: `bg-muted` (zinc-800 in dark), `rounded-lg`.
- `TabsTrigger` active: white text, slight bg lift.
### Dialogs / Sheets
Standard shadcn `Dialog` / `Sheet`. Content uses `bg-zinc-900` / card surface. Destructive actions use red confirm buttons.
### Toasts / Notifications
- Library: **Sonner** (``)
- `toast.success(…)` — green
- `toast.error(…)` — red
- Always called after async actions complete.
### Dropdown Menus
Standard shadcn `DropdownMenu`. Destructive actions get `text-destructive` styling on the `DropdownMenuItem`.
### Collapsible / Expandable Rows
Shot and asset cards use a chevron toggle (`ChevronDown` / `ChevronRight`) to expand inline line-item tables. Pattern:
```tsx
```
---
## 7. Icons
Library: **Lucide React** (`lucide-react`)
Standard icon size: `h-4 w-4` (16px). Larger decorative: `h-5 w-5`.
Common icons used:
| Purpose | Icon |
|---|---|
| Dashboard | `LayoutDashboard` |
| Clients | `Users` |
| Jobs / Quotes | `Briefcase` |
| Invoices | `FileText` |
| Rate Cards | `CreditCard` |
| Settings | `Settings` |
| Back | `ArrowLeft` |
| Download PDF | `Download` |
| Duplicate | `Copy` |
| Delete | `Trash2` |
| Edit | `Pencil` |
| Add | `Plus` |
| More options | `MoreHorizontal` |
| Search | `Search` |
| Loading | `Loader2` (with `animate-spin`) |
| Drag handle | `GripVertical` |
| App logo | `Film` |
| Send | `Send` |
| Approve / Mark paid | `Check` / `CheckCircle` |
---
## 8. Motion & Transitions
- Sidebar collapse: `transition-all duration-200`
- Nav item colour: `transition-colors`
- Buttons: `transition-all`
- Drag-and-drop (DnD Kit): opacity `0.5` while dragging.
- Animation library: `tw-animate-css` (imported in globals.css).
---
## 9. Tech Stack
| Layer | Technology |
|---|---|
| Framework | Next.js 15 (App Router, React Server Components) |
| Styling | Tailwind CSS v4 |
| Component system | shadcn/ui (`base-nova` style) + `@base-ui/react` primitives |
| Icon library | Lucide React |
| Font | Inter (Google Fonts via `next/font`) |
| Notifications | Sonner |
| Forms | React Hook Form + Zod |
| Drag & Drop | `@dnd-kit/core` + `@dnd-kit/sortable` |
| ORM | Prisma |
| DB | PostgreSQL |
| Color space | OKLCH (CSS variables) |
---
## 10. Quick Reference — Recurring Class Combinations
```
# Page wrapper
p-8
# Page title
text-3xl font-bold text-white
# Page subtitle
text-zinc-400 mt-1
# Section heading
text-xl font-semibold text-white mb-4
# Top bar (detail pages)
border-b border-zinc-800 px-8 py-4 flex items-center gap-4 bg-zinc-950
# Card (dark surface)
bg-zinc-900 border-zinc-800
# Card text hierarchy
text-white (value) | text-zinc-400 (label) | text-zinc-500 (meta)
# Form input (dark)
bg-zinc-900 border-zinc-700
# Form error
text-red-400 text-xs
# Table header
border-b border-zinc-800 text-zinc-500 uppercase tracking-wider text-xs
# Empty state text
text-center text-sm text-zinc-500
# Active nav
bg-amber-500/10 text-amber-400
# Inactive nav
text-zinc-400 hover:text-white hover:bg-zinc-800
```