Skip to content

Commit 9b71d32

Browse files
committed
fix(conversation): give map ticks a 24px target on touch screens
The map's ticks shrink so the whole conversation fits on the rail: 14px tall at most, 6px on a long chat. That is fine for a mouse but below the 24px target WCAG 2.5.8 asks for, and hard to hit with a finger. On a coarse pointer each tick now keeps a 24px height and the rail scrolls, which already keeps the current tick in view. A mouse still gets the dense rail.
1 parent b4e2ab7 commit 9b71d32

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

‎e2e/conversation-map.spec.ts‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,34 @@ test.describe("conversation map", () => {
269269
);
270270
});
271271
});
272+
273+
const tickSizes = (page: Page) =>
274+
page.locator("[data-slot='conversation-map-tick']").evaluateAll((ticks) =>
275+
ticks.map((element) => {
276+
const box = element.getBoundingClientRect();
277+
return { width: box.width, height: box.height };
278+
}),
279+
);
280+
281+
test("with a mouse the rail fits every turn", async ({ page }) => {
282+
await open(page);
283+
expect((await railState(page)).overflows).toBe(false);
284+
});
285+
286+
test.describe("on a touch screen", () => {
287+
test.use({ hasTouch: true, isMobile: true });
288+
289+
test("every tick is a 24px target and the rail scrolls instead", async ({
290+
page,
291+
}) => {
292+
await open(page);
293+
for (const size of await tickSizes(page)) {
294+
expect(size.width).toBeGreaterThanOrEqual(24);
295+
expect(size.height).toBeGreaterThanOrEqual(24);
296+
}
297+
// The current tick, the last turn's, is scrolled into the rail's view.
298+
await expect
299+
.poll(() => railState(page))
300+
.toEqual({ overflows: true, scrolled: true, showsCurrent: true });
301+
});
302+
});

‎src/ui/conversation-map.tsx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ export function ConversationMap({
272272
aria-current={current ? "location" : undefined}
273273
aria-describedby={described ? previewTextId : undefined}
274274
tabIndex={turn.id === stopId ? 0 : -1}
275-
className="group flex min-h-1.5 w-full shrink grow-0 basis-3.5 cursor-pointer items-center rounded-sm focus-visible:-outline-offset-2"
275+
// A mouse gets the dense rail, the whole conversation at a
276+
// glance. A finger needs a 24px target (WCAG 2.5.8), so on a
277+
// touch screen each tick keeps that height and the rail scrolls.
278+
className="group flex min-h-1.5 w-full shrink grow-0 basis-3.5 cursor-pointer items-center rounded-sm focus-visible:-outline-offset-2 pointer-coarse:min-h-6 pointer-coarse:shrink-0 pointer-coarse:basis-6"
276279
onPointerEnter={(event) => {
277280
if (event.pointerType === "mouse") {
278281
show(turn.id, event.currentTarget);

0 commit comments

Comments
 (0)