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.
svelte-kit-vice/audit/components/time-range-picker.md

61 lines
7.0 KiB

# Audit: time-range-picker
audit-version: 1
audited-at: 2026-06-26
scope: soma + sema only; eidos dir exists → SYS-1 scope-drift (SCOPE-DRIFT → SYS-1)
method: adversarially-verified workflow (analyze → refute); HIGH/CRITICAL personally re-verified by the lead. Batch-3 ground-truth: each picker fires trigger(close) (close NOT inert), but open/commit-reset ARE inert; calendar/range-calendar are MID-REFACTOR (uncommitted view-switch work).
provider: src/uix/soma/components/time-range-picker/time-range-picker-provider.svelte.ts
## Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 2.
systemic hits: SYS-1: scope-drift (morfo scope omits eidos when eidos dir exists).
composition (A27): Composes. Trigger wraps PopoverTriggerProvider.create(). Provider wires PopoverProvider + TimeRangeFieldProvider via shared writableActive refs. Clock composes Slider parts (range/thumb/tick re-exported, not re-implemented). All per-endpoint sliders delegate to SliderProvider. Trigger + Clock + sliders via eidos wrap soma components — A27 composition pattern correct.
## Findings
### MEDIUM: SYS-1: scope-drift — time-range-picker-001 <!-- id: time-range-picker-001 -->
- dimension: A
- rule: SYS-1: scope-drift
- location: src/uix/morfo/components/time-range-picker.ts:13
- evidence: morfo declares `scope: ['soma', 'sema']` but eidos recipe directory exists at src/uix/eidos/components/time-range-picker/ with 13 component files (time-range-picker.svelte, index.ts, time-range-picker.css, etc.)
- impact: morfo scope declaration is incomplete. Consumers expecting eidos provider will not find it listed, creating discovery/contract mismatch.
- proposed-fix: Update morfo scope: `scope: ['soma', 'sema', 'eidos']`
- verify: [confirmed] CONFIRMED — SYS-1 scope-drift. morfo line 13: `scope: ['soma', 'sema'],` omits 'eidos', yet a full eidos recipe dir exists at src/uix/eidos/components/time-range-picker/ (14 files: time-range-picker.css 392 lines, .svelte parts, index.ts, types.ts, README.md). This is the known systemic SYS-1 pattern (MEDIUM). The eidos layer genuinely materializes this component (CSS targets [data-time-range-picker]*) so the scope array is incomplete. Confidence high, severity MEDIUM as baselined.
- fix-status: open
### LOW: Magic literals in CSS (gap/spacing/block-size) — time-range-picker-002 <!-- id: time-range-picker-002 -->
- dimension: E-bis
- rule: Magic literals in CSS (gap/spacing/block-size)
- location: src/uix/eidos/components/time-range-picker/time-range-picker.css:235,241,254,265,266,329,339
- evidence: Lines 235 `gap: 2px`, 241 `block-size: 0.875rem`, 254 `gap: 1px`, 265 `inline-size: 1px`, 266 `block-size: 4px`, 329 `padding: 2px`, 339 `min-inline-size: 2.25rem`. These are literal measurements, not token references.
- impact: Hardcoded values prevent consistent scaling via design tokens. Updates to spacing/sizing token system won't cascade to these edge cases.
- proposed-fix: Extract to --space-* and --radius-* tokens or --_time-range-picker-* local vars. E.g., `gap: var(--space-px)` or `gap: var(--_scale-tick-gap, 2px)` as fallback.
- verify: [downgraded] DOWNGRADED MEDIUM→LOW. Re-read the cited lines: 235 `gap: 2px` (.time-range-picker-slider), 241 `block-size: 0.875rem` (.time-range-picker-scale), 254 `gap: 1px` (.time-range-picker-scale-tick), 265 `inline-size: 1px` + 266 `block-size: 4px` (.time-range-picker-scale-mark — a hairline ruler tick mark), 329 `padding: 2px` (.day-period-toggle inner padding), 339 `min-inline-size: 2.25rem` (.day-period-item min width). These are decorative RULER geometry on plain `.time-range-picker-*` HELPER classes (not morfo data-attr selectors) — sub-pixel tick/mark dimensions that are intrinsic hairline geometry, not layout on the design-token rhythm. The 2px toggle padding and 2.25rem item width are borderline tokenizable but cosmetic and decorative-scaffold scoped. Note 0.875rem == --font-size-xs value but used as a block-size for a ruler band, not a font. MEDIUM overstates user/contract impact; this is LOW token-hygiene on ornamental ruler chrome.
- fix-status: open
### LOW: Magic literal: min-inline-size breakpoint + font-size literal — time-range-picker-003 <!-- id: time-range-picker-003 -->
- dimension: E-bis
- rule: Magic literal: min-inline-size breakpoint + font-size literal
- location: src/uix/eidos/components/time-range-picker/time-range-picker.css:197,102,152
- evidence: Line 197 `@media (max-width: 40rem)` + lines 102/152 `flex: 1 1 7rem` (field width). Line 241 `block-size: 0.875rem` (scale height). No token references.
- impact: Responsive breakpoint and sizing coupled to hardcoded values. Violates token-driven design consistency.
- proposed-fix: Use responsive size tokens or --space-* family. E.g., `--_endpoint-input-basis: var(--space-28, 7rem)`. Align breakpoints to canonical design system.
- verify: [downgraded] DOWNGRADED MEDIUM→LOW. Line 197 `@media (max-width: 40rem)` is a local responsive breakpoint collapsing the 2-col clock grid to 1-col; lines 102 `flex: 1 1 7rem` ([data-time-range-field-input]) and 152 `flex: 1 1 7rem`... (actually 102 is `flex: 1 1 7rem`, 152 is `inline-size: calc(var(--_time-field-height) - var(--space-2))` which IS token-based). The real literal is the 7rem flex-basis (endpoint input min width) and the 40rem media query. These are component-local layout tuning, not on the spacing/size token scale, and there is no canonical responsive-token primitive for arbitrary flex-basis. Same family as 002 — LOW token-hygiene, not MEDIUM. The 152 part of the cited evidence is actually correct token usage (`var(--_time-field-height) - var(--space-2)`), so the evidence is partly inaccurate.
- fix-status: open
## No-findings dimensions
C, D, F
## Theming facts (E-bis)
- magic z-index: none
- magic literals: gap: 2px | block-size: 0.875rem | gap: 1px | inline-size: 1px | block-size: 4px | padding: 2px | min-inline-size: 2.25rem | flex: 1 1 7rem | max-width: 40rem | min-inline-size: 28rem | min-inline-size: 14rem | line-height: 1 | transform: translateX(-50%) | border-radius: calc(var(--radius-md) - 2px)
- undeclared parts: none
- roles clean: true · variants clean: true
## Tests (F)
- exists: true · env: jsdom
- covers: provider part registration; placeholder resolution per endpoint; per-endpoint value writes; 12-hour cycle mapping; hour/minute/second/day-period getters/setters; readonly segments filtering; close-on-range-complete behavior
- untested: grid keyboard routes (N/A, not a grid); focus trap / dismissal; popover integration end-to-end; eidos visual composition; clock surface interactions; slider drag behavior
## Style observations (non-blocking)
- CSS structure mirrors TimePicker recipe (time-field tokens reused for field portion, popover surface tokens for clock body). Per-channel accent palette (Hour=primary, Minute=secondary, Second=neutral) is intentional design (documented in comments 279-284). Color-mix() for end-endpoint muting is elegant (line 321).
- Endpoint layout (start/end columns) via flex wrapper .time-range-picker-endpoint — no grid, clean separation.

Powered by TurnKey Linux.