PPMS Design System

Pelagia Purchase Management System · v1

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-semibold

Section heading

text-lg font-semibold

Card title

text-base font-semibold

Body / table text — the workhorse size for the whole app.

text-sm

Muted description & helper text

text-sm text-neutral-500

Eyebrow / label

text-xs uppercase tracking-wider

PMS/HNR1/9000/2024-25

font-mono

Radius · Shadow · Spacing

Radius

rounded-md
rounded-lg
rounded-full

lg for cards/buttons/inputs, md for nav items, full for badges & avatars.

Elevation

border
shadow-sm
shadow-lg

Flat by default — a 1px border-neutral-200 separates surfaces. shadow-sm on cards, shadow-lg only for popovers/dialogs.

Spacing rhythm

gap-2 · 8px
gap-3 · 12px (rows)
p-5 · 20px (cards)
p-6 / gap-6 · 24px

Page 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.

Dashboard

Buttons

From components/ui/button.tsx (CVA). Base: inline-flex items-center gap-2 rounded-lg text-sm font-medium + focus ring.

<Button variant="default|secondary|success|warning|destructive|ghost|link" size="sm|md|lg|icon">copied ✓

Badges

From components/ui/badge.tsx. Base: rounded-full px-2.5 py-0.5 text-xs font-medium.

default secondary success warning danger outline

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 NumberVesselStatusAmount
PMS/HNR1/9001/2025-26MV Pelagia StarApproved₹4,82,000
PMS/OCD2/9002/2025-26MV Ocean DawnEdits Requested₹1,15,500
PMS/CRT3/9003/2025-26MV Coral TridentClosed₹92,300

Alerts & dialog

Inline callouts use the semantic -50 tint + -700 text + matching border.

ℹ InfoImported POs are created directly in the Closed state.
✓ SuccessPurchase order approved and sent for payment.
⚠ WarningThis vendor is unverified — verify before assigning a vendor code.
✕ ErrorPayment date cannot be in the future.

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

₹3Cr₹1.5Cr₹0

Monthly trend

Multi-series palette

Formatting conventions

CurrencyIndian locale, INR — formatCurrency() → ₹4,82,000
Compact moneyformatCompactINR() → ₹2 Cr · ₹49 L · ₹75 K (lakh/crore scale)
DatesformatDate() → Jun 22, 2026 · financial year is Apr–Mar (2025-26)
PO numbersMono font, COMPANY/VESSEL/ID/FY → PMS/HNR1/9000/2024-25
Accounting codes6-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_VARIANTS for any PO status pill.
  • • Keep one primary action per view; everything else secondary/ghost.
  • • Right-align and tabular-nums all 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-lg for boxes, rounded-full for pills.
  • • Don't crowd charts — one chart per card, generous whitespace.
  • • Don't hardcode ₹ formatting — use the shared helpers.