diff --git a/MOBILE_RESPONSIVE.md b/MOBILE_RESPONSIVE.md new file mode 100644 index 0000000..91d1325 --- /dev/null +++ b/MOBILE_RESPONSIVE.md @@ -0,0 +1,314 @@ +# Mobile-Responsive Implementation Guide + +## Overview + +This document describes the mobile-responsive updates implemented for the CPAS Tracker application. The design targets **standard phones (375px+ width)** with graceful degradation for smaller devices. + +## Key Changes + +### 1. **Responsive Utility Stylesheet** (`client/src/styles/mobile.css`) + +A centralized CSS file providing: +- Media query breakpoints (768px, 480px) +- Touch-friendly tap targets (min 44px height) +- iOS input zoom prevention (16px font size) +- Utility classes for mobile layouts +- Card-based layout helpers +- Horizontal scroll containers + +**Utility Classes:** +- `.hide-mobile` - Hide on screens ≀768px +- `.hide-tablet` - Hide on screens ≀1024px +- `.mobile-full-width` - Full width on mobile +- `.mobile-stack` - Stack flex items vertically +- `.mobile-scroll-x` - Enable horizontal scrolling +- `.mobile-card` - Card layout container +- `.mobile-sticky-top` - Sticky header positioning + +### 2. **App Navigation** (`client/src/App.jsx`) + +**Desktop Behavior:** +- Horizontal navigation bar +- Logo left, tabs center, docs button right +- Full tab labels displayed + +**Mobile Behavior (768px):** +- Logo centered with full width +- Tabs stacked horizontally below logo +- Docs button positioned absolutely top-right +- Shortened tab labels ("πŸ“Š Dashboard" β†’ "πŸ“Š") +- Flexible padding (40px β†’ 16px) + +**Features:** +- `useMediaQuery()` hook for responsive detection +- Dynamic style injection via ` + {/* Component JSX */} + +); +``` + +## Testing Checklist + +### Desktop (>768px) +- [ ] Navigation displays horizontally +- [ ] Dashboard shows full table +- [ ] All columns visible +- [ ] Docs button on right side +- [ ] Full tab labels visible + +### Tablet (768px - 1024px) +- [ ] Reduced padding maintains readability +- [ ] Stats cards wrap to 2-3 columns +- [ ] Table scrolls horizontally if needed + +### Mobile Portrait (375px - 768px) +- [ ] Logo centered, tabs stacked +- [ ] Dashboard shows card layout +- [ ] Search input full width +- [ ] Buttons stack vertically +- [ ] Employee cards display all data +- [ ] Tap targets β‰₯44px +- [ ] No horizontal scroll required + +### Small Mobile (<480px) +- [ ] Stat cards single column +- [ ] Text remains readable +- [ ] No layout breakage +- [ ] Footer wraps properly + +### iOS-Specific +- [ ] Input focus doesn't zoom page (16px font) +- [ ] Smooth momentum scrolling +- [ ] Tap highlights work correctly + +### Android-Specific +- [ ] Touch feedback visible +- [ ] Back button behavior correct +- [ ] Keyboard doesn't break layout + +## Browser Support + +- **Chrome/Edge:** 88+ +- **Firefox:** 85+ +- **Safari:** 14+ +- **iOS Safari:** 14+ +- **Chrome Android:** 88+ + +## Performance Considerations + +1. **Media query hook** re-renders only on breakpoint changes, not continuous resize +2. **Card layout** renders fewer DOM elements than table on mobile +3. **CSS injection** happens once per component mount +4. **No external CSS libraries** (zero KB bundle increase) + +## Future Enhancements + +### Phase 2 (Optional) +- [ ] ViolationForm mobile optimization with multi-step wizard +- [ ] Modal responsive sizing and animations +- [ ] Swipe gestures for employee cards +- [ ] Pull-to-refresh on mobile +- [ ] Offline support with service workers + +### Phase 3 (Advanced) +- [ ] Progressive Web App (PWA) capabilities +- [ ] Native app shell with Capacitor +- [ ] Biometric authentication +- [ ] Push notifications + +## File Structure + +``` +client/src/ +β”œβ”€β”€ App.jsx # Updated with mobile nav +β”œβ”€β”€ components/ +β”‚ β”œβ”€β”€ Dashboard.jsx # Responsive table/card switch +β”‚ β”œβ”€β”€ DashboardMobile.jsx # Mobile card layout (NEW) +β”‚ └── ... # Other components +└── styles/ + └── mobile.css # Responsive utilities (NEW) +``` + +## Maintenance Notes + +### Adding New Components + +When creating new components, follow this pattern: + +1. **Import mobile.css utility classes:** + ```javascript + import '../styles/mobile.css'; + ``` + +2. **Use media query hook:** + ```javascript + const isMobile = useMediaQuery('(max-width: 768px)'); + ``` + +3. **Provide mobile-specific styles:** + ```javascript + const mobileStyles = ` + @media (max-width: 768px) { + .my-component { /* mobile overrides */ } + } + `; + ``` + +4. **Test on real devices** (Chrome DevTools is insufficient for touch testing) + +### Debugging Tips + +- Use Chrome DevTools Device Mode (Ctrl+Shift+M) +- Test on actual devices when possible +- Check console for media query match state +- Verify tap target sizes with Chrome Lighthouse audit +- Test keyboard behavior on Android + +## Deployment + +1. Merge `feature/mobile-responsive` into `master` +2. Rebuild client bundle: `cd client && npm run build` +3. Restart server +4. Clear browser cache (Ctrl+Shift+R) +5. Test on production URL with mobile devices + +## Support + +For issues or questions about mobile-responsive implementation: +- Check browser console for errors +- Verify `mobile.css` is loaded +- Test with different screen sizes +- Review media query breakpoints + +--- + +**Branch:** `feature/mobile-responsive` +**Target Width:** 375px+ (standard phones) +**Last Updated:** March 8, 2026 +**Maintainer:** Jason Stedwell diff --git a/client/src/App.jsx b/client/src/App.jsx index 0055663..2b02499 100755 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -3,6 +3,7 @@ import ViolationForm from './components/ViolationForm'; import Dashboard from './components/Dashboard'; import ReadmeModal from './components/ReadmeModal'; import ToastProvider from './components/ToastProvider'; +import './styles/mobile.css'; const REPO_URL = 'https://git.alwisp.com/jason/cpas'; const PROJECT_START = new Date('2026-03-06T11:33:32-06:00'); @@ -56,8 +57,19 @@ function AppFooter({ version }) { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.75); } } + + /* Mobile-specific footer adjustments */ + @media (max-width: 768px) { + .footer-content { + flex-wrap: wrap; + justify-content: center; + font-size: 10px; + padding: 10px 16px; + gap: 8px; + } + } `} -