Skip to content

feat: mobile responsive layout with PWA support#23

Open
shakogegia wants to merge 22 commits intomainfrom
gego/pwa-standalone-padding
Open

feat: mobile responsive layout with PWA support#23
shakogegia wants to merge 22 commits intomainfrom
gego/pwa-standalone-padding

Conversation

@shakogegia
Copy link
Copy Markdown
Owner

Summary

  • Adds a mobile-first responsive layout with full-screen tab views and bottom navigation bar for screens below 768px, while preserving the existing desktop sidebar+preview layout
  • Adds PWA support with web app manifest, app icons, and theme-color meta tags so the app can be installed on mobile home screens
  • Fixes various mobile UX issues: viewport height (dvh), safe area padding for standalone mode, scrollable preview, centered empty states, and persistent tab selection across refreshes

Test plan

  • Verify desktop layout is unchanged at widths >= 768px
  • Test mobile layout at < 768px: bottom nav, full-screen tabs, tab switching
  • Install as PWA on iOS/Android and verify standalone mode with proper safe area insets
  • Test library and Calibre tabs on mobile with touch interactions

🤖 Generated with Claude Code

shakogegia and others added 22 commits March 28, 2026 13:02
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The default variant added bg-muted, rounded corners, h-8 constraint,
and forced icon sizing that broke the bottom navigation appearance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Content was extending behind the dynamic island/status bar on
notched iPhones since viewport-fit=cover was set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
viewport-fit=cover behaves inconsistently between Chrome and Safari
on iOS. The default viewport-fit=contain lets browsers handle safe
areas natively, which works consistently on both.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e tabs

- h-dvh on mobile prevents content extending behind browser chrome
  (100vh includes address bar on iOS, 100dvh does not)
- MobileLayout uses ?view= instead of ?tab= to avoid hydration
  mismatch with Sidebar (which doesn't have a "preview" tab)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Inline style overrides h-screen on browsers that support dvh,
falls back to 100vh (h-screen) on browsers that don't. Fixes
bottom tab bar being hidden behind Chrome's mobile toolbar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DevicePreview clips overflow, so on small screens the generate button
and controls were hidden. Wrap in scrollable container so users can
scroll to see the full device frame and controls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Give DevicePreview min-h-full so its flex centering works when
no book is loaded, while still allowing scroll when content overflows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use flex wrapper with shrink-0/basis-auto overrides on DevicePreview:
- Empty: flex-grow fills wrapper, centering works
- Loaded: basis-auto preserves content size, wrapper scrolls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server has no access to URL params, so urlSync causes server/client
divergence. Mobile tabs are ephemeral and always start on library
(library-first design).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "preview" to valid tabs in page.tsx so server passes it through
- MobileLayout writes ?tab= to URL on tab change (write-only, no
  read on mount) so the server can restore the correct tab on refresh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Web App Manifest with app name, icons (192/512 PNG + SVG), standalone display
- Theme-color meta adapts to light/dark mode
- Apple web app meta for iOS home screen
- Fix preview scroll on mobile (conditional wrapper based on bookLoaded)
- Suppress hydration warning on OPDS input (Chrome extension injects attrs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Re-add viewport-fit=cover (needed for env() safe area values) and
pad the bottom tab bar for the home indicator in standalone mode.
In browser mode env(safe-area-inset-bottom) returns 0, so no effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@shakogegia shakogegia force-pushed the gego/pwa-standalone-padding branch from d3e57db to 47d4b3a Compare March 28, 2026 12:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant