diff --git a/Cargo.toml b/Cargo.toml index 7770689..4246bfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,6 @@ gloo-timers = { version = "0.3", features = ["futures"] } tracing = "0.1" tracing-wasm = "0.2" console_error_panic_hook = "0.1" -web-sys = { version = "0.3", features = ["Window", "Location"] } +web-sys = { version = "0.3", features = ["Window", "Location", "MediaQueryList", "MediaQueryListEvent"] } js-sys = "0.3" futures = "0.3" diff --git a/DESIGN.md b/DESIGN.md index aad49b7..7bd540b 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -224,6 +224,18 @@ by default. ## Layout +### Breakpoints + +- **Mobile:** < 480px. Single column, collapsed nav, card view, secondary + row details hidden. +- **Tablet:** 480–767px. Compact spacing, dashboard forced to card view. +- **Desktop-small:** 768–1023px. Full nav and table restored. +- **Desktop:** ≥ 1024px. Full experience (content max 1280px). + +Media queries use these exact pixel values — CSS custom properties cannot +be used inside `@media`, so the values live in `style.css` under +"Responsive breakpoints" and this section documents them. + ### Grid - **Max width:** 1280px, centered. diff --git a/ROADMAP.md b/ROADMAP.md index e1965b6..2e791a8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -134,15 +134,21 @@ dark-first/sky-blue identity was reverted in `294d214`; needs a redo. Most developers check dashboards on desktop, but a quick phone check should work too. -- [ ] **Breakpoint system.** Mobile, tablet, desktop-small, desktop. -- [ ] **Table → card fallback.** The sortable table is unusable on small - screens. Force card view below tablet width. -- [ ] **Responsive navigation.** Top nav on desktop; collapsed menu on - mobile. -- [ ] **Touch targets.** All interactive elements meet WCAG AA sizing. +- [x] **Breakpoint system.** Mobile (<480px), tablet (480–767px), + desktop-small (768–1023px), desktop (≥1024px). Documented in DESIGN.md + "Layout > Breakpoints", with the pixel values written out at each + `@media` query in `style.css`. +- [x] **Table → card fallback.** The dashboard watches + `matchMedia("(max-width: 767px)")`, forces the card view below the + tablet breakpoint and hides the Table/Cards toggle. +- [x] **Responsive navigation.** Hamburger button below 768px; the nav + links become a dropdown panel under the sticky header and close on + selection. Theme toggle + rate badge stay in the top row. +- [x] **Touch targets.** `@media (pointer: coarse)` gives interactive + elements a 44px minimum height; desktop density is untouched. **Acceptance:** usable from phone to ultrawide; table auto-converts to -cards on mobile. +cards on mobile. ✅ Phase complete. ### 5. Keyboard navigation diff --git a/crates/app/src/app.rs b/crates/app/src/app.rs index ec07137..4ececfd 100644 --- a/crates/app/src/app.rs +++ b/crates/app/src/app.rs @@ -37,6 +37,10 @@ pub fn App() -> impl IntoView { let settings = expect_context::(); + // Mobile nav: the links collapse behind this menu button below the tablet + // breakpoint (see DESIGN.md "Breakpoints"). + let (menu_open, set_menu_open) = signal(false); + // Reflect the theme onto the document root so `:root[data-theme]` CSS applies. let theme_attr = move || settings.theme.get().as_attr(); leptos::prelude::Effect::new(move |_| { @@ -67,11 +71,15 @@ pub fn App() -> impl IntoView { "Lepo" -