One system for the website, admin, owner portal, POS and app. It is built from the Kaki icon: an ivory tile with a gold edge, a green k and a red square. Everything here maps 1:1 to the tokens in @kaki/design-tokens and the components in @kaki/ui-web / @kaki/ui-native.
Warm paper (the current site’s off-white) or true black ground, white cards, grouped lists, glass bars. It should feel native, but still like Kaki.
The tile. Ivory face, gold edge. Seats, ranks, venue marks and primary buttons are tiles; they press down 3px like a tile on felt.
Green = act. Red = live / needs you now. Gold = only the tile’s edge. Nothing else is coloured.
Wherever a game appears, show seats and winds the way a player sees them, never “3/4 players”.
Every token has a light and dark value and every surface follows the device setting. Components only ever read tokens, never literal hex values; a lint guard enforces it.
--felt, --deep or --dragon fills..st pills.#F2F2F7 for the page. Light pages are warm paper #FBF8F1.The Archivo brand family everywhere, loaded with next/font on web and @expo-google-fonts in the apps. Kanji uses the device’s own Chinese font in bold, never a serif.
The illustration language. An ivory face with a gold bottom edge, like the icon. The White Dragon is always a blank tile: never print 白. A face-down tile shows the gold back.
Sizes
東 南 西Dragons
中 發Face-down
Locked (not yet earned)
清Medal ranks
1 2 3App icon as a tile
Buttons are tiles: a raised bottom edge that sinks 3px on press. One primary per view. Destructive actions are red with white text, the same height as the buttons beside them.
Segmented
Chips & status
18/32 pemain 1 kursi lagi Ranked Paid Arriving Checked in RefundedToggle
Time slots (½ = half price)
Grouped lists for lists, and one raised card per view for the thing that matters now. Not everything is a card.
Numbers are Archivo 800–900, tabular. Leaderboards are compact: place, name, points. Top three sit on gold, silver and bronze tiles. The viewer’s own row is tinted green.
| # | Pemain | Poin |
|---|---|---|
| 1 | DDewi | +214,6 |
| 2 | AAgus | +188,1 |
| 3 | KKamu | +142,0 |
The score tracker keeps the plus board that already works. East is on top. Winds are text labels. The corner shows the round as a big 東 over “East - 2”. Honba is in English. Player cards are raised because they are tappable.
Every table is a card headed by its number on a tile. The card’s state shows in both colour and words: live (felt), ending (red), due (gold outline), free (outlined), blocked (striped).
Small, physical and quick. Everything is readable at rest, and all motion switches off for anyone whose device is set to reduce motion.
Tiles and buttons sink 2–3px with their edge shrinking. 90ms.
Cards rise 4px on hover and tiles tip −8° with a spring. 350–450ms.
Cards rise 18px into place as they scroll in, staggered 70ms. Transform only, never hidden first.
Scores and money count up once when first seen. 1.1s ease-out.
Taking a seat or picking a slot scales 0.5 → 1.15 → 1. Spring.
Only live things pulse: the red square on an active booking, an ending table’s clock.
Rp 60.000, times in WIB, dates like “Rab, 23 Sep”.The shared components every surface uses. Web versions live in @kaki/ui-web, native versions in @kaki/ui-native; both take the same props and read the same tokens from @kaki/design-tokens.
| Component | Used by | Variants / props |
|---|---|---|
Tile | all | size xs/sm/md/lg · glyph · tone default/grn/red · haku (blank) · faceDown · locked · medal 1/2/3 |
TileButton | all | primary/ivory/danger/done · size sm/md · loading · disabled · icon |
Chip · StatusPill | all | neutral/felt/hot · paid/due/done/refunded/… |
Segmented · Tabs | all | items · value · onChange · size |
Group · Cell | all | leading (tile/avatar/icon) · title · meta · trailing (price/chevron/switch) |
Card · LiveCard | all | raised · pressable · deep panel |
Avatar · AvatarStack | all | image or monogram · you (red ring) · +N |
Sheet · Dialog · Toast | all | capped height (shrinks), destructive confirm, success toast |
EmptyState · ErrorState · Skeleton | all | title · body · action; no emoji |
TitleDot (large title with red square) | all | eyebrow · title · trailing |
SlotPicker · DayStrip | web, app, POS | slots · sold · halfPrice · :30 starts · trading night |
OpenTableCard | web, app | variants A (tile row), B (compact), C/C2/D (invite cards) |
Ticket | web, app | booking code (mono) · QR · wallet · share |
LeaderboardTable | web, app, POS, admin | compact 3-col · medal tiles · me row |
ScoreBoard · SeatCard · RoundCorner | web /game, app | plus board · East top · dealer/riichi · font-scale safe |
TableCard · BillPanel · Timeline | POS (web + native) | live/ending/due/free/blocked · QRIS/Tunai/Kartu · Jadwal rows |
KpiCard · NeedsYouList · BarChart | admin, owner | trend · sparkline · sample-safe empty |
SiteNav · SiteFooter · SideNav | web · admin/owner | ID/EN switch · grouped sections · badges |