diff --git a/src/components/settings/settings-shell.tsx b/src/components/settings/settings-shell.tsx
index 08b9b62..bf2cfd0 100644
--- a/src/components/settings/settings-shell.tsx
+++ b/src/components/settings/settings-shell.tsx
@@ -3,6 +3,7 @@
import {
useCallback,
useEffect,
+ useState,
type ComponentType,
type ReactNode,
} from "react"
@@ -12,6 +13,7 @@ import {
GitBranch,
Globe,
Keyboard,
+ Menu,
SendHorizontal,
Palette,
PlugZap,
@@ -26,6 +28,8 @@ import { AppToaster } from "@/components/ui/app-toaster"
import { cn } from "@/lib/utils"
import { detectEnvironment } from "@/lib/transport/detect"
import { AppTitleBar } from "@/components/layout/app-title-bar"
+import { useIsMobile } from "@/hooks/use-mobile"
+import { Sheet, SheetContent, SheetTitle } from "@/components/ui/sheet"
interface SettingsNavItem {
href: string
@@ -118,6 +122,8 @@ export function SettingsShell({ children }: SettingsShellProps) {
const pathname = usePathname()
const router = useRouter()
const normalizedPathname = normalizePath(pathname)
+ const isMobile = useIsMobile()
+ const [navOpen, setNavOpen] = useState(false)
useEffect(() => {
document.title = `${t("title")} - codeg`
@@ -129,67 +135,108 @@ export function SettingsShell({ children }: SettingsShellProps) {
const target = normalizePath(href)
const current = normalizePath(window.location.pathname)
- if (current === target) return
+ if (current === target) {
+ setNavOpen(false)
+ return
+ }
if (isWindowsRuntime()) {
- // WebView2 on Windows: hard navigation is more reliable than client routing.
window.location.assign(target)
return
}
- // macOS/Linux: keep client-side routing for snappier transitions.
router.push(target)
+ setNavOpen(false)
},
- [router]
+ [router, setNavOpen]
+ )
+
+ const filteredNavItems = SETTINGS_NAV_ITEMS.filter(
+ (item) =>
+ !(item.labelKey === "web_service" && detectEnvironment() === "web")
+ )
+
+ const navContent = (
+ <>
+
+ {t("preferences")}
+
+
+ >
)
return (
setNavOpen(true)}
+ >
+
+
+ ) : undefined
+ }
center={
{t("title")}
}
/>
-
+ {/* Desktop sidebar */}
+ {!isMobile && (
+
+ )}
-
+ {/* Mobile navigation Sheet */}
+ {isMobile && (
+
+
+ {t("title")}
+ {navContent}
+
+
+ )}
+
+
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
index 10087cf..652d5d3 100644
--- a/src/components/ui/button.tsx
+++ b/src/components/ui/button.tsx
@@ -5,7 +5,7 @@ import { Slot } from "radix-ui"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
- "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-4xl border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
+ "group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
@@ -15,9 +15,9 @@ const buttonVariants = cva(
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
ghost:
- "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
destructive:
- "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx
index b52b7d4..611a140 100644
--- a/src/components/ui/command.tsx
+++ b/src/components/ui/command.tsx
@@ -34,7 +34,7 @@ function CommandDialog({
}) {
return (