The invite is three questions on a card that looks like the app, and it works from the keyboard. Two things stop it: Send invite is the only blue thing in an app that acts in apricot, and it closes the card without a word, so an admin cannot tell the invitation went.
Does it work for your users?
Send invite ends in silence
/people · Invite member
Role and permissions ask the same question twice
/people · Invite member
Does it look right?
impeccable engine · reading your design system from the code
Send invite is the only blue in the app
/people · Invite member · styles.css:388
Is it solid?
The close button has no name
index.html:184
The Export menu answers the one question a person has at that toolbar, which file do I get, and it works from the keyboard. Nothing to fix.
Does it work for your users?
Sessions
nothing to fix
nothing to fix

The report toolbar with the Export menu open beside Print: CSV, rows as filtered; PDF, formatted report.
Measured
| Measure | This change | Total | Where |
|---|---|---|---|
| 0 | 0 | ||
| 0 | 0 | ||
| 0 | 0 | ||
| 0 KB | 31 KB | no images |
For agents
nothing to do
About this review
Reviewed 3 files at 2f0a9c1. 2 of 2 routes rendered at 1280 and 390 px; 2 sessions. The menu opens from its button, arrows move between the two items, Escape and Tab close it and hand focus back, a click outside closes it.
Ledgerline is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.
The invite is three questions on a card that looks like the app, and it works from the keyboard. Two things stop it: Send invite is the only blue thing in an app that acts in apricot, and it closes the card without a word, so an admin cannot tell the invitation went.
Does it work for your users?
Sessions
Sent the invite and could not tell.
nothing to fix
nothing to fix
Send invite ends in silence
/people · Invite member
The card closes and clears. No Invited row in the People table, nothing in Activity where the description says it shows up. As far as the admin can tell, the invitation did not go.
Keep the card open until the email passes, then say what happened: an Invited row, or a line in Activity.

Role and permissions ask the same question twice
/people · Invite member
The role decides what a person can do, and three checkboxes under it let the admin contradict it: a Member with the directory unchecked, a Workspace admin who cannot invite.
Drop the checkboxes. Under the role, one line saying what it allows; edit permissions on the member’s page.

Does it look right?
Send invite is the only blue in the app
/people · Invite member · styles.css:388
The button hardcodes #3b82f6. Every other primary, the Invite member trigger included, takes --accent, the apricot this app acts in — and the app has no blue anywhere else. White on that blue is 3.7:1.
Drop the colour rules and let
.btn-primary style the button.


Is it solid?
The close button has no name
index.html:184
A bare × with no aria-label: a screen reader announces “button” and nothing else.
Give it
aria-label="Close".
Measured
| Measure | This change | Total | Where |
|---|---|---|---|
| 0 | 0 | ||
| 3 | 3 | styles.css:304, :376, :383 | |
| 1 | 1 | #3b82f6 where the accent is green | |
| 1 | 1 | Send invite, 3.7:1 | |
| 1 | 1 | the close button | |
| 0 | 0 | ||
| +4 KB | 47 KB | no images |
For agents
P2 · Send invite is the only blue in the app · /people · styles.css:388 · fix: drop the colour rules; let .btn-primary style it. P1 · Send invite ends in silence · /people · modal.js:29 · fix: keep the card open until the email passes, then an Invited row or a line in Activity. P2 · Role and permissions ask the same question twice · /people · index.html:196 · fix: drop the checkboxes; one line under the role saying what it allows. P3 · The close button has no name · /people · index.html:184 · fix: aria-label="Close".
About this review
Reviewed 3 files at 8c41e0d. 2 of 2 routes rendered at 1280 and 390 px; 3 sessions. The dialog opens with focus in the email field, traps it, closes on Escape and returns focus to the button.
Crewline is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.
The page is the right shape and reads in one pass: a short form that says where each thing shows up, on the app’s own ground. Delete show wears the accent the app keeps for its primary action, and one click from it is 48 episodes gone. Two decisions go against the app: a sidebar of its own, and a section that is a heading over nothing.
Does it work for your users?
Sessions
Stuck at Connected services: nothing to connect, nothing said.
Found the setting past two rows of dead links.
nothing to fix
Delete show is one click from 48 episodes gone
/settings.html · Danger zone
One click is the whole flow: nothing between it and the deletion, and the button sits a few lines under Save changes.
A confirmation that names the show and what goes with it, with Cancel as the default.
The page invents its own navigation
/settings.html · sidebar
A sidebar of four section links while every other page navigates from the masthead, and on a phone it wraps into two rows between the heading and the first field.
Cut the sidebar and its column. The section headings already do the job.

Connected services is a heading over nothing
/settings.html · Connected services
An empty list under a heading. A host cannot tell whether they have none or the feature is not built yet — and the pull request body knows the answer.
Write the empty state: the Spotify and Apple sync is coming, nothing to do now. If that cannot be said yet, leave the section out.

Does it look right?
Delete show wears the accent, not the danger colour
/settings.html · Danger zone · styles.css:226
The same filled --accent orange as Save changes. The app declares --danger and no screen uses it, so the one destructive button on the page reads as its primary action.
Give it
--danger, outlined, and keep the filled accent for the action that is not destructive.

Is it solid?
Two field names reach no control
settings.html:49
The Category label points at an id the select does not have, and Description is a heading above a textarea with no label. Both look labelled and neither is.
Point the label at
category, and turn the Description heading into <label for="show-description">.

Spacing in the new sections is off the app’s scale
styles.css:194
28 px gaps, 18 px section padding and a 10 px rhythm where the rest of the app moves in 12, 16 and 24.
Replace the literals with the steps the stylesheet already names.
Measured
| Measure | This change | Total | Where |
|---|---|---|---|
| 0 | 0 | ||
| 9 | 9 | styles.css:194, :200, :226 … | |
| 1 | 1 | --accent on the destructive action | |
| 2 | 2 | Category, Description | |
| 0 | 0 | ||
| 0 | 0 | ||
| +11 KB | 58 KB | no images |
For agents
P2 · Delete show wears the accent, not the danger colour · /settings.html · styles.css:226 · fix: --danger, outlined. P1 · Delete show is one click from 48 episodes gone · /settings.html · settings.html:91 · fix: a confirmation that names the show, Cancel as the default. P2 · The page invents its own navigation · /settings.html · settings.html:23 · fix: cut the sidebar and its column. P2 · Connected services is a heading over nothing · /settings.html · settings.html:77 · fix: write the empty state, or leave the section out. P3 · Two field names reach no control · /settings.html · settings.html:49 · fix: label for="category"; label the description. P3 · Spacing off the app’s scale · /settings.html · styles.css:194 · fix: the named steps.
About this review
Reviewed 4 files at 5b2d91e. 3 of 3 routes rendered at 1280 and 390 px; 3 sessions.
Wavecast is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.




