KDS
Containers

ScrollArea

Container scrollable com scrollbar themeable — para casos onde o native bar não atende.

Overview

ScrollArea substitui a barra de rolagem nativa por uma versão estilizada e cross-OS. Native scroll é fine 99% do tempo — só recorra a ScrollArea quando você precisar de:

  1. Estilo consistente entre macOS, Windows e Linux (em macOS a barra esconde por default; em Windows/Linux ocupa espaço).
  2. Containers com border-radius onde a barra nativa "vaza" além do raio.
  3. Eixos não convencionais (carrosséis horizontais com indicador visível).

Não use por reflexo — adicionar ScrollArea sem necessidade introduz uma camada de JS e quebra o instinto muscular do usuário com scroll nativo.

Preview
Lista vertical longa, ScrollArea com altura fixa.

Tags

Tag #001
Tag #002
Tag #003
Tag #004
Tag #005
Tag #006
Tag #007
Tag #008
Tag #009
Tag #010
Tag #011
Tag #012
Tag #013
Tag #014
Tag #015
Tag #016
Tag #017
Tag #018
Tag #019
Tag #020
Tag #021
Tag #022
Tag #023
Tag #024
Tag #025
Tag #026
Tag #027
Tag #028
Tag #029
Tag #030
Tag #031
Tag #032
Tag #033
Tag #034
Tag #035
Tag #036
Tag #037
Tag #038
Tag #039
Tag #040
Tag #041
Tag #042
Tag #043
Tag #044
Tag #045
Tag #046
Tag #047
Tag #048
Tag #049
Tag #050

Anatomy

<ScrollArea className="h-72 w-48">
  {/* conteúdo que extrapola */}
  <ScrollBar orientation="horizontal" />  ← opcional
</ScrollArea>

A ScrollArea já monta uma barra vertical por padrão. Para horizontal, adicione um <ScrollBar orientation="horizontal" /> explicitamente. Para ambos os eixos, adicione um por orientação.

Subcomponents

ComponenteDescrição
ScrollAreaContainer scrollable. Aceita classes de altura/largura.
ScrollBarA barra; aceita orientation="vertical" (default) ou "horizontal".

Usage

import { ScrollArea } from "@kalvner/kds/containers/scroll-area";

export function NotificationsList({ items }) {
  return (
    <ScrollArea className="h-72 w-full">
      <ul className="divide-y">
        {items.map((item) => (
          <li key={item.id} className="px-4 py-3">{item.title}</li>
        ))}
      </ul>
    </ScrollArea>
  );
}

Variants

Horizontal
Carrosséis e tracks de imagens com indicador visível.
Image #1
Foto #1
Image #2
Foto #2
Image #3
Foto #3
Image #4
Foto #4
Image #5
Foto #5
Image #6
Foto #6
Image #7
Foto #7
Image #8
Foto #8
Image #9
Foto #9
Image #10
Foto #10
Image #11
Foto #11
Image #12
Foto #12
Image #13
Foto #13
Image #14
Foto #14
Image #15
Foto #15
Image #16
Foto #16

Composition

Long list inside a card
Header fixo, lista scrollável dentro do mesmo card.
Notificações
  • Atualização #1

    Resumo curto da atualização.

  • Atualização #2

    Resumo curto da atualização.

  • Atualização #3

    Resumo curto da atualização.

  • Atualização #4

    Resumo curto da atualização.

  • Atualização #5

    Resumo curto da atualização.

  • Atualização #6

    Resumo curto da atualização.

  • Atualização #7

    Resumo curto da atualização.

  • Atualização #8

    Resumo curto da atualização.

  • Atualização #9

    Resumo curto da atualização.

  • Atualização #10

    Resumo curto da atualização.

  • Atualização #11

    Resumo curto da atualização.

  • Atualização #12

    Resumo curto da atualização.

  • Atualização #13

    Resumo curto da atualização.

  • Atualização #14

    Resumo curto da atualização.

  • Atualização #15

    Resumo curto da atualização.

  • Atualização #16

    Resumo curto da atualização.

  • Atualização #17

    Resumo curto da atualização.

  • Atualização #18

    Resumo curto da atualização.

  • Atualização #19

    Resumo curto da atualização.

  • Atualização #20

    Resumo curto da atualização.

When to use

  • Cards com bordas arredondadas onde o native bar bleeds para fora do radius.
  • Carrosséis horizontais que precisam de indicador visível.
  • Apps cross-platform onde scrollbar consistency importa para branding.
  • Notificações, history feeds, comments dentro de containers fixos.

When not to use

  • Página inteira. Não envolva o <body> em ScrollArea — perde scroll-restoration, behavior nativo de pull-to-refresh, etc.
  • Conteúdo curto que não extrapola. ScrollArea sem overflow é dead code (mas não dá erro — a barra simplesmente não aparece).
  • Áreas com input pesado (grandes textareas, code editors) — use o container nativo do editor.
  • Quando a equipe tem aversão a JS no scroll path. ScrollArea é Radix + DOM observer; não é nada pesado, mas tem custo zero não tem.

Best practices

  • Defina altura/largura. ScrollArea precisa de constraint para scrollar — h-72, max-h-[60vh], etc.
  • Indicador horizontal explícito. Para scroll lateral, mostre o <ScrollBar orientation="horizontal" /> ou afford com gradient de fade nas bordas.
  • focus-visible no viewport. Já existe — não remova; é importante para keyboard scrolling.
  • Não aninhe ScrollAreas. Dois eventos de scroll concorrem; use uma só.

Accessibility

ConcernComportamento
RolesRadix preserva tabindex no viewport — a área é focável e teclado funciona.
KeyboardArrow move; PageUp/PageDown paginam; Home/End saltam.
TouchDrag funciona normalmente em touch devices.
Reduced motionA barra anima com fade — respeite prefers-reduced-motion no nível do tema (já configurado nos tokens de motion).
  • Stack — quando o conteúdo cabe sem overflow.
  • AspectRatio — reservar espaço para mídia.

On this page