Design System
The visual language of the Pelagia Purchase Management System — an internal PO tool for a maritime company.
Everything here is lifted from the live codebase (app/globals.css +
components/ui/*), so screens built from these tokens drop straight in.
Framework
Next.js 15 · App Router
Styling
Tailwind CSS v4
Primitives
Radix UI · CVA
Charts · Icons
recharts · lucide
Tip: click any code snippet to copy it.
Color
Five ramps. Primary = actions, links, active nav. Success = approved / paid. Warning = needs action (edits, vendor ID, partial). Danger = rejected / destructive. Neutral = all structure, text and borders.
Typography
Inter for UI, JetBrains Mono for codes & numbers (PO numbers, accounting codes).
Page title
text-2xl font-semiboldSection heading
text-lg font-semiboldCard title
text-base font-semiboldBody / table text — the workhorse size for the whole app.
text-smMuted description & helper text
text-sm text-neutral-500Eyebrow / label
text-xs uppercase tracking-widerPMS/HNR1/9000/2024-25
font-monoRadius · Shadow · Spacing
Radius
rounded-mdrounded-lgrounded-fulllg for cards/buttons/inputs, md for nav items, full for badges & avatars.
Elevation
bordershadow-smshadow-lgFlat by default — a 1px border-neutral-200 separates surfaces. shadow-sm on cards, shadow-lg only for popovers/dialogs.
Spacing rhythm
gap-2 · 8pxgap-3 · 12px (rows)p-5 · 20px (cards)p-6 / gap-6 · 24pxPage padding p-6; cards p-5/p-6; controls gap gap-2/3.
Icons
lucide-react, stroke 2, sized h-4 w-4 inline / h-5 w-5 standalone. They inherit text color (currentColor).
App shell
Fixed w-60 sidebar (white, border-r) + h-16 top bar + scrollable main on bg-neutral-50 with p-6. Nav links: rounded-md px-3 py-2 text-sm font-medium; active = bg-primary-50 text-primary-700; section eyebrow = text-xs uppercase tracking-wider text-neutral-400.
Page header
Title + muted subtitle on the left, primary action on the right.
Purchase Orders
Create, track and approve orders across the fleet.
<div class="flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-semibold text-neutral-900">Title</h1>
<p class="mt-1 text-sm text-neutral-500">Subtitle</p>
</div>
<Button>New PO</Button>
</div>copied ✓Badges
From components/ui/badge.tsx. Base: rounded-full px-2.5 py-0.5 text-xs font-medium.
PO status badges
The 13 lifecycle states map to badge variants in lib/utils.ts (PO_STATUS_LABELS / PO_STATUS_VARIANTS). Reuse this mapping — don't invent new status colors.
Cards & KPI stats
Card = rounded-lg border border-neutral-200 bg-white shadow-sm. KPI stat cards drop the shadow and use p-4/5.
Vendor details
GST-verified supplier on file.
Acme Marine Supplies Pvt Ltd
GSTIN 27ABCDE1234F1Z5
Open POs
24
▲ 8% vs last month
Awaiting approval
7
across 3 vessels
Spend (FY)
₹2.4 Cr
FY 2025–26
Overdue
2
needs attention
Forms
Inputs from components/ui/input.tsx: h-10 rounded-lg border-neutral-300, focus border-primary-500 ring-2 ring-primary-500/20.
Inline validation error sits under the field in text-danger-700.
Tabs & segmented controls
Toolbar filters use a pill segmented control; page sections use an underline tab bar.
Tables
Header row bg-neutral-50 with text-xs uppercase tracking-wider text-neutral-400; body rows divide-y divide-neutral-100, hover hover:bg-neutral-50; numbers tabular-nums text-right.
| PO Number | Vessel | Status | Amount |
|---|---|---|---|
| PMS/HNR1/9001/2025-26 | MV Pelagia Star | Approved | ₹4,82,000 |
| PMS/OCD2/9002/2025-26 | MV Ocean Dawn | Edits Requested | ₹1,15,500 |
| PMS/CRT3/9003/2025-26 | MV Coral Trident | Closed | ₹92,300 |
Alerts & dialog
Inline callouts use the semantic -50 tint + -700 text + matching border.
Dialog
Delete accounting code?
This removes 5110 · Fuel & Lubricants. This action can't be undone.
Charts
recharts inside a standard card. Grid strokeDasharray="3 3" in #f0f0f0; axis ticks fontSize 11, #737373; bars radius, lines strokeWidth 2. Y-axis money formatted via formatCompactINR.
Spend by cost centre
Monthly trend
Multi-series palette
Formatting conventions
| Currency | Indian locale, INR — formatCurrency() → ₹4,82,000 |
| Compact money | formatCompactINR() → ₹2 Cr · ₹49 L · ₹75 K (lakh/crore scale) |
| Dates | formatDate() → Jun 22, 2026 · financial year is Apr–Mar (2025-26) |
| PO numbers | Mono font, COMPANY/VESSEL/ID/FY → PMS/HNR1/9000/2024-25 |
| Accounting codes | 6-digit mono codes; graphs label headings/sub-headings by name, leaves by code |
Do & don't
Do
- • Separate surfaces with a 1px
border-neutral-200, not heavy shadows. - • Reuse
PO_STATUS_VARIANTSfor any PO status pill. - • Keep one primary action per view; everything else secondary/ghost.
- • Right-align and
tabular-numsall money columns. - • Use semantic color only for meaning (success=paid, warning=action, danger=stop).
Don't
- • Don't introduce new hues — stay within the five ramps.
- • Don't use primary blue for decoration; it signals an action.
- • Don't mix radii —
rounded-lgfor boxes,rounded-fullfor pills. - • Don't crowd charts — one chart per card, generous whitespace.
- • Don't hardcode ₹ formatting — use the shared helpers.