Jobs: the board card, five states on one silhouette #174

Closed
opened 2026-08-23 19:46:04 +00:00 by nalum · 0 comments
Owner

Part of the jobs flow redesign. The design handoff (design_handoff_jobs_flow, held outside the repo) is the source; the facts it depends on are repeated here so this issue stands alone.

One card shape, min-height: 280px, growing only with the user's text-scale setting so a board needs no masonry and never reflows. All cards on a board share a scale and stay level; inside a card the progress block gives up space before the title does.

  • Pips (12 sub-jobs or fewer) — equal-width pips, N of M done left, percent right.
  • Bar (13 or more) — same block, one continuous bar. Pips stop being countable.
  • Waiting on others — avatar stack capped at two faces plus a +n disc, over WAITING ON / 4 to do with Ali, Sam, Jo. The count leads the line: the names belong to sub-jobs, and a name-first line reads as co-ownership, which the data cannot express.
  • Plain — no indicator; the panel takes the space back as content, on a fallback ladder of description, then owner, then the repeat rule.
  • Up for grabs — no accent left rail, a dashed ? disc for the avatar, and the shipped Take this job / Taking... strings. This state is what keeps takeJob and the pool reachable; taking it turns the card into the plain state.

JobCard also renders the Today board, so every change lands on both. It currently draws open sub-jobs as an aria-disabled span (JobCard.tsx:133-136) — that is a deletion, not a restyle: controls are absent, never disabled and grey.

Reuse the sheet's progress block so opening a card feels like it grew rather than navigated.


Update — the late modifier, and one line that changes on every card

Late is a modifier on any of the five states, not a sixth state. It changes
one line, the due/points line between the panel and the button:

⚠ Late — was due 09:45   ·   10 points
  • The accent left rail keeps the owner's colour. Recolouring it for lateness
    gives one element two meanings, which is what makes the up-for-grabs card's
    missing rail readable.
  • Amber, not red. Red is destruction. A late job is one you can finish in ten
    seconds, so the card should look impatient rather than alarmed. The amber
    token does not exist yet — see #170.
  • Glyph, colour and word, so the state survives the Mono theme and a
    colour-blind reader.
  • Done ✓ is unchanged and still celebrates in full. Completing late claims
    the linked points in full; the product does not dock for lateness, so nothing
    on the card may imply it does.
  • The shipped red 🕐 Overdue pill is retired (app.css:1454-1460); the
    wording ladder is #179.

The merged line is a change to every card, not only the late one. Today the
due line and the worth line are two separate elements (job-deadline,
job-worth, JobCard.tsx:97-111).

Whether a card is late is derived on the device and flips on the minute — that
behaviour is #186, and this issue depends on it.


Two requirements added after #213 shipped

The job sheet went out to the family's cluster three times before it was right.
Seven visual defects, none caught by a suite: pickers that unfolded forms
instead of opening, three Save buttons on a commit-on-blur screen, (optional)
labels, a reward's name used as a field label, an unstyled add row, checkboxes
with a ghosted tick, and a create form with a browser spinner. Every one had to
be found by a person looking at a screen.

1. Screenshot goldens are part of this ticket

Record gallery (Playwright) and Roborazzi cases for every surface this ticket
builds or visibly changes, and treat them as a deliverable rather than a
follow-up. Three of #213's defects — the unstyled add row, the ghosted
checkboxes, the spinner in the create form — were pixel faults that a golden
would have caught before a deploy did.

#172 deferred its goldens on the reasoning that later tickets would re-record
them. That reasoning was sound then and is not now: the row grammar and the
pickers are settled, so an image recorded here stays valid.

Mechanics, from AGENTS.md: a new case rides in the same commit as the code
that adds it — a commit that adds a gallery or Roborazzi case without its image
is red on its own, because check / web runs npm run test:screens and
android / build runs verifyRoborazziDebug. A re-recorded existing case
goes in its own commit, so the reviewable diff stays code.

2. Check for leaked form styling before you finish

Every visual defect on #213 came from one place: the shipped app's form
fragments reused inside the new row grammar. They pass every test, because the
tests assert the pieces exist rather than that the screen reads right.

Before you call this done, grep the surfaces you touched and report what you
found and what you did about each:

  • a raw <input> / OutlinedTextField / BasicTextField outside the row and
    picker components — a form field dropped into a list of rows
  • type="number", which renders browser spinner arrows
  • btn, link-btn, btn-quiet or TextButton where a row or a quiet row
    verb belongs — underlined links reading as broken text
  • (optional) in any label — §8 names that pattern as the form admitting it
    should not have asked
  • any Save button on a surface that commits on blur, including Save changes and Save the points
  • a disabled-and-grey control where law 5 wants it absent
  • a record's title used as a field row's label — that column is for a
    field's name (Who, When, Worth), and a long title wraps in it

If your ticket is the first to land after this was written, add the check to
AGENTS.md beside the goldens rule, so it stops being a thing I remember to say.

Part of the jobs flow redesign. The design handoff (`design_handoff_jobs_flow`, held outside the repo) is the source; the facts it depends on are repeated here so this issue stands alone. One card shape, `min-height: 280px`, growing only with the user's text-scale setting so a board needs no masonry and never reflows. All cards on a board share a scale and stay level; inside a card the progress block gives up space before the title does. - **Pips** (12 sub-jobs or fewer) — equal-width pips, `N of M done` left, percent right. - **Bar** (13 or more) — same block, one continuous bar. Pips stop being countable. - **Waiting on others** — avatar stack capped at two faces plus a `+n` disc, over `WAITING ON` / `4 to do with Ali, Sam, Jo`. **The count leads the line**: the names belong to sub-jobs, and a name-first line reads as co-ownership, which the data cannot express. - **Plain** — no indicator; the panel takes the space back as content, on a fallback ladder of description, then owner, then the repeat rule. - **Up for grabs** — no accent left rail, a dashed `?` disc for the avatar, and the shipped `Take this job` / `Taking...` strings. This state is what keeps `takeJob` and the pool reachable; taking it turns the card into the plain state. `JobCard` also renders the Today board, so every change lands on both. It currently draws open sub-jobs as an `aria-disabled` span (`JobCard.tsx:133-136`) — that is a deletion, not a restyle: controls are absent, never disabled and grey. Reuse the sheet's progress block so opening a card feels like it grew rather than navigated. --- ## Update — the late modifier, and one line that changes on every card Late is a **modifier on any of the five states, not a sixth state**. It changes one line, the due/points line between the panel and the button: ``` ⚠ Late — was due 09:45 · 10 points ``` - The accent left rail keeps the owner's colour. Recolouring it for lateness gives one element two meanings, which is what makes the up-for-grabs card's missing rail readable. - Amber, not red. Red is destruction. A late job is one you can finish in ten seconds, so the card should look impatient rather than alarmed. The amber token does not exist yet — see #170. - Glyph, colour **and** word, so the state survives the Mono theme and a colour-blind reader. - `Done ✓` is unchanged and still celebrates in full. Completing late claims the linked points in full; the product does not dock for lateness, so nothing on the card may imply it does. - The shipped red `🕐 Overdue` pill is retired (`app.css:1454-1460`); the wording ladder is #179. **The merged line is a change to every card, not only the late one.** Today the due line and the worth line are two separate elements (`job-deadline`, `job-worth`, `JobCard.tsx:97-111`). Whether a card is late is derived on the device and flips on the minute — that behaviour is #186, and this issue depends on it. --- ## Two requirements added after #213 shipped The job sheet went out to the family's cluster three times before it was right. Seven visual defects, none caught by a suite: pickers that unfolded forms instead of opening, three Save buttons on a commit-on-blur screen, `(optional)` labels, a reward's name used as a field label, an unstyled add row, checkboxes with a ghosted tick, and a create form with a browser spinner. Every one had to be found by a person looking at a screen. ### 1. Screenshot goldens are part of this ticket Record gallery (Playwright) and Roborazzi cases for every surface this ticket builds or visibly changes, and treat them as a deliverable rather than a follow-up. Three of #213's defects — the unstyled add row, the ghosted checkboxes, the spinner in the create form — were pixel faults that a golden would have caught before a deploy did. `#172` deferred its goldens on the reasoning that later tickets would re-record them. That reasoning was sound then and is not now: the row grammar and the pickers are settled, so an image recorded here stays valid. Mechanics, from AGENTS.md: a **new** case rides in the same commit as the code that adds it — a commit that adds a gallery or Roborazzi case without its image is red on its own, because `check / web` runs `npm run test:screens` and `android / build` runs `verifyRoborazziDebug`. A **re-recorded existing** case goes in its own commit, so the reviewable diff stays code. ### 2. Check for leaked form styling before you finish Every visual defect on #213 came from one place: the shipped app's form fragments reused inside the new row grammar. They pass every test, because the tests assert the pieces exist rather than that the screen reads right. Before you call this done, grep the surfaces you touched and report what you found and what you did about each: - a raw `<input>` / `OutlinedTextField` / `BasicTextField` outside the row and picker components — a form field dropped into a list of rows - `type="number"`, which renders browser spinner arrows - `btn`, `link-btn`, `btn-quiet` or `TextButton` where a row or a quiet row verb belongs — underlined links reading as broken text - `(optional)` in any label — §8 names that pattern as the form admitting it should not have asked - **any Save button on a surface that commits on blur**, including `Save changes` and `Save the points` - a disabled-and-grey control where law 5 wants it absent - a record's title used as a field row's `label` — that column is for a field's name (`Who`, `When`, `Worth`), and a long title wraps in it If your ticket is the first to land after this was written, add the check to AGENTS.md beside the goldens rule, so it stops being a thing I remember to say.
nalum closed this issue 2026-08-26 18:34:06 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
eagraiclainne/app#174
No description provided.