W WOW UI Kit · v1.0.0 GMT+8 ·

Design tokens & components

Everything on this page is rendered live from assets/tokens.css and assets/components.css. Change a token there and every page using this kit follows. Desktop-first at 1280px min-width, light theme only in v1; the same tokens also cover a 360px+ mobile shell (see below).

Principles

  • Money and dates are never ambiguousOne format each, fixed GMT+8, tabular figures, right-aligned money. See Formats.
  • Status has one colourEvery status word maps to exactly one badge colour. The same colour never means two things.
  • Dense but calm13px table text, 36px controls, generous row hover, no decorative colour.
  • Action lives top-rightPage-level primary action sits in the page header; row-level actions appear on hover; destructive actions are outlined red and confirm first.
  • One primary per regionOne primary button per page region (page header, modal footer). Everything else is secondary or ghost.
  • Built for reviewAnything mocked or unresolved gets a yellow dashed .proto-note so reviewers know what to comment on.

Colour

Primary is a deep plum, quiet enough for all-day use; gold accent is reserved for highlights and trial/attention states. Semantic colours are shared between badges, alerts, stat tiles and table rows.

Primary (plum)
Neutral
Semantic & accent

Aliases used in components

--bg-app --bg-surface --bg-subtle --bg-sidebar --text-primary --text-secondary --text-muted --text-link --border-default --border-strong --border-focus --status-<name> e.g. --status-paid, --status-needs-checking, --status-signed-off

Typography

Inter for UI, JetBrains Mono for anything a human might copy: date-times in inputs, reference numbers, ID numbers. All numerals use tabular figures so columns line up.

--text-3xl 28Salary Run · August 2026page title (stat value)
--text-2xl 22Fee Runh1, page header
--text-xl 18Checking Tableh2, modal title
--text-lg 16Ballet Grade 1h3, card title
--text-base 14Fees are billed in advance; salary is paid in arrears.body
--text-sm 13Register 2026-09-15, first fee covers 2026-09-15 to 2026-10-14.tables, forms, buttons
--text-xs 12Marked by Aisyah · 2026-09-03 09:12:44meta, badges, hints
monoKL-2026-000123 · 2026-09-06 20:31:00 · 990101-14-5678identifiers, inputs

Spacing, radius, shadow

4px base. Components use 8 / 12 / 16 internally; page sections use 24 / 32. Radius: 4 inputs and tags, 6 buttons and menus, 10 cards and tables.

1 · 4
2 · 8
3 · 12
4 · 16
5 · 20
6 · 24
8 · 32
10 · 40
12 · 48
Radius & shadow
sm 4
md 6
lg 10
shadow-sm
shadow-md
shadow-lg
Layout constants
--sidebar-width 240px --topbar-height 56px --content-padding 24px --admin-min-width 1280px --mobile-min-width 360px touch target 44px

Date, time, money

These are global rules, not preferences — pick them once per app and apply everywhere. Helpers live in app.js: WOW.fmtDateTime, WOW.fmtDate, WOW.fmtTime, WOW.fmtMoney.

KindRenderedClassWhere
Date-time2026-09-06 20:31:00.datetimeAudit lines, run timestamps, approvals, history
Date2026-09-06.dateLists, From/To pickers, document dates
Time20:30.timeSchedules, slot start, bookings
MoneyRM 1,234.00.moneyRight-aligned in tables, always two decimals
Negative money(RM 50.00).money.negRefunds, reversals, deductions
Live clock[data-now]Sidebar footer, run screens
Inputs
RM

Icons

Stroke icons at 16px (18px in a sidebar, 22px in mobile tabs), injected as an SVG sprite by app.js. Use <svg class="icon"><use href="#i-name"/></svg>.

Buttons

One primary per page region. Secondary for the rest. Ghost for icon-only and table rows. Danger is outlined until the confirm step, then solid.

Sizes & icon buttons
Segmented (view switcher)

Forms

Two-column grid on desktop. Labels above inputs, hints below. Required marked with a red asterisk. Errors inline in red. Selects are native for speed.

Recorded on first contact.
Code is bound to a different product.
Mandatory on open-amount records.
Assigned on Issue.

Status badges & tags

Badges carry status and always show a dot. Tags are plain labels with no dot. Give every status word in your app exactly one badge colour — add it to tokens.css, don't reuse someone else's.

Example statuses
NewContactedTrial BookedConvertedLost
ScheduledUsedCancelledReleasedRescheduled
DraftIssuedPartially PaidPaidVoid
Variants
PaidIssuedPaidVoid
Tags & capacity
BalletPianoKuala LumpurOwner· 8 / 12 12 / 12

Stat tiles & cards

Active records
184
+6 this month
Needs checking
4
This run
Unpaid
RM3,120.00
11 issued
Paid
RM41,600.00
162 records

Customer

Member
Name
Tan Mei Ling
ID
820405-10-5566
Phone
012-345 6789
Outstanding
RM 240.00

Approval · Aug 2026

Draft
Draft 2 Confirmed 3 Signed off
2 items pendingConfirm is blocked until they're resolved.

Tables

Sticky uppercase header, 13px rows, hover reveals row actions, money right-aligned, totals in a footer. A flagged row is tinted red; a selected row is tinted brand. Toolbar sits above with search and filters; pagination below.

NameItemAmountMatchedStatus
Tan Jia YiParent: Tan Mei LingBallet Grade 2RM 120.00RM 120.00Paid
Lim Wei JunAdultPiano 1-to-1RM 320.00RM 160.00Partially paid
Chong Zi Xuanstarted 2026-09-15Ballet Grade 1RM 100.00RM 50.00 open amountNeeds checking
3 recordsRM 540.00RM 330.001 needs checking

Tabs

Used inside detail pages. Counts are optional. Click to switch below.

Enrolment list goes here.

Alerts & toasts

Alerts are inline and persistent (blockers, warnings, run summaries). Toasts are transient confirmations at bottom-right and never carry a decision.

Informational noteRe-running the same period recalculates and shows diffs; it never duplicates records.
Run complete162 records · 148 paid · 3 partially paid · 7 unpaid.
CollisionAn item falls on a holiday. Shift it to another date.
Double-bookedThis slot is already taken.

Modal & drawer

Modal for a decision that needs a reason (void, reject, flip a flag). Drawer for a record detail you peek at without leaving the list.

Empty & loading

Nothing pending

Everything older than 24 hours has been actioned.

Timeline & stepper

Timeline for follow-up logs and history. Stepper for approval state and multi-step wizards.

Follow-up log
  • Farah (Operator)2026-09-04 11:20:05Trial Booked
    Booked trial. Next action 2026-09-09.
  • System2026-09-01 20:03:55New
    Record created.
Approval
Draft Confirmed Signed off
Draft! Rejected3 Signed off

Mobile shell primitives

360px minimum width. .phone, .m-topbar, .m-body, .m-tabbar, .m-card, .m-list-item and .att-btn live in components.css alongside the desktop set — same tokens, same badges. Touch targets are 44px minimum via .touch.

Home
Kuala Lumpur · Ms A
2 items pendingOlder than 24 hours.
Ballet Grade 1
10:0011:00 · 8 students
Marked
Ballet Grade 2
11:3012:30 · 10 students
Home
Schedule
Students
Salary
Ballet Grade 2
2026-09-07 11:30
Scheduled
Tan Jia Yi
Home
Schedule
Students
Salary

Do / don't

  • Use the status badge component for every statusNever a coloured word, never a custom colour. If a new status appears, add it to tokens first.
  • Don't invent a second date/time/money formatPick one per kind for the app and use it everywhere.
  • Right-align money, left-align text, centre nothingMoney columns get .money. Totals in tfoot.
  • Don't put two primary buttons on one screen regionOne primary in the page header, one in a modal footer. Everything else is secondary or ghost.
  • Every destructive or money-changing action needs a reason fieldVoid, reject, override, refund.
  • Don't restyle a component per appIf it doesn't fit, extend tokens/components here and re-copy — don't fork with inline styles.

Using this kit in a new app

  1. Copy the whole assets/ folder (tokens.css, components.css, app.js) into the new app.
  2. Load Google Fonts Inter + JetBrains Mono, then tokens.css, then components.css in <head>.
  3. Load app.js at the end of <body> — it injects the icon sprite and wires up tabs, modals, toasts and the live clock automatically.
  4. Build screens with the classes documented on this page. Don't edit the copied files in place — see README.md for how changes flow back.