feat(mobile): give the mobile shell a bottom tab bar - #557
Merged
Conversation
The mobile shell shared MainLayout's off-canvas drawer as its only navigation, so every page switch cost two taps and a full-screen scrim, and the drawer showed a shrunk copy of the desktop information architecture whose maintenance/admin sections are empty on the read-only Android client. Add a mobile-runtime-only bottom tab bar for the four frequent destinations — Library, Recently read, Downloads, Settings — reachable in one tap. The drawer stays for shelf switching, Home, and the folder tree; its now-redundant nav sections (Recently read, Downloads, Logs, Settings) are hidden on the mobile runtime. The tab bar is a shared component that imports nothing mobile-only, so it clears the module-boundary check while MainLayout gates it on isMobileRuntime() — the same signal the shell itself uses, and the one under which the Downloads destination exists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5wyZmR7Uw8Cw47atghjnK
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00f8c1d070
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
`library` (/books) and `book-detail` (/books/:id) are sibling route records, so RouterLink's record-based active matching lit the Library tab on neither. Compute the tab's active state from the current path instead, so it owns the whole /books subtree (list, a book, the maintenance filters that redirect into it) while the leaf tabs match their own path only. The unit test now drives a real memory router with the same sibling shape rather than a RouterLink stub, which is what let the bug through. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5wyZmR7Uw8Cw47atghjnK
The new fixed bottom tab bar sat on top of the mobile multi-select "Download to device" action bar (both fixed at the bottom edge), so its button's taps were intercepted and mobile-multiselect e2e timed out. Reserve the bar's height as a shared --mobile-tab-bar-height token and offset the selection action bar above it. The action bar only renders on the mobile runtime — the same condition under which the tab bar exists — so the offset always clears it. MainLayout's page padding uses the same token instead of a hard-coded height. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5wyZmR7Uw8Cw47atghjnK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Ticket: 手機導覽是桌面側邊欄塞進抽屜,切頁要兩次點擊 (PlainShelf 工作項目)
The mobile shell reused
MainLayout's off-canvas drawer as its only navigation, so every page switch cost two taps and a full-screen scrim, and the drawer rendered a shrunk copy of the desktop information architecture — whose maintenance/admin sections are empty on the read-only Android client.The ticket was blocked on a product decision (is Android a primary reading device?). That was resolved: yes → walk A (bottom tab bar + drawer kept only for the folder tree).
Changes
MobileTabBar.vue— a bottom tab bar for the four frequent destinations, reachable in one tap:/books· 最近閱讀/read-history· 下載/downloads· 設定/settingscheck-boundaries;MainLayoutgates it onisMobileRuntime()— the same signal the shell itself uses, and the one under which the Downloads destination exists. A narrow desktop browser keeps the existing drawer.MainLayout.vue— renders the tab bar on the mobile runtime, adds bottom padding so content clears the fixed bar, and hides the drawer's now-redundant nav sections there (Recently read, Downloads, Logs, Settings). The drawer keeps shelf switching, Home, and the folder tree.libraryicon (tabler/books) andlayout.library/layout.tabNavLabellabels in bothenandzh-Hant.Scope notes
isMobileRuntime()./home) stays reachable from the drawer, per the ticket's "fold dashboard into the drawer".Checks
npm --prefix frontend test— 1292 passed (incl. newMobileTabBar.test.ts)npm --prefix frontend run build(vue-tsc + vite) — cleannpm --prefix frontend run check-boundaries— OK (3 rules)npm --prefix frontend run check-licenses— OKmobile-read-only,sidebar-rail,sidebar-foldable,mobile-downloads,mobile-shelves,mobile-download-badge-layout,read-history,locale,settings-tabs— 34 passed. Added a tab-bar assertion tomobile-read-only.spec.ts(Downloads stays a single link, now via the tab).🤖 Generated with Claude Code
https://claude.ai/code/session_01K5wyZmR7Uw8Cw47atghjnK
Generated by Claude Code