Skip to content

Draw the window's confirmations as the design system's notices, and say a failed setup there - #602

Merged
zaerl merged 3 commits into
redesign/wpdsfrom
add/toasts
Oct 3, 2026
Merged

zaerl merged 3 commits into
redesign/wpdsfrom
add/toasts

Conversation

@zaerl

@zaerl zaerl commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Why

Part of the redesign in #542, item 8 of #557: the toasts. The window's confirmations were the older component library's snackbars, restyled by hand in the page's own stylesheet, and only one of their sentences could be translated.

One thing they could not say at all: why a site failed to set up. That was shown only if the create-site dialog happened to be open when the setup failed, and lost otherwise (#600 left it for here).

What changes

The confirmations are the design system's notices, stacked in the window's bottom corner as the prototype has them: green for what worked, red for what did not, each with a Dismiss button.

What they do is what the snackbars did:

  • One for something that worked is said politely and goes by itself after six seconds.
  • One for something that did not is said at once and does not time out.
  • A repeat of the newest is not shown or said twice, and three are kept at most.

What is different:

  • Every notice has a Dismiss button. A snackbar was dismissed by pressing it anywhere. Dismissing one leaves the focus on the stack, as the snackbars' list had it.
  • The stack is a region named "Notifications", which a screen reader can go to.
  • A site that could not be set up is said there, as an error. The create-site dialog's message is its own again: which answer is missing. Its two ways in no longer differ over a message left behind, since none is.
  • The sentences can be translated. The ones a value or a branch chooses are worded in confirmations.cjs, with unit tests: what the apply flow did, a saved patch, an opened pull request, a deletion or a setup that failed.
  • Tooltips of the design system are drawn over everything. They were under the stack, so the name of a notice's button was hidden by the notice above it.

Not in this pull request, by decision: no new confirmations. The prototype raises a toast for many things the app does not confirm (a rename, a deletion, a server starting). The app says what it said before, plus the failed setup.

How to test this

Platforms: any. The change is in the renderer only.

The journeys walk the stack on both platforms. From the repository's root:

npm run build:once && npx playwright test --project=journeys toasts.spec create-site.spec i18n.spec

toasts.spec.js is new: a confirmation is shown and said once, goes at its time and not before, can be dismissed; an error is said at once, stays, and is joined by a later success without going with it; a notice's tooltip is over the notice above it. create-site.spec.js covers the failed setup, with a dialog open and with none. Each claim was checked by breaking it: 23 breaks, all red.

By hand, on the current head, on either platform:

Starting state: a site that is set up.

  1. Open the site's menu (⋮, top right) and choose Copy path.
    • A green notice "Copied the path" appears in the bottom right corner, above the footer. It goes after about six seconds.
  2. Choose Copy path again and click the notice's ✕.
    • It goes at once.
  3. Turn the network off, click Create new site, fill the dialog in and click Create site.
    • The dialog closes. When the clone fails, a red notice says "The site could not be created." and why. It is still there a minute later.
  4. While it is showing, choose Copy path again and rest the pointer on the green notice's ✕.
    • The green notice is under the red one. A "Dismiss" tooltip shows over the red notice, not behind it.
  5. Click the red notice's ✕.
    • It goes.

What must not have happened:

  • Step 3 left nothing in the sites list for the site that failed, and no dialog open.
  • The red notice did not go by itself in step 4, when the green one did.
  • A notice never stopped a click on what is beside it: the stack takes a press only where a notice is.

Risks and limitations

  • Review: two passes by a separate context. 3 to fix here on each, all fixed. The first pass caught a mistake of mine: I had set the lifetime to ten seconds, believing that was the snackbars'. It was six, and is six. Details below.
  • Checked on macOS only, at the default size and in a 1024×728 window. Windows is CI's.
  • With the site's status read slowed by a second, two journeys fail that this change does not touch: site-header.spec.js (a viewport check) and trunk-update.spec.js (an update asked for straight after a ticket is linked). Both fail the same way on redesign/wpds without this change; I checked. They pass at normal speed and have been passing on the Windows runner. The eight other files that read a toast pass slowed, 25 of 25.
  • The manual steps above were not run by a person. I looked at screenshots of one notice, of two, and of the tooltip.
  • A failed setup's notice shows the error as the main process words it ("Error invoking remote method 'wordpress:setup': Error: …"). The dialog showed the same text. It is now in a notice that stays in front of a newcomer.
  • Three newer notices push out the oldest, an error included. As before. A reducer that drops successes first would be a change of behaviour.
  • A notice raised while a dialog is open cannot be reached by keyboard until the dialog closes: the dialog keeps the focus. It is still said, and can be dismissed with the pointer, which leaves the dialog open; I ran that with the rename dialog.
  • The "Notifications" region is always there, empty when nothing is said.
  • The five sentences worded where they are raised ("Updated to the latest trunk", "This site is ready to work on", and three more) go through the translator, but no test would notice if one stopped: the unit tests reach the module's, and the pseudo-locale journey reads "Copied the path".
  • The guide's other pages still describe the redesign's earlier screens (Retake all screenshots and update guide text #561). One sentence is corrected here because this change made it false.

Related

Part of #557. Part of #542. Follows #601. Settles what #600 left about a failed setup.


Design decisions and alternatives considered
  • Six seconds, not the prototype's 3.2. The prototype's is short for a sentence, and the app's has not changed.
  • A Dismiss button on every notice. The prototype's notices have none, and its errors time out like the rest. An error that stays needs a way to go, and a success could always be sent away early.
  • The dialog no longer shows why a setup failed. Two places saying it, one of them only sometimes, is what lost it. With the notice saying it always, the dialog's line is its own and needs no owner outside it.
  • No shadow in the prototype; one here. A notice over a page of cards reads as one more card without it. It is the design system's elevation token.
  • The journeys find the stack by its label, not its role. A confirmation can be raised while a dialog is open, for something done inside it, and an open dialog hides everything else from the roles.
  • Every lookup of a toast's text goes through the stack. A notice is said through a live region elsewhere in the document, which holds the same text; a search of the whole page finds both.
Review outcome (required — see AGENTS.md)

3 [fix here] · 3 [follow-up] on the first pass, all 3 fixed. 3 [fix here] · 2 [follow-up] on the second, all 3 fixed.

  • Review: completed — a separate agent context, against .github/instructions/code-review.instructions.md; head 3297f74, base 6c7e6792026c533f8e91de7105c61ef5505d6e2b; it read the diff and the libraries' source and ran lint and the unit tests, not the journeys. Fixed:
    1. The lifetime was ten seconds, said to be the snackbars'. Theirs was six (NOTICE_TIMEOUT in @wordpress/components 41). It is six.
    2. Dismissing a notice left the focus at the top of the document. It is put on the stack.
    3. The guide said a failed setup's reason goes to the log and not to a dialog.
    • Follow-ups taken: the design system's tooltips under the stack; two steps of the journey. Not reproduced when run: dismissing a notice closing an open dialog.
  • Second pass: completed — a separate agent context; head 953f4a32e08a9b3a274a7a9979a4382d7f87b755, same base. No finding in the app's code. Fixed, all in toasts.spec.js:
    1. The check that a confirmation is still there depended on how fast the machine was. The clock is stopped under it.
    2. The check that a repeat is not shown twice could be read before a second one had appeared. It is told by what is left after one is dismissed, and by what was said by the end.
    3. The tooltip's place could be read before the tooltip had been moved to its button. It is read once it reaches the notice above.
    • Also taken: the guide's sentence said the notice stays until dismissed, which three newer ones can undo. Left: the main process's wording in the notice; in Risks.
  • Since review: 953f4a3 → ba41d4e633b8c7f8e001a5e3ef9930907302f67e: the journey and one sentence of the guide. No source under src/ changed. Not reviewed again; every suite was run on it, and eight breaks go red against the rewritten journey.

Checks on ba41d4e633b8c7f8e001a5e3ef9930907302f67e, macOS:

Check Result
npx eslint . --max-warnings=0 clean
npm test 1846 pass, 2 skipped
npm run test:electron 1847 pass, 1 skipped
npm run test:e2e 95 of 95
npm run test:e2e:packaged 15 of 15, on an unsigned build
Ten journey files in a 1024×728 window 33 of 33
Eight journey files with the status read slowed 25 of 25
Implementation notes
  • src/renderer/components/toast-stack.jsx (new): ToastStack.
  • src/renderer/confirmations.cjs: the reducer is as it was. New: toastView, TOAST_LIFETIME_MS, setupFailureMessage, applyDoneMessage, patchSavedMessage, savedAndResetMessage. The module now needs @wordpress/i18n.
  • src/renderer/index.jsx: the stack in the same portal on body; the failed setup's notice; createSiteError gone.
  • src/renderer/index.html: the snackbars' rules are gone. src/renderer/shell.css: the stack, and --wp-ui-tooltip-z-index on :root, which is where the design system reads it from.
  • tests/e2e/helpers/ui.cjs: toasts, toast. Eight journey files used getByTestId( 'snackbar' ) or a search of the whole page.
  • The toasts journey uses Playwright's clock. Stopped, it also stops the app's menus from being pressed, so it is stopped only between a notice appearing and its time being up.
Screenshots or recording

Not attached: I have no way to upload an image from here. What the screenshots I took show:

  • Two notices in the bottom right corner, above the footer, 360 pixels wide: a red one with a warning icon and four lines of bold text, and under it a green one with a tick, "Copied the path". Each has a ✕ at its right.
  • The tooltip: a small dark "Dismiss" label above the green notice's ✕, drawn over the lower edge of the red notice.

🤖 Generated with Claude Code

zaerl and others added 3 commits October 3, 2026 15:20
…ay a failed setup there

The confirmations in the window's corner are the design system's notices
(#557), stacked as the prototype has them: green for what worked, red for
what did not, each with a button that dismisses it. What they do is what
the snackbars did: one that worked is said politely and goes by itself
after ten seconds, one that did not is said at once and stays, a repeat is
not said twice, and three are kept at most. The stack is a region named
"Notifications".

A site that could not be set up is said there, as an error, until it is
dismissed. It was said only in a create-site dialog that happened to be
open, and lost otherwise. The dialog's message is its own again: which
answer is missing.

The sentences are translatable. The ones a value or a branch chooses are
worded in confirmations.cjs: what the apply flow did, a saved patch, an
opened pull request, a deletion or a setup that failed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… is dismissed

The first commit said a confirmation that worked goes after ten seconds, as
the snackbars did. They went after six. It is six again, so that nothing
about how long one is read has changed.

Dismissing a notice took its button away with the focus on it, which left
the focus at the top of the document. It is put on the stack, as the
snackbars' list had it.

A tooltip of the design system was drawn under the stack, so the name of a
notice's button was hidden by the notice above it. Tooltips are over
everything.

The toasts journey asks whether a confirmation is still there straight
after it appeared, and reads a repeat once and not until it were so. The
guide said a failed setup's reason goes to the log and not to a dialog; it
says where it is said now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…its place

The toasts journey asked whether a confirmation was still there half its
time on, with the clock running by itself as well: a slow machine's seconds
were counted with it. The clock is stopped as soon as the confirmation has
appeared, and only the test moves it: it is there two seconds short of its
time, and gone at its time. A repeat is told by there being one to dismiss
and none after, and by what was said by the end, and not by a count read as
the second one might still be on its way.

The tooltip's place is read once it reaches the notice above: it is drawn
in the window's corner first, where it is over nothing and would pass.

The guide said a failed setup's notice stays until it is dismissed. Three
newer ones push it out, so it says what is true: it does not time out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a9778be7-ba7e-47ec-8246-940523fe113f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zaerl
zaerl merged commit 4bee60f into redesign/wpds Oct 3, 2026
10 checks passed
@zaerl
zaerl deleted the add/toasts branch October 3, 2026 14:07
zaerl added a commit that referenced this pull request Oct 3, 2026
…e design system (#605)

## Why

Part of the redesign in #542, item 9 of #557: replace all hardcoded
colours with tokens. What is left is about 190 hardcoded colours and 200
inline style blocks, too much to review in one go, so it comes as a
short series. This is the first part.

What the site's page says above its cards was drawn by hand: each box
with its own colours, padding and font size written into the markup.
None of it could follow a theme, and each box was a little different
from the next.

## What changes

Everything above the cards is drawn by the design system, so that none
of its CSS is written here. Tokens put into the same inline styles would
have replaced the colours and kept the rest; components take all of it.

- **The notices are the design system's notice.** A site the old engine
made, a merge left half done, an update that did not finish, code that
is old, an update that is done, a ticket handed over by a link, a folder
that would not open. And what the ticket card says back: a refusal, a
switch under way, edits carried or saved, the question about loose
edits. Each keeps its words, its role, its buttons and what they do.
- **An update of trunk under way is a card** with the list of steps the
apply card has. That list is one component for both now, `StepList`.
- **The setup checklist is a card with a list of steps**, each with a
badge for how it stands and the button that does it. The prototype has
no checklist; it is kept and redrawn.

In `index.jsx` this takes the hardcoded colours from 100 to 23 and the
inline style blocks from 106 to 34. The 23 are the terminal, the logs
and the mail.

What looks different:

- A notice's title and what follows it are two lines, with the design
system's icon. They were one run of text.
- The checklist's rows are not tinted by state. A badge and a mark say
it.
- "Retry install & build" and the question's "Discard…" are not red. The
design system's button has no destructive tone, and the other redrawn
cards draw theirs the same way.

Not in this pull request:

- **The words.** They are as they were, and still not translatable where
they were not.
- **The rest of the series:** the terminal, logs and mail panels and the
page's leftover styles; the review dialog and its destinations, and the
discard and email dialogs; and a lint rule that keeps hardcoded colours
out of the renderer.

## How to test this

Platforms: any. The change is in the renderer only.

The journeys walk these on both platforms. From the repository's root:

```bash
npm run build:once && npx playwright test --project=journeys site-page.spec legacy-site.spec merge-in-progress.spec trunk-update.spec trunk-update-watch.spec
```

`site-page.spec.js` is new: the checklist's steps, how each stands, its
button and the way out; and the notice for old code, with its button and
the next-action cue on it. The update journeys now read the update card
as a region with a list and a current step, and dismiss the summary.
Each claim was checked by breaking it: 21 breaks, all red.

What a journey cannot judge is how it looks. By hand, on the current
head, on either platform:

**Starting state:** the app with no site.

1. Create a site and leave it alone.
- The page shows a card headed **Initial setup checklist**. A blue
notice at its top says "Setting this site up for you — step N of 3" and
has a **Stop setup** button.
- Each step is a row: a mark, its name, a badge (Completed, In progress,
Locked), a line about it, and its button. The step under way has a
spinner, and its button can be read and cannot be pressed.
2. When the setup has ended, click **Start dev server and finish the
wizard**.
   - The checklist goes and the site's cards appear.
3. Open the site's menu (⋮) and choose **Update to latest trunk**.
- A card headed **Updating to latest trunk** says "step N of 3" and
lists the steps, the current one with a spinner.
- When it ends, a green notice says "Up to date with trunk as of today."
Its **✕** sends it away.
4. Edit a file of the site by hand, then link a ticket in **Trac
ticket**.
- A yellow notice under the field asks what should happen to the edit,
with three buttons and **Cancel**.

**What must not have happened:**

- Step 1's buttons were never pressable while their step ran, and the
setup went on to the build by itself.
- Step 4 moved nothing before a button was pressed: the edit is still in
the file, and no branch was made.
- No notice's buttons sit off to one side or leave a gap at its end.

## Risks and limitations

- **Review:** two passes by a separate context. 5 to fix here on the
first, all fixed; 1 on the second, fixed. No behaviour was found lost.
Details below.
- **Checked on macOS only**, at the default size, in a 1024×728 window,
and with the site's status read slowed by a second. Windows is CI's.
- **The manual steps above were not run by a person.** I looked at
screenshots of the checklist, the question about loose edits, and the
old-engine notice.
- **A real setup was not run.** The checklist under way (the blue
notice, a step in progress, a failed step) is drawn from the same states
as before and has no journey; `tests/e2e/real-setup/create-site.spec.js`
runs one by hand and was not run.
- **Nothing is announced that was not before, and nothing less.** Every
notice is told to say nothing of its own: the ones that were alerts or
status regions still are, by their role, and the static ones were
silent.
- **The focus is lost when a notice with a focused button goes**
(Dismiss, Hide, Not now, Retry, Update), as it was before.
- **The next-action ring has a corner a little rounder than the notice
or card it is on.** Its rule is in the page's own stylesheet, which is
the next part of this series.
- **The guide calls "Skip initialization wizard" a link**; it is a
button now. That is #561.

## Related

Part of #557. Part of #542. Follows #602.

---

<details>
<summary>Design decisions and alternatives considered</summary>

- **Components, not tokens in the old styles.** The request was for as
little hard-coded CSS as possible. A notice of the design system needs
no CSS here at all; a box with token values would still carry its
padding, radius, font size and layout in the markup.
- **The checklist loses its tints.** Five states each had a background,
a border, a text colour and an indicator colour: twenty values. A badge
has the state's colour by its intent, and the mark is an icon. What is
left in CSS is the row and the mark's size.
- **The checklist's buttons are not given the design system's loading
state.** It hides a button's words behind a spinner and says "Loading"
to a screen reader. An install takes minutes, and the site it belongs to
may not be the one on screen. The buttons are held while their step
runs, as before; the step's mark spins and its badge says "In progress".
- **One step list.** The update card and the apply card show the same
thing, a plan with a current step, and were drawn twice.
- **A class on the page's notices, for now.** The page's stylesheet
gives every `button` a right margin, which the redrawn areas are each
cleared of. That rule goes with the next part, and the list of
exceptions with it.
- **A failed discard's reason is a line of text, not a notice.** It
follows a sentence inside the ticket card, where a notice inside a
sentence would be too much.

</details>

<details>
<summary>Review outcome (required — see AGENTS.md)</summary>

5 [fix here] · 1 [follow-up] on the first pass, all 5 fixed. 1 [fix
here] · 2 [follow-up] on the second, fixed, with one follow-up taken.

- **Review:** completed — a separate agent context, against
`.github/instructions/code-review.instructions.md`; head `495db32`, base
`4bee60f003b363548d4a3a697c33d6d120a6145e`; it compared each removed
block with what replaced it (conditions, handlers, refs, cue props,
roles, text) and found none lost; it ran lint and the unit tests, not
the journeys. Fixed:
1. A journey looked for "Dependencies unchanged" on the whole page,
which the terminal says too.
  2. A failed discard's reason ran on from the sentence before it.
3. The checklist's buttons said a bare "Loading" and hid their words
while a step ran.
  4. The page's notices' buttons had the page's older margin.
  5. The screenshots' crop of "Update incomplete" took the column.
  - Follow-up left: the guide's word for the skip button.
- **Second pass:** completed — a separate agent context; head `3be3413`,
same base. No defect in the fix-up. Fixed: the question about loose
edits is also drawn in the review dialog, where its buttons still had
the margin. Taken: the update journey's look for the summary is by the
summary's own sentence. Left as it is: the legacy journey's count of
alerts can be answered as the page settles and would not catch one that
came later; its comment says so now.
- **Since review:** `3be3413` →
`8c1512be3d5d2374b600a0549271fdf0b202d2d2`: that class on one notice,
one redundant prop removed, and two lines of journeys. Not reviewed
again; every suite was run on it.

Checks on `8c1512be3d5d2374b600a0549271fdf0b202d2d2`, macOS:

| Check | Result |
|---|---|
| `npx eslint . --max-warnings=0` | clean |
| `npm test` | 1847 pass, 2 skipped |
| `npm run test:electron` | 1848 pass, 1 skipped |
| `npm run test:e2e` | 97 of 97 |
| `npm run test:e2e:packaged` | 15 of 15, on an unsigned build |
| Ten journey files in a 1024×728 window | 31 of 31 |
| Nine journey files with the status read slowed | 28 of 28 |

</details>

<details>
<summary>Implementation notes</summary>

- `src/renderer/index.jsx`: the boxes are `Notice`, `Stack` and `Text`;
`UPDATE_STEP_MARKS` and `checklistVisuals` are gone; `pageNotice(id)`
gives a page-level notice its class and, where it has one, its cue.
- `src/renderer/components/step-list.jsx` (new): `StepList`, from the
apply card's `Progress`.
- `src/renderer/components/trunk-update-card.jsx`, `setup-checklist.jsx`
(new).
- `src/renderer/setup-steps.cjs`: `setupStepBadge`, with a unit test.
- `src/renderer/shell.css`: `.apply-step*` is `.step-list*`;
`.setup-step*`; `.error-text`. Every value is a token with its fallback.
- `scripts/screenshots/shots.cjs`: two crops follow the new markup.

</details>

<details>
<summary>Screenshots or recording</summary>

Not attached: I have no way to upload an image from here. What the
screenshots I took show:

- **The checklist:** a card headed "Initial setup checklist"; each step
a bordered row with a green tick, the step's name in bold with a green
"Completed" badge beside it, a grey line under it, and an outlined
button at the right ("Dependencies installed", "Build complete"); the
last step ringed as the next thing to do, with a blue "Ready" badge and
a solid blue button.
- **The question about loose edits:** a yellow notice with an icon under
the ticket field, the question, then three outlined buttons and a plain
"Cancel".
- **A site the old engine made:** a red notice with an icon at the top
of the page, a bold first line, three lines under it and a blue "Create
site" button; under the ticket field, a second red notice with the
refusal.

</details>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
zaerl added a commit that referenced this pull request Oct 5, 2026
## Why

#542 replaces the app's interface with the one in the
[prototype](https://github.com/jameskoster/wordpress-contributor-toolkit-prototype),
drawn with the WordPress Design System. It was built in slices on
`redesign/wpds`, so that trunk, which releases are cut from, never held
a half-redesigned window. The window is whole now: the shell, the page
header and details, every card and dialog, and the tray. This pull
request is how the branch reaches trunk.

It lands before the last three sub-issues, on purpose. The settings
dialog (#559) and dark mode (#560) add to a finished window and do not
need a branch to hide in, and the guide (#561) is easier to rewrite
against what is on trunk. They follow as pull requests against trunk.

## What changes

Everything `redesign/wpds` holds; this pull request adds nothing of its
own. Each slice was reviewed in its own pull request against that
branch, and says there how to test it and what it leaves out.

- **The shell** (#555): a sites list, the page area and a footer, in a
larger window. #590
- **The page header and the details** (#556): the site's menu in the
header, and what the checkout is in a sidebar that can be put away.
#594
- **The site's page** (#557): the server and the build watch in the
header and the details
(#595); the ticket
card, the apply card with a preview dialog, and the list of a site's
tickets (#596,
#597,
#599); the
create-site, rename and delete dialogs
(#600,
#601);
confirmations as notices in the window's corner
(#602); the page's
notices, update card and setup checklist
(#605); the
terminal, logs, mail and the review dialogs painted with the design
system's tokens
(#606,
#608); and lint
rules that keep it so
(#609,
#610).
- **The tray** (#558): along the bottom of the window, holding the
terminal, the logs or the mail, with a count of unseen debug.log lines
on the footer
(#612,
#613,
#614,
#615).
- Along the way:
#611 (the site
menu's update item says why it is held), and three that tidy up before
landing: #616 (a
journey's race with the page's clock),
#617 (comments the
finished redesign made untrue) and
#618 (the server's
button by its present name in `AGENTS.md`).

**What a contributor will notice first:** the terminal, the logs and the
mail are no longer on the page but behind three buttons at the foot of
the window; the terminal is dark text on light; the server and the build
watch are started from the header; a patch is previewed in a dialog
before it is applied; and what worked is said in the window's corner.

**Not in this pull request:**

- The settings dialog (#559). Until it, nothing about how the window is
arranged is remembered across restarts: the details, the tray's height,
the apply card's fold.
- Dark mode (#560). The terminal reads its colours once, when it is
made, and will need to follow the theme.
- The user guide and its screenshots (#561), which describe the old
interface. They are published from release tags, so they are not wrong
until a release ships this; #561 is next, ahead of #559 and #560, for
that reason.
- How a mail is drawn, and how the window handles a link. Both are
unchanged and tracked separately.

## How to test this

Platforms: macOS and Windows, both. Buildkite builds signed artifacts
for this pull request; use the build for its current head, and check
that it is: a push to the branch makes earlier builds stale.

The suite, from the repository root, after `npm ci`:

```
npm run lint
npm test
npm run test:e2e
```

113 journeys walk every slice on macOS and Windows on each push. What
they do not do is run a real site: a clone of `wordpress-develop`, an
install, a build and a server are stood in for. The one test that does,
`real-setup.yml`, is run by hand and was run on this branch at `548c020`
(https://github.com/WordPress/contributor-toolkit/actions/runs/37298667056):
a Core site on macOS and on Windows and a Gutenberg site on macOS were
created, installed, built and served, and passed. **The Gutenberg site
on Windows did not finish.** Its first attempt was cancelled after 74
minutes inside the journey, a minute short of the limit that would have
failed it with evidence, so it says nothing about where it was; a second
attempt was still running when this was written and its result is not in
this description. The commits since `548c020` change a journey, comments
and prose.

**A pass by hand, on a real machine** (any platform; Apple Silicon for
the server, which no test on a pull request starts for real). It follows
the order a contributor meets things in:

1. Open the app with no sites. **Create new site**, a Core site, in a
folder with a space in its path. The setup checklist runs its steps; the
terminal's button at the foot of the window shows what each is doing.
2. Let the checklist's last step start the server, and finish
WordPress's own setup in the browser. Back in the app the header says
"Server running" and "Build watching". Stop the server and start it
again: from **Server running** in the header, or with **Stop** and
**Start** beside "Server" in the details.
3. Press the three buttons at the left of the footer in turn. Terminal:
type `help`. Logs: the server's lines, the build watch's, and Debug.log.
Email: where SMTP is listening. Drag the tray's top edge.
4. Link a ticket by its number. The card shows the ticket and its pull
requests and patches.
5. Apply one of them. The preview dialog names the files; **Apply and
rebuild** runs the steps on the card.
6. Edit a file under `src/`, then **Review & submit changes**. The diff
is the edit and nothing else.
7. Create a second site, or open one from before, and move between the
two from the sites list. Each has its own terminal, logs and mail.
8. **Update to latest trunk** from the site's menu.

**What must not have happened:** work lost in a link, an apply, a switch
or an update that did not say so; `node_modules` rebuilt where nothing
changed; a failure said only in a tray that stayed closed; one site's
output in another's tray; anything on the page under the tray.

**What cannot be tested by hand, and what was not:** none of the slices'
manual steps were run by a person. I looked at screenshots and drove the
app through the journeys; everything local was on macOS, with Windows
left to CI. This pass is the first one by hand.

## Risks and limitations

- **It is one commit on trunk**, since the repository allows only squash
merges. The slices' pull requests are its record. `redesign/wpds` should
not be branched from after this: it will have diverged from trunk.
- **Reviewed in slices, not as a whole.** Twenty-two pull requests, all
but a two-word change to `AGENTS.md` reviewed by a separate reviewer
context before they were opened, most in two passes; see below. The
branch was then swept once for what falls between slices, which found
comments and one unread field
(#617) and the
three points that follow.
- **Three questions and two failures still use the system's own
dialogs**: the discards ask through its confirm box, and a path that
could not be copied and a server started before there is a build are
said in its alert. #557 meant to replace them and did so for deletions
only.
- **Some dialogs are repainted, not rebuilt.** The review dialog and its
destinations, the mail dialog and the question an update asks about
loose edits have the design system's colours and type on the old
component library's parts.
- **A real Gutenberg setup on Windows is not shown to pass on this
branch.** See "How to test this". It passed on trunk before the
redesign, in 35 minutes; here it was past 46 on its second attempt.
Whether that is the runner or the branch is not known.
- **The guide describes the old interface** until #561. Do not cut a
release before it.
- **The bundle roughly doubled**
(#590): the sites
list brings `DataViews` and what it needs. Launch time was not measured.
- **Less is always in view.** A build's output, a new line in debug.log
and a caught mail are in a tray that may be closed. A failure opens the
terminal, or the logs if nothing else is open; unseen debug.log lines
are counted on the footer; a mail that arrives shows nowhere until its
tray is opened, which was decided and is not an oversight.
- **Translation is about half done.** The shell, the cards, the tray and
most dialogs go through the translator. Roughly 200 strings in
components and hooks do not yet (the review dialog and its destinations,
the setup checklist, the logs, most of what the hooks say), nor about
150 in the modules they take sentences from. Strings that are new are in
English in the shipped translations until they are translated.
- **Focus is lost in a few places**: when the app swaps what the tray
holds from under it, when a notice with a focused button goes, when a
row's own action removes the row.
- **Some failures are still worded by the main process** ("Error
invoking remote method…"): a failed rename, a failed setup.
- **Things carried over, not made by this:** a start that throws leaves
the server's button dead until a restart; erasing typed input in the
terminal breaks once the line wraps; a line written to debug.log while
it is being attached to can be shown twice.
- **#571 and
#603 will conflict
with trunk after this**, in the mail's journey and helpers and in the
dev server's hook.
- Each slice's own list has more, and says which of its limits were
chosen.

## Related

Closes #557. Closes #558. Part of #542, which stays open for #559, #560
and #561. #555 and #556 are closed already.

---

<details>
<summary>Design decisions and alternatives considered</summary>

- **An integration branch, and one landing.** A window drawn half by the
old view and half by the new one could not be released, and the slices
were too many to hold back one by one behind a flag. Fixes and changes
with no visible effect went to trunk first and were merged across, so
this diff is the redesign and little else.
- **Landing before #559 to #561.** The plan was to land when all seven
sub-issues were in the branch. The remaining three do not change what is
there: two add to it and one documents it. Holding a finished window on
a branch for them only lengthens the time trunk and the branch can drift
apart.
- **What the prototype lacks is kept and redrawn**, and what it has
somewhere else moves to where it puts it. Its labels are adopted. Where
a slice departs from it, the slice says so.

</details>

<details>
<summary>Review outcome (required — see AGENTS.md)</summary>

**No review of the whole diff was run. The record is the slices':
twenty-two pull requests into `redesign/wpds`, each but one reviewed
before it was opened by a separate, read-only reviewer context following
`.github/instructions/code-review.instructions.md`, most in two passes
(the change, then its fix-up), with the counts and the findings in each
pull request's own review outcome. The one is
#618, two words in
a line of prose.**

- **Review:** completed, per slice —
#590,
#594 to
#602,
#605,
#606,
#608 to
#617 (no review was
run for #618);
everything marked to fix in a slice was fixed in that slice, and what
was left is in its Risks.
- **Review:** completed, for leftovers only — a separate agent context,
read-only; `redesign/wpds` at `548c020` against trunk; not a review of
correctness, which the slices had: a search for dead CSS and code,
comments that waited for a slice that has landed, what is left of the
old component library and of the system's dialogs, strings not yet
translatable, and repository docs that name the branch. Nothing found in
the stylesheet, the dependencies or the docs; thirteen comments and one
unread field, fixed in
#617; the rest is
in Risks above.
- **CodeRabbit:** not run. Its check reads "Review skipped: automatic
reviews are disabled" on this pull request and on the slices, so the
slices' pre-PR reviews are the reviews of record, each for the head it
names.
- **Since review:** nothing was added to the branch outside a reviewed
slice, apart from three merges of trunk (`da19ac6`, `3344172`,
`23d46e7`).

</details>

<details>
<summary>Implementation notes</summary>

- `git diff origin/trunk...origin/redesign/wpds`: 148 files, about
14,800 lines added and 3,000 removed; about 6,300 of the added lines are
tests.
- The site's view, which was one component of five thousand lines, is
spread over the four regions the layout has: the header, the cards, the
details and the tray. Decisions are in `src/renderer/*.cjs` with unit
tests; components draw them.
- New for the suite: journeys per region under `tests/e2e/journeys/`,
lint rules of the repository's own (`eslint-rules/`), and Stylelint over
the window's stylesheet.
- The main process changed in one place for the redesign's sake: the
debug.log tail says which lines the file already held
(#614).

</details>

<details>
<summary>Screenshots or recording</summary>

Not attached: I have no way to upload images from the command line. The
prototype shows the design; the signed build shows the app.

</details>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@zaerl zaerl added this to the v2.0.0 milestone Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant