Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c42fb0e
docs(specs): specify component refactor
remarkablemark Feb 15, 2026
18378d2
docs(specs): clarify project structure
remarkablemark Feb 15, 2026
c4df6ef
docs(specs): clarify reusable components
remarkablemark Feb 15, 2026
f3dcef9
docs(specs): create plan
remarkablemark Feb 15, 2026
88f3114
docs(windsurf): update agent context
remarkablemark Feb 15, 2026
be7f5ac
docs(specs): correct test in plan
remarkablemark Feb 15, 2026
42c99f1
docs(specs): generate tasks
remarkablemark Feb 15, 2026
1b7b2c1
docs(specs): correct path conventions in tasks
remarkablemark Feb 15, 2026
a2cea76
docs(specs): analyze and remediate critical issues
remarkablemark Feb 15, 2026
6c06b08
docs(AGENTS): ask before editing dot files
remarkablemark Feb 15, 2026
b0b0b91
chore(components): create Button and complete phase 1 and 2
remarkablemark Feb 15, 2026
9654911
refactor(components): integrate TextInput in App
remarkablemark Feb 15, 2026
06e38fb
test(components): get coverage to 100%
remarkablemark Feb 15, 2026
f9e601f
refactor(components): modularize ReadingDisplay from App
remarkablemark Feb 15, 2026
b4bcf3b
docs(specs): mark ReadingDisplay tasks as complete
remarkablemark Feb 15, 2026
56a91f3
refactor(components): modularize more components from App
remarkablemark Feb 15, 2026
fb93d79
test(App): remove dead code and get coverage to 100%
remarkablemark Feb 15, 2026
4ce7ad8
refactor(components): remove duplicate and unused code
remarkablemark Feb 15, 2026
dcd7367
fix(components): improve copy in SessionDetails
remarkablemark Feb 15, 2026
f77e180
docs(specs): update specs and mark all tasks as complete
remarkablemark Feb 15, 2026
d41787d
fix(components): remove keyboard shortcuts
remarkablemark Feb 15, 2026
d567df9
fix(ControlPanel): fix Pause/Resume button losing focus on space key
remarkablemark Feb 15, 2026
107f1bd
fix(ControlPanel): don't cut off button outline
remarkablemark Feb 15, 2026
d76b50b
feat(components): add button icon and improve copy
remarkablemark Feb 15, 2026
af787d6
docs(specs): update copy
remarkablemark Feb 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .windsurf/rules/specify-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Auto-generated from all feature plans. Last updated: 2026-02-14

## Active Technologies

- TypeScript 5 (strict mode) with React 19 + React 19, Vite 7, Vitest 4, Tailwind CSS 4 (001-component-refactor)
- N/A (client-side state management) (001-component-refactor)

- TypeScript 5 (strict) with React 19 + React 19, React DOM 19, Vite 7, Tailwind CSS 4 (001-speed-reading-app)

## Project Structure
Expand All @@ -24,6 +27,8 @@ TypeScript 5 (strict) with React 19: Follow standard conventions

## Recent Changes

- 001-component-refactor: Added TypeScript 5 (strict mode) with React 19 + React 19, Vite 7, Vitest 4, Tailwind CSS 4

- 001-speed-reading-app: Added TypeScript 5 (strict) with React 19 + React 19, React DOM 19, Vite 7, Tailwind CSS 4

<!-- MANUAL ADDITIONS START -->
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ src/components/ComponentName/
## Boundaries

- ✅ **Always:** Write to `src/`; run lint, type check, and tests before commits; follow naming conventions
- ⚠️ **Ask first:** Adding dependencies, modifying CI/CD config, changing build configuration
- ⚠️ **Ask first:** Adding dependencies, modifying CI/CD config, changing build configuration, editing dot files
- 🚫 **Never:** Commit secrets or API keys, edit `node_modules/`, disable ESLint rules, commit with failing tests

## Development Notes
Expand Down
97 changes: 97 additions & 0 deletions specs/001-component-refactor/checklists/accessibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Accessibility Checklist: Component Refactoring

**Purpose**: Verify accessibility compliance across all extracted components
**Created**: 2026-02-14
**Feature**: [Component Refactoring](./spec.md)

## Keyboard Navigation

- [x] All interactive elements are keyboard accessible
- [x] Tab order follows logical visual sequence
- [x] Focus indicators are visible and meet contrast requirements
- [x] No keyboard traps - all elements can be navigated away from

## Screen Reader Support

- [x] All buttons have proper aria-labels or accessible text
- [x] Form elements have associated labels and descriptions
- [x] Dynamic content updates use aria-live regions appropriately
- [x] Semantic HTML elements are used correctly (button, input, etc.)

## ARIA Attributes

- [x] aria-live="polite" and aria-atomic="true" for reading display
- [x] role="status" for current word display
- [x] Proper aria-labels for speed slider and controls
- [x] aria-expanded for collapsible session details
- [x] aria-disabled for disabled buttons

## Color Contrast

- [x] Text meets WCAG AA contrast ratios (4.5:1 normal, 3:1 large)
- [x] Interactive elements have sufficient contrast in all states
- [x] Focus indicators meet contrast requirements
- [x] Error messages are distinguishable from normal text

## Responsive Design

- [x] All components work on mobile breakpoints (max-[480px])
- [x] Touch targets meet minimum size requirements (44px)
- [x] Text remains readable at smaller sizes
- [x] No horizontal scroll on mobile devices

## Component-Specific Checks

### Button Component

- [x] Primary and secondary variants have distinct visual states
- [x] Disabled state is properly communicated
- [x] Focus styles are consistent across variants
- [x] Responsive sizing works on mobile

### TextInput Component

- [x] Textarea has proper label association
- [x] Validation errors are announced to screen readers
- [x] Form submission prevention works with keyboard
- [x] Placeholder text does not replace label

### ReadingDisplay Component

- [x] Current word is properly announced
- [x] Large text remains readable on mobile
- [x] Focus management is appropriate
- [x] Empty state is handled gracefully

### ControlPanel Component

- [x] Speed slider has accessible labels
- [x] Button state changes are announced
- [x] Grouping of controls is logical
- [x] Mobile touch targets are adequate

### SessionDetails Component

- [x] Collapsible details are keyboard accessible
- [x] Summary text is descriptive
- [x] Progress information is clearly communicated
- [x] Expand/collapse state is announced

### SessionCompletion Component

- [x] Success message is properly announced
- [x] Completion status is semantically correct
- [x] Visual styling doesn't interfere with readability

## Testing Requirements

- [x] Manual keyboard navigation testing completed
- [x] Screen reader testing completed (VoiceOver/NVDA/JAWS)
- [x] Automated accessibility testing completed
- [x] Mobile accessibility testing completed

## Notes

- All components must maintain existing accessibility features
- New components should improve upon current accessibility where possible
- Test with actual assistive technology, not just automated tools
36 changes: 36 additions & 0 deletions specs/001-component-refactor/checklists/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Specification Quality Checklist: Component Refactoring

**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-02-14
**Feature**: [Component Refactoring](./spec.md)

## Content Quality

- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed

## Requirement Completeness

- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified

## Feature Readiness

- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification

## Notes

- Specification is complete and ready for planning phase
- All components are clearly defined with their responsibilities
- Success criteria are measurable and technology-agnostic
151 changes: 151 additions & 0 deletions specs/001-component-refactor/contracts/component-interfaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Component Interface Contracts

**Date**: 2026-02-14
**Purpose**: Define component prop interfaces for extracted components

## Button Component Contract

```typescript
interface ButtonProps {
variant: 'primary' | 'secondary';
children: React.ReactNode;
disabled?: boolean;
onClick?: () => void;
type?: 'button' | 'submit';
className?: string;
}
```

**Behavior Contract**:

- Primary variant renders with sky-600 background and white text
- Secondary variant renders with slate-300 border and white background
- Disabled state applies opacity-50 and cursor-not-allowed styles
- Responsive design reduces padding and text size on mobile (max-[480px])
- All variants maintain focus-visible outline with sky-500 color

## TextInput Component Contract

```typescript
interface TextInputProps {
value: string;
onChange: (value: string) => void;
onSubmit: (text: string) => void;
isValid: boolean;
disabled?: boolean;
}
```

**Behavior Contract**:

- Renders textarea with 10 rows and minimum height of 56 (14rem)
- Displays validation message when isValid is false
- Calls onChange callback on each input change
- Calls onSubmit callback when form is submitted with valid input
- Prevents form submission when input is invalid
- Applies focus styles with sky-500 border and ring

## ReadingDisplay Component Contract

```typescript
interface ReadingDisplayProps {
currentWord: string;
hasWords: boolean;
}
```

**Behavior Contract**:

- Renders current word with 48px font size (3rem) on desktop
- Responsive design reduces to 32px (2rem) on mobile (max-[480px])
- Minimum height of 160px (10rem) on desktop, 136px (8.5rem) on mobile
- Applies aria-live="polite" and aria-atomic="true" for screen readers
- Uses role="status" for proper semantic meaning
- Applies tracking-wide and font-semibold for readability

## ControlPanel Component Contract

```typescript
interface ControlPanelProps {
selectedWpm: number;
onSpeedChange: (wpm: number) => void;
onStartReading: () => void;
onPauseReading: () => void;
onResumeReading: () => void;
onRestartReading: () => void;
onEditText: () => void;
isInputValid: boolean;
status: ReadingSessionStatus;
}
```

**Behavior Contract**:

- Renders speed slider with min/max values from readerConfig
- Calls onSpeedChange when slider value changes
- Conditionally renders action buttons based on status:
- idle: Read button (primary)
- running: Pause button (secondary) + Restart + Edit Text
- paused: Play button (primary) + Restart + Edit Text
- completed: Restart + Edit Text
- Read button disabled when isInputValid is false
- All buttons maintain responsive design patterns

## SessionDetails Component Contract

```typescript
interface SessionDetailsProps {
wordsRead: number;
totalWords: number;
progressPercent: number;
msPerWord: number;
}
```

**Behavior Contract**:

- Renders collapsible details with summary "Session details"
- Displays progress as "X / Y (Z%)" format
- Displays tempo as "X milliseconds/word" format
- Uses aria-live="polite" for screen reader announcements
- Rounds percentage and ms/word values for display

## SessionCompletion Component Contract

```typescript
interface SessionCompletionProps {
wordsRead: number;
elapsedMs: number;
}
```

**Behavior Contract**:

- Renders success message with emerald-200 border and emerald-50 background
- Displays "Session complete" heading with font-semibold
- Shows completion message with word count and elapsed time
- Uses semantic h2 heading for proper document structure

## Shared Type Contracts

### ReadingSessionStatus

```typescript
type ReadingSessionStatus = 'idle' | 'running' | 'paused' | 'completed';
```

### TokenizedContent

```typescript
interface TokenizedContent {
totalWords: number;
words: string[];
}
```

**Validation Rules**:

- All props are required unless explicitly marked optional
- Component callbacks must be called with correct parameter types
- Status-dependent rendering must match the specified conditions
- Accessibility attributes must be present as specified
Loading