Composition lab
Do these agree with each other?
The gallery shows every component on its own. This page shows them together — thirteen
banking screens built from nothing but gok-* elements and
the token layer, with no per-screen tuning. Turn on the grid, change the density, flip
the theme: if a row of five different controls stops sharing one height or one
baseline, it shows up here first.
Coverage
Elements exercised
—
Instances on the page
—
gok-* tag, rig included
Compositions
—
Seen once only
—
Presence is not proof. The first number says every element in the library is on this page next to its neighbours; it does not say each one has been seen in enough contexts to trust. The last is the honest counterweight — an element that appears once has been judged against one arrangement, at one density, in one theme. What is left there is —, and those are page-level shells: one per page is the contract, so a second instance would be a defect rather than evidence.
Atoms
Control parity
Every control reads --gok-density-control-height, so a
row of them should be one unbroken band with no per-pair tuning. A row of bare
controls centres; a form is a stack of field units — never mix the two in one flex
row.
Bare controls, one row — centred; all on the control height
Field units, one row — labels flush, controls flush, message lines flush
The trap — a button in a row of labelled fields
Wrong · button aligns to the label
Right · the label's line is reserved
Entry
Sign in
Two small surfaces side by side. A card's inset should sit within about one step of the gaps inside it — 24 around 16, not 32 around 16, or the card reads as a frame around loose parts. One primary action per card, and one only.
Secure area
Sign in
Protected by device binding.
Step 2 of 2
Verify it's you
I sent a six-digit code to the number ending 44.
Task
Identity check
A stepped task, and a second home for three controls the bench had only seen once:
the code boxes out of their card and into the flow, an upload beside a text area, and
a page header on a sparse screen rather than a dense one. The step count is a
gok-progress because the system ships no stepper — a
gap the bench is meant to expose, not paper over with a local one.
A confirmation code went to the number ending 91.
Overview
Dashboard
A stat strip repeating one column width, a full-width band for the thing that needs a measure, and a rail. Watch the eyebrows: on a screen this dense they belong on the section head and one or two announcing cards, not on every tile.
Net worth
SEK 412,900
Available
SEK 38,140
Spent this month
SEK 11,480
Savings goal
72%
Recent activity
Last seven days
-
Vattenfall Pending −874.50 -
Transfer to Savings −4,000.00 -
Northvolt AB — salary +42,180.00 -
Coop Konsum Card −612.20 -
SL Access −1,020.00
Task
Transfer
Fields in two columns are the hardest alignment case: the components are shadow
roots, so an outer subgrid can't reach their internal rows.
reserve-message is what keeps every label, control and
message line flush across columns — and what stops an error shoving the next row
down.
Data
Accounts table
A toolbar is a row of bare controls: search, a range, a filter, a view switch and a menu all land on the same control height, and the grid's sticky header picks up the same rhythm below it. Switch the density and the toolbar and the rows should move together.
July 2026
Transactions
Archive
Documents
The same grid, paged the other way. The accounts table pages itself
(paginated); an archive that pages on the server owns
the control, so gok-pagination sits in a footer row
beside the count — and it has to land on the toolbar's control height, or one band
reads as two systems. A trail, a header, a filter drawer and an upload sit around it.
Showing 25–30 of 148
Send one back — drop or browse
Filtered to nothing — the state a live archive spends real time in
No documents between January and July match “chargeback”.
Preferences
Settings
A setting row is a two-line name/description block with a control pinned to the end. The control aligns to the row's optical centre, not to the first line — and the row rhythm should survive a density change without the switch drifting off centre.
Notifications — trailing control rows
Push and email whenever money leaves an account.
Warn me when an account drops below SEK 2,000.
Product news and offers. Off by default.
How monthly statements are delivered.
Limits — a slider beside a figure
Grouped disclosure — tabs over an accordion
A code from your authenticator app is required for every transfer over SEK 10,000.
Three devices are currently signed in.
Last sign-in from Stockholm, 31 July at 08:14.
Freeze a card instantly; it can be unfrozen at any time.
Limits are shared across every card on the account.
Filter chips — a multi-select group, each its own toggle
Help
Support
The contents rail moved into the content. The same
gok-toc that runs this page's chrome, shrunk to a topic
list beside an FAQ — two carriers of the numbered register on one screen, which is
the hardest test of it. If the in-content one reads louder than the page's own, the
register is doing too much work.
A euro transfer that settles in under ten seconds, any hour of any day. Most European banks accept it; a few still don't.
The mid-market rate plus 0.4% on weekdays, 1.0% at weekends. Cash withdrawals are free up to €200 a month.
The receiving bank has to accept SEPA Instant too. When it doesn't, the payment falls back to a standard transfer and arrives the next working day.
Open the transaction and choose Dispute. You have 120 days from the charge, and the amount is held while it's reviewed.
No — move the balance first. Anything left after 30 days is transferred to your main account at that day's rate.
Nothing matched — the compact empty inside a panel
No article answers “chargeback deadline”. A person can.
Surfaces
Account cards
One repeated column width in the 20–22rem band, chosen by the grid rather than left over from the viewport. Corners nest by subtraction — a 4px inner mark inside a 12px card, never two concentric 12s.
Everyday
Main
SEK 38,140.22
SEK 1,220.00 held · SEK 39,360.22 current
•••• 7466
Goal
Savings
SEK 214,000.00
SEK 86,000 to go · on track for March
•••• 6543
Foreign currency
Euro
€6,893.93
•••• 2291
Feedback
States
Five statuses across four components. The signature has to be one shape everywhere: a neutral surface, a 2px inline-start rule, an icon and a word — never a saturated banner, never colour on its own.
Alerts
Marks
Progress
Nothing there yet
No standing orders yet.
Still loading
Layers
Overlays
Every floating surface should read as the same system as the page under it: the same hairline, the surface corner rather than a new one, and the same inset. Open two at once and the only difference should be the elevation.
- To
- Hyresbolaget AB
- IBAN
- SE45 5000 0000 0583 9825 7466
- Arrives
- 1 August, before 09:00
- Reference
- Rent August
Closing the Euro account moves the remaining €6,893.93 to Main at today's rate. This can't be undone.
Chrome
Navigation chrome
Five carriers of the editorial register — mono uppercase, hairline rows, a 2px accent marking the current thing. They're built separately, so this is where a drift in the register shows: one of them using a different label size or a different current-mark would break the voice.
Top bar
Trail, tabs, rail
142 transactions in July.
98 outgoing transactions.
44 incoming transactions.
No fees this month.