Split Apps sidebar item: label links to /apps, chevron toggles sub-nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { NavLink, useLocation, useNavigate } from "react-router-dom";
|
import { NavLink, useLocation } from "react-router-dom";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import {
|
import {
|
||||||
Home,
|
Home,
|
||||||
@@ -24,7 +24,6 @@ export default function Sidebar() {
|
|||||||
const [sidebarExpanded, setSidebarExpanded] = useState(true);
|
const [sidebarExpanded, setSidebarExpanded] = useState(true);
|
||||||
const { logout } = useAuth();
|
const { logout } = useAuth();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
|
||||||
const { data: user } = useQuery({ queryKey: ["me"], queryFn: getMe });
|
const { data: user } = useQuery({ queryKey: ["me"], queryFn: getMe });
|
||||||
|
|
||||||
const isAppsRoute = location.pathname.startsWith("/apps");
|
const isAppsRoute = location.pathname.startsWith("/apps");
|
||||||
@@ -97,36 +96,44 @@ export default function Sidebar() {
|
|||||||
|
|
||||||
{/* Apps — expandable */}
|
{/* Apps — expandable */}
|
||||||
<div>
|
<div>
|
||||||
<button
|
{sidebarExpanded ? (
|
||||||
onClick={() => {
|
<div
|
||||||
if (!sidebarExpanded) {
|
|
||||||
navigate("/apps");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setAppsOpen((o) => !o);
|
|
||||||
}}
|
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full flex items-center rounded-lg transition-colors",
|
"flex items-center rounded-lg transition-colors",
|
||||||
sidebarExpanded ? "px-3 py-2 gap-3" : "justify-center py-3",
|
|
||||||
isAppsRoute
|
isAppsRoute
|
||||||
? "bg-primary/10 text-primary"
|
? "bg-primary/10 text-primary"
|
||||||
: "text-muted hover:bg-muted/20 hover:text-foreground"
|
: "text-muted hover:bg-muted/20 hover:text-foreground"
|
||||||
)}
|
)}
|
||||||
|
>
|
||||||
|
<NavLink
|
||||||
|
to="/apps"
|
||||||
|
end
|
||||||
|
className="flex items-center gap-3 px-3 py-2 flex-1 min-w-0"
|
||||||
>
|
>
|
||||||
<Grid2X2 className="h-5 w-5 shrink-0" />
|
<Grid2X2 className="h-5 w-5 shrink-0" />
|
||||||
{sidebarExpanded && (
|
<span className="text-sm font-medium whitespace-nowrap">Apps</span>
|
||||||
<>
|
</NavLink>
|
||||||
<span className="text-sm font-medium whitespace-nowrap flex-1 text-left">
|
<button
|
||||||
Apps
|
onClick={() => setAppsOpen((o) => !o)}
|
||||||
</span>
|
className="px-2 py-2 rounded-r-lg"
|
||||||
|
aria-label={appsOpen ? "Collapse apps" : "Expand apps"}
|
||||||
|
>
|
||||||
{appsOpen ? (
|
{appsOpen ? (
|
||||||
<ChevronDown className="h-4 w-4 shrink-0" />
|
<ChevronDown className="h-4 w-4 shrink-0" />
|
||||||
) : (
|
) : (
|
||||||
<ChevronRight className="h-4 w-4 shrink-0" />
|
<ChevronRight className="h-4 w-4 shrink-0" />
|
||||||
)}
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<NavLink
|
||||||
|
to="/apps"
|
||||||
|
end
|
||||||
|
className={({ isActive }) => navItemClass(isActive)}
|
||||||
|
>
|
||||||
|
<Grid2X2 className="h-5 w-5 shrink-0" />
|
||||||
|
</NavLink>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Apps sub-items — only when sidebar is expanded and appsOpen */}
|
{/* Apps sub-items — only when sidebar is expanded and appsOpen */}
|
||||||
{sidebarExpanded && appsOpen && (
|
{sidebarExpanded && appsOpen && (
|
||||||
|
|||||||
Reference in New Issue
Block a user