DS | Adila.co
Componentes

Sidebar

Componente sidebar do design system adila.co.

Instalação

bun add @adila-sh/ui

Uso

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-authority
  • lucide-react

Componentes relacionados

Nesta página