Navigation restructure: five-tab bottom bar, no phone drawer
Drawer removed (phones only; desktop rail untouched) - MobileSidebar, sidebarOpen/useSidebarOpen, MenuIcon and the drawer's back-gesture layer are gone; the shared nav content now serves only the desktop rail (dead mobile branches deleted). No drawer-specific CSS existed; the three drawer strings (header.openMenu, sidebar.closeMenu, common.menu) and library.importAria are removed. - The header drops the hamburger: logo + name on the left, the single theme chip on the right. Five-tab bottom bar - Library / Progress / New deck (prominent centre +) / Exam / Settings, in that order; Progress and Exam reuse the existing /stats and /exam screens, Settings keeps opening the dialog. Sliding pill, icon bounce, press feedback, re-tap-to-top and safe-area padding kept; every item is >=44px (72px wide at 360px). - New short tab.* keys (EN + CS) so all five labels stay on one line at 360px — 'Zkouškový režim' became 'Zkouška'. No ellipsis anywhere. - The bar is mounted once in AppHeader so library, progress, exam and share get it; the wizards keep their own bottom action bar and the tab bar steps aside there, exactly as before. Re-homed drawer destinations - Smart Review card loses the Exam link (it is a tab now); Review due and Mistakes stay. - New deck screen (and /homework) get a Study deck / Make my homework segmented switch; the library's homework empty-state button stays. - The phone import icon becomes a ... button opening a sheet with Import JSON and New folder (back-gesture and Escape close it); folder chips still appear only once at least one folder exists, and folder creation stays in the New deck options step. Verified: mobile suite 134 checks (no hamburger/drawer, tab order and 44px targets, label matrix at 360/390 x EN/CS x dark/light x reduced motion, per-tab routing, deep links, Back from every tab, the ... sheet with folder creation) plus regression 74/74, wizard 83/83, declutter 116/116, animation 8/8, native 35/35, i18n 25/25, phase1 38/38, phase2 43/43, phase3 20/20, freeze-loading 6/6. Key parity 740/740. Lint + build clean. SW freezmo-v28.
This commit is contained in:
parent
4513364019
commit
8557b04621
19 changed files with 357 additions and 325 deletions
56
README.md
56
README.md
|
|
@ -54,7 +54,7 @@ no database, no data leaving your machine except the requests you send to Ollama
|
|||
the safe area (the tab bar hides inside the wizard), and it is portalled to `<body>` so the
|
||||
screen entrance animation can never displace it. The desktop page is unchanged.
|
||||
- **Native-feel touches (phones)**: the Android Back gesture closes the topmost layer first
|
||||
(sheet, drawer, actions panel, then one wizard step); deleting a deck shows an *Undo*
|
||||
(sheet, actions sheet, then one wizard step); deleting a deck shows an *Undo*
|
||||
toast instead of a confirm; the deck menu can share a deck as JSON through the system share
|
||||
sheet (clipboard fallback); content shared from other apps opens a chooser and lands
|
||||
pre-filled in either wizard; haptics (Settings → Haptics, on by default) tick on tab
|
||||
|
|
@ -67,8 +67,8 @@ no database, no data leaving your machine except the requests you send to Ollama
|
|||
1 day, then 3, then interval × ease; wrong ones after ten minutes. The Library shows a **Smart
|
||||
review** card with the due count, a **Mistakes** count (activities whose latest answer was wrong —
|
||||
they clear themselves once answered correctly) and today's **daily goal** progress. A **Progress**
|
||||
screen (drawer) has the day streak, a five-week calendar, accuracy per subject and per deck and
|
||||
the weakest topics. **Exam mode** (drawer) takes one or more decks, a question count and an
|
||||
tab has the day streak, a five-week calendar, accuracy per subject and per deck and
|
||||
the weakest topics. **Exam mode** (its own tab) takes one or more decks, a question count and an
|
||||
optional timer, hides hints and shows a per-deck/per-topic breakdown at the end. **Daily
|
||||
reminders** appear in Settings only when the server has VAPID keys configured; subscriptions are
|
||||
stored as endpoint + keys only, and `node scripts/send-reminders.mjs` (cron/systemd timer) does
|
||||
|
|
@ -172,9 +172,9 @@ no database, no data leaving your machine except the requests you send to Ollama
|
|||
- **Two pools, never mixed**: a **Study Decks** tab (the folder + card library) and a **Homework**
|
||||
tab with saved solutions and step-by-step guides — each with its own empty state and call to
|
||||
action, and the active tab lives in the URL (`/?tab=homework`)
|
||||
- **Phone library, decluttered**: no stats line, the folder row and “Unorganized” heading only
|
||||
appear once folders exist (the drawer has *New folder*), and Import is a small icon button in
|
||||
the tab row. Deck cards shrink to title + one meta line (activities · difficulty · best
|
||||
- **Phone library, decluttered**: no stats line, the folder chips and “Unorganized” heading only
|
||||
appear once folders exist, and a **⋯** button next to the pool switcher opens a small sheet with
|
||||
**Import JSON** and **New folder**. Deck cards shrink to title + one meta line (activities · difficulty · best
|
||||
score) + a one-line description that expands on tap, with the whole card tappable and a small
|
||||
**Study** pill; homework cards match.
|
||||
- Decks saved locally with title, subject, folder, activity count, date, play count and best score
|
||||
|
|
@ -188,10 +188,14 @@ no database, no data leaving your machine except the requests you send to Ollama
|
|||
|
||||
**Design**
|
||||
|
||||
- **ChatGPT-style shell**: a persistent left **sidebar** (brand, a quiet "New deck" row, a *Folders*
|
||||
list with per-folder counts, Settings/Dark mode pinned to the bottom). It **collapses** to a 68px
|
||||
icon rail (remembered in `localStorage`) and becomes a slide-in **drawer** behind a hamburger on
|
||||
phones; mobile also keeps the frosted header + iOS tab bar
|
||||
- **ChatGPT-style shell on desktop, five tabs on phones**: desktop keeps the persistent left
|
||||
**sidebar** (brand, a quiet "New deck" row, a *Folders* list with per-folder counts,
|
||||
Settings/Dark mode pinned to the bottom), which **collapses** to a 68px icon rail (remembered in
|
||||
`localStorage`). Phones have no drawer and no hamburger: a frosted header (logo + theme chip) sits
|
||||
above an iOS-style bottom tab bar — **Library · Progress · New deck · Exam · Settings** — with the
|
||||
New deck button as the prominent centre action and Settings opening the sheet. The wizards keep
|
||||
their own bottom action bar instead of the tab bar, and the in-page segmented switch moves between
|
||||
the deck and homework wizards.
|
||||
- **Frosted ice glass, both themes**: light page `#eef5fd` (pale ice) with white glass panels;
|
||||
dark page `#0a1120` with `rgba(255,255,255,.06)` glass. Every large surface shares one recipe —
|
||||
translucent tint, 24px `backdrop-blur` (16px on phones), a bright 1px rim, an inner top highlight
|
||||
|
|
@ -209,11 +213,11 @@ no database, no data leaving your machine except the requests you send to Ollama
|
|||
- Micro-interactions: 160–200ms colour/transform transitions, `active:scale-[0.985]`, skeleton
|
||||
shimmer, hairline hover washes on every row and card
|
||||
- **Motion (phones)**: one shared language (`lib/motion.ts`) — every button, card, chip, tab and
|
||||
drawer row scales to 0.96 on press with a spring release; the tab bar, segmented controls and
|
||||
nav row scales to 0.96 on press with a spring release; the tab bar, segmented controls and
|
||||
difficulty/size pickers glide their highlight with a shared `layoutId`; wizard steps slide
|
||||
forward and backward and page content enters direction-aware; the Settings sheet and drawer
|
||||
follow the finger and settle on release velocity; library cards fade up in a capped stagger and
|
||||
animate out on delete; score and XP count up; correct answers pulse, wrong ones shake;
|
||||
forward and backward and page content enters direction-aware; the Settings sheet and the library
|
||||
actions sheet follow the finger and settle on release velocity; library cards fade up in a capped
|
||||
stagger and animate out on delete; score and XP count up; correct answers pulse, wrong ones shake;
|
||||
`prefers-reduced-motion` collapses everything to short fades. Only transform and opacity
|
||||
animate — never blur.
|
||||
- **iOS-flavoured PWA**: standalone mode, safe-area insets, bottom tab bar, sheet-style dialogs with
|
||||
|
|
@ -537,8 +541,8 @@ on Android Chrome a captured `beforeinstallprompt` turns into a real **Install**
|
|||
can be reopened any time from **Settings → Install app** (mobile only).
|
||||
|
||||
It launches full-screen in standalone mode (no browser chrome), respects the notch/home-indicator
|
||||
safe areas, and has an iOS-style bottom tab bar (Library · New deck · Settings) with sheet-style
|
||||
dialogs. Android Chrome also offers "Install app" from the ⋮ menu; Freezmo works offline for the
|
||||
safe areas, and has an iOS-style bottom tab bar (Library · Progress · New deck · Exam · Settings)
|
||||
with sheet-style dialogs. Android Chrome also offers "Install app" from the ⋮ menu; Freezmo works offline for the
|
||||
parts that don't need a model.
|
||||
|
||||
What's included:
|
||||
|
|
@ -1018,6 +1022,22 @@ Things I chose while building, with the reasoning:
|
|||
phone and desktop check flows, the shorter follow-up with restore, the guide's explain action,
|
||||
and the deck hand-off).
|
||||
|
||||
43. **Phones navigate with five tabs, not a drawer.** The drawer, its hamburger, its
|
||||
drag-to-close gesture and its back-gesture layer are gone (`MobileSidebar`, `sidebarOpen`,
|
||||
`MenuIcon` and the three drawer strings deleted); the desktop rail is untouched and is now the
|
||||
only consumer of the shared nav content. The bottom bar is **Library · Progress · New deck (the
|
||||
prominent centre +) · Exam · Settings**, keeping the sliding pill, press feedback, re-tap-to-top
|
||||
and safe-area padding. Tab labels use dedicated short `tab.*` keys because the old names
|
||||
(“Zkouškový režim”) can't fit five-up at 360px; the matrix in the mobile suite checks every
|
||||
label against clipping at 360/390, EN/CS, dark/light and with reduced motion on and off. The
|
||||
wizards keep their own bottom action bar, so the tab bar steps aside there, exactly as before.
|
||||
Drawer-only destinations were re-homed: Progress and Exam became tabs, the New deck screen got
|
||||
a **Study deck ⇄ Make my homework** segmented switch (also on `/homework`), and the library's
|
||||
phone row gained a **⋯** sheet with Import JSON + New folder (folder chips still appear only
|
||||
once a folder exists). Verified by the mobile suite (134 checks: no hamburger/drawer, tab order,
|
||||
the label matrix, per-tab routing, deep links, Back from every tab and the ⋯ sheet) plus the
|
||||
other ten standing suites.
|
||||
|
||||
36. **The mobile declutter pass reshapes, it doesn't fork.** Phones (≤639px) get a 3-step deck
|
||||
flow and a 2-step homework flow that share the exact state and handlers with the desktop
|
||||
cards (one `UploadScreen` / one `HomeworkInput`, two layouts switched by `useIsPhone()`);
|
||||
|
|
@ -1046,7 +1066,7 @@ Things I chose while building, with the reasoning:
|
|||
transform on an ancestor becomes the containing block for `position: fixed`, so the bar
|
||||
used to paint inside the content and jump to the viewport bottom a second later. It now
|
||||
only fades in, pinned to the bottom from its first frame — verified by sampling its
|
||||
position across the entrance (5 frames, 60–450ms) from the tab bar, the drawer and the
|
||||
position across the entrance (5 frames, 60–450ms) from the tab bar, the mode switch and the
|
||||
empty state, at 360/390, both themes, both languages and with reduced motion.
|
||||
|
||||
39. **Native feel is layered onto the platform, never around it.** The Back gesture closes the
|
||||
|
|
@ -1059,7 +1079,7 @@ Things I chose while building, with the reasoning:
|
|||
Wizard drafts and the last URL are per-browser; the share target hands POSTed files to the
|
||||
client through a ten-minute in-memory store so nothing touches disk. Verified by the native
|
||||
suite (35 checks: manifest/head/viewport, offline banner + disabled generate, share target GET
|
||||
and POST, back-gesture closing for drawer/sheet/wizard, undo toast, share fallback, tab
|
||||
and POST, back-gesture closing for sheet/wizard, undo toast, share fallback, tab
|
||||
re-tap, haptics persistence, draft restore) plus the six standing suites.
|
||||
|
||||
**Needs a real device to verify** (emulation can't do these honestly): the iOS hidden-switch
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue