Sidebar
Uma barra lateral de app que recolhe para ícones ou fora da tela, permanece fixa sob o seu cabeçalho e vira uma sheet com deslize no celular.
pnpm dlx shadcn@latest add https://hextaui.com/r/sidebar.jsonAdiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.
Adicione os tokens de tema ao seu CSS global, se ainda não o fez.
Instale as dependências.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopie e cole o código a seguir no seu projeto.
components/ui/sidebar.tsx components/ui/button.tsx components/ui/input.tsx components/ui/sheet.tsx components/ui/skeleton.tsx components/ui/tooltip.tsx hooks/use-composed-ref.ts lib/hotkey.ts Atualize os caminhos de importação para corresponder à configuração do seu projeto.
Envolva seu layout em <SidebarProvider /> e coloque a página em <SidebarInset />, depois da sidebar.
SidebarProviderguarda o estado de aberto, o atalho de teclado e as larguras.Sidebaré uma coluna que permanece fixa enquanto a página rola. Abaixo de 768px vira um sheet.SidebarHeadereSidebarFooterficam no lugar.SidebarContentrola entre eles.SidebarGroupé uma seção com rótulo e ação opcionais.SidebarMenucontém os links.SidebarInseté a página ao lado da sidebar.
Variantes
variant define a aparência: uma sidebar de altura total, um painel floating, ou inset, em que a página vira um card sobre a cor da sidebar. Alterne entre elas para ver o layout animar.
Collapsible
offcanvas desliza a sidebar para fora da vista, icon a reduz aos seus ícones e mostra cada rótulo em um tooltip, e none a mantém aberta. Pressione ⌘B ou Ctrl+B para alternar a sidebar em que você está trabalhando.
Grupos e submenus recolhíveis
Envolva um SidebarGroup ou um SidebarMenuItem em um Collapsible, renderize o rótulo ou o botão como gatilho e aninhe um SidebarMenuSub.
Lado direito
Defina side="right" e coloque a sidebar depois de SidebarInset. O rail e o sheet mobile seguem o lado.
Sob um cabeçalho
A sidebar é sticky, então começa abaixo de tudo o que está acima dela. Com um cabeçalho sticky, defina --sidebar-top com a altura dele e a sidebar fixa abaixo dele e ocupa o resto da tela.
Controlado
Passe open e onOpenChange. O gatilho, o rail e o atalho passam todos por onOpenChange.
Carregando
SidebarMenuSkeleton preenche um menu enquanto ele carrega. As larguras variam por linha e coincidem entre servidor e cliente.
Da direita para a esquerda
Defina dir="rtl" e side="right". Espaçamento, linhas de submenu, tooltips e o ícone do gatilho são espelhados.
A sidebar tem 16rem de largura, 18rem em celulares e 3rem quando reduzida a ícones. Sobrescreva --sidebar-width, --sidebar-width-mobile e --sidebar-width-icon no provider.
A sidebar não tem efeitos colaterais. Para lembrar se estava aberta, salve em onOpenChange e leia de volta em defaultOpen ao renderizar no servidor.
| Tecla | Ação |
|---|---|
| ⌘ + BCtrl + B | Alterna a sidebar. Com várias sidebars em uma página, responde a que tem o foco, senão a primeira. Ignorado ao digitar em um editor de rich text. |
| TabShift + Tab | Percorre os links. Uma sidebar recolhida fora da tela é ignorada. |
| EnterSpace | Ativa o link, botão ou gatilho com foco. |
| Esc | Fecha a sidebar em celulares. |
SidebarTriggeré rotulado “Toggle Sidebar” e expõearia-expandedearia-controls.isActivedefinearia-current="page".- Recolher para fora da tela oculta o conteúdo do teclado e dos leitores de tela. Se o foco estava dentro, ele vai para o gatilho.
- Reduzida a ícones, os rótulos permanecem no nome acessível de cada link e aparecem como tooltip no hover e no foco do teclado. Rótulos de grupo, ações e badges ficam ocultos.
- Em celulares a sidebar é um sheet modal: o foco fica preso, deslizar ou Esc a fecha, e seguir um link a fecha. Links que abrem uma nova aba, downloads e cliques com modificadores a mantêm aberta.
- Com movimento reduzido ativado, o recolhimento é instantâneo.
| Prop | Tipo | Padrão |
|---|---|---|
defaultOpen | boolean | true |
open | boolean | – |
onOpenChange | (open: boolean) => void | – |
keyboardShortcutmod é ⌘ em plataformas Apple e Ctrl nas demais. null desativa. | string | null | "mod+b" |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-wrapper" | O wrapper de layout. |
--sidebar-width | Largura expandida. O padrão é 16rem. |
--sidebar-width-mobile | Largura do sheet do celular. O padrão é 18rem. |
--sidebar-width-icon | Largura quando reduzida a ícones. O padrão é 3rem. |
--sidebar-top | Onde a sidebar fixa ao rolar, como abaixo de um cabeçalho sticky. O padrão é 0px. |
className e outras props vão para o contêiner da sidebar.
| Prop | Tipo | Padrão |
|---|---|---|
side | "left" | "right" | "left" |
variantplain remove a superfície, a linha da borda, a barra de rolagem e o espaço entre os itens do menu, para uma sidebar que fica sobre a página. | "sidebar" | "floating" | "inset" | "plain" | "sidebar" |
collapsible | "offcanvas" | "icon" | "none" | "offcanvas" |
mobileComo abre em celulares: um sheet pela lateral, ou deslizando para preencher a tela, como nos apps de chat. | "sheet" | "fullscreen" | "sheet" |
dirTambém define a direção do sheet no celular. | "ltr" | "rtl" | – |
| Atributo | Descrição |
|---|---|
data-slot="sidebar" | A sidebar, ou o sheet em celulares. |
data-state | "expanded" ou "collapsed". |
data-collapsible | O modo recolhível enquanto recolhida, senão "". Estilize os filhos com group-data-[collapsible=icon]:. |
data-variant | A variante. |
data-side | O lado. |
data-mobile | Presente no sheet do celular. |
data-slot="sidebar-container" | O painel que desliza e se redimensiona. |
data-slot="sidebar-inner" | A superfície que contém o conteúdo. |
Um Button ghost com ícone que chama toggleSidebar. Chame event.preventDefault() em onClick para impedir. Passe children para substituir o ícone.
| Atributo | Descrição |
|---|---|
data-slot="sidebar-trigger" | O gatilho. |
aria-expanded | Se a sidebar está aberta. |
Uma área de toque fina na borda da sidebar que a alterna ao clicar. Fica fora da ordem de tabulação porque o gatilho e o atalho atendem usuários de teclado. Com a sidebar fora da tela, o rail permanece na borda da tela.
| Atributo | Descrição |
|---|---|
data-slot="sidebar-rail" | O rail. |
Um <main> que ocupa o resto da largura. Ao lado de uma sidebar inset, vira um card arredondado.
| Prop | Tipo | Padrão |
|---|---|---|
renderRenderiza um elemento diferente. Passe um <div /> quando a página já tem um landmark <main>. | React.ReactElement | (props) => React.ReactElement | – |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-inset" | A área da página. |
Elementos <div> simples. O conteúdo rola com uma barra de rolagem fina e esmaecimentos suaves nas bordas.
| Atributo | Descrição |
|---|---|
data-slot="sidebar-header" | Seção superior. |
data-slot="sidebar-content" | Meio rolável. |
data-slot="sidebar-footer" | Seção inferior. |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-group" | Uma seção da sidebar. |
data-slot="sidebar-group-content" | O conteúdo do grupo. |
| Prop | Tipo | Padrão |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-group-label" | Sobe e some com fade quando reduzida a ícones. |
| Prop | Tipo | Padrão |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-group-action" | Precisa de um rótulo acessível. |
Um <ul> e seus itens <li>. Defina gap="none" para listas densas como histórico de chat, onde as linhas ficam coladas.
| Prop | Tipo | Padrão |
|---|---|---|
gapEspaço entre os itens. Também em SidebarMenuSub. | "default" | "none" | "default" |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-menu" | A lista. |
data-slot="sidebar-menu-item" | Um item. group/menu-item para estilos de hover. |
| Prop | Tipo | Padrão |
|---|---|---|
isActiveDestaca-o e define aria-current="page". | boolean | false |
variant | "default" | "outline" | "default" |
size | "default" | "sm" | "lg" | "default" |
tooltipExibido quando reduzida a ícones. O conteúdo desliza entre os itens conforme você percorre o menu. | ReactNode | TooltipContentProps | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-menu-button" | peer/menu-button para estilos de irmãos. |
data-active | Presente enquanto isActive. |
data-size | O tamanho. |
| Prop | Tipo | Padrão |
|---|---|---|
showOnHoverMostra só enquanto o item está com hover ou foco, ou seu menu está aberto. Sempre visível em telas touch. | boolean | false |
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-menu-action" | Precisa de um rótulo acessível. |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-menu-badge" | Uma contagem no fim do item. |
| Prop | Tipo | Padrão |
|---|---|---|
showIcon | boolean | false |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-menu-skeleton" | Oculto das tecnologias assistivas. |
Uma lista aninhada com uma linha na borda inicial. Ela se recolhe quando a sidebar é reduzida a ícones.
| Prop | Tipo | Padrão |
|---|---|---|
isActiveEm SidebarMenuSubButton. | boolean | false |
sizeEm SidebarMenuSubButton. | "sm" | "md" | "md" |
renderEm SidebarMenuSubButton. | ReactElement | (props, state) => ReactElement | <a> |
| Atributo | Descrição |
|---|---|
data-slot="sidebar-menu-sub" | A lista aninhada. |
data-slot="sidebar-menu-sub-button" | Um link aninhado. |
data-active | Presente enquanto isActive. |
Um Input pequeno sobre o fundo da página e um separador de linha fina.
| Atributo | Descrição |
|---|---|
data-slot="sidebar-input" | O input. |
data-slot="sidebar-separator" | O separador. |
Lê e controla a sidebar mais próxima. Lança erro fora de SidebarProvider.
| Prop | Tipo | Padrão |
|---|---|---|
state | "expanded" | "collapsed" | – |
open | boolean | – |
setOpen | (open: boolean) => void | – |
openMobile | boolean | – |
setOpenMobile | (open: boolean) => void | – |
isMobile | boolean | – |
toggleSidebarAlterna o sheet em celulares, senão a sidebar. | () => void | – |
- ButtonBotões em todas as variantes e tamanhos, com um fluxo integrado de carregamento, sucesso e erro que dispensa o spinner em requisições rápidas.
- HotkeyAnalise, rotule, anuncie e compare atalhos de teclado, com ⌘ nas plataformas Apple e Ctrl em todas as outras.
- InputUm campo de texto com três tamanhos, estados inválido e somente leitura, estilo de validação nativa e fonte de 16px no toque para que os celulares nunca façam zoom.
- SheetUm painel que desliza a partir de qualquer borda, com deslize para dispensar, bloqueio de rolagem e aninhamento empilhado.
- SkeletonPlaceholders que esperam 150ms antes de aparecer, assumem o tamanho exato do conteúdo que envolvem e o fazem surgir com fade sem mover nada.
- TooltipUma dica curta no hover ou no foco do teclado que abre após uma breve pausa, alterna instantaneamente entre vizinhos e exibe atalhos.
Usado em blocos
Blocos que se baseiam em Sidebar.
- Chat SidebarA barra lateral de um app de chat. Logo, busca e Novo chat no topo, seus próprios links abaixo, chats fixados, projetos que se expandem para mostrar seus chats, recentes agrupados por dia e linhas com menus de hover e de clique direito, renomeação inline, exclusão com desfazer e estados de resposta ao vivo.
- HextaAIUm app de chat de IA completo, construído com todos os blocos de IA do HextaUI. Conversas em uma barra lateral, raciocínio com fontes, chamadas de ferramentas com diffs e aprovações, um plano que você revisa antes de o agente executar, Markdown e código em streaming e modo de voz silencioso, tudo movido por partes de mensagem do AI SDK.