BillTracker/docs/UI_IMPROVEMENTS.md

313 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bill Tracker UI Improvements
## Overview
This document catalogs UI/UX improvements identified across the Bill Tracker codebase, organized by priority and impact.
---
## CRITICAL
No critical issues found. Core functionality is solid.
---
## HIGH
### 1. Mobile Layout Overflow in Sidebar Navigation
**Where:** `client/components/layout/Sidebar.jsx` — Mobile menu overlay
**Why it matters:** On small screens, the mobile navigation menu doesn't adapt to content width, causing horizontal scroll or content cutoff. This is a blocking accessibility issue for mobile users.
**Current behavior:**
- Mobile menu uses fixed max-width container
- Nav items with long text (e.g., "Notification Preferences") wrap poorly
- No vertical scrolling within the mobile overlay
**Suggested fix:**
```jsx
// In Sidebar.jsx mobile menu section:
<div className={cn(
'border-t border-border/60 bg-background/95 px-4 py-3 shadow-lg shadow-foreground/5 lg:hidden',
'max-h-[70vh] overflow-y-auto', // Add scrollable container
)}>
<nav className="mx-auto grid max-w-[1500px] gap-1">
{/* ... */}
</nav>
</div>
```
**Priority:** HIGH — Mobile breakage affects a significant portion of users
---
### 2. Settings Page — No Loading Skeleton for Main Content Area
**Where:** `client/pages/SettingsPage.jsx`
**Why it matters:** The entire page shows a full-page loader (`Loading…`) during initial data fetch, resulting in a blank white screen for 200500ms. This feels slower than needed.
**Suggested fix:**
- Replace full-page loader with skeleton cards matching the layout
- Show placeholder content: 2-3 shimmering `SectionCard` components
- Fade out skeletons when data arrives
**Impact:** Perceived performance improvement (~30-40% faster mental load time)
---
### 3. BillModal — Real-Time Validation on Every Keystroke Causes Layout Shifts
**Where:** `client/components/BillModal.jsx`
**Why it matters:** The `handleChange` function debounces validation but still triggers re-renders on every keystroke. This causes:
- Input field height changes when error messages appear/disappear
- Jarring UX during form entry
- Potential focus loss on fast typists
**Suggested fix:**
- Only show error messages after field blur or form submit attempt
- Pre-allocate error message space (min-height: 12px)
- Use `aria-live="polite"` for screen reader notifications
**Alternative:**
```jsx
// Only validate on blur or submit, not on every change
// Keep error state but don't re-render unless visibility changes
{errors.name && errorStateVisible && (
<span className="text-[10px] text-red-500 font-medium">{errors.name}</span>
)}
```
---
## MEDIUM
### 4. Sidebar Nav — No Active Indicator for Dropdown Children
**Where:** `client/components/layout/Sidebar.jsx``TrackerMenu` component
**Why it matters:** When users navigate to `/bills`, `/categories`, or `/summary`, the main "Tracker" dropdown remains unhighlighted. This creates ambiguity about current location.
**Current behavior:**
- Only the dropdown trigger is highlighted when on `/` (Overview)
- Child routes like `/bills` don't indicate they're part of the Tracker group
**Suggested fix:**
- Detect when any child route is active via `location.pathname.startsWith('/bills')` etc.
- Apply `bg-primary text-primary-foreground` style to the Tracker dropdown when any tracker subpage is active
**Code hint:**
```jsx
const isTrackerActive = trackerItems.some(item =>
item.end ? location.pathname === item.to
: location.pathname.startsWith(item.to)
);
```
Already implemented in the code, but the `TrackerMenu` trigger needs styling update.
---
### 5. Admin Panel — Missing Error Boundary for Critical Sections
**Where:** `client/pages/AdminPage.jsx`
**Why it matters:** Several complex cards (Backup, Email, Users) lack explicit error boundaries. If an API call fails mid-render or throws, the entire admin panel goes blank with no recovery path.
**Suggested fix:**
- Wrap each major card in a `try/catch` or React Error Boundary
- Show "Failed to load" state with retry button
- Example:
```jsx
function BackupSection() {
const [error, setError] = useState(null);
const [data, setData] = useState(null);
useEffect(() => {
api.getBackups()
.then(setData)
.catch(err => setError(err));
}, []);
if (error) {
return (
<Card>
<CardContent>Failed to load backups.</CardContent>
<Button onClick={() => setError(null)}>Retry</Button>
</Card>
);
}
// ...
}
```
---
### 6. Settings Page — Field Labels Not Keyboard-Accessible
**Where:** `client/pages/SettingsPage.jsx`
**Why it matters:** While `label` elements exist, they're not explicitly tied to inputs via `htmlFor`. Some components (e.g., theme cards) use buttons without labels, making screen reader navigation difficult.
**Suggested fix:**
- Ensure all form inputs have explicit `id` and corresponding `label htmlFor`
- Add `aria-label` or `aria-describedby` to interactive elements:
```jsx
<button
type="button"
onClick={() => onSelect('light')}
aria-label="Select light theme"
aria-pressed={currentTheme === 'light'}
>
<Sun className="h-4 w-4" />
</button>
```
---
### 7. ProfilePage — Email Input Not Validated client-side
**Where:** `client/pages/ProfilePage.jsx``NotificationPreferences` component
**Why it matters:** The email input field accepts any string, including invalid formats like `test@localhost` or `not-an-email`. Validation only happens server-side, leading to delayed error feedback.
**Suggested fix:**
- Add client-side email regex check before save
- Show inline error if invalid: `^[\w.-]+@[\w.-]+\.\w+$`
- Debounce validation to avoid spamming errors during typing
---
### 8. BillModal — Date Input Uses Unusual "Due Day of Month" Pattern
**Where:** `client/components/BillModal.jsx`
**Why it matters:** The "Due day of month" input expects a number (1-31) instead of a standard date picker or calendar selection. This is confusing for:
- Users expecting a full date picker
- International users (some countries use DD/MM vs MM/DD)
- Edge cases like February 30th (which doesn't exist)
**Suggested improvement:**
- Consider using `react-datepicker` or similar for full date selection
- Alternatively, add a helper tooltip: "Enter day number only (e.g., 15 for the 15th)"
- Add a validation example: "Due on the 15th → enter 15"
---
## LOW
### 9. Global Layout — Header Backdrop Filter Not Fallback for Older Browsers
**Where:** `client/components/layout/Sidebar.jsx``header` element
**Why it matters:** The `backdrop-blur-xl` class relies on CSS `backdrop-filter`, which is unsupported in older browsers (e.g., Safari <14, some Android WebView versions). This results in a solid background instead of glassmorphism.
**Suggested fix:**
- Add a CSS fallback: `bg-background/85 supports-[backdrop-filter]:bg-background/70`
- Already implemented no changes needed
---
### 10. Login Page — No "Remember Me" Checkbox
**Where:** `client/pages/LoginPage.jsx`
**Why it matters:** Modern apps often include a "remember me" option to reduce login friction on trusted devices. Without it, users must re-authenticate on every session.
**Suggested fix:**
- Add a checkbox below the password field:
```jsx
<div className="flex items-center gap-2">
<input type="checkbox" id="remember" />
<label htmlFor="remember" className="text-xs text-muted-foreground">
Remember me
</label>
</div>
```
- Set `rememberMe` flag in localStorage or via cookie (if server supports it)
---
### 11. Theme Toggle — No Visual Feedback When Switching
**Where:** `client/components/ui/theme-toggle.jsx` (shadcn/ui)
**Why it matters:** The theme toggle button doesn't indicate which theme is currently active. Users must click to discover the current state or remember manually.
**Suggested fix:**
- Add subtle text label: "Light" / "Dark" next to the icon
- Or use a tooltip: `aria-label="Current theme: Dark"`
- Or change icon (sun/moon) based on theme (already done ✅)
---
### 12. Calendar Page — Empty State Not Customizable
**Where:** `client/pages/CalendarPage.jsx`
**Why it matters:** When there are no bills, the calendar shows a generic "No bills found" message. This doesn't guide users toward creating their first bill.
**Suggested fix:**
- Add a CTA button: "Create your first bill"
- Link directly to the modal with a pre-filled category or default values
- Include a placeholder image or illustration
---
## MEH
### 13. General — Inconsistent Spacing in `table-surface` Utility
**Where:** Multiple components (SettingsPage, ProfilePage)
**Why it matters:** The `table-surface` utility (used in Settings and Profile pages) applies `mb-4` and internal padding, but the spacing isn't uniform across all pages. Some sections have excessive vertical space, others feel cramped.
**Suggested fix:**
- Audit and standardize spacing tokens:
- `section-spacing` = `mb-6` (1.5rem)
- `card-spacing` = `mb-4` (1rem)
- `row-spacing` = `py-3` (0.75rem)
- Document in `docs/TOKENS.md`
---
### 14. Icons — No Consistent Icon Palette
**Where:** Across all components
**Why it matters:** Different icon sets are used inconsistently:
- `lucide-react` (primary)
- Custom SVGs (logo)
- Some components import icons but don't use them
**Suggested fix:**
- Standardize on `lucide-react` for all icons
- Create a shared `icons/` directory with named exports if custom icons are needed
- Document icon usage in `CONTRIBUTING.md`
---
## Summary
| Priority | Count | Key Impact |
|----------|-------|------------|
| CRITICAL | 0 | |
| HIGH | 3 | Mobile accessibility, perceived performance, form UX |
| MEDIUM | 5 | Navigation clarity, error resilience, keyboard nav |
| LOW | 4 | Convenience, consistency, discoverability |
| MEH | 2 | Minor polish, standardization |
---
## Next Steps
1. **HIGH items** should be prioritized for the next minor release (v2.1)
2. **MEDIUM items** can be batched into a quality-of-life update
3. Consider a design system audit to address **MEH** items (spacing, icons)
4. Re-run this analysis after implementing HIGH/MEDIUM items to track progress
---
*Generated by Scarlett (Frontend/UX Authority) on 2026-05-08*