---
title: "Abas roláveis em React — sem precisar do Material UI"
description: "Abas roláveis em React com rolagem nativa: a aba ativa se centraliza sozinha, as setas aparecem só quando necessário, conteúdo de aba livre. Demo ao vivo e código-fonte."
canonical: "https://react-horizontal-scrolling-menu.dev/pt-br/scrollable-tabs"
image: "https://react-horizontal-scrolling-menu.dev/og.png"
---

# Abas roláveis em React que rolam como o navegador

Uma barra de abas para de caber assim que seu produto passa de seis abas. A solução não é uma fonte menor — é uma barra que rola: o overflow fica por conta do navegador, clicar em uma aba a centraliza, e as setas aparecem só quando há para onde ir.

Overview

Getting started

Visibility

Arrows

Drag to scroll

RTL

apiRef

Helpers

TypeScript

Testing

Changelog

FAQ

Clique em uma aba perto da borda — ela rola sozinha até o centro.

[Edite este exemplo ao vivo no Storybook](https://asmyshlyaev177.github.io/react-horizontal-scrolling-menu/?path=/story/examples-centeronclick--center-on-click)

## O único comportamento que importa: centralizar ao selecionar

Uma barra de abas rolável vive ou morre pelo que acontece quando você clica em uma aba na borda: ela deve deslizar até o meio, revelando as vizinhas dos dois lados. Aqui isso é uma única chamada — `scrollToItem(el, 'smooth', 'center')` — ligada no [exemplo center-on-click](https://react-horizontal-scrolling-menu.dev/pt-br/examples/center-on-click.md). Restaurar a aba ativa ao montar o componente é a mesma chamada com `'auto'`, mostrada em [salvar e restaurar posição](https://react-horizontal-scrolling-menu.dev/pt-br/examples/save-restore-position.md).

As setas vêm dos mesmos dados de visibilidade: `useLeftArrowVisible` só é falso enquanto a primeira aba está fora da tela, então a seta esquerda é renderizada exatamente quando é útil. Sem código de medição, sem resize observers próprios.

## Se você está deixando as abas roláveis do MUI para trás

As abas `variant="scrollable"` do Material UI são a resposta certa dentro do design system do Material — até suas "abas" pararem de ser abas. O MUI solda a barra à semântica de Tabs: um par `value`/`onChange`, painéis de aba e botões de rolagem que o MUI esconde no mobile por padrão. No momento em que sua fileira passa a ter chips, cards, avatares ou conteúdo misto, ou precisa de arraste para rolar, ou precisa saber quais itens estão visíveis, você está lutando contra o componente em vez de usá-lo.

Esta biblioteca é a camada abaixo disso: uma fileira rolável com rastreamento de visibilidade, sem opinião sobre o que é uma "aba". Sua aba é qualquer componente com um `itemId` — estilize com Tailwind, o `styled` do próprio MUI, ou CSS puro. O estado de seleção continua seu, exatamente como a demo acima o mantém em um único `useState`.

## Acessibilidade é quase de graça — atenção às duas lacunas

Como a barra é um contêiner de rolagem nativa, o foco de teclado, a ordem de leitura do leitor de tela e o RTL vêm da plataforma — mover o foco pelas abas as rola para a área visível sem nenhum código, e o [RTL](https://react-horizontal-scrolling-menu.dev/pt-br/examples/rtl.md) não precisa de configuração. Duas coisas continuam por sua conta, como em qualquer UI de abas: escolher seu padrão ARIA (`role="tablist"` se painéis reais forem trocados, `aria-current` se as "abas" forem navegação) e manter a supressão de clique da receita de [arraste para rolar](https://react-horizontal-scrolling-menu.dev/pt-br/examples/mouse-drag.md) para que soltar um arraste nunca ative uma aba.

## O padrão, no mínimo

Abas são botões comuns com um `itemId`; selecionar uma a centraliza. Essa é a ideia toda — a demo acima adiciona estilização e arraste.

ScrollTabs.tsx

```
function ScrollTabs({ tabs }: { tabs: string[] }) {
  const [active, setActive] = React.useState(tabs[0]);
  return (
    <ScrollMenu LeftArrow={LeftArrow} RightArrow={RightArrow}>
      {tabs.map((tab) => (
        <Tab itemId={tab} key={tab} label={tab}
          active={tab === active} onSelect={() => setActive(tab)} />
      ))}
    </ScrollMenu>
  );
}

function Tab({ itemId, label, active, onSelect }: TabProps) {
  const api = React.useContext<publicApiType>(VisibilityContext);
  return (
    <button
      aria-current={active}
      onClick={(ev) => {
        onSelect();
        // The behavior that makes tabs feel native: selecting an
        // edge tab glides it to the center of the strip.
        api.scrollToItem(ev.currentTarget, 'smooth', 'center');
      }}
    >
      {label}
    </button>
  );
}
```

## Ou instale como um componente shadcn

O item de registro [scroll-tabs](https://react-horizontal-scrolling-menu.dev/r/scroll-tabs.json) entrega esse padrão orientado a dados — passe `tabs`, `value`, `onValueChange` — como um componente editável no seu `components/ui/`:

shadcn

```
npx shadcn@latest add https://react-horizontal-scrolling-menu.dev/r/scroll-tabs.json
```

## Exemplos relacionados

-   [Centralizar o item clicadoscrollToItem com inline: center — o padrão de abas roláveis.](https://react-horizontal-scrolling-menu.dev/pt-br/examples/center-on-click.md)
-   [Salvar e restaurar a posição de rolagemMantenha o deslocamento de rolagem entre desmontagens e recargas.](https://react-horizontal-scrolling-menu.dev/pt-br/examples/save-restore-position.md)
-   [Arrastar para rolar com o mouseArraste com o mouse que ainda deixa os cliques funcionarem.](https://react-horizontal-scrolling-menu.dev/pt-br/examples/mouse-drag.md)

[Todos os exemplos (21)](https://react-horizontal-scrolling-menu.dev/pt-br/examples.md)

---

More examples: <https://react-horizontal-scrolling-menu.dev/examples.md>
Library summary for LLMs: <https://react-horizontal-scrolling-menu.dev/llms.txt>
