Files
initiative/specs/028-semantic-hover-tokens/spec.md

97 lines
7.8 KiB
Markdown

# Feature Specification: Semantic Hover Tokens
**Feature Branch**: `028-semantic-hover-tokens`
**Created**: 2026-03-10
**Status**: Draft
**Input**: User description: "Unify hover color semantics across all interactive elements and make them globally configurable via CSS custom properties in the theme."
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Theme Author Changes Hover Colors in One Place (Priority: P1)
A theme author (or future-self) wants to change the hover color for all editable fields across the app. They edit a single CSS custom property in the theme file and every editable field (name, initiative, HP, AC, conditions) updates its hover color consistently.
**Why this priority**: The entire point of this feature is centralizing hover color control. If tokens exist but aren't referenced everywhere, the feature delivers no value.
**Independent Test**: Change the neutral-interactive hover token value in the theme file and verify all editable fields reflect the new color without any other code changes.
**Acceptance Scenarios**:
1. **Given** the theme defines a neutral-interactive hover token, **When** the token value is changed from grey-to-white to any other color, **Then** all editable fields (name, initiative, HP, AC, conditions) display the new hover color.
2. **Given** the theme defines a primary-action hover token, **When** the token value is changed, **Then** the Add button and step forward/back navigation buttons display the new hover color.
3. **Given** the theme defines a destructive-action hover token, **When** the token value is changed, **Then** the clear encounter and remove combatant buttons display the new hover color.
---
### User Story 2 - Consistent Visual Language for Interaction Types (Priority: P1)
A user hovers over different interactive elements and perceives a consistent visual language: editable data fields share one hover style, primary action buttons share another, and destructive actions share a third. This replaces the current inconsistent mix where blue is used for both editable fields and navigation.
**Why this priority**: Consistent hover semantics improve usability by communicating interaction intent. This is the user-facing motivation for the feature.
**Independent Test**: Hover over each interactive element category and verify visual consistency within tiers and clear distinction between tiers.
**Acceptance Scenarios**:
1. **Given** a combatant row is displayed, **When** the user hovers over the name, initiative, HP, or AC fields, **Then** each field transitions to the neutral-interactive hover color (a subtle grey-to-white shift).
2. **Given** the top bar is displayed, **When** the user hovers over the Add button or step forward/back navigation, **Then** the element transitions to the primary-action hover color (blue).
3. **Given** the combatant row or top bar is displayed, **When** the user hovers over the remove combatant button or clear encounter button, **Then** the element transitions to the destructive-action hover color (red).
4. **Given** the condition tags on a combatant row, **When** the user hovers over a condition tag, **Then** it uses the neutral-interactive hover style, not the primary-action blue.
---
### User Story 3 - No One-Off Hover Colors Remain (Priority: P2)
A developer reviewing the codebase finds no hardcoded hover color values outside the theme file. Every hover color reference uses one of the three semantic token classes.
**Why this priority**: Eliminating one-offs (like the amber hover) ensures long-term maintainability and prevents drift back to inconsistency.
**Independent Test**: Search the codebase for hover color classes that do not reference the three semantic tokens and confirm none exist in the affected components.
**Acceptance Scenarios**:
1. **Given** the affected components (combatant-row, condition-tags, condition-picker, turn-navigation, action-bar), **When** a developer searches for hover color classes, **Then** every hover color reference resolves to one of the three semantic tokens.
2. **Given** the current amber one-off hover color, **When** the feature is complete, **Then** the amber hover is replaced with the appropriate semantic token.
---
### Edge Cases
- What happens when a component needs hover colors for both text and background? The tokens should support both text and background variants where needed (e.g., condition picker items use background hover, not text hover).
- What happens when hover colors interact with disabled states? Disabled elements should not display hover color changes regardless of token values.
- What happens when an element fits multiple tiers (e.g., clicking a condition tag both edits data and could be seen as an action)? The tier assignment is based on the primary interaction intent: editing data = neutral-interactive, triggering a distinct action = primary-action.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: The theme MUST define three semantic hover color tokens as CSS custom properties: one for neutral-interactive elements, one for primary-action elements, and one for destructive-action elements.
- **FR-002**: Neutral-interactive hover token MUST be used for all editable data fields: combatant name, initiative value, HP display, AC display, and condition tags.
- **FR-003**: Primary-action hover token MUST be used for navigation and additive action elements: Add Combatant button, step forward button, step back button, and Roll All button.
- **FR-004**: Destructive-action hover token MUST be used for removal and clearing actions: remove combatant button and clear encounter button.
- **FR-005**: Components MUST reference the semantic tokens via theme-aware classes, not hardcoded color values.
- **FR-006**: Changing a token value in the theme file MUST propagate to all components using that token without any other code changes.
- **FR-007**: The existing amber one-off hover color MUST be replaced with the appropriate semantic token.
- **FR-008**: Where components use hover background colors (e.g., condition picker items, navigation buttons), the semantic tokens MUST also provide background hover variants.
### Key Entities
- **Hover Token**: A CSS custom property defining a semantic hover color. Has a name (e.g., neutral-interactive), a text color value, and optionally a background color value.
- **Interaction Tier**: A classification of interactive elements by intent — neutral-interactive (data editing), primary-action (navigation/creation), or destructive-action (removal/clearing).
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: All hover colors across the five affected components are controlled by exactly three semantic tokens — zero hardcoded hover color values remain in those components.
- **SC-002**: Changing any single hover token value updates every element in its tier — verified by modifying each token and confirming all associated elements reflect the change.
- **SC-003**: Users perceive three distinct hover color tiers when interacting with the app — neutral editing feels understated (grey-to-white), primary actions feel prominent (blue), and destructive actions feel cautionary (red).
- **SC-004**: No visual regressions in hover behavior — all elements that had hover states before the change still have hover states after.
## Assumptions
- The three-tier system (neutral, primary, destructive) is sufficient for all current interactive elements. MVP baseline does not include additional tiers (e.g., warning, success).
- Background hover variants are needed only where components currently use background hover (condition-picker, navigation buttons). Text-only hover is the default.
- The default token values match the described colors: neutral = grey-to-white (#e2e8f0 or similar), primary = blue (#3b82f6), destructive = red (#ef4444).
- This feature is purely presentational — no domain or application layer changes are needed.