Files
MealQuest/web/src/test/hitArea.ts
T
dev_agentandClaude Opus 5.5 d9a26b81ec
CI / ci (push) Successful in 2m32s
Independent review Codex gpt-6-sol high: CHANGES_REQUIRED (2 medium)
CI / ci (pull_request) Successful in 1m35s
Add core UI primitives in web/src/ui
Button, IconButton, Tag, Chip, TextInput, Segmented, Toggle, Checkbox,
Slider, Card and ListRow, styled with CSS Modules over the design tokens.
Every interactive primitive keeps a hit area of at least 44 px; visually
smaller controls draw their face inside a larger hit box.

Vitest now injects CSS Modules into jsdom (css: true) so tests assert the
sizes the stylesheets declare, alongside roles, aria states and keyboard
behaviour (Segmented arrow keys, Toggle Space/Enter, Chip "Remove X").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:23:42 -04:00

27 lines
1.0 KiB
TypeScript

import { expect } from 'vitest'
// Minimum tap target from the handoff's accessibility rules.
export const MIN_HIT_AREA = 44
function px(value: string): number {
return value.endsWith('px') ? Number.parseFloat(value) : 0
}
// The tap target an element's stylesheet guarantees: the larger of its
// declared size and declared minimum size, per axis. jsdom does no layout, so
// this reads the CSS Modules' computed values (Vitest runs with css: true).
// A dimension the CSS leaves unsized counts as 0 and fails the check.
export function hitArea(element: Element): { width: number; height: number } {
const style = getComputedStyle(element)
return {
width: Math.max(px(style.width), px(style.minWidth)),
height: Math.max(px(style.height), px(style.minHeight)),
}
}
export function expectMinHitArea(element: Element) {
const { width, height } = hitArea(element)
expect(width, 'hit area width').toBeGreaterThanOrEqual(MIN_HIT_AREA)
expect(height, 'hit area height').toBeGreaterThanOrEqual(MIN_HIT_AREA)
}