UI Micro-Interactions Component Map (MI6)
This document maps StellaOps UI components to their interaction types and motion token usage. Components must use tokens from the catalog (tokens/motion.scss, motion-tokens.ts) rather than bespoke values.
Token Catalog Reference
| Token |
CSS Variable |
Duration |
Use Case |
| durationXs |
--motion-duration-xs |
80ms |
Focus rings, instant feedback |
| durationSm |
--motion-duration-sm |
140ms |
Hover states, button presses |
| durationMd |
--motion-duration-md |
200ms |
Modal open/close, panel slide |
| durationLg |
--motion-duration-lg |
260ms |
Page transitions, accordions |
| durationXl |
--motion-duration-xl |
320ms |
Complex sequences, onboarding |
| easeStandard |
--motion-ease-standard |
cubic-bezier(0.2,0,0,1) |
Default for all transitions |
| easeEntrance |
--motion-ease-entrance |
cubic-bezier(0.18,0.89,0.32,1) |
Elements appearing |
| easeExit |
--motion-ease-exit |
cubic-bezier(0.36,0,-0.56,-0.56) |
Elements leaving |
| easeBounce |
--motion-ease-bounce |
cubic-bezier(0.34,1.56,0.64,1) |
Playful feedback only |
Component Mapping
| Component |
Interaction Type |
Tokens Used |
Reduced-Motion Behavior |
| Button (primary) |
Hover lift, press scale |
durationSm, easeStandard, scaleSm |
No transform, instant state change |
| Button (secondary) |
Hover border, press |
durationXs, easeStandard |
Instant state change |
| Modal/Dialog |
Fade + slide up |
durationMd, easeEntrance/Exit, translateMd |
Instant show/hide |
| Dropdown/Menu |
Fade + scale |
durationSm, easeStandard, scaleSm |
Instant show/hide |
| Toast/Snackbar |
Slide in, auto-dismiss |
durationMd, easeEntrance, translateLg |
Instant show/hide |
| Accordion |
Height expand |
durationMd, easeStandard |
Instant toggle |
| Tabs |
Indicator slide |
durationSm, easeStandard |
Instant indicator |
| Progress bar |
Width fill |
durationMd, easeStandard |
No animation, instant fill |
| Spinner/Loader |
Rotate animation |
N/A (CSS keyframe) |
Static icon or hidden |
| Skeleton |
Shimmer pulse |
durationXl, easeStandard |
Static skeleton, no shimmer |
| Badge (status) |
Scale pop on change |
durationXs, easeBounce, scaleSm |
No scale, instant |
| Focus ring |
Fade in |
durationXs, easeStandard |
Always visible, no fade |
| Tooltip |
Fade + offset |
durationSm, easeEntrance, translateSm |
Instant show/hide |
| Banner (info) |
Slide down |
durationMd, easeEntrance, translateMd |
Instant show/hide |
| Error state |
Shake animation |
durationSm, easeStandard |
No shake, border only |
Perf Budget Compliance (MI5)
| Metric |
Budget |
Measurement |
| Interaction response |
<= 100ms |
Time to visual feedback |
| Animation frame (avg) |
<= 16ms |
Chrome DevTools Performance |
| Animation frame (p95) |
<= 50ms |
Chrome DevTools Performance |
| Layout shift |
<= 0.05 CLS |
Lighthouse CI |
| LCP placeholder |
Show within 400ms |
Lighthouse CI |
Validation Rules
- Lint rule: ESLint/Stylelint blocks non-catalog easing values in
.scss and .ts files
- Storybook check: All component stories must demonstrate reduced-motion variant
- Playwright check: Snapshot tests run with
--disable-animations and reduced-motion emulation
- CI gate: Perf budget failures block merge
TTFS Component Interactions
Per advisory §15: Component-to-interaction mapping for Time-to-First-Signal.
FirstSignalCard Component
Location: src/app/features/runs/components/first-signal-card/
| Interaction |
Trigger |
Duration |
Easing |
Token |
| Skeleton shimmer |
Initial load |
2s loop |
linear |
Custom keyframe |
| Skeleton → Content |
Signal loaded |
200ms |
easeEntrance |
durationMd |
| Badge appear |
Kind change |
140ms |
easeEntrance |
durationSm |
| Progress update |
Phase change |
140ms |
easeStandard |
durationSm |
| Button hover |
Mouse enter |
80ms |
easeStandard |
durationXs |
| Button press |
Click |
80ms |
easeExit |
durationXs |
| Error shake |
Load error |
260ms |
easeStandard |
durationLg |
Telemetry Events:
| Event |
Trigger |
Payload |
ttfs_start |
Component mount |
{ runId, surface, t } |
ttfs_signal_rendered |
Signal displayed |
{ runId, surface, cacheHit, source, kind, ttfsMs } |
ui.click.action |
Action button click |
{ runId, actionType, target } |
ui.retry |
Retry button click |
{ runId, errorCode } |
Accessibility:
| Requirement |
Implementation |
| Focus visible |
:focus-visible outline on buttons |
| Screen reader |
aria-live="polite" on content area |
| Loading state |
aria-busy="true" on card |
| Status |
role="status" on badge |
| Keyboard |
Tab navigation, Enter/Space activation |
| Reduced motion |
Disable shimmer, use instant transitions |
EvidencePanel Component
Location: src/app/features/evidence/evidence-panel.component.ts
| Interaction |
Trigger |
Duration |
Easing |
Token |
| Tab switch |
Tab click |
200ms |
easeStandard |
durationMd |
| Panel expand |
Accordion open |
260ms |
easeEntrance |
durationLg |
| Panel collapse |
Accordion close |
200ms |
easeExit |
durationMd |
| Copy success |
Copy button |
140ms |
easeEntrance |
durationSm |
| Copy tooltip |
After copy |
2s visible |
— |
— |
| Export progress |
Export start |
Indeterminate |
linear |
Spinner |
Telemetry Events:
| Event |
Trigger |
Payload |
finding_open |
Panel mount |
{ findingId, entryPoint, t } |
proof_rendered |
Proof visible |
{ findingId, proofKind, source, t } |
ui.copy.verify_command |
Copy verify cmd |
`{ type: 'cosign' |
evidence.export |
Export complete |
{ findingId, fileSize } |
ProofSpine Component
Location: src/app/features/evidence/components/proof-spine/
| Interaction |
Trigger |
Duration |
Easing |
Token |
| Hash truncation expand |
Hover/focus |
140ms |
easeStandard |
durationSm |
| Copy single |
Copy button |
80ms |
easeExit |
durationXs |
| Copy all |
Copy all button |
140ms |
easeEntrance |
durationSm |
| Status badge |
Load |
200ms |
easeEntrance |
durationMd |
TTFS Telemetry Event Catalog
Core Events
| Event |
Category |
Sampling |
Always Sample |
ttfs_start |
ttfs |
Per config |
No |
ttfs_signal_rendered |
ttfs |
Per config |
No |
ttfs_timeout |
ttfs |
— |
Yes |
ttfs_error |
ttfs |
— |
Yes |
TTE Events
| Event |
Category |
Sampling |
Always Sample |
finding_open |
tte |
Per config |
No |
proof_rendered |
tte |
Per config |
No |
UX Events
| Event |
Category |
Sampling |
Always Sample |
ux.bounce |
ui |
— |
Yes |
ux.non_bounce |
ui |
Per config |
No |
ux.open_to_action |
ui |
Per config |
No |
ui.copy.* |
ui |
Per config |
No |
ui.click.* |
ui |
Per config |
No |
evidence.export |
ui |
Per config |
No |
Sampling Configuration
| Environment |
TTFS Rate |
TTE Rate |
UI Rate |
| Development |
100% |
100% |
100% |
| Staging |
100% |
100% |
100% |
| Production |
≥25% |
50% |
25% |
TTFS State Machine
File Locations (TTFS)
| Deliverable |
Path |
| FirstSignalCard |
src/Web/StellaOps.Web/src/app/features/runs/components/first-signal-card/ |
| FirstSignalStore |
src/Web/StellaOps.Web/src/app/features/runs/stores/first-signal.store.ts |
| EvidencePanel |
src/Web/StellaOps.Web/src/app/features/evidence/evidence-panel.component.ts |
| ProofSpine |
src/Web/StellaOps.Web/src/app/features/evidence/components/proof-spine/ |
| TTFS Telemetry |
src/Web/StellaOps.Web/src/app/core/telemetry/ttfs-telemetry.service.ts |
| Sampling Config |
src/Web/StellaOps.Web/src/app/core/telemetry/telemetry-config.ts |
| i18n Keys |
src/Web/StellaOps.Web/src/assets/i18n/en.json |
| Test Fixtures |
tests/fixtures/ttfs/ttfs-fixtures.ts |
| E2E Tests |
src/Web/StellaOps.Web/tests/e2e/micro-interactions.spec.ts |
Evidence
- Token catalog:
src/Web/StellaOps.Web/src/styles/tokens/_motion.scss
- TypeScript tokens:
src/Web/StellaOps.Web/src/app/styles/motion-tokens.ts
- Storybook stories:
src/Web/StellaOps.Web/src/stories/motion-tokens.stories.ts
- TTFS Architecture:
docs/modules/telemetry/ttfs-architecture.md
- Advisory:
docs/product-advisories/14-Dec-2025 - UX and Time-to-Evidence Technical Reference.md
References
- Sprint 0338: TTFS Foundation
- Sprint 0339: First Signal API
- Sprint 0340: FirstSignalCard UI
- Sprint 0341: TTFS Enhancements