hamburger nav on all touch devices, add eruda for debugging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 20:34:54 +00:00
co-authored by Claude Opus 4.6
parent e0f470137b
commit 1cbf9553ec
4 changed files with 24 additions and 6 deletions
@@ -2,24 +2,25 @@ import { useDock } from 'officerdev';
import { Background } from './Background'; import { Background } from './Background';
import { Header } from './Header'; import { Header } from './Header';
import { Dock, ALL_DOCK_ITEMS, DEFAULT_DOCK_PATHS } from './Dock'; import { Dock, ALL_DOCK_ITEMS, DEFAULT_DOCK_PATHS } from './Dock';
import { useIsTouch } from './useIsTouch';
type DashboardLayoutProps = { type DashboardLayoutProps = {
children?: React.ReactNode; children?: React.ReactNode;
}; };
export function DashboardLayout({ children }: DashboardLayoutProps) { export function DashboardLayout({ children }: DashboardLayoutProps) {
const { items: visibleItems } = useDock(ALL_DOCK_ITEMS, DEFAULT_DOCK_PATHS); const { items: visibleItems } = useDock(ALL_DOCK_ITEMS, DEFAULT_DOCK_PATHS);
const isTouch = useIsTouch();
return ( return (
<div className="relative overflow-hidden h-dvh outline-none inset-0"> <div className="relative overflow-hidden h-dvh outline-none inset-0">
<Header dockItems={visibleItems} /> <Header dockItems={visibleItems} />
<section className="relative h-dvh snap-start overflow-hidden"> <section className="relative h-dvh snap-start overflow-hidden">
<Background /> <Background />
<Dock items={visibleItems} className="hidden md:flex" /> {!isTouch && <Dock items={visibleItems} className="hidden md:flex" />}
<div className="absolute inset-0 z-2 pt-[52px] md:pt-[64px] pb-2 overflow-y-auto"> <div className="absolute inset-0 z-2 pt-[52px] md:pt-[64px] pb-2 overflow-y-auto">
{children} {children}
</div> </div>
</section> </section>
</div> </div>
); );
}; };
@@ -2,8 +2,8 @@ import { useState } from 'react';
import { Link, useLocation } from 'react-router'; import { Link, useLocation } from 'react-router';
import { Menu } from 'lucide-react'; import { Menu } from 'lucide-react';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet'; import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { useIsMobile } from 'hooks/useIsMobile';
import type { DockItem } from '../Dock'; import type { DockItem } from '../Dock';
import { useIsTouch } from '../useIsTouch';
import { UserMenu } from './UserMenu'; import { UserMenu } from './UserMenu';
type HeaderProps = { type HeaderProps = {
@@ -12,7 +12,7 @@ type HeaderProps = {
export function Header({ dockItems }: HeaderProps) { export function Header({ dockItems }: HeaderProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const isMobile = useIsMobile(); const isTouch = useIsTouch();
const location = useLocation(); const location = useLocation();
const isActive = (to: string) => (to === '/' ? location.pathname === '/' : location.pathname.startsWith(to)); const isActive = (to: string) => (to === '/' ? location.pathname === '/' : location.pathname.startsWith(to));
@@ -24,7 +24,7 @@ export function Header({ dockItems }: HeaderProps) {
style={{ backgroundColor: 'rgba(255, 255, 255, 0.25)', borderColor: 'rgba(255, 255, 255, 0.35)' }} style={{ backgroundColor: 'rgba(255, 255, 255, 0.25)', borderColor: 'rgba(255, 255, 255, 0.35)' }}
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{isMobile && dockItems && ( {isTouch && dockItems && (
<button onClick={() => setOpen(true)} className="p-1.5 rounded-md hover:bg-white/20 transition-colors"> <button onClick={() => setOpen(true)} className="p-1.5 rounded-md hover:bg-white/20 transition-colors">
<Menu className="h-5 w-5 text-white" /> <Menu className="h-5 w-5 text-white" />
</button> </button>
@@ -41,7 +41,7 @@ export function Header({ dockItems }: HeaderProps) {
<UserMenu /> <UserMenu />
</div> </div>
{isMobile && dockItems && ( {isTouch && dockItems && (
<Sheet open={open} onOpenChange={setOpen}> <Sheet open={open} onOpenChange={setOpen}>
<SheetContent side="left"> <SheetContent side="left">
<SheetHeader> <SheetHeader>
@@ -0,0 +1,15 @@
import { useState, useEffect } from 'react';
export const useIsTouch = () => {
const [isTouch, setIsTouch] = useState(false);
useEffect(() => {
const mql = window.matchMedia('(pointer: coarse)');
setIsTouch(mql.matches);
const onChange = (ev: MediaQueryListEvent) => setIsTouch(ev.matches);
mql.addEventListener('change', onChange);
return () => mql.removeEventListener('change', onChange);
}, []);
return isTouch;
};
+2
View File
@@ -31,6 +31,8 @@
<link rel="manifest" href="https://static.officer.dev/site.webmanifest" /> <link rel="manifest" href="https://static.officer.dev/site.webmanifest" />
<meta name="theme-color" content="#1F2620" /> <meta name="theme-color" content="#1F2620" />
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>
<script type="module" src="./frontend.tsx" async></script> <script type="module" src="./frontend.tsx" async></script>
</head> </head>
<body> <body>