From afff8388b092cb43adcf99625e19f872a588d213 Mon Sep 17 00:00:00 2001 From: fireshaper Date: Wed, 28 Oct 2026 09:42:14 -0400 Subject: [PATCH] Polish layout for mobile and desktop - Mobile bottom nav: icons, 56px targets, safe-area padding, and a "More" menu so Genetics/Shows/Settings are reachable on phones - Sticky sidebar, max-width content column, min-w-0 so wide children (pedigree tree, tables) scroll in place instead of widening the page - PageHeader owns no gutter and stacks actions on small screens; pages share one flex/gap structure and a consistent loading header - 16px inputs on mobile to stop iOS focus zoom; disabled button styling - Remove placeholder "0 litters / 0 kits" on rabbit cards, duplicate name on Rabbit Detail; proper Genetics placeholder and 404 pages Co-Authored-By: Claude Opus 5.5 --- memory-bank/architecture.md | 4 +- mykindlebox/client/index.html | 2 +- mykindlebox/client/src/components/Button.jsx | 8 +- mykindlebox/client/src/components/Layout.jsx | 223 +++++++++++++++--- .../client/src/components/PageHeader.jsx | 11 +- .../client/src/components/PedigreeTree.jsx | 17 +- .../client/src/components/QuickSearch.jsx | 4 +- .../client/src/components/RabbitCard.jsx | 1 - mykindlebox/client/src/index.css | 11 + mykindlebox/client/src/pages/AddBreeding.jsx | 6 +- mykindlebox/client/src/pages/AddLitter.jsx | 6 +- mykindlebox/client/src/pages/AddRabbit.jsx | 6 +- mykindlebox/client/src/pages/Dashboard.jsx | 6 +- mykindlebox/client/src/pages/EditLitter.jsx | 6 +- mykindlebox/client/src/pages/EditRabbit.jsx | 6 +- mykindlebox/client/src/pages/Genetics.jsx | 18 +- mykindlebox/client/src/pages/Herd.jsx | 5 +- mykindlebox/client/src/pages/LitterDetail.jsx | 10 +- mykindlebox/client/src/pages/Litters.jsx | 4 +- mykindlebox/client/src/pages/NotFound.jsx | 19 +- mykindlebox/client/src/pages/RabbitDetail.jsx | 17 +- mykindlebox/client/src/pages/Settings.jsx | 6 +- .../client/src/pages/ShowEventDetail.jsx | 4 +- 23 files changed, 300 insertions(+), 100 deletions(-) diff --git a/memory-bank/architecture.md b/memory-bank/architecture.md index a1ebf54..07aeeca 100644 --- a/memory-bank/architecture.md +++ b/memory-bank/architecture.md @@ -45,12 +45,12 @@ docker-compose.yml — orchestrates both services for self-hosted deployment |---|---| | `src/App.jsx` | Root component. Wraps the app in `QueryClientProvider` (React Query) and `BrowserRouter`, defining every IA route nested under a single `Layout` layout-route (`}>`) so the sidebar/bottom-nav persists across page navigation. Includes a catch-all `*` → `NotFound` route. | | `src/api.js` | Plain JS (not `.ts` — the client is deliberately plain JS/JSX per Step 1.3, not TypeScript), one fetch function per backend endpoint (rabbits CRUD/search/quick-search/ancestors/photo, litters CRUD, events CRUD (`getEvents`/`createEvent`/`updateEvent`/`deleteEvent`), settings, stats, export, `importData` which POSTs a `FormData` file to `/api/import`, shows (`getArbaShows`/`refreshArbaShows`), show events (`getShowEvents`/`getShowEvent`/`createShowEvent`/`updateShowEvent`/`deleteShowEvent`/`addShowToEvent`/`removeShowFromEvent`), show entries + report (`addShowEntry`/`updateShowEntry`/`removeShowEntry`/`getEventReport`), judges + placements (`addShowJudge`/`updateShowJudge`/`removeShowJudge`/`setShowEntryPlacement`)), all targeting `http://localhost:3001/api`. Shared `request()` helper throws on non-2xx (surfacing the JSON `{ error }` body's message) and only sets `Content-Type: application/json` when the body is a JSON string, so the multipart `FormData` photo-upload call isn't given the wrong header. | -| `src/components/Layout.jsx` | Persistent app shell rendered via React Router's ``. Desktop: 240px left sidebar (`hidden md:flex`) with `NavLink`s for Dashboard/Herd/Litters/Genetics/Shows/Settings. Mobile (`≤768px`): fixed-bottom nav (`md:hidden`) with Dashboard/Herd/Litters/Add (→ `/herd/add`)/Settings. Active-route styling comes from `NavLink`'s `isActive` callback, not manual path matching. Also renders `` at the top of the `
` content area (above ``), so the quick-search bar appears on every page. | +| `src/components/Layout.jsx` | Persistent app shell rendered via React Router's ``. Desktop: 240px left sidebar (`hidden md:flex`) with `NavLink`s for Dashboard/Herd/Litters/Genetics/Shows/Settings. Mobile (`≤768px`): fixed-bottom nav (`md:hidden`, icon + label, 56px tall, padded by `env(safe-area-inset-bottom)`) with Dashboard/Herd/Add (→ `/herd/add`)/Litters/More — "More" opens a small menu for Genetics/Shows/Settings so every page is reachable on a phone. The sidebar is `sticky` and the content column is `min-w-0` + `max-w-6xl`, so wide children (tables, the 900px pedigree tree) scroll inside their own containers instead of stretching the page. `
` owns the page gutter (`px-4 md:px-8`); pages must not add their own horizontal padding. Active-route styling comes from `NavLink`'s `isActive` callback, not manual path matching. Also renders `` at the top of the `
` content area (above ``), so the quick-search bar appears on every page. | | `src/components/QuickSearch.jsx` | Global quick-search bar (top of every page via `Layout`). A debounced (200ms) text input + a "Filters" popover of four checkboxes (Farm Name / Rabbit Name / Ear Number / Color), **all selected by default**, controlling which fields `GET /api/rabbits/quick-search` prefix-matches. Results render in a dropdown as the user types; each row shows name · farm plus a chip per `matched_fields` entry (value-bearing chips for ear/color, e.g. `Ear #: A15`). Selecting a result navigates to `/herd/:id`. Reuses `lib/keyboardNav.js`'s `handleSearchInputKeyDown`/`handleResultKeyDown` for the same `