Separador
Una línea divisoria horizontal o vertical simple que se utiliza para separar visualmente secciones de contenido o grupos de elementos relacionados.
Casos de uso
- Separar secciones de una página de configuración o formulario
- Dividir grupos de navegación en un menú lateral
- Dividir contenido de tarjeta en bloques lógicos
- Crear distinción visual entre elementos de lista
- Dividir un diseño en paneles izquierdo y derecho con un divisor vertical
- Proporcionar un divisor "o" entre acciones alternativas (por ejemplo, inicio de sesión social vs correo electrónico)
- Separar áreas de encabezado, cuerpo y pie de página dentro de una modal o tarjeta
Implementación más simple
export function Separator() {
return <hr className="border-t border-gray-200" />;
}Una regla horizontal simple con estilo de Tailwind. No se necesita "use client" ya que no hay interactividad. El border-t asegura que solo se renderice el borde superior, evitando el efecto de línea doble de un <hr> predeterminado.
Variaciones
Separador horizontal
interface SeparatorProps {
className?: string;
}
export function Separator({ className }: SeparatorProps) {
return (
<hr
role="separator"
aria-orientation="horizontal"
className={`border-t border-gray-200 ${className ?? ""}`}
/>
);
}Añade atributos ARIA explícitos para que las tecnologías de asistencia anuncien correctamente el divisor. El prop className permite a los consumidores anular espaciado o color por uso.
Separador vertical
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 una fila flex
function Toolbar() {
return (
<div className="flex h-10 items-center gap-4">
<button className="text-sm">Cortar</button>
<VerticalSeparator />
<button className="text-sm">Copiar</button>
<VerticalSeparator />
<button className="text-sm">Pegar</button>
</div>
);
}Un divisor vertical renderizado como un div con ancho w-px y h-full para estirarse a la altura del padre. Debe vivir dentro de un contenedor flex con altura definida, de lo contrario el separador se colapsa a cero.
Con etiqueta de texto
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="o" />El patrón clásico del divisor "o". Dos líneas flex-1 se expanden por igual en cada lado del texto centrado. Usar h-px en lugar de border-t proporciona una alineación más predecible cuando los elementos flex tienen alturas variadas.
Estilo punteado
interface SeparatorProps {
className?: string;
}
export function DashedSeparator({ className }: SeparatorProps) {
return (
<hr
role="separator"
className={`border-t border-dashed border-gray-300 ${className ?? ""}`}
/>
);
}La utilidad border-dashed crea un divisor punteado que se siente más ligero que una línea sólida. Útil en secciones de formulario o paneles de configuración donde se necesita una separación sutil sin límites visuales fuertes.
Con variantes de espaciado
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 ?? ""}`}
/>
);
}Los ajustes de espaciado predefinidos evitan que valores de margen ad-hoc aparezcan en toda la base de código. La opción none es útil cuando el contenedor padre ya gestiona el espaciado a través de gap o padding.
Gradiente decorativo
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 ?? ""}`}
/>
);
}Una línea de gradiente que se desvanece desde ambos bordes, creando una separación visual más suave. Usa el modificador via- de Tailwind para un gradiente de tres paradas. Funciona mejor en secciones de héroe o entre bloques de contenido grandes donde una regla tradicional se siente demasiado pesada.
Implementación compleja
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 ?? ""}`}
/>
);
}
);Aspectos clave:
- Orientación dual -- un componente individual maneja divisores horizontales y verticales intercambiando clases de dimensión y dirección de borde basándose en el prop
orientation. - Soporte de etiqueta -- cuando se proporciona una
labelen un separador horizontal, el componente se divide en dos líneas flanqueando el texto centrado, usando el mismo subcomponenteSeparatorLinepara consistencia. - Sistema de variantes --
solid,dashed,dottedygradientcubren los estilos visuales más comunes. La variante gradiente usa una ruta de renderizado completamente diferente (gradiente de fondo vs borde) para evitar conflictos de propiedades CSS. - Espesor proporcional -- las variantes basadas en borde mapean espesor a
border-t,border-t-2yborder-t-4, mientras que las variantes gradiente usanh-px,h-0.5eh-1para un peso visual equivalente. - forwardRef -- tanto el
Separatorexterno como elSeparatorLineinterno aceptan refs, permitiendo que bibliotecas de animación o lógica de medición se adjunten directamente al elemento DOM. - Mapas de espaciado por orientación -- los separadores horizontales usan margen vertical (
my-) y los separadores verticales usan margen horizontal (mx-), por lo que el espaciado siempre se aplica en el eje correcto.
Problemas comunes
-
El separador vertical se colapsa a altura cero -- un separador vertical con
h-fullrequiere un padre con altura explícita o un contenedor flex. Sin él, el divisor es invisible. -
Tailwind purga clases de color dinámico -- interpolar
border-${color}ovia-${color}en cadenas de clase causa que Tailwind purgue esas clases en producción. Usa un safelist o un mapa de clase estática en su lugar. -
<hr>tiene margen predeterminado -- los navegadores aplican un margen predeterminado a los elementos<hr>. Si no lo restableces conmy-0o tu propia clase de margen, obtienes espaciado extra inesperado. -
Rol ARIA en divisores decorativos -- los separadores puramente decorativos deben usar
role="none"oaria-hidden="true"en lugar derole="separator"para evitar saturar el árbol de accesibilidad con puntos de referencia sin sentido. -
Dirección de gradiente ignorada en modo oscuro -- si usas
via-gray-300para el punto medio del gradiente, puede volverse invisible en fondos oscuros. Cambia avia-gray-600en modo oscuro usando el prefijodark:de Tailwind. -
Renderizado de border-dashed varía por navegador -- la longitud y el espacio de los guiones difieren entre Chrome, Firefox y Safari. Si se requieren guiones pixel-perfecto, usa un patrón SVG o una imagen de fondo repetitiva en su lugar.
Relacionado
- Card -- Los separadores se usan a menudo dentro de tarjetas para dividir encabezado, cuerpo y pie de página
- Sidebar -- Los separadores verticales y horizontales dividen grupos de navegación en barras laterales
- Modal -- Las modales usan separadores entre áreas de título, contenido y acción
- Tabs -- Un separador debajo de la barra de pestañas distingue las pestañas del contenido del panel