Separador
Uma linha divisória horizontal ou vertical simples usada para separar visualmente seções de conteúdo ou grupos de elementos relacionados.
Busque em todas as páginas da documentação
Uma linha divisória horizontal ou vertical simples usada para separar visualmente seções de conteúdo ou grupos de elementos relacionados.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
export function Separator() {
return <hr className="border-t border-gray-200" />;
}Uma regra horizontal simples estilizada com Tailwind. Não é necessário "use client", pois não há interatividade. O border-t garante que apenas a borda superior seja renderizada, evitando o efeito de linha dupla de um <hr> padrão.
interface SeparatorProps {
className?: string;
}
export function Separator({ className }: SeparatorProps) {
return (
<hr
role="separator"
aria-orientation="horizontal"
className={`border-t border-gray-200 ${className ?? ""}`}
/>
);
}Adiciona atributos ARIA explícitos para que tecnologias assistivas anunciem o divisor corretamente. A prop className permite que os consumidores substituam o espaçamento ou a cor em cada uso.
interface SeparatorProps {
className?: string;
}
export function VerticalSeparator({ className }: SeparatorProps) {
return (
<div
role="separator"
aria-orientation="vertical"
className={`h-full w-px bg-gray-200 ${className ?? ""}`}
/>
);
}
// Uso dentro de uma linha flex
function Toolbar() {
return (
<div className="flex h-10 items-center gap-4">
<button className="text-sm">Cut</button>
<VerticalSeparator />
<button className="text-sm">Copy</button>
<VerticalSeparator />
<button className="text-sm">Paste</button>
</div>
);
}Um divisor vertical renderizado como um div com largura w-px e h-full para se estender à altura do pai. Ele deve estar dentro de um contêiner flex com uma altura definida, caso contrário, o divisor colapsará para zero.
interface LabeledSeparatorProps {
label: string;
}
export function LabeledSeparator({ label }: LabeledSeparatorProps) {
return (
<div className="flex items-center gap-4">
<div className="h-px flex-1 bg-gray-200" />
<span className="text-sm text-gray-500">{label}</span>
<div className="h-px flex-1 bg-gray-200" />
</div>
);
}
// Uso
<LabeledSeparator label="or" />O clássico padrão de divisor "ou". Duas linhas flex-1 se expandem igualmente em cada lado do texto centralizado. Usar h-px em vez de border-t oferece um alinhamento mais previsível quando os itens flex têm alturas variadas.
interface SeparatorProps {
className?: string;
}
export function DashedSeparator({ className }: SeparatorProps) {
return (
<hr
role="separator"
className={`border-t border-dashed border-gray-300 ${className ?? ""}`}
/>
);
}A utilidade border-dashed cria um divisor pontilhado que parece mais leve do que uma linha sólida. Útil em seções de formulário ou painéis de configurações onde uma separação sutil é necessária sem limites visuais rígidos.
type SpacingSize = "none" | "sm" | "md" | "lg" | "xl";
interface SeparatorProps {
spacing?: SpacingSize;
className?: string;
}
const spacingClasses: Record<SpacingSize, string> = {
none: "my-0",
sm: "my-2",
md: "my-4",
lg: "my-6",
xl: "my-8",
};
export function Separator({ spacing = "md", className }: SeparatorProps) {
return (
<hr
role="separator"
className={`border-t border-gray-200 ${spacingClasses[spacing]} ${className ?? ""}`}
/>
);
}Presets de espaçamento predefinidos evitam que valores de margem ad hoc apareçam em todo o codebase. A opção none é útil quando o contêiner pai já gerencia o espaçamento por meio de gap ou padding.
interface SeparatorProps {
className?: string;
}
export function GradientSeparator({ className }: SeparatorProps) {
return (
<div
role="separator"
aria-orientation="horizontal"
className={`h-px bg-gradient-to-r from-transparent via-gray-300 to-transparent ${className ?? ""}`}
/>
);
}Uma linha gradiente que desaparece de ambas as extremidades, criando uma separação visual mais suave. Usa o modificador via- do Tailwind para um gradiente de três paradas. Isso funciona melhor em seções de herói ou entre grandes blocos de conteúdo onde uma regra tradicional parece muito pesada.
import { forwardRef } from "react";
type Orientation = "horizontal" | "vertical";
type Variant = "solid" | "dashed" | "dotted" | "gradient";
type Thickness = "thin" | "medium" | "thick";
type SpacingSize = "none" | "sm" | "md" | "lg" | "xl";
interface SeparatorProps {
orientation?: Orientation;
variant?: Variant;
thickness?: Thickness;
spacing?: SpacingSize;
label?: string;
color?: string;
className?: string;
}
const spacingMap: Record<Orientation, Record<SpacingSize, string>> = {
horizontal: { none: "", sm: "my-2", md: "my-4", lg: "my-6", xl: "my-8" },
vertical: { none: "", sm: "mx-2", md: "mx-4", lg: "mx-6", xl: "mx-8" },
};
const thicknessMap: Record<Orientation, Record<Thickness, string>> = {
horizontal: { thin: "h-px", medium: "h-0.5", thick: "h-1" },
vertical: { thin: "w-px", medium: "w-0.5", thick: "w-1" },
};
export const Separator = forwardRef<HTMLDivElement, SeparatorProps>(
function Separator(
{
orientation = "horizontal",
variant = "solid",
thickness = "thin",
spacing = "md",
label,
color = "gray-200",
className,
},
ref
) {
const spacingClass = spacingMap[orientation][spacing];
if (label && orientation === "horizontal") {
return (
<div
ref={ref}
role="separator"
aria-orientation="horizontal"
className={`flex items-center gap-4 ${spacingClass} ${className ?? ""}`}
>
<SeparatorLine
orientation="horizontal"
variant={variant}
thickness={thickness}
color={color}
/>
<span className="shrink-0 text-sm text-gray-500">{label}</span>
<SeparatorLine
orientation="horizontal"
variant={variant}
thickness={thickness}
color={color}
/>
</div>
);
}
return (
<SeparatorLine
ref={ref}
orientation={orientation}
variant={variant}
thickness={thickness}
color={color}
className={`${spacingClass} ${className ?? ""}`}
/>
);
}
);
interface LineProps {
orientation: Orientation;
variant: Variant;
thickness: Thickness;
color: string;
className?: string;
}
const SeparatorLine = forwardRef<HTMLDivElement, LineProps>(
function SeparatorLine({ orientation, variant, thickness, color, className }, ref) {
const size = thicknessMap[orientation][thickness];
const stretch = orientation === "horizontal" ? "w-full" : "h-full";
if (variant === "gradient") {
const direction = orientation === "horizontal" ? "bg-gradient-to-r" : "bg-gradient-to-b";
return (
<div
ref={ref}
role="separator"
aria-orientation={orientation}
className={`${size} ${stretch} ${direction} from-transparent via-${color} to-transparent ${className ?? ""}`}
/>
);
}
const borderSide = orientation === "horizontal" ? "border-t" : "border-l";
const borderStyle =
variant === "dashed" ? "border-dashed" : variant === "dotted" ? "border-dotted" : "";
const borderThickness =
thickness === "thick" ? `${borderSide}-4` : thickness === "medium" ? `${borderSide}-2` : borderSide;
return (
<div
ref={ref}
role="separator"
aria-orientation={orientation}
className={`${stretch} ${borderThickness} border-${color} ${borderStyle} ${className ?? ""}`}
/>
);
}
);Principais aspectos:
orientation.label é fornecido em um separador horizontal, o componente se divide em duas linhas flanqueando o texto centralizado, usando o mesmo subcomponente SeparatorLine para consistência.solid, dashed, dotted e gradient cobrem os estilos visuais mais comuns. A variante gradiente usa um caminho de renderização completamente diferente (gradiente de fundo vs. borda) para evitar conflitos de propriedades CSS.border-t, border-t-2 e border-t-4, enquanto variantes gradiente usam h-px, h-0.5 e h-1 para peso visual equivalente.Separator externo quanto o SeparatorLine interno aceitam refs, permitindo que bibliotecas de animação ou lógica de medição se anexem diretamente ao elemento DOM.my-) e separadores verticais usam margem horizontal (mx-), para que o espaçamento sempre se aplique no eixo correto.Separador vertical colapsa para altura zero -- um separador vertical com h-full requer um pai com altura explícita ou um contêiner flex. Sem isso, o divisor fica invisível.
Tailwind purge remove classes de cor dinâmicas -- interpolar border-${color} ou via-${color} em strings de classe faz com que o Tailwind remova essas classes em produção. Use uma safelist ou um mapa de classes estático em vez disso.
<hr> tem margem padrão -- os navegadores aplicam uma margem padrão aos elementos <hr>. Se você não a redefinir com my-0 ou sua própria classe de margem, obterá um espaçamento extra inesperado.
Role ARIA em divisores decorativos -- divisores puramente decorativos devem usar role="none" ou aria-hidden="true" em vez de role="separator" para evitar sobrecarregar a árvore de acessibilidade com pontos de referência sem sentido.
Direção do gradiente ignorada no modo escuro -- se estiver usando via-gray-300 para o ponto médio do gradiente, ele pode ficar invisível em fundos escuros. Mude para via-gray-600 no modo escuro usando o prefixo dark: do Tailwind.
Renderização de border-dashed varia por navegador -- o comprimento e o espaçamento dos traços diferem entre Chrome, Firefox e Safari. Se traços com precisão de pixel forem necessários, use um padrão SVG ou uma imagem de fundo repetida em vez disso.
Revisado por Chris St. John·Última atualização: 7 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥