Files
ColaFlow/docs/plans/sprint_4_story_1_task_6.md
Yaojia Wang 88d6413f81 feat(frontend): Create Sprint 4 Stories and Tasks for Story Management
Created comprehensive Story and Task files for Sprint 4 frontend implementation:

Story 1: Story Detail Page Foundation (P0 Critical - 3 days)
- 6 tasks: route creation, header, sidebar, data loading, Edit/Delete, responsive design
- Fixes critical 404 error when clicking Story cards
- Two-column layout consistent with Epic detail page

Story 2: Task Management in Story Detail (P0 Critical - 2 days)
- 6 tasks: API verification, hooks, TaskList, TaskCard, TaskForm, integration
- Complete Task CRUD with checkbox status toggle
- Filters, sorting, and optimistic UI updates

Story 3: Enhanced Story Form (P1 High - 2 days)
- 6 tasks: acceptance criteria, assignee selector, tags, story points, integration
- Aligns with UX design specification
- Backward compatible with existing Stories

Story 4: Quick Add Story Workflow (P1 High - 2 days)
- 5 tasks: inline form, keyboard shortcuts, batch creation, navigation
- Rapid Story creation with minimal fields
- Keyboard shortcut (Cmd/Ctrl + N)

Story 5: Story Card Component (P2 Medium - 1 day)
- 4 tasks: component variants, visual states, Task count, optimization
- Reusable component with list/kanban/compact variants
- React.memo optimization

Story 6: Kanban Story Creation Enhancement (P2 Optional - 2 days)
- 4 tasks: Epic card enhancement, inline form, animation, real-time updates
- Contextual Story creation from Kanban
- Stretch goal - implement only if ahead of schedule

Total: 6 Stories, 31 Tasks, 12 days estimated
Priority breakdown: P0 (2), P1 (2), P2 (2 optional)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 21:49:57 +01:00

11 KiB

task_id, story_id, sprint_id, status, type, assignee, created_date, estimated_hours
task_id story_id sprint_id status type assignee created_date estimated_hours
sprint_4_story_1_task_6 sprint_4_story_1 sprint_4 not_started frontend Frontend Developer 1 2025-11-05 3

Task 6: Implement Responsive Design and Accessibility

Description

Ensure the Story detail page works flawlessly on all screen sizes (mobile, tablet, desktop) and meets WCAG 2.1 Level AA accessibility standards. This includes responsive layout adjustments, keyboard navigation, ARIA labels, and focus management.

What to Do

  1. Test and fix responsive layout on all breakpoints
  2. Implement mobile-specific UI adjustments (sidebar to tabs)
  3. Add keyboard navigation support (Tab, Enter, ESC)
  4. Add ARIA labels to all interactive elements
  5. Implement focus management (dialog open/close)
  6. Ensure proper heading hierarchy (h1 → h2 → h3)
  7. Test color contrast ratios (WCAG AA: 4.5:1 minimum)
  8. Test with screen reader (NVDA/JAWS)
  9. Add skip links for keyboard users
  10. Run Lighthouse accessibility audit

Files to Modify

  • app/(dashboard)/stories/[id]/page.tsx (modify, responsive tweaks)
  • components/projects/story-header.tsx (modify, accessibility)
  • components/projects/story-metadata-sidebar.tsx (modify, responsive)
  • All related components (add ARIA labels)

Implementation Details

Responsive Layout Breakpoints

// app/(dashboard)/stories/[id]/page.tsx
// Adjust grid layout for different screens

<div className="grid grid-cols-1 lg:grid-cols-[1fr_320px] gap-6">
  {/* Main content - full width on mobile, 70% on desktop */}
  <div className="space-y-6 order-2 lg:order-1">
    {/* Story description, acceptance criteria, tasks */}
  </div>

  {/* Sidebar - full width on mobile (at top), fixed width on desktop */}
  <aside className="order-1 lg:order-2">
    {/* Metadata sidebar */}
  </aside>
</div>

Mobile-Specific Adjustments

// Convert sidebar sections to tabs on mobile
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';

function MobileStoryMetadata({ story, parentEpic }: Props) {
  return (
    <Tabs defaultValue="details" className="lg:hidden">
      <TabsList className="w-full">
        <TabsTrigger value="details">Details</TabsTrigger>
        <TabsTrigger value="time">Time</TabsTrigger>
        <TabsTrigger value="epic">Epic</TabsTrigger>
      </TabsList>

      <TabsContent value="details">
        {/* Status, Priority, Assignee */}
      </TabsContent>

      <TabsContent value="time">
        {/* Time tracking, Dates */}
      </TabsContent>

      <TabsContent value="epic">
        {/* Parent Epic card */}
      </TabsContent>
    </Tabs>
  );
}

ARIA Labels and Roles

// Story header with accessibility
<header role="banner" aria-labelledby="story-title">
  <h1 id="story-title" className="text-3xl font-bold">
    {story.title}
  </h1>

  <div role="group" aria-label="Story metadata">
    <Badge aria-label={`Status: ${story.status}`}>
      {story.status}
    </Badge>

    <Badge aria-label={`Priority: ${story.priority}`}>
      {story.priority}
    </Badge>
  </div>

  <div role="group" aria-label="Story actions">
    <Button
      onClick={onEdit}
      aria-label="Edit story details"
      aria-describedby="edit-help"
    >
      <Edit className="h-4 w-4" aria-hidden="true" />
      Edit
    </Button>
    <span id="edit-help" className="sr-only">
      Opens a dialog to edit story title, description, and metadata
    </span>

    <Button
      onClick={onDelete}
      aria-label="Delete story permanently"
      aria-describedby="delete-help"
    >
      <Trash2 className="h-4 w-4" aria-hidden="true" />
      Delete
    </Button>
    <span id="delete-help" className="sr-only">
      Permanently deletes this story and all associated tasks
    </span>
  </div>
</header>

// Main content sections
<main role="main" aria-labelledby="story-title">
  <section aria-labelledby="description-heading">
    <h2 id="description-heading">Description</h2>
    <div role="document" aria-label="Story description">
      {story.description}
    </div>
  </section>

  <section aria-labelledby="criteria-heading">
    <h2 id="criteria-heading">Acceptance Criteria</h2>
    {/* Criteria list */}
  </section>

  <section aria-labelledby="tasks-heading">
    <h2 id="tasks-heading">Tasks</h2>
    {/* Tasks list */}
  </section>
</main>

// Sidebar
<aside role="complementary" aria-label="Story metadata">
  <h2 className="sr-only">Story Details</h2>
  {/* Metadata cards */}
</aside>

Keyboard Navigation

// Add keyboard shortcuts
useEffect(() => {
  const handleKeyDown = (e: KeyboardEvent) => {
    // ESC - Go back to Epic
    if (e.key === 'Escape' && !isEditDialogOpen && !isDeleteDialogOpen) {
      router.push(`/epics/${story.epicId}`);
    }

    // Cmd/Ctrl + E - Edit Story
    if ((e.metaKey || e.ctrlKey) && e.key === 'e') {
      e.preventDefault();
      setIsEditDialogOpen(true);
    }

    // Cmd/Ctrl + Backspace - Delete Story
    if ((e.metaKey || e.ctrlKey) && e.key === 'Backspace') {
      e.preventDefault();
      setIsDeleteDialogOpen(true);
    }
  };

  window.addEventListener('keydown', handleKeyDown);
  return () => window.removeEventListener('keydown', handleKeyDown);
}, [isEditDialogOpen, isDeleteDialogOpen]);

// Add keyboard shortcut hints
<footer className="mt-8 text-xs text-muted-foreground">
  <p>Keyboard shortcuts:</p>
  <ul className="list-disc list-inside">
    <li>ESC - Back to Epic</li>
    <li>Cmd/Ctrl + E - Edit Story</li>
    <li>Cmd/Ctrl + Backspace - Delete Story</li>
  </ul>
</footer>

Focus Management

// Trap focus in dialogs
import { useFocusTrap } from '@/lib/hooks/use-focus-trap';

function EditStoryDialog({ isOpen, onClose }: Props) {
  const dialogRef = useRef<HTMLDivElement>(null);
  useFocusTrap(dialogRef, isOpen);

  // Auto-focus first field when dialog opens
  useEffect(() => {
    if (isOpen) {
      const firstInput = dialogRef.current?.querySelector('input');
      firstInput?.focus();
    }
  }, [isOpen]);

  // Return focus to trigger element when dialog closes
  const triggerRef = useRef<HTMLButtonElement | null>(null);

  const handleOpen = () => {
    triggerRef.current = document.activeElement as HTMLButtonElement;
    setIsOpen(true);
  };

  const handleClose = () => {
    setIsOpen(false);
    triggerRef.current?.focus();
  };

  return (
    <Dialog open={isOpen} onOpenChange={handleClose}>
      <DialogContent ref={dialogRef}>
        {/* Dialog content */}
      </DialogContent>
    </Dialog>
  );
}
// Add skip link for keyboard users
<a
  href="#main-content"
  className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-primary focus:text-primary-foreground focus:rounded-md"
>
  Skip to main content
</a>

<main id="main-content" tabIndex={-1}>
  {/* Main content */}
</main>

Acceptance Criteria

Responsive Design

  • Desktop (> 1024px): Two-column layout (content + sidebar)
  • Tablet (640px - 1024px): Two-column layout with narrower sidebar
  • Mobile (< 640px): Single-column layout, sidebar moves to top or tabs
  • All buttons and controls accessible on touch devices
  • No horizontal scrolling on any screen size
  • Text remains readable on all screen sizes (minimum 14px)

Accessibility (WCAG 2.1 Level AA)

  • All interactive elements keyboard accessible (Tab navigation)
  • Focus indicators visible (2px outline, high contrast)
  • ARIA labels on all buttons, links, and form controls
  • Proper heading hierarchy (h1 → h2 → h3)
  • Color contrast ratio >= 4.5:1 for all text
  • Large text (18px+) contrast ratio >= 3:1
  • Screen reader announces all content correctly
  • Focus trapped in dialogs (cannot Tab outside)
  • Focus returns to trigger element when dialog closes
  • Skip links available for keyboard users
  • Icons have aria-hidden="true" (text labels present)
  • Loading states announced to screen readers (role="status")
  • Error messages announced (role="alert")

Keyboard Navigation

  • Tab - Navigate through interactive elements
  • Enter - Activate buttons and links
  • Space - Toggle checkboxes and buttons
  • ESC - Close dialogs and navigate back
  • Cmd/Ctrl + E - Edit Story (custom shortcut)
  • Cmd/Ctrl + Backspace - Delete Story (custom shortcut)

Testing

Manual Testing

Responsive Design:

  1. Open Story detail page on desktop → Verify two-column layout
  2. Resize to tablet width (768px) → Verify layout adjusts
  3. Resize to mobile width (375px) → Verify single-column layout
  4. Verify sidebar moves to top on mobile
  5. Test all buttons clickable on touch device
  6. Verify no horizontal scrolling on any screen
  7. Test landscape and portrait orientations

Keyboard Navigation:

  1. Navigate to Story page using only keyboard
  2. Press Tab → Verify focus moves through all interactive elements
  3. Verify focus indicator visible (blue outline)
  4. Press ESC → Verify navigates back to Epic
  5. Press Cmd/Ctrl + E → Verify Edit dialog opens
  6. Press Tab in dialog → Verify focus trapped
  7. Press ESC in dialog → Verify dialog closes and focus returns

Screen Reader (NVDA/JAWS):

  1. Enable screen reader
  2. Navigate to Story page
  3. Verify page structure announced (heading hierarchy)
  4. Verify all buttons have labels
  5. Verify badges announced with context ("Status: In Progress")
  6. Verify loading states announced
  7. Verify error messages announced
  8. Open Edit dialog → Verify form fields labeled correctly

Automated Testing

Lighthouse Audit:

# Run Lighthouse accessibility audit
npm run lighthouse

# Expected results:
# Accessibility: >= 90 (ideally 100)
# Best Practices: >= 90
# SEO: >= 90
# Performance: >= 80 (acceptable for dynamic content)

axe DevTools:

# Install axe DevTools browser extension
# Open Story page
# Run axe scan
# Expected: 0 violations

Color Contrast Testing

# Test all text colors
# Use browser DevTools > Accessibility > Color contrast

# Required ratios (WCAG AA):
# Normal text (< 18px): 4.5:1
# Large text (>= 18px): 3:1
# UI components: 3:1

# Test combinations:
Story Title (32px):     Should pass (large text)
Description (16px):     Should pass 4.5:1
Metadata labels (14px): Should pass 4.5:1
Badges:                 Should pass 3:1 (UI components)
Buttons:                Should pass 3:1 (UI components)

Dependencies

Prerequisites:

  • Task 1, 2, 3, 4, 5 (all components must exist)
  • shadcn/ui components with built-in accessibility
  • Tailwind CSS responsive utilities
  • ARIA attributes support

Blocks:

  • None (final polish task)

Estimated Time

3 hours

Notes

Testing Tools:

  • Chrome DevTools > Lighthouse (accessibility audit)
  • axe DevTools browser extension (automated WCAG testing)
  • NVDA/JAWS screen reader (manual testing)
  • WAVE browser extension (visual accessibility check)
  • Contrast Checker (color contrast ratios)

Common Accessibility Issues to Avoid:

  • Missing alt text on images
  • Insufficient color contrast
  • Missing ARIA labels on icon-only buttons
  • Broken keyboard navigation (focus trap)
  • Missing heading hierarchy (h1 → h3, skip h2)
  • Form inputs without labels
  • Loading states not announced to screen readers

Responsive Design Checklist:

  • Test on real devices (iPhone, Android, tablet)
  • Test different orientations (portrait, landscape)
  • Test different zoom levels (100%, 150%, 200%)
  • Verify touch targets >= 44x44px
  • No horizontal scrolling on any screen