Sidebar
Componente sidebar do design system adila.co.
Instalação
bun add @adila-sh/uiUso
Envolva a aplicação com SidebarProvider, coloque a navegação dentro de
Sidebar com collapsible="icon" e use SidebarInset para o conteúdo
principal. O SidebarTrigger e o SidebarRail abrem e recolhem a barra
entre a navegação completa e o trilho de ícones (também via Ctrl/Cmd + B).
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@adila-sh/ui";
import { Calendar, Home, Inbox, Search, Settings } from "lucide-react";
const items = [
{ title: "Início", url: "#", icon: Home },
{ title: "Caixa de entrada", url: "#", icon: Inbox },
{ title: "Calendário", url: "#", icon: Calendar },
{ title: "Buscar", url: "#", icon: Search },
{ title: "Configurações", url: "#", icon: Settings },
];
export function Example() {
return (
<SidebarProvider>
<Sidebar collapsible="icon">
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Aplicativo</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton
render={<a href={item.url} />}
tooltip={item.title}
>
<item.icon />
<span>{item.title}</span>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<SidebarTrigger />
</SidebarInset>
<SidebarRail />
</SidebarProvider>
);
}App shell persistente
Monte o SidebarProvider uma única vez no layout persistente do roteador. As
páginas devem trocar dentro do SidebarInset; não recrie o provider em cada
rota, pois isso remonta a navegação e reinicia estados do shell.
Com TanStack Router, use uma rota pathless e um Outlet:
import { createFileRoute, Outlet } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { getCookie } from "@tanstack/react-start/server";
const getSidebarDefaultOpen = createServerFn({ method: "GET" }).handler(
() => getCookie("sidebar_state") !== "false",
);
export const Route = createFileRoute("/_app")({
loader: () => getSidebarDefaultOpen(),
component: AppShell,
});
function AppShell() {
const sidebarDefaultOpen = Route.useLoaderData();
return (
<SidebarProvider defaultOpen={sidebarDefaultOpen}>
<AppSidebar />
<SidebarInset>
<AppHeader />
<Outlet />
</SidebarInset>
</SidebarProvider>
);
}Use arquivos filhos como _app.clientes.tsx e _app.configuracoes.tsx. O
segmento _app não aparece na URL e o shell continua montado durante a
navegação. Para links internos, renderize o Link do roteador através de
SidebarMenuButton e derive isActive da rota atual. Em aplicações SSR, leia
o cookie no loader para que o primeiro HTML já use o estado correto; não faça a
restauração em useEffect.
Dependências
class-variance-authoritylucide-react