انتقل إلى المحتوى
uiify

Segmented control

صف من المقاطع لاختيار خيار واحد فقط.

المتصفحات
Chrome 123+Firefox 121+Safari 17.5+
الفئة
0
الحجم المضغوط
995 B
ميزانية التخطيط القسري
0 ms
ميزانية axe
0
متوافق مع SSR
نعم
مبني على
elements/choice
العقد المنشور
بيئة الاختبار

المختبر

Segmented Control

افتراضي

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

الخاصيةالنوعافتراضيالوصف
id*string—أساس المعرّفات الحتمية والاسم المشترك لمجموعة أزرار الاختيار.
items*readonly SegmentedControlItem[]—صيغة كل عنصر هي { value, label, disabled? }.
defaultValuestring | undefined—القيمة المحدّدة عند أول عرض. غير متحكّم بها، لذا تستمر بالعمل دون JavaScript.
valuestring—القيمة المتحكّم بها في SegmentedControlClient.
onValueChange(value: string) => void—دالة رد نداء التغيير في SegmentedControlClient.
disabledbooleanfalseيعطّل كل مقطع ويضع data-disabled على المجموعة.
aria-label / aria-labelledbystring—اسم مجموعة radiogroup للتقنيات المساعدة؛ حدّده إن لم توجد تسمية مرئية للمجموعة.
orientation"horizontal" | "vertical""horizontal"الاتجاه الذي تُرتّب فيه المقاطع.
fullWidthbooleanfalseيعيّن data-full-width على الجذر لتتمدد المقاطع وتملأ حاويتها.
classNamestring—الفئة المطبّقة على جذر المجموعة.

لوحة المفاتيح

المفتاحالإجراء
Tabنقل التركيز إلى المجموعة
Arrow keysالتنقل بين المقاطع
Spaceتحديد المقطع المركّز

إمكانية الوصول

مجموعة radiogroup أصلية للتحديد المفرد مبنية على مدخلات radio مخفية. استخدم SegmentedControlClient لسلوك value/onValueChange المتحكّم به.

نقاط التنسيق

data-partdata-disableddata-full-width