restructure tasks
This commit is contained in:
111
tasks/shieldai-unified-restructure/26-error-loading-states.md
Normal file
111
tasks/shieldai-unified-restructure/26-error-loading-states.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# 26. Polish — Error Boundaries, Loading States, Skeletons, and Transitions
|
||||
|
||||
meta:
|
||||
id: shieldai-unified-restructure-26
|
||||
feature: shieldai-unified-restructure
|
||||
priority: P1
|
||||
depends_on: [shieldai-unified-restructure-24, shieldai-unified-restructure-25]
|
||||
tags: [frontend, polish, ux, accessibility, solidjs]
|
||||
|
||||
objective:
|
||||
- Add production polish to the web app: error boundaries for graceful failure handling, skeleton screens for loading states, smooth page transitions, and comprehensive accessibility improvements.
|
||||
|
||||
deliverables:
|
||||
- `web/src/components/ui/ErrorBoundary.tsx` — Global error boundary:
|
||||
- Catches runtime errors in child components
|
||||
- Displays friendly error page with ShieldAI branding
|
||||
- "Try again" button to reset error boundary
|
||||
- "Report issue" button (placeholder for Sentry integration)
|
||||
- Logs error details to console (and eventually monitoring)
|
||||
- `web/src/components/ui/Skeleton.tsx` — Skeleton loading components:
|
||||
- `SkeletonText` — animated pulse lines for text placeholders
|
||||
- `SkeletonCard` — card-shaped skeleton with header, body, footer
|
||||
- `SkeletonAvatar` — circular skeleton for profile images
|
||||
- `SkeletonTable` — table row skeletons
|
||||
- All use `.bg-bg-tertiary` with shimmer animation
|
||||
- `web/src/components/ui/PageTransition.tsx` — Page transition wrapper:
|
||||
- Fade-in + slight translate-y on route change
|
||||
- Respects `prefers-reduced-motion`
|
||||
- Uses SolidJS `<Transition>` or CSS animations
|
||||
- Loading states integrated:
|
||||
- Dashboard widgets show skeletons while `createResource` is loading
|
||||
- Service pages show skeleton layouts while data fetches
|
||||
- Buttons show spinner inside during mutation loading
|
||||
- Forms show disabled state with spinner during submission
|
||||
- Accessibility improvements:
|
||||
- All images have `alt` text
|
||||
- All interactive elements have focus rings
|
||||
- Color contrast meets WCAG AA (4.5:1 for text)
|
||||
- ARIA labels on icon-only buttons
|
||||
- Skip-to-content link for keyboard navigation
|
||||
- Reduced motion support for all animations
|
||||
- `web/src/components/ui/EmptyState.tsx` — Empty state component:
|
||||
- Icon, title, description, and optional action button
|
||||
- Used when lists have no items (e.g., no watchlist items, no alerts)
|
||||
|
||||
steps:
|
||||
1. Create `web/src/components/ui/ErrorBoundary.tsx`:
|
||||
- Use SolidJS `ErrorBoundary` component as base
|
||||
- Custom fallback UI with ShieldAI logo, error message, retry button
|
||||
- Capture stack trace for debugging
|
||||
2. Create `web/src/components/ui/Skeleton.tsx`:
|
||||
- Use Tailwind `animate-pulse` or custom shimmer animation
|
||||
- Each skeleton variant accepts `lines`, `width`, `height` props
|
||||
- Use rounded rectangles that mimic content shape
|
||||
3. Create `web/src/components/ui/PageTransition.tsx`:
|
||||
- Wrap route content in transition group
|
||||
- Apply `opacity-0 translate-y-2` → `opacity-100 translate-y-0` on enter
|
||||
- Duration: 200ms, easing: ease-out
|
||||
4. Integrate skeletons:
|
||||
- Dashboard: replace `Loading...` text with `SkeletonCard` grids
|
||||
- Service pages: add skeleton layouts matching final content shape
|
||||
- Tables: use `SkeletonTable` with 5 rows
|
||||
5. Integrate loading states in buttons:
|
||||
- Update `Button` primitive to show spinner when `loading` prop is true
|
||||
- Disable button and reduce opacity during loading
|
||||
6. Add accessibility:
|
||||
- Audit all pages with axe DevTools
|
||||
- Fix any contrast issues (adjust colors in theme if needed)
|
||||
- Add `aria-label` to all icon buttons
|
||||
- Add `aria-live="polite"` regions for toast notifications
|
||||
- Ensure all form inputs have associated labels
|
||||
7. Create `EmptyState` component and use it across pages:
|
||||
- DarkWatch: "No watchlist items yet" with "Add first item" button
|
||||
- VoicePrint: "No voice enrollments" with "Enroll voice" button
|
||||
- SpamShield: "No custom rules" with "Create rule" button
|
||||
- etc.
|
||||
8. Test all improvements across light/dark modes.
|
||||
|
||||
steps:
|
||||
- Unit: ErrorBoundary catches thrown errors and renders fallback
|
||||
- Unit: Skeleton components render with correct dimensions
|
||||
- Unit: PageTransition applies enter animation
|
||||
- Accessibility: axe DevTools audit passes with 0 critical violations
|
||||
- Visual: All loading states look polished and match content layout
|
||||
- Visual: Empty states display correctly when lists are empty
|
||||
|
||||
acceptance_criteria:
|
||||
- [ ] ErrorBoundary catches and displays friendly error UI for all routes
|
||||
- [ ] Skeleton screens match the shape of final content (no layout shift)
|
||||
- [ ] All buttons show loading state during mutations
|
||||
- [ ] Page transitions are smooth and respect reduced motion
|
||||
- [ ] Empty states are informative and provide clear next actions
|
||||
- [ ] axe DevTools audit shows 0 critical or serious violations
|
||||
- [ ] All color combinations meet WCAG AA contrast standards
|
||||
- [ ] Keyboard navigation works for all interactive elements
|
||||
|
||||
validation:
|
||||
- Throw an error in a component and verify ErrorBoundary catches it
|
||||
- Throttle network to 3G and verify skeletons appear during loading
|
||||
- Navigate between routes and verify smooth transitions
|
||||
- Run axe DevTools on each page and fix any issues
|
||||
- Test keyboard-only navigation (Tab, Enter, Escape) on all pages
|
||||
- Run `cd web && pnpm test` for polish-related unit tests
|
||||
|
||||
notes:
|
||||
- Reference Lendair's skeleton components: `~/code/Lendair/web/src/components/skeletons/`
|
||||
- The `animate-pulse` Tailwind class is sufficient for skeletons. For a more polished look, consider a custom shimmer animation with a moving gradient.
|
||||
- Error boundaries should NOT catch errors in event handlers or async code — only render errors. Use try/catch for async operations.
|
||||
- For monitoring integration, consider adding Sentry in a follow-up task. For now, log errors to console.
|
||||
- The `EmptyState` component should be reusable across all service pages. Keep it generic but allow customization of icon, title, description, and action.
|
||||
- Test reduced motion by enabling "Reduce motion" in OS settings and verifying all animations are suppressed.
|
||||
Reference in New Issue
Block a user