Segmented Control

Permite elegir una o varias opciones dentro de un grupo compacto de segmentos, para alternar vistas o aplicar filtros rápidos sin salir de la pantalla actual.

  • Alternar entre vistas o modos de un mismo contenido: cambiar la forma de visualizar la misma información sin salir de la pantalla actual. Ej.: "Lista", "Grilla".
  • Filtrar contenido por un criterio simple: acotar una lista según un estado o categoría, cuando las opciones son pocas y conocidas de antemano. Ej.: "Todos", "Activos", "Archivados".
  • Comparar alternativas excluyentes: elegir entre un conjunto reducido de opciones que compiten entre sí, como una periodicidad o un método. Ej.: "Mensual", "Anual".
  • Combinar más de un filtro a la vez: cuando el criterio lo permite, seleccionar varios segmentos en simultáneo, ya que selectedSegments acepta más de un ID a la vez. Ej.: combinar "Envío gratis" y "En oferta" en un buscador de productos.
  • Elegir entre más de 5 opciones: el componente pierde legibilidad y, en mobile, el área táctil de cada segmento se reduce demasiado. En su lugar, usar Select o MultiSelect.
  • Mostrar contenido extenso por sección: si cada opción despliega un bloque grande de contenido en lugar de solo alternar una vista liviana o aplicar un filtro, usar Tabs.
  • Activar o desactivar una única condición binaria: un interruptor de sí/no no necesita un grupo de segmentos. En su lugar, usar Toggle.
  • Elegir una opción dentro de un formulario extenso: cuando la elección es un campo más de un formulario con FormField (no una vista o un filtro rápido), usar Radio o Checkbox, que se integran mejor a ese contexto.
1
2

Solo texto

4
3

Ícono + texto

5

Texto + badge

  1. Group (componente SegmentedControl): contenedor que agrupa los segmentos y aplica el espaciado compartido. Expone fullWidth para que todos los segmentos repartan el ancho disponible en partes iguales.
  2. Segment (componente SegmentedControl.Button): cada botón individual que representa una opción seleccionable dentro del grupo.
  3. Text: contenido visible del segmento.
  4. Icon (opcional): elemento ubicado antes del texto, que refuerza el criterio representado.
  5. Badge (opcional): elemento para mostrar un contador o un dato adicional asociado al segmento, como una cantidad o un descuento.

Ancho automático (default): cada segmento ocupa solo el espacio que necesita su contenido. Es el comportamiento recomendado cuando el grupo convive con otros elementos en la misma fila. Ej.: un filtro de "Todos"/"Activos"/"Archivados" junto al buscador de una tabla.

fullWidth: cada segmento reparte el ancho disponible en partes iguales. Conviene en mobile o cuando el grupo ocupa un contenedor angosto por sí solo. Ej.: alternar entre "Lista" y "Grilla" en la parte superior de un listado.

Matriz de estados del Segmented Control: segmentos unselected y selected en los estados Rest, Hover, Active, Focus y Disabled.

El Segmented Control suele ubicarse junto al elemento que filtra o alterna: el encabezado de una tabla, la barra superior de un listado o el título de una sección con vistas alternativas. Al vivir cerca de ese contenido, la relación entre el control y lo que modifica queda clara sin necesidad de una etiqueta adicional.

Ventas

124 abiertas

En mobile, el grupo de segmentos se aplica dentro de un scroll pane horizontal: el contenedor recorta el ancho disponible a la pantalla y el usuario desliza para acceder a los segmentos que no entran en el ancho visible, en lugar de reducir el tamaño de cada segmento o forzar el salto de línea.

Ventas

2 abiertas

Mostrar la cantidad de elementos de cada segmento con Badge, cuando ese dato ayuda a decidir dónde priorizar la atención, como pedidos agrupados por estado de envío.

Evitar mezclar criterios distintos en un mismo grupo, como estado, vista y periodicidad: cada segmento debe representar la misma dimensión.

Reservarlo para un grupo reducido de opciones (hasta 5): así se lee de un vistazo.

Evitar sumar tantas opciones que el grupo pierda legibilidad.

Usar labels cortos y sin verbos: nombran el estado o la vista, no una acción, como "Activos" o "Archivados".

Evitar labels con verbos o demasiado largos: fuerzan el truncamiento o el salto de línea en lugar de un nombre de estado corto.

  • Foco visible al navegar con teclado: cada segmento muestra el anillo de foco de Nimbus (:focus-visible) al recibir el foco por Tab, sin depender solo del color para indicarlo.
  • Estado de selección expuesto a lectores de pantalla: cada segmento comunica si está seleccionado mediante aria-pressed, el mismo patrón que un grupo de botones de alternancia (toggle buttons), no el de un grupo de radio buttons.
  • Navegación por Tab, no por flechas: el grupo no reimplementa un roving tabindex; cada segmento es un punto de tabulación independiente y se selecciona con Enter o Space, como cualquier botón nativo. Esto aplica al render por defecto (<button>): con as="a" el segmento es un link y no activa con Space.
  • Etiqueta accesible independiente del contenido visible: la prop label de SegmentedControl.Button permite dar un nombre accesible distinto del contenido visible, útil cuando el segmento se compone solo de un ícono. Un ícono sin label y sin texto visible queda sin nombre para un lector de pantalla.
  • Estado deshabilitado nativo: disabled en SegmentedControl.Button usa el atributo nativo del elemento <button>, por lo que un segmento deshabilitado queda fuera del orden de tabulación automáticamente. Con as="a" no hay disabled nativo: un link no admite ese atributo, así que evitar esa combinación si el segmento necesita deshabilitarse.

Instalá el componente via terminal.

npm install @nimbus-ds/segmented-control
import React, { useState } from "react";
import { SegmentedControl } from "@nimbus-ds/components";
import { mockSegmentedControlLabels as labels } from "lib/mocks/mock-labels";

const Example: React.FC = () => {
  const [selectedSegments, setSelectedSegments] = useState<string[]>([
    labels[0],
  ]);

  return (
    <SegmentedControl
      selectedSegments={selectedSegments}
      onSegmentsSelect={(segments) => {
        if (segments.length > 0) {
          setSelectedSegments(segments);
        }
      }}
    >
      {labels.map((label, index) => (
        <SegmentedControl.Button
          id={label}
          key={label}
          label={label}
          disabled={index === labels.length - 1}
        >
          {label}
        </SegmentedControl.Button>
      ))}
    </SegmentedControl>
  );
};

export default Example;

Las propiedades adicionales se pasan al elemento <SegmentedControl>. Consultá la documentación del elemento div para ver la lista de atributos aceptados.

  • Tabs — para alternar entre secciones que muestran contenido extenso, no solo una vista liviana o un filtro.
  • Toggle — para una condición binaria de sí/no, en lugar de un grupo de opciones.
  • Select — para elegir entre más de 5 opciones.
  • MultiSelect — para seleccionar múltiples opciones entre un conjunto grande.
  • Badge — usado dentro de un segmento para mostrar un contador o un dato adicional.

SegmentedControl

NameTypeDefaultDescription

children

React.ReactNode

The content of the segmented control. Should contain SegmentedControlButton components with unique id props.

fullWidth

boolean

'false'

Determines if segments span all available width.

selectedSegments*

array

The currently selected segment IDs. Allows for single or multiple selection.

onSegmentsSelect

object

Callback fired when the selected segments change.

SegmentedControl.Button

NameTypeDefaultDescription

id*

string

Unique identifier for the segment button. Required for proper state management and accessibility.

label

string

Label of the segment used for accessibility.

fullWidth

boolean

'false'

Determines if segment spans all available width.

children

React.ReactNode

Represents all of the things React can render. Where {@link ReactElement} only represents JSX, `ReactNode` represents everything that can be rendered.

SegmentedControl.ButtonSkeleton

NameTypeDefaultDescription

Ayudanos a mejorar la documentación

¿Encontraste un problema o tenés una sugerencia? Contanos.