Ir al contenido
uiify

Segmented control

Fila de segmentos para elegir una sola opción.

Navegadores
Chrome 123+Firefox 121+Safari 17.5+
Nivel
0
Tamaño comprimido
995 B
Presupuesto de diseño forzado
0 ms
Presupuesto de axe
0
Compatible con SSR
Sí
Basado en
elements/choice
Contrato publicado
Entorno de pruebas

Zona de pruebas

Segmented Control

Predeterminado

import { SegmentedControl } from "@gunkin/uiify";

export default function Example() {
  return (
    <SegmentedControl
      aria-label="Time range"
      className=""
      id="period"
      defaultValue="week"
      items={[
        { value: "day", label: "Day" },
        { value: "week", label: "Week" },
        { value: "month", label: "Month" },
      ]}
    />
  );
}
/* Segmented control — pill toggle group with sliding indicator. */

@layer components {
  :where([data-uiify-segmented-control], [data-uiify-segmented-control]) {
    position: relative;
    display: inline-flex;
    padding: var(--space-xs);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-full);
    background-color: var(--muted);
  }

  [data-uiify-segmented-control][data-full-width] {
    inline-size: 100%;
  }

  [data-uiify-segmented-control][data-orientation="vertical"] {
    flex-direction: column;
  }

  [data-uiify-segmented-control] [data-part="item"] {
    position: relative;
  }

  [data-uiify-segmented-control][data-full-width] [data-part="item"] {
    flex: 1 1 0;
  }

  [data-uiify-segmented-control] [data-part="item"] > input {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* The segments are Button-skinned labels (`ghost`, `sm`); only their place in the track
     is set here. */
  [data-uiify-segmented-control] [data-part="item"] > label {
    z-index: 1;
    min-inline-size: 4rem;
  }

  [data-uiify-segmented-control][data-full-width] [data-part="item"] > label {
    inline-size: 100%;
  }
}
import { SegmentedControl } from "@gunkin/uiify";

export default function Example() {
  return (
    <SegmentedControl
      aria-label="Time range"
      className={
        "relative inline-flex p-xs border-[length:var(--border-width)] border-solid border-border rounded-[var(--rad" +
        "ius-full)] bg-muted data-[full-width]:[inline-size:100%] data-[orientation=vertical]:flex-col [&_[data-part" +
        "=item]]:relative [&[data-full-width]_[data-part=item]]:[flex:1_1_0] [&_[data-part=item]>input]:absolute [&_" +
        "[data-part=item]>input]:[inline-size:1px] [&_[data-part=item]>input]:[block-size:1px] [&_[data-part=item]>i" +
        "nput]:[margin:-1px] [&_[data-part=item]>input]:overflow-hidden [&_[data-part=item]>input]:[clip-path:inset(" +
        "50%)] [&_[data-part=item]>input]:whitespace-nowrap [&_[data-part=item]>label]:relative [&_[data-part=item]>" +
        "label]:isolate [&_[data-part=item]>label]:inline-flex [&_[data-part=item]>label]:min-h-8 [&_[data-part=item" +
        "]>label]:min-w-8 [&_[data-part=item]>label]:items-center [&_[data-part=item]>label]:justify-center [&_[data" +
        "-part=item]>label]:gap-1 [&_[data-part=item]>label]:rounded-full [&_[data-part=item]>label]:border-[length:" +
        "var(--border-width)] [&_[data-part=item]>label]:border-solid [&_[data-part=item]>label]:border-transparent " +
        "[&_[data-part=item]>label]:bg-transparent [&_[data-part=item]>label]:text-foreground [&_[data-part=item]>la" +
        "bel]:bg-clip-padding [&_[data-part=item]>label]:px-3 [&_[data-part=item]>label]:py-0 [&_[data-part=item]>la" +
        "bel]:text-foreground [&_[data-part=item]>label]:text-sm [&_[data-part=item]>label]:font-medium [&_[data-par" +
        "t=item]>label]:leading-5 [&_[data-part=item]>label]:no-underline [&_[data-part=item]>label]:cursor-pointer " +
        "[&_[data-part=item]>label]:[transition:var(--transition-colors)] [&_[data-part=item]>input:checked+label]:b" +
        "order-transparent [&_[data-part=item]>input:checked+label]:bg-primary [&_[data-part=item]>input:checked+lab" +
        "el]:text-primary-foreground [&_[data-part=item]>label[data-variant=outline]]:[--uiify-button-rim:color-mix(" +
        "in_oklch,_var(--foreground)_25%,_transparent)] [&_[data-part=item]>input:checked+label[data-variant=outline" +
        "]]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [&_[data-part=item]>label[data-variant=outline]]:before:cont" +
        "ent-none [&_[data-part=item]>label[data-variant=outline]]:after:content-[''] [&_[data-part=item]>label[data" +
        "-variant=outline]]:after:absolute [&_[data-part=item]>label[data-variant=outline]]:after:z-[-1] [&_[data-pa" +
        "rt=item]>label[data-variant=outline]]:after:[inset:calc(-1_*_var(--border-width))] [&_[data-part=item]>labe" +
        "l[data-variant=outline]]:after:rounded-[inherit] [&_[data-part=item]>label[data-variant=outline]]:after:poi" +
        "nter-events-none [&_[data-part=item]>label[data-variant=outline]]:after:[padding:var(--border-width)] [&_[d" +
        "ata-part=item]>label[data-variant=outline]]:after:[background-image:linear-gradient(to_bottom,_var(--uiify-" +
        "button-rim),_transparent_75%)] [&_[data-part=item]>label[data-variant=outline]]:after:[mask:linear-gradient" +
        "(#fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [@media_(any-hover:_hover)_and_(any-pointer:_fin" +
        "e)]:[&_[data-part=item]>input:not(:disabled)+label[data-variant=outline]:hover]:[background-color:color-mix" +
        "(in_oklch,_var(--foreground)_10%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&_[dat" +
        "a-part=item]>input:checked:not(:disabled)+label[data-variant=outline]:hover]:[background-color:color-mix(in" +
        "_oklch,_var(--primary)_88%,_var(--primary-foreground))] [&_[data-part=item]>input:where(:not(:disabled))+la" +
        "bel[data-variant=outline]:active]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)" +
        "] [&_[data-part=item]>label]:z-[1] [&_[data-part=item]>label]:[min-inline-size:4rem] [&[data-full-width]_[d" +
        "ata-part=item]>label]:[inline-size:100%]"
      }
      id="period"
      defaultValue="week"
      items={[
        { value: "day", label: "Day" },
        { value: "week", label: "Week" },
        { value: "month", label: "Month" },
      ]}
    />
  );
}
/* app.css */

@layer reset, ui, app, tokens, base, demo, components, utilities, theme;

@import "@gunkin/uiify/styles/reset";

@import "@gunkin/uiify/components/behavior.css";

@import "@gunkin/uiify/styles/tokens";

@import "@gunkin/uiify/styles/tailwind";

@import "tailwindcss/utilities.css";

@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }

@source inline('relative inline-flex p-xs border-[length:var(--border-width)] border-solid border-border rounded-[var(--radius-full)] bg-muted data-[full-width]:[inline-size:100%] data-[orientation=vertical]:flex-col [&_[data-part=item]]:relative [&[data-full-width]_[data-part=item]]:[flex:1_1_0] [&_[data-part=item]>input]:absolute [&_[data-part=item]>input]:[inline-size:1px] [&_[data-part=item]>input]:[block-size:1px] [&_[data-part=item]>input]:[margin:-1px] [&_[data-part=item]>input]:overflow-hidden [&_[data-part=item]>input]:[clip-path:inset(50%)] [&_[data-part=item]>input]:whitespace-nowrap [&_[data-part=item]>label]:relative [&_[data-part=item]>label]:isolate [&_[data-part=item]>label]:inline-flex [&_[data-part=item]>label]:min-h-8 [&_[data-part=item]>label]:min-w-8 [&_[data-part=item]>label]:items-center [&_[data-part=item]>label]:justify-center [&_[data-part=item]>label]:gap-1 [&_[data-part=item]>label]:rounded-full [&_[data-part=item]>label]:border-[length:var(--border-width)] [&_[data-part=item]>label]:border-solid [&_[data-part=item]>label]:border-transparent [&_[data-part=item]>label]:bg-transparent [&_[data-part=item]>label]:text-foreground [&_[data-part=item]>label]:bg-clip-padding [&_[data-part=item]>label]:px-3 [&_[data-part=item]>label]:py-0 [&_[data-part=item]>label]:text-sm [&_[data-part=item]>label]:font-medium [&_[data-part=item]>label]:leading-5 [&_[data-part=item]>label]:no-underline [&_[data-part=item]>label]:cursor-pointer [&_[data-part=item]>label]:[transition:var(--transition-colors)] [&_[data-part=item]>input:checked+label]:border-transparent [&_[data-part=item]>input:checked+label]:bg-primary [&_[data-part=item]>input:checked+label]:text-primary-foreground [&_[data-part=item]>label[data-variant=outline]]:[--uiify-button-rim:color-mix(in_oklch,_var(--foreground)_25%,_transparent)] [&_[data-part=item]>input:checked+label[data-variant=outline]]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [&_[data-part=item]>label[data-variant=outline]]:before:content-none [&_[data-part=item]>label[data-variant=outline]]:after:absolute [&_[data-part=item]>label[data-variant=outline]]:after:z-[-1] [&_[data-part=item]>label[data-variant=outline]]:after:[inset:calc(-1_*_var(--border-width))] [&_[data-part=item]>label[data-variant=outline]]:after:rounded-[inherit] [&_[data-part=item]>label[data-variant=outline]]:after:pointer-events-none [&_[data-part=item]>label[data-variant=outline]]:after:[padding:var(--border-width)] [&_[data-part=item]>label[data-variant=outline]]:after:[background-image:linear-gradient(to_bottom,_var(--uiify-button-rim),_transparent_75%)] [&_[data-part=item]>label[data-variant=outline]]:after:[mask:linear-gradient(#fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&_[data-part=item]>input:not(:disabled)+label[data-variant=outline]:hover]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&_[data-part=item]>input:checked:not(:disabled)+label[data-variant=outline]:hover]:[background-color:color-mix(in_oklch,_var(--primary)_88%,_var(--primary-foreground))] [&_[data-part=item]>input:where(:not(:disabled))+label[data-variant=outline]:active]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] [&_[data-part=item]>label]:z-[1] [&_[data-part=item]>label]:[min-inline-size:4rem] [&[data-full-width]_[data-part=item]>label]:[inline-size:100%]');

@source inline("[&_[data-part=item]>label[data-variant=outline]]:after:content-['']");

@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }

/* Authored animation and registered properties used by the Tailwind skin.
 * Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
  @keyframes uiify-presence-in {
    from {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@layer components {
  @keyframes uiify-presence-out {
    to {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@property --uiify-spinner-tail {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@property --uiify-spinner-length {
  syntax: "<angle>";
  inherits: false;
  initial-value: 36deg;
}

@layer components {
  @keyframes uiify-spinner-rotate {
    to {
      transform: rotate(360deg);
    }
  }
}

@layer components {
  @keyframes uiify-spinner-orbit {
    0% {
      --uiify-spinner-tail: 0deg;
      --uiify-spinner-length: 36deg;
    }

    50% {
      --uiify-spinner-tail: 90deg;
      --uiify-spinner-length: 324deg;
    }

    100% {
      --uiify-spinner-tail: 360deg;
      --uiify-spinner-length: 36deg;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-pulse {
    50% {
      opacity: 0.45;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-shimmer {
    to {
      background-position: -200% 0;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-reveal {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}

@property --candle-body-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-body-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-slot {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

@property --candle-wick-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-wick-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-x {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@property --line-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-prev-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-count {
  syntax: "<integer>";
  inherits: false;
  initial-value: 1;
}

@property --line-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@layer components {
  @keyframes uiify-otp-input-caret-blink {
    50% {
      opacity: 0;
    }
  }
}

API

SegmentedControl

PropTipoPredeterminadoDescripción
id*string—Base para los ids deterministas y el nombre compartido del grupo de botones de opción.
items*readonly SegmentedControlItem[]—Cada elemento tiene la forma { value, label, disabled? }.
defaultValuestring | undefined—Valor seleccionado en el primer renderizado. Es no controlado, por lo que se conserva sin JavaScript.
valuestring—Valor controlado en SegmentedControlClient.
onValueChange(value: string) => void—Callback de cambio en SegmentedControlClient.
disabledbooleanfalseDesactiva todos los segmentos y marca el grupo con data-disabled.
aria-label / aria-labelledbystring—Nombre accesible del radiogroup; proporciona uno si no hay una etiqueta de grupo visible.
orientation"horizontal" | "vertical""horizontal"Dirección en la que se distribuyen los segmentos.
fullWidthbooleanfalseEstablece data-full-width en la raíz para que los segmentos ocupen todo el contenedor.
classNamestring—Clase aplicada a la raíz del grupo.

Teclado

TeclaAcción
TabLlevar el foco al grupo
Arrow keysMover el foco entre segmentos
SpaceSeleccionar el segmento con foco

Accesibilidad

Radiogroup nativo de selección única basado en botones de opción ocultos. Usa SegmentedControlClient para el comportamiento controlado con value/onValueChange.

Puntos de estilo

data-partdata-disableddata-full-width
Esta página se tradujo automáticamente y aún no se ha revisado.