# Reviewing changes

Every build has a page that lists its snapshots next to the baseline. The check on the pull request links to it.

## The builds list

The project page lists its builds, newest first, with how far each review got and who reviewed it. Click the Build column header to put the oldest first. Filter picks which states show. By default it hides builds with no changes and expired builds, so the list shows what needs attention. Default and All at the top of the menu reset it.

A build of a pull request that was merged shows "PR merged", and one that was closed without merging shows "PR closed", in the list and on the build page. Reopening the pull request removes the label.

Click a branch or a pull request number in a row to show only its builds. Each filter shows as a chip you can clear, and Clear filters removes them all. Filters and the order are part of the address, so a filtered list can be shared.

## The build page

The page refreshes every 5 seconds while it is open, so new shards and other reviewers' approvals show up without a reload.

The snapshot list on the left groups snapshots into Changed, Added, Removed, Failed and Unchanged. The first changed snapshot opens when the page loads, and each snapshot has its own link you can share. Drag the edge of the list to resize it, and double-click the edge to reset it.

Type in the filter at the top of the snapshot list, or press `/`, to show only snapshots whose name contains the text. When a build has snapshots from more than one browser, a Browser menu under the filter shows the snapshots of one browser. The browser comes from the `browser` field in the snapshot metadata, which `snapshot` from [Playwright](https://stateofpixel.com/docs/playwright.md) writes for you. See [Metadata](https://stateofpixel.com/docs/any-screenshots.md#metadata) to send it from other tools. `j` and `k` move through the snapshots that match.

Snapshots that differ only in the brackets at the end of the name, like `Checkout/Empty [chromium 1280]` and `Checkout/Empty [firefox 375]`, are listed under one row with their name and count. Click the count, or press `h` and `l`, to fold the row up and open it again. A folded row opens the snapshot with the largest change, and `j` and `k` move past it in one step. When a build has more than one browser, rows that changed in only some of them come first, under Some browsers, with the browsers they changed in.

- **Changed**: more pixels differ from the baseline than the project ignores, each by more than the threshold, or the size changed.
- **Added**: the baseline has no snapshot with this name.
- **Removed**: the baseline has it and this build does not. Removed snapshots never need review.
- **Failed**: the upload or the diff failed on CI. A build with a failed snapshot cannot pass, so push again after fixing the cause.

## Compare

- **Side by side**: baseline left, new right, with the diff drawn over the new image. Press `d` to hide it.
- **Diff**: the new image with the changed pixels in magenta. Press `d` for Diff only, which shows the changed pixels without the image.
- **Slider**: drag a handle to wipe between the two.
- **Flip**: one frame that switches between baseline and new when you press `space`. The best mode for 1 pixel shifts.

The diff is magenta by default. While it shows, the color at the right of the toolbar changes it to green, red or blue: point at it or tab to it to see all four, or press `c` for the next one. The color stays as you move between snapshots and goes back to magenta when you reload the page.

Images show at Fit by default. Scroll or drag to pan, and pinch, or scroll with `ctrl` held, to zoom. You can also zoom with `+` and `-`, and `0` shows real pixels at 100%. Fit, or `f`, resets the view. The same buttons show in the bottom right of the images when you point at them. You can zoom out to half the size that shows the whole image. In Side by side both images pan and zoom together. When the sizes differ, both images align at the top left.

## Approve and reject

Anyone with write access to the repository on GitHub can review. See [Who can review](#who-can-review).

The dock at the bottom of the images reviews the open snapshot, and the switch in the build header reviews the whole build.

- Approve a snapshot with `a` or the check in the dock, which also moves to the next pending one. On a folded row, it approves every snapshot in it.
- Reject with `r` or the cross, which also moves to the next pending one. One rejection makes the check fail with "1 change rejected".
- Comment with `m` or the speech bubble next to the dock. A comment does not approve or reject anything. Comments are up to 500 characters, and every comment on a snapshot stays in its thread, oldest first, with who left it, so comments from several reviewers do not replace each other.
- Undo a review with `u` or the arrow in the dock.
- Approve build, or `shift` `a`, approves every pending snapshot, and Reject build, or `shift` `r`, rejects them. The middle of the switch then reads Undo, which takes the build action back without changing reviews made one by one. Picking the other side switches the build action. Once nothing is left to review, the switch shows the result: Rejected when any snapshot is rejected, Approved otherwise. Undo, or `shift` `u`, then returns every snapshot to review, including the ones reviewed one by one.

When every change is approved, the check turns green on GitHub. See [The GitHub check](https://stateofpixel.com/docs/checks.md).

## Snapshot details

Under the image, the snapshot shows what else is known about it:

- **Review**: who approved or rejected it and when, with a comment if one was left, or the build an approval carried over from.
- **Looks flaky**: shown when the snapshot changed back and forth on the default branch, or another build of the same commit has a different image. See [Find flaky snapshots](https://stateofpixel.com/docs/stable-screenshots.md#find-flaky-snapshots).
- **Mark unstable**: shown on a changed snapshot. It adds the story to the project's unstable snapshots and approves its pending changes. A snapshot already on the list says "Marked unstable" instead. See [Mark snapshots unstable](https://stateofpixel.com/docs/stable-screenshots.md#mark-snapshots-unstable).
- **History**: the recent builds on the default branch where the image changed. History opens the snapshot on the Baselines page. See [Baselines](https://stateofpixel.com/docs/baselines.md).
- **Details**: the metadata your test sent, like browser, viewport and test file.

## Who can review

Access follows the repository on GitHub, and there are no seats:

- Read access opens builds and baselines.
- Write access, including maintain and admin, approves and rejects changes. Everyone else sees "You need write access on GitHub to review".
- Write access also changes the diff settings. Admin access changes the rest of the project settings.

stateofpixel asks GitHub for your permission again when you open a project and the last check is more than 5 minutes old, so a change on GitHub applies within about 5 minutes. If that check cannot run, the last known permission is kept for up to 15 minutes. Links to images of a private project that were already shown keep working for up to 2 hours.

Roles on the account, which decide who changes the plan, are read from GitHub each time you load the site. Changing the plan always checks with GitHub first.

## New pushes

A new push on the pull request makes a new build, and the older build is marked superseded, with a link to the newest one. A superseded build cannot be reviewed, so review the newest one. Approvals carry over: if an image was approved in an earlier build of the same pull request and suite, it is approved again, and the page says who approved it and in which build. So a rebase does not ask you to review the same pixels twice.

Rejections do not carry over. A rejected image that shows up again is pending, with a note that it was rejected before.

## Keyboard shortcuts

Press `?` on the build page to see them.

| Action                                          | Keys                   |
| ----------------------------------------------- | ---------------------- |
| Next / previous snapshot                        | `j` `k`                |
| Show / hide the snapshots of a name             | `l` `h`                |
| Focus filter                                    | `/`                    |
| Close the snapshot list                         | `esc`                  |
| Show shortcuts                                  | `?`                    |
| Approve, move to next pending                   | `a`                    |
| Reject, move to next pending                    | `r`                    |
| Undo review                                     | `u`                    |
| Comments                                        | `m`                    |
| Approve build                                   | `shift` `a`            |
| Reject build                                    | `shift` `r`            |
| Undo the build review                           | `shift` `u`            |
| Side by side, Diff, Slider, Flip                | `1` `2` `3` `4`        |
| Diff overlay in Side by side, Diff only in Diff | `d`                    |
| Next diff color                                 | `c`                    |
| Toggle image in Flip mode                       | `space`                |
| Move the Slider divider by 10%                  | `shift` `left` `right` |
| Fit / 100% zoom                                 | `f` `0`                |
| Zoom in / out                                   | `+` `-`                |
| Jump to a project, account or page              | `cmd` `k`              |
| Fold the app sidebar                            | `cmd` `b`              |
