Add responsive mobile layout for the Play screen and nav
The stylesheet had no real mobile design (one media query that only hid a nav hint), so on phones the Play screen's four side-by-side columns overflowed horizontally. Add a max-width:720px layer that collapses the Play layout to a single story column, turns the World/Script State rails into left-edge tabs that open as slide-in overlays, and makes the Plot/Memory/Scripts/Insights side-panel a full-screen overlay. Also add a hamburger dropdown for the top nav, switch the play-layout heights from vh to dvh (fixes the mobile address-bar jump), and bump inputs to 16px to stop iOS zoom-on-focus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UWVyFKvqJGjfbXdibLgkMe
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
141eec7c64
commit
8fc6d4d2e0
+39
-28
@@ -7,6 +7,7 @@ export default function App() {
|
||||
// null until /auth/me resolves; in local mode multi_user=false hides all auth UI.
|
||||
const [me, setMe] = useState(null)
|
||||
const [authMode, setAuthMode] = useState(null) // 'register' | 'login' | null
|
||||
const [navOpen, setNavOpen] = useState(false) // mobile hamburger menu
|
||||
|
||||
useEffect(() => {
|
||||
api.getMe().then(setMe).catch(() => {})
|
||||
@@ -31,34 +32,44 @@ export default function App() {
|
||||
<>
|
||||
<nav className="topnav">
|
||||
<span className="brand">⚔ AI D&D</span>
|
||||
<NavLink to="/" end className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Adventures
|
||||
</NavLink>
|
||||
<NavLink to="/scenarios" className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Scenarios
|
||||
</NavLink>
|
||||
<NavLink to="/scripts" className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Scripts
|
||||
</NavLink>
|
||||
<NavLink to="/settings" className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Settings
|
||||
</NavLink>
|
||||
{me?.multi_user && (
|
||||
<div className="nav-account">
|
||||
{me.is_guest ? (
|
||||
<>
|
||||
<span className="guest-nudge">Playing as guest — sign up to keep your adventures</span>
|
||||
<button onClick={() => setAuthMode('login')}>Log in</button>
|
||||
<button className="primary" onClick={() => setAuthMode('register')}>Sign up</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="account-email" title={me.email}>{me.email}</span>
|
||||
<button onClick={logout}>Log out</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
className="nav-hamburger"
|
||||
aria-label="Menu"
|
||||
aria-expanded={navOpen}
|
||||
onClick={() => setNavOpen((o) => !o)}
|
||||
>
|
||||
{navOpen ? '✕' : '☰'}
|
||||
</button>
|
||||
<div className={`nav-links${navOpen ? ' open' : ''}`} onClick={() => setNavOpen(false)}>
|
||||
<NavLink to="/" end className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Adventures
|
||||
</NavLink>
|
||||
<NavLink to="/scenarios" className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Scenarios
|
||||
</NavLink>
|
||||
<NavLink to="/scripts" className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Scripts
|
||||
</NavLink>
|
||||
<NavLink to="/settings" className={({ isActive }) => `navlink${isActive ? ' active' : ''}`}>
|
||||
Settings
|
||||
</NavLink>
|
||||
{me?.multi_user && (
|
||||
<div className="nav-account">
|
||||
{me.is_guest ? (
|
||||
<>
|
||||
<span className="guest-nudge">Playing as guest — sign up to keep your adventures</span>
|
||||
<button onClick={() => setAuthMode('login')}>Log in</button>
|
||||
<button className="primary" onClick={() => setAuthMode('register')}>Sign up</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="account-email" title={me.email}>{me.email}</span>
|
||||
<button onClick={logout}>Log out</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
<Outlet context={{ me, setMe }} />
|
||||
{authMode && (
|
||||
|
||||
Reference in New Issue
Block a user