Development only
CUSTOMS design system
Every reusable component rendered live against the real tokens. Nothing here is a screenshot — if a specimen breaks, the component broke. Tokens are defined once in src/app/globals.css.
Typography
Archivo sets every display heading, eyebrow and technical label. Inter carries body copy. Barlow Condensed is reserved for dense spec tables.
Display scale — .display, uppercase, Archivo 800
Eyebrow + technical label
Body scale — Inter
Font tokens
--font-display Archivo · --font-sans Inter · --font-condensed Barlow Condensed. Loaded once in the root layout; never import a font in a page.Colours
Swatches are painted with their own utility class, so this sheet fails visibly if a token is renamed. Hex values are documentation — never copy them into a component.
Brand palette
--color-navy
#071A2B
Anchors every dark surface
--color-navy-900
#050F1A
--color-navy-800
#0A2136
--color-navy-700
#0F2D47
--color-navy-600
#163A59
--color-navy-500
#1E4A6D
--color-orange
#FF5A1F
Action only — never decoration
--color-orange-600
#E64A12
--color-orange-100
#FFE9E0
--color-blue
#176B87
Supporting accent
--color-blue-600
#12586F
--color-blue-400
#2C8AA8
--color-ink
#101417
Body copy
--color-bone
#F5F3EE
Large clean commerce sections
--color-mist
#E9ECEF
--color-slate
#68727D
Secondary copy
--color-slate-400
#8D959E
Semantic surfaces + lines
--color-surface
#FFFFFF
--color-surface-alt
#F5F3EE
--color-surface-mist
#E9ECEF
--color-surface-dark
#071A2B
--color-line
#DFE3E8
--color-line-strong
#C6CCD4
--color-line-dark
#163A59
Status
--color-success
#1F8A5B
--color-success-bg
#E6F4EE
--color-warning
#B06A00
--color-warning-bg
#FDF1DE
--color-danger
#C02B1D
--color-danger-bg
#FBE9E7
--color-info
#176B87
--color-info-bg
#E4F0F4
Inputs
Every control is labelled. Error state paints the border danger and replaces helper text with the message.
Printed exactly as typed.
Enter a valid email address.
Embroidery adds to lead time.
Optional. We read every one.
Checkbox
Switch + standalone label
Tabs
Segmented tabs switch a view in place. Underline tabs divide a page into sections.
SegmentedTabs — light
SegmentedTabs — dark
UnderlineTabs
Active panel: details
Upload zone
Files never leave the browser in the prototype — the component creates an object URL and hands it straight to the renderer.
Default
Drag & drop your file here
or
PNG, JPG, SVG, AI, PDF (max 25MB)
Compact
Replace artwork
or
PNG, SVG or PDF
Cards
One card. Tight radius, hairline border, no shadow until it is interactive. Never a generic SaaS panel.
Default card — 4px radius, hairline border, white surface, 20px padding.
Production
Current order
CardHeader carries an eyebrow, a title and an action.
padded = false
Product cards
The catalogue workhorse. Hovering a blank card swaps to the customer's brand — the clearest single expression of what CUSTOMS does.
Blank — hover to brand
Branded
With add-to-collection
Badges
Nine tones. Orange marks the MVP catalogue; outline marks roadmap products that are visible but not yet orderable.
Order statuses
Every ProductionStatus a job can hold, from design review to delivered. The same pill renders in order history, order detail and confirmation.
Source of truth: STATUS_META in @/components/ui/OrderStatus.
Alerts
Six tones. Progress spins. Alerts state what is happening — they never claim a service ran when it did not.
Artwork check
Design saved
Low resolution
Unsupported file
Demo data
Compact
Quantity, progress and option controls
The controls that turn a blank product into a configured one. Swatches and chips read straight from the shared option vocabularies.
QuantitySelector
Quantity
Compact
ColorSwatches — FLAG_COLORS
Flag colour
Small
ChipGroup — light
Size
ChipGroup — dark
Decoration
ProgressStepper — light
ProgressStepper — dark
Image gallery
The product gallery is a ProductRender view switcher, not a photo carousel. Swapping to photography later is a component swap, not a layout change.
- Shape
- flag-rectangle
- Body colour
- #071A2B
- Guides
- off
Guides draw the bleed line in orange and the safe zone in ocean blue — the same overlay Studio uses when a design is being placed.
Empty states and skeletons
An empty state always offers the next action. Skeletons match the shape of what is loading so nothing jumps.
EmptyState
No saved products yet
Configure a product in Studio and it lands here, ready to reorder in one click.
Skeleton
ProductCardSkeleton
Modal and drawer
Both trap Escape, lock body scroll and carry an accessible name. The drawer is the cart and filter surface; the modal is for decisions.
Studio controls
The tool rail and history controls as they appear beside the Studio canvas. Presentation-only markup — the working rail ships with Studio itself.
History + zoom
Rail width is the --spacing-studiorail token (4.75rem), so the canvas maths never hardcodes a pixel value. These specimens are markup only and do nothing — open Studio for the working controls.
Product rendering
Every one of the 30 shape keys at small size. This sheet is the visual regression test for the renderer — if a silhouette or a decoration area breaks, it shows here first.
flag-rectangle
flag-burgee
flag-pennant
flag-feather
flag-garden
banner
tablecloth
tent
tee
longsleeve
hoodie
polo
tank
quarterzip
jacket
trucker
rope-hat
dad-hat
snapback
bucket
koozie
towel
dry-bag
cooler
dock-mat
umbrella
beach-bag
sticker
decal
sticker-sheet
Shapes live in @/components/product/shapes. Swapping the silhouettes for photography later is a one-file change — keep the artwork box contract.