Studio's landing shape. A grid of cards that answer one question — what needs me today? — and hand off to the section that can do something about it.
Part of the Konjo design language. The laws in the spine apply here unless this chapter contradicts them. Studio-specific — see the dialect and Studio metrics.
This chapter exists because a completeness test specified Studio's Home screen and found the whole shape described in twenty words — "snapshot cards with a title, a few key numbers/rows, and a '→' link to the full section" — next to a table chapter of 158 lines and a form chapter of 323. The agent invented a grid, a gutter, a span rule, a panel radius, a card-row anatomy, an internal spacing scale, a card-height rule, an ordering rule and a state model, and every one of those inventions was a place two engineers would have chosen differently.
When a dashboard
- The person is triaging, not browsing — they came to find out what changed, not to look something up.
- The answer is spread across unrelated domains (money, attendance, testing, people) and no single list holds it.
- Every region has a real home elsewhere, and this screen is the doorway, not the desk.
If one domain dominates, that is a table or an index with filters, not a dashboard. A dashboard whose cards are all attendance is the attendance screen, wearing six boxes.
Anatomy
HOME eyebrow, text.secondary
Blue Heron Martial Arts display 34/800 — the DOJO, not the screen name
Saturday, Aug 23 body 15/400, text.secondary
( Blue Heron ) ( Riverside ) dojo chips, only when there is more than one
↕24
┌── the alert slot — at most one, and usually empty ──────────────────────┐
│ Adult Intermediate at 7:15pm has no instructor. Assign a sub → │
└─────────────────────────────────────────────────────────────────────────┘
↕24
┌ Today ─────────────── span 2 ─┐ ┌ Needs attention ─────┐
│ Today 4 classes│ │ Needs attention 7 │ title 22/700 ⟷ caption
│ ↕12 │ │ │
│ Kids Beginner │ │ Ana Torres │ rowTitle 16/600
│ 6:00pm · Marcus Webb │ │ ( Waiver missing ) │ caption / pills
│ · 8 booked │ │ │
│ ↕12 │ │ │
│ Adult Intermediate ( No sub )│ │ … │
│ 7:15pm · Unassigned │ │ │
│ · 12 booked │ │ │
│ ↕16 │ │ ↕16 │
│ Open the schedule → │ │ Open the risk queue → │ label 13/700, pinned to the floor
└───────────────────────────────┘ └───────────────────────┘
↕24
┌ Growth ──────┐ ┌ Testing ─────┐ ┌ Birthdays ───┐
└──────────────┘ └──────────────┘ └──────────────┘
↕24
┌ Money ─────────────── span 2 ─┐
└───────────────────────────────┘
The screen inventory puts six cards on Home — Money, Today, Needs attention, Growth, Testing, Birthdays — and Money is the one blocked on a product fact (refund and revoke semantics), not on a design one. The sketch shows six so nobody builds five and calls it done.
The grid
| Value | |
|---|---|
| Columns | 3 at ≥1280. Not 4 — a 4-column card at Studio's widths holds a title and two rows before it lies about how much fits |
| Gutter | spacing.s24, both axes — the same value as panel→panel in metrics, because that is what it is |
| Column width | equal, minmax(0, 1fr). Never content-driven: a grid whose columns resize as the data changes cannot be learned |
| Span | a card may span 2; never 3, which is a section, not a card |
| Row alignment | align-items: stretch — cards in a row are the same height, and the footer link pins to the floor with margin-top: auto |
| Card count | 3 to 6. Fewer is a detail screen; more is a screen with no opinion |
One card may span 2, and it is the one with the most fields per row. A row carrying four facts (name, time, person, count) needs the width; a row carrying two does not. If two cards both want the span, one of them has too many columns and belongs in a table.
Card order is fixed and never reorders by urgency
The card an owner needs is in the same place every morning. This is the same law as stable column widths and for the same reason: a layout that changes shape with its data cannot be learned, and a dashboard is looked at every day by the same person.
Urgency is expressed by the alert slot and by pill tone inside a card — never by moving a card, resizing one, or colouring its whole surface.
The alert slot — how a dashboard spends its budgets
This is the part of the shape that no other pattern has, and the part most likely to be got wrong.
Every other screen in Konjo has a fixed subject, so the four budgets can be spent at design time: the designer decides which thing is loud, and it is the same thing on every render. A dashboard's most important fact changes daily — on Tuesday an uncovered class, on Wednesday three unsigned waivers, on Thursday nothing at all — and loudness in this system is a property of a component, not of a fact.
So the emphasis is allocated to a slot, not to a card:
- One alert slot, directly under the page header, above the grid, full content width, in flow — never floating, never a toast. See notifications.
- At most one alert renders, ever. Two urgent things is one alert plus a pill.
- It renders only when a stated bar is met. What clears the bar is a product fact, not a design judgement — "which costs the dojo more, an uncovered class or an unsigned waiver" is a business answer. If the bar for a surface is not written down, the slot renders only for facts whose urgency is unambiguous, and you name the missing bar rather than inventing a ranking.
- On a quiet morning the slot is empty and the page has no loud element. That is correct. The skill's closing bar — if you cannot point at the one loud thing within a second, it isn't finished — is asked of a screen with a fixed subject. Here, the absence of an alert is the answer to the screen's question, and it is a good answer. Never manufacture urgency to fill the slot: no "all clear" banner, no green celebration, no card promoted to loud because nothing else was.
| Fill | feedback.errorFill, or feedback.warningFill if the bar it cleared is a warning-tone fact |
| Border | 1px matching feedback.*Border — a fill alone is ~1.02:1 on the page and reads as a different background |
| Text | caption 13/400 in the matching feedback.*Text |
| Radius | radius.card 12 |
| Padding | spacing.s16 |
| Action | exactly one, a text link — label 13/700 in text.primary, min-height controlHeight.chip 32 |
The alert does not spend the red role. feedback.errorText reports a fact; brand.red
invites an action. See what a status means. A dashboard
normally spends zero of the red role, zero loud blocks and zero filled primaries, and
one uppercase register on the eyebrow. Zero is not a failure on this shape.
The card
| Token | |
|---|---|
| Surface | surface.card on surface.page. Tone separates it; see tables |
| Radius | radius.card 12 — a Studio panel is a card, not a radius.large feature block |
| Border | none required. A hairline is an optical edge, never the separator |
| Shadow, gradient | never |
| Padding | spacing.s16 |
| Title | typography.title 22/700, text.primary |
| Status line, beside the title | caption 13/400, text.secondary, right-aligned. Usually a count — "4 classes", both plural forms written out, the unit on every row that carries one. It may instead be the card's one framing fact where a count is not the answer: "Next test Sep 14". One or the other, never both |
| Title → first row | spacing.s12 |
| Row → row | spacing.s12 |
| Last row → footer link | spacing.s16 |
| Footer link | label 13/700, text.primary, min-height controlHeight.chip 32, pinned with margin-top: auto |
| Arrow | → typed, or iconSize.inline 16 — one or the other on a screen, not both |
The card is not a link. Its rows and its footer link navigate; the card body does not. Otherwise the same destination is reachable twice in one viewport and a keyboard user tabs through a card-sized target with no name.
Three cards, three shapes, and no fourth:
A row card
Rows of records. Subject rowTitle 16/600 text.primary; supporting line caption 13/400
text.secondary; min-height controlHeight.chip 32.
- Five rows maximum, then the footer link. A card is a sample, not a list.
- At five or fewer, no hairlines — 12pt of space groups them, per L3. Above five you are building a table in a box; move it.
- The subject leads. Never invert to put a time or a date first — an inverted row is anti-pattern #12.
- One status pill per row, right-aligned. More than one and the row has become a table row. Where a record genuinely has several reasons, show the highest tone and enumerate all of them in the accessible name.
- Row actions are text links,
label13/700, never buttons. Five bordered buttons down a card is five controls of equal weight competing with the footer link.
A stat card
Label, value, hint. See charts for when a number should be a chart instead.
- Label:
eyebrow,text.secondary. - Value:
typography.metric28/800,text.primary. Neverhero— that is a loud block, counted per instance. - Hint:
caption13/400. The comparison lives here ("+12 vs last month"), and its sign is the only place afeedback.*tone is legal on a stat card. - At most three stats in one card. Four is a table.
A mixed card
One stat on top, up to three rows under it. Used when the number needs naming — "6 test-ready" over the three students closest to it. The stat and the rows must be the same fact; a number over unrelated rows is two cards pretending to be one.
States
Each card loads, empties, and fails independently. A dashboard assembles from unrelated queries, and one slow endpoint must not hold the other five.
Loading
- Under 1s, nothing. See states.
- Then, per card: the frame renders immediately — title and footer link — and the body is
Skeleton.Textat the line height of the token it stands in for. No pulse, no shimmer. This is the same rule as a table's header rendering before its rows. - A dashboard is the daily landing screen, so it always qualifies for skeletons: the person has seen this layout before by definition.
- Skeletons are hidden from assistive tech; completion is announced once, politely, for the page — not six times, once per card.
Empty — nothing today
One line of body 15/400 in text.secondary, left-aligned, in flow. No action, no
illustration, never centred in a void.
No classes today. · Nobody needs attention today. · No birthdays in the next 30 days.
The card still renders. (Shape-local. It overrides the detail-screen rule deliberately.) states says a section with nothing to say does not render, and that rule is written for a detail screen, whose sections vary by record. A dashboard's grid is fixed, and a card that disappears on a quiet day changes the page's shape every morning — which is the thing card order is fixed exists to prevent. On this shape, "nothing today" is an answer worth printing.
Not yet set up — the third state
Empty means nothing happened. Not-yet-set-up means this was never switched on, and reporting the first when the second is true is the design lying to the owner. A dashboard is where the difference shows, because a new dojo's Home is mostly unconfigured.
One line of body 15/400, plus one text link — this is the actionable-emptiness exception:
Lead capture isn't turned on. ·
Set up your public page →
Tell them what is off and where the switch is. Never dress it as data ("0 leads"), and never as an error.
Error — one card fails
The card keeps its title and footer link and replaces its body:
feedback.errorFill, 1pxfeedback.errorBorder,radius.card12,spacing.s16padding.- One line of
captioninfeedback.errorText. No codes, no raw messages. - Retry is a bordered secondary,
controlHeight.dense36 — a state's action inherits the weight of what it replaced, and what it replaced was a list, not a primary action. - Every other card keeps rendering.
Error — the page fails
Nothing else is on screen, so the retry is the filled primary: eyebrow, title 22/700,
one body line, one filled button at controlHeight.primary 48.
Responsive
Studio's stated range is 1280–1440, and a laptop outside it is not a reason to invent a phone layout.
| Viewport | Behaviour |
|---|---|
| ≥ 1440 | 3 columns; they grow, there is no max width |
| 1280–1439 | 3 columns |
| 1024–1279 | 2 columns; the spanning card spans both |
| < 1024 | 1 column; the rail collapses to icons with aria-labels and the cards keep their order |
The page never scrolls horizontally. A card that cannot fit its content at 1024 has too many columns in its rows.
Accessibility
The web contract in accessibility covers the general rules; these are the ones this shape needs.
- Each card is a
<section>with anaria-labelledbypointing at its<h2>, so a screen reader can list the regions and jump between them. The count line is the section'saria-describedby. <h1>is the page title,<h2>is every card title. Do not skip to<h3>because a card looks smaller than a page.- The alert slot is not
role="alert". It is present at page load, so nothing changed —role="alert"would interrupt the screen reader every single morning. It is a labelled<section>like the cards.role="alert"is for something that appears after an action. - A row action names its row:
aria-label="Assign a sub for Adult Intermediate at 7:15pm", never bare "Assign". - A row with several status reasons enumerates all of them in its accessible name, even when only the highest tone is drawn.
- Rows are separate tab stops on the web. Mobile's "group a row into one stop" is a VoiceOver rotor idiom; on the web a row with a link, a pill and a second link is correctly two stops, and collapsing it into one hides the second action from a keyboard.
- A skip link is mandatory on every Studio screen: the rail is ~25 links and comes before the content in DOM order on every page.
- Every pill carries its word — status is never colour alone.
The self-check
- Can the owner name the one thing that needs them, in under a second, on a busy morning?
- On a quiet morning, does the page say so plainly rather than performing calm?
- Is every card in the same place it was yesterday?
- Does every card end in a doorway — a link to the place the work actually happens?
- Is any card doing a table's job? Move it.