You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.8 KiB
4.8 KiB
Audit: tooltip
audit-version: 1 audited-at: 2026-06-26 scope: ['soma', 'eidos', 'sema'] method: adversarially-verified workflow (analyze → refute); HIGH/CRITICAL personally re-verified against cited code by the lead. provider: src/uix/soma/components/tooltip/tooltip-provider.svelte.ts
Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 1. systemic hits: SYS-6.
Findings
MEDIUM: Test Coverage — Keyboard/Dismissal — tooltip-003
- dimension: F
- rule: Test Coverage — Keyboard/Dismissal
- location: src/uix/soma/components/tooltip/tooltip-provider.svelte.test.ts:1-322
- evidence: Test env is @vitest-environment jsdom (line 1). 4 test cases (describe lines 116-322) cover: timer delay/close/skip-delay, focus/blur/disabled state, click/Enter/Space on trigger, parts registration/linking. MISSING: Escape key close, dismissal flow, content pointer enter (which cancels close).
- impact: Keyboard routes (Enter/Space) and Escape dismissal behavior are not verified. jsdom-only environment cannot catch DOM interaction edge cases. High-risk behavior untested on the difficult path (keyboard/escape).
- proposed-fix: Add test case for onkeydown with Escape key triggering handleClose via Dismissal layer. Add test for content onpointerenter calling cancelClose(). Consider promoting at least the Escape path to a client/Playwright test to verify in real browser.
- verify: [confirmed] Confirmed. Test env is jsdom (test file line 1
// @vitest-environment jsdom). The 4itblocks (lines 122,178,218,265) cover: delay/close/skip-delay timers, focus/blur/disabled, click + Enter/Space close (lines 241-259), parts registration/aria-describedby/role linking. There is NO test exercising (a) the Escape -> Dismissal.onEscapeKeydown -> handleClose path (provider lines 456-465) or (b) content onpointerenter -> cancelClose() (provider lines 482-486), which is the hoverable-tooltip cancel-close behavior. Both are real provider behaviors on a moderate-risk path left unexercised. MEDIUM is appropriate; matches SYS-3 (interaction-heavy + jsdom-only + dismissal/cancel paths untested). - fix-status: open
LOW: E-bis MAGIC NUMBERS — tooltip-002
- dimension: E-bis
- rule: E-bis MAGIC NUMBERS
- location: src/uix/eidos/components/tooltip/tooltip.css:86
- evidence: stroke-width: 1px; in outline variant arrow selector. Recipe base.ts declares tooltip.'border-width': 'var(--border-width)' (line ~1), but CSS uses literal 1px instead of that token.
- impact: Design token inconsistency. Outline variant arrow stroke width is hardcoded; if border-width is ever updated at the design system level, outline arrow won't scale with it. Token discipline breach.
- proposed-fix: Replace 'stroke-width: 1px;' with 'stroke-width: var(--tooltip-border-width);' or confirm 1px is intentionally different from the canonical border-width scale (unlikely).
- verify: [downgraded] Confirmed the literal exists but downgraded MEDIUM->LOW. tooltip.css:86 reads
stroke-width: 1px;in the outline-variant arrow rule. The recipe DOES declare base.ts:3908'border-width': 'var(--border-width)', and the box border at tooltip.css:31 usesborder: var(--tooltip-border-width) solid .... So the 1px on the SVG arrow stroke is a real but trivial token-discipline nit on a 1px hairline that conceptually mirrors the box border (--border-widthitself resolves to 1px). No user-visible, behavioral, or theming consequence — token hygiene only. LOW, not MEDIUM. - fix-status: open
No-findings dimensions
A, B, C, D
Theming facts (E-bis)
- magic z-index: none
- magic literals: stroke-width: 1px (line 86, should use --tooltip-border-width)
- undeclared parts: data-size (content part) | data-variant (content part)
- roles clean: true · variants clean: true
Tests (F)
- exists: true · env: jsdom
- covers: timer-based open/close delay; group skip-delay coordination; focus/blur instant open/close; disabled state respect; click/Enter/Space trigger close; part registration and id linking; aria-describedby linking
- untested: Escape key dismissal; Content pointer enter (cancelClose); Dismissal onEscapeKeydown flow
Style observations (non-blocking)
- Morfo contract is clean and well-structured; trigger + content both use correct 'instant-open' state derivation
- A30 id registration pattern is correct (constructor-time assignment via opts.id)
- SafePolygon integration for hoverable content is properly configured with transitIntentTimeout
- Timer disposal in $effect root is correct
- Two-moments sequence 'pre' is correct for all three events (open/close/close-dismiss)
- Eidos recipe properly declares all component tokens including content-z, padding variants, and font-size scale
- Keyboard handling on trigger (Enter/Space to close when open) matches the pattern from baseline dropdown-menu