Variants
All three are 44px tall, up from 24px. Every hit is 44px tall and stops exactly at the bar's edge, so a click lands on the bar only where you see it. Icons are 20px (from 17), and labels and the count are 15px (from 13), with icons only below 640px. The variants differ in where the bar sits and what it is made of. A Fable polish pass is already applied: the menu shadow, a round end that covers the time on phones, Clear set apart, a thinner 20px X, a focus ring inside the bar, an open envelope for Mark read, and in B and C a fade-in that drops from the row.
A · Centred card
The bar sits on the gap and covers 18px of both rows.
Trade-off. It cuts the checked row's preview line and the next row's sender line in half at every width, which reads as a rendering bug.
B · Hanging card (recommended)
The bar hangs from the checked row, so that row stays fully readable. It covers exactly the next row's sender line and ends between its two lines. Same card and shadow as the menus.
Trade-off. The next row's sender is hidden while the bar shows. Its checkbox stays clickable. On dense rows the bar ends 1px above the preview text.
C · Hanging ink
B's placement on the dark surface of the undo toast. It reads most clearly as a layer above the list.
Trade-off. It becomes the loudest thing on the page. The purple checkbox and focus ring are near 2.8:1 on ink, and with an undo toast showing there are two dark slabs.
Screenshots
2x crops of the bar and its neighbour rows, Before, A, B, C from top to bottom. Click one for actual size.
1440 px, one seen row checked, seen rows around it
1440 px, three rows checked, the bar under Carla (fresh) over Rail Tickets (checked)
768 px, one seen row checked, seen rows around it
768 px, three rows checked, the bar under Carla (fresh) over Rail Tickets (checked)
390 px, one seen row checked, seen rows around it
390 px, three rows checked, the bar under Carla (fresh) over Rail Tickets (checked)
390 px, whole screen, three rows checked
Videos
Each clip: check Carla, check Rail Tickets, uncheck it, scroll down and check the last seen row, scroll up so the bar pins above the bottom edge, scroll back, Archive, then z to undo.
1440 px
390 px
Numbers
Case 1: one seen row checked, seen rows above and below. Case 3: three rows checked, the bar under a fresh row. Sizes in CSS px. Ink clear is the gap from the bar's edge to the nearest text ink outside it, read from the 2x screenshot; "covers" means a text line runs across that edge. Next row: what a click on its checkbox and on its sender line hits.
| Variant | Width, case | Bar height | Icon | Label | Count | Smallest hit | Ink clear above / below | Covers | Next row: checkbox / sender | Edge probes out · in |
|---|---|---|---|---|---|---|---|---|---|---|
| Before | 1440 px, case 1 | 24 | 17 | 13 | 13 | 44 × 24, 0 out | 5.5 / 6.0 | none | row / row | 0/4 · 4/4 |
| Before | 1440 px, case 3 | 24 | 17 | 13 | 13 | 44 × 24, 0 out | 9.5 / 9.5 | none | row / row | 0/4 · 4/4 |
| Before | 390 px, case 1 | 24 | 17 | icons only | 13 | 44 × 24, 0 out | 8.0 / 6.0 | none | row / row | 0/4 · 4/4 |
| A | 1440 px, case 1 | 44 | 20 | 15 | 15 | 44 × 44, 0 out | covers / covers | checked row's preview and next row's sender line | row / row | 0/4 · 4/4 |
| A | 1440 px, case 3 | 44 | 20 | 15 | 15 | 44 × 44, 0 out | covers / covers | checked row's preview and next row's sender line | row / row | 0/4 · 4/4 |
| A | 390 px, case 1 | 44 | 20 | icons only | 15 | 44 × 44, 0 out | covers / covers | checked row's preview and next row's sender line | row / row | 0/4 · 4/4 |
| B | 1440 px, case 1 | 44 | 20 | 15 | 15 | 44 × 44, 0 out | 12.5 / 1.0 | next row's sender line | row / bar | 0/4 · 4/4 |
| B | 1440 px, case 3 | 44 | 20 | 15 | 15 | 44 × 44, 0 out | 16.5 / 5.5 | next row's sender line | row / bar | 0/4 · 4/4 |
| B | 390 px, case 1 | 44 | 20 | icons only | 15 | 44 × 44, 0 out | 15.0 / 1.0 | next row's sender line | row / bar | 0/4 · 4/4 |
| C | 1440 px, case 1 | 44 | 20 | 15 | 15 | 44 × 44, 0 out | 12.5 / 1.0 | next row's sender line | row / bar | 0/4 · 4/4 |
| C | 1440 px, case 3 | 44 | 20 | 15 | 15 | 44 × 44, 0 out | 16.5 / 5.5 | next row's sender line | row / bar | 0/4 · 4/4 |
| C | 390 px, case 1 | 44 | 20 | icons only | 15 | 44 × 44, 0 out | 15.0 / 1.0 | next row's sender line | row / bar | 0/4 · 4/4 |
Checks
| Check | Result | Output |
|---|---|---|
vitest SelectionBar.svelte.test.ts | Passed | 6 of 6 on each branch, with the new positions (44px bar, 4px right inset). |
svelte-check | Passed | 0 errors, 0 warnings on seam-size-c. A and B only change classes and numbers. |
| Hits equal the bar (Chromium, 390 / 768 / 1440) | Passed | Every hit is 44px tall and 0px outside the bar. elementFromPoint 1px outside each edge: 0 of 4 hit the bar; 1px inside: 4 of 4. The next row's checkbox hits the row in every variant. |
| End of list with the bar pinned (Chromium, B and C) | Passed | A seen row is checked, then Previously seen is hidden, so the bar pins at the bottom. After a scroll to the end, the last row's checkbox, its actions, and the Show toggle are reachable. The list ends 144px above the window bottom, and the pinned bar starts at most 128px above it (390, above Compose). No extra end padding is needed; A has the same bar size and pin rules. |
| Safari 27 on the Mac mini, B and main | Partly | Geometry passed: hits 44 × 44, 0 of 4 edge probes outside, and the next row's checkbox is reachable. Screenshots are not verified because the automation window stops painting after a check, on main too. The fade-in there stays on its first frame, 4px off. |
Full gate (task check, task test:ci) | Not run | This is an experiment. CI runs on the PR for the pick. |