Scran design system

Premium through restraint. Clean neutral base, black type doing the hierarchy work, one signature colour used sparingly. Glass is a layering tool, never an effect. The system is the chrome; the vendor's brand is the tint.

Colour

Accent discipline: if a screen uses accent in more than ~3 places, it is wrong. Accent means primary CTA, live state, selection. Nothing else.

Light (default)

accent#00C853CTA, live, selection only
ink#0A0A0A
ink-mutedink 60%
canvas#FFFFFFbg-canvas in CSS (base in TS)
surface#F5F5F4
line#E7E5E4
warning#FFB300
danger#E53935

Dark overrides

accent#00E676
ink#FAFAFA
ink-mutedink 64%
canvas#0A0A0A
surface#161616
line#262626
warning#FFB300
danger#FF5252

Surface theme defaults

Light default

Admin, Platform, Storefront, Customer app, Marketplace, Vendor Hub, Super Vendor, Kiosk, Till, Scanner, Order Manager

Dark default

KDS (kitchen glare), Signage / menu boards, Driver (night driving)

Staff tools (till, KDS, scanner) also apply the reduce-transparency high-contrast variant: solid background, hairline border, no blur.

Type — Hanken Grotesk

One family, six roles. Money is always tabular. Hierarchy comes from weight and size, never colour.

displayBold 32/38, -2% trackingFresh from your local
titleSemiBold 20/26Today's orders
bodyRegular 16/24Hierarchy comes from weight and size, never colour.
priceSemiBold 16/24, tabular£12.40
metaMedium 13/16, ink-mutedUpdated 2 minutes ago
labelMedium 11/14, caps, +6% trackingNet sales

Shape — radius tokens

Four steps: sm 8, md 12, lg 16, pill 999. Clean but not bubbly. Buttons use md, cards lg, badges and status dots pill.

--radius-sm8pxInput corners, small chips
--radius-md12pxButtons, form controls (rounded-md)
--radius-lg16pxCards, panels, tiles (rounded-lg)
--radius-pill999pxBadges, switch track, spinner (rounded-pill)
sm · 8
md · 12
lg · 16
pill · 999

Elevation

Three tiers: page content, card (hairline border, no shadow), floating glass. That is the whole z-axis.

Tier 0 · Page

Content area

No border, no shadow. Canvas background.

Tier 1 · Card

Card / well

Hairline border. No shadow in light theme.

Tier 2 · Glass

Floating glass

Nav bars, sheets, popovers. Blur 24, soft shadow.

Staff tools swap glass for solid + hairline via .reduce-transparency on the root. Same component code, token-level switch. Doubles as the accessibility mode product-wide.

Motion

Two durations, one easing curve. Motion conveys state change, not decoration. No orchestrated page-load sequences on staff tools.

motion.standard150msButtons, badges, tab underlines, hover states
motion.sheet250msSheet/drawer slide, dialog fade-in
--ease-scrancubic-bezier(0.2, 0, 0, 1)Ease-out-expo feel. Used for all transitions.
Every animation honours prefers-reduced-motion: typically a crossfade or instant transition instead of a slide. No decorative animation on staff tools (till, KDS, scanner).

Components

Every block rendered in light and dark. Source: @getscran/ui-web.

Light

Button — variant + size

Badge

LiveDraftLow stockOverdueUber Eats

Form controls

Shown on menus and receipts

Price is required

Tabs

Active tab uses ink weight + underline. Never accent colour.

Dialog + sheet

Table

ItemStatusPrice
Classic burgerLive£6.50
Coke 330mlLow · 4£1.40
FriesDraft£2.99

Loading states

Spinner (inline only, not page-level)

Empty state

No orders yet

New orders from every channel land here in realtime. Share your shop link to start receiving orders.

Dark

Button — variant + size

Badge

LiveDraftLow stockOverdueUber Eats

Form controls

Shown on menus and receipts

Price is required

Tabs

Active tab uses ink weight + underline. Never accent colour.

Dialog + sheet

Table

ItemStatusPrice
Classic burgerLive£6.50
Coke 330mlLow · 4£1.40
FriesDraft£2.99

Loading states

Spinner (inline only, not page-level)

Empty state

No orders yet

New orders from every channel land here in realtime. Share your shop link to start receiving orders.

Patterns

Composed pieces the products are built from.

StatCard — dashboard metrics

Delta direction is weight + glyph, not colour. Down delta uses danger text. No delta = just value.

Net sales today£2,418 12% vs last Tue
Orders184 3% vs last Tue
Avg basket£13.14

OrderCard — order queue

Ageing states: ok (muted), warn (warning colour), late (danger). Channel badge is always outline. Status badge is contextual.

#421:05
TillIn progress
  • 2× Classic burger+ cheese
  • 1× Fries
#436:12
Uber EatsNew
  • 1× Chicken wrapno mayo
#3911:48
WebIn progress
  • 3× Waffle stack

TileCard — browse grid

Unified menu/category tile across storefront, customer app, till, kiosk. Pass href for navigation (renders an <a>, crawlable, middle-clickable); pass onClick for app-like surfaces (till). Clients render what /browse returns and never branch on vendor type.

href mode (anchor, storefront/marketplace)
onClick mode (button, till right panel)

Skeleton loading pattern

Replace content regions with Skeleton while data loads. No full-page spinners. Maintain layout structure so the loaded state does not cause a visual jump.

Teaching empty states

Empty states explain what the section does and give a next action. Never blank. Never just "No items."

No orders yet

New orders from every channel land here in realtime.

No items in this category

Add items to start building this section of your menu.

Price component

Always integer pence. Always tabular numerals. Always SemiBold. Use Price pence={number} or formatPence() for text contexts. Never format money ad-hoc with string concatenation.

Small item£0.99
Meal£12.99
Basket total£47.40
Inline bodyClassic burger: £6.50