v0.17.0 — Mobile menu (#3) + Suggestions readability & header lightbulb (#2)

Addresses Gitea suggestions #3 and #2.

#3 Mobile: the sidebar was desktop-only (hidden md:flex), leaving phones with no
nav at all. Added a slide-out drawer (hamburger in the top bar, md:hidden) that
reuses the nav. Lifted navItems/settingsItems into src/components/layout/nav-items.ts
so the sidebar and mobile drawer share one source + active-state logic. No HTTPS
needed (pure responsive UI).

#2 Suggestions: the @otm/account-panel SuggestionsPanel hardcodes light neutral-*
text that assumes a white backdrop, so it washed out on the app theme — now
rendered on a white card for contrast in light/dark. Added a lightbulb button in
the header that jumps to Suggestions (like FMB).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-16 02:16:57 -05:00
parent b8af0f986b
commit 4aacffdf4e
7 changed files with 163 additions and 55 deletions

View File

@@ -0,0 +1,34 @@
import {
LayoutDashboard, Leaf, BookOpen, Package, PawPrint, MapPin, Bell,
Lightbulb, KeyRound, HardDrive, RefreshCw, type LucideIcon,
} from "lucide-react";
export type NavItem = { label: string; href: string; icon: LucideIcon };
export const navItems: NavItem[] = [
{ label: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
{ label: "Garden", href: "/garden", icon: Leaf },
{ label: "Plant types", href: "/garden/types", icon: BookOpen },
{ label: "Inventory", href: "/inventory", icon: Package },
{ label: "Animals", href: "/animals", icon: PawPrint },
{ label: "Locations", href: "/locations", icon: MapPin },
{ label: "Reminders", href: "/tasks", icon: Bell },
];
export const settingsItems: NavItem[] = [
{ label: "Suggestions", href: "/suggestions", icon: Lightbulb },
{ label: "API tokens", href: "/settings/tokens", icon: KeyRound },
{ label: "Backup & Restore", href: "/settings/backup", icon: HardDrive },
{ label: "Updates", href: "/settings/updates", icon: RefreshCw },
];
// Active on exact match or a sub-path, unless a more specific item (e.g.
// /garden/types) already claims the current path.
export function isNavActive(path: string, href: string, all: NavItem[]): boolean {
if (path === href) return true;
if (href === "/dashboard") return false;
if (!path.startsWith(href + "/")) return false;
return !all.some(
(o) => o.href.length > href.length && (path === o.href || path.startsWith(o.href + "/")),
);
}