HextaUI

BetaVercel UI SDK 0.1.0-beta.2 üzerine kurulu. API’si değişebilir.

Segmented control

Vercel UI SDK üzerinde kayan gösterge, üç boyut, yalnızca simgeli öğeler, tam genişlik, dikey düzen ve radyo grubu klavyesi olan bir segmentli kontrol.

Bağımlılıklar
  • @ui-sdk/core
  • @ui-sdk/react
import { IconLayoutGrid, IconLayoutKanban, IconList } from "@tabler/icons-react"

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlDemo() {
  return (
    <SegmentedControl aria-label="View" defaultValue="list">
      <SegmentedControlItem value="list">
        <IconList aria-hidden="true" />
        List
      </SegmentedControlItem>
      <SegmentedControlItem value="grid">
        <IconLayoutGrid aria-hidden="true" />
        Grid
      </SegmentedControlItem>
      <SegmentedControlItem value="board">
        <IconLayoutKanban aria-hidden="true" />
        Board
      </SegmentedControlItem>
    </SegmentedControl>
  )
}

export { UiSdkSegmentedControlDemo }
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-segmented-control.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

UI SDK, ui-sdk adlı bir cascade katmanında kendi CSS’ini biraz ekler. Sınıflarınızın kazanması için bu katmanı genel stil dosyanızın en üstünde, Tailwind import’unun üzerinde tanımlayın.

@layer ui-sdk;

@import "tailwindcss";
import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"
<SegmentedControl aria-label="View" defaultValue="list">
  <SegmentedControlItem value="list">List</SegmentedControlItem>
  <SegmentedControlItem value="grid">Grid</SegmentedControlItem>
</SegmentedControl>

Segmentli kontrol birkaç görünüm veya ayar arasında geçiş yapar. Tek değeri ve tek sekme durağı olan bir radyo grubu gibi çalışır; seçili öğenin arkasındaki gösterge yeni seçime kayar. Onu aria-label veya aria-labelledby ile adlandırın. UI SDK onu 0.1.0-beta.2 sürümünde deneysel olarak işaretler.

SegmentedControl
├── SegmentedControlItem
└── SegmentedControlItem

Kontrol kendi göstergesini çizer, siz yalnızca öğeleri eklersiniz.

size, sm, default veya lg olur. Öğeler dokunmatik ekranlarda büyür.

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

const sizes = ["sm", "default", "lg"] as const

function UiSdkSegmentedControlSizes() {
  return (
    <div className="flex flex-col items-center gap-4">
      {sizes.map((size) => (
        <SegmentedControl
          key={size}
          aria-label={`Effort, ${size}`}
          size={size}
          defaultValue="balanced"
        >
          <SegmentedControlItem value="fast">Fast</SegmentedControlItem>
          <SegmentedControlItem value="balanced">Balanced</SegmentedControlItem>
          <SegmentedControlItem value="thorough">Thorough</SegmentedControlItem>
        </SegmentedControl>
      ))}
    </div>
  )
}

export { UiSdkSegmentedControlSizes }

Yalnızca simge içeren bir öğe kare olur. Onu aria-label ile adlandırın.

import {
  IconAlignCenter,
  IconAlignJustified,
  IconAlignLeft,
  IconAlignRight,
} from "@tabler/icons-react"

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlIcons() {
  return (
    <SegmentedControl aria-label="Text alignment" defaultValue="left">
      <SegmentedControlItem value="left" aria-label="Align left">
        <IconAlignLeft aria-hidden="true" />
      </SegmentedControlItem>
      <SegmentedControlItem value="center" aria-label="Align center">
        <IconAlignCenter aria-hidden="true" />
      </SegmentedControlItem>
      <SegmentedControlItem value="right" aria-label="Align right">
        <IconAlignRight aria-hidden="true" />
      </SegmentedControlItem>
      <SegmentedControlItem value="justify" aria-label="Justify">
        <IconAlignJustified aria-hidden="true" />
      </SegmentedControlItem>
    </SegmentedControl>
  )
}

export { UiSdkSegmentedControlIcons }

Kontrole w-full verin, öğeler genişliği paylaşır.

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlFullWidth() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <p id="billing-period" className="m-0 text-sm font-medium">
        Billing period
      </p>
      <SegmentedControl
        aria-labelledby="billing-period"
        defaultValue="yearly"
        className="w-full"
      >
        <SegmentedControlItem value="monthly">Monthly</SegmentedControlItem>
        <SegmentedControlItem value="yearly">Yearly</SegmentedControlItem>
      </SegmentedControl>
    </div>
  )
}

export { UiSdkSegmentedControlFullWidth }

orientation="vertical" öğeleri üst üste dizer. Her iki eksendeki ok tuşları yine öğeler arasında gezinir.

import {
  IconLayoutAlignBottom,
  IconLayoutAlignMiddle,
  IconLayoutAlignTop,
} from "@tabler/icons-react"

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlVertical() {
  return (
    <SegmentedControl
      aria-label="Vertical alignment"
      orientation="vertical"
      defaultValue="middle"
    >
      <SegmentedControlItem value="top">
        <IconLayoutAlignTop aria-hidden="true" />
        Top
      </SegmentedControlItem>
      <SegmentedControlItem value="middle">
        <IconLayoutAlignMiddle aria-hidden="true" />
        Middle
      </SegmentedControlItem>
      <SegmentedControlItem value="bottom">
        <IconLayoutAlignBottom aria-hidden="true" />
        Bottom
      </SegmentedControlItem>
    </SegmentedControl>
  )
}

export { UiSdkSegmentedControlVertical }

Kontroldeki disabled her şeyi kapatır ve hiçbir şey göndermez. Bir öğede ise ok tuşları onu atlar.

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlDisabled() {
  return (
    <div className="flex flex-col items-center gap-4">
      <SegmentedControl aria-label="Theme" defaultValue="system" disabled>
        <SegmentedControlItem value="light">Light</SegmentedControlItem>
        <SegmentedControlItem value="dark">Dark</SegmentedControlItem>
        <SegmentedControlItem value="system">System</SegmentedControlItem>
      </SegmentedControl>
      <SegmentedControl aria-label="Model" defaultValue="mini">
        <SegmentedControlItem value="mini">Mini</SegmentedControlItem>
        <SegmentedControlItem value="standard">Standard</SegmentedControlItem>
        <SegmentedControlItem value="pro" disabled>
          Pro
        </SegmentedControlItem>
      </SegmentedControl>
    </div>
  )
}

export { UiSdkSegmentedControlDisabled }

value verin ve onValueChange içinde güncelleyin. createSegmentedControlController() ile oluşturulan bir denetleyici her yerden bir öğe seçer.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  SegmentedControl,
  SegmentedControlItem,
  createSegmentedControlController,
} from "@/components/ui/ui-sdk-segmented-control"

type Range = "day" | "week" | "month"

function UiSdkSegmentedControlControlled() {
  const [controller] = React.useState(() =>
    createSegmentedControlController<Range>()
  )
  const [range, setRange] = React.useState<Range | null>("week")

  return (
    <div className="flex flex-col items-center gap-3">
      <SegmentedControl<Range>
        aria-label="Range"
        value={range}
        onValueChange={(value) => setRange(value)}
        controller={controller}
      >
        <SegmentedControlItem value="day">Day</SegmentedControlItem>
        <SegmentedControlItem value="week">Week</SegmentedControlItem>
        <SegmentedControlItem value="month">Month</SegmentedControlItem>
      </SegmentedControl>
      <div className="flex items-center gap-2">
        <Button
          size="sm"
          variant="outline"
          onClick={() => controller.setValue("month")}
        >
          Show month
        </Button>
        <p className="m-0 text-xs text-muted-foreground">
          {`Showing ${range ?? "nothing"}`}
        </p>
      </div>
    </div>
  )
}

export { UiSdkSegmentedControlControlled }

Her öğe gizli bir yerel radyo içerir; bu yüzden name seçili değeri gönderir, required bir seçim bekler ve sıfırlama varsayılana döner.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlForm() {
  const [saved, setSaved] = React.useState<string | null>(null)

  return (
    <form
      className="flex flex-col items-start gap-4"
      onSubmit={(event) => {
        event.preventDefault()
        const data = new FormData(event.currentTarget)
        setSaved(`theme=${data.get("theme")}, density=${data.get("density")}`)
      }}
    >
      <div className="flex flex-col gap-2">
        <p id="form-theme" className="m-0 text-sm font-medium">
          Theme
        </p>
        <SegmentedControl
          aria-labelledby="form-theme"
          name="theme"
          defaultValue="system"
          required
        >
          <SegmentedControlItem value="light">Light</SegmentedControlItem>
          <SegmentedControlItem value="dark">Dark</SegmentedControlItem>
          <SegmentedControlItem value="system">System</SegmentedControlItem>
        </SegmentedControl>
      </div>
      <div className="flex flex-col gap-2">
        <p id="form-density" className="m-0 text-sm font-medium">
          Density
        </p>
        <SegmentedControl
          aria-labelledby="form-density"
          name="density"
          defaultValue="comfortable"
        >
          <SegmentedControlItem value="compact">Compact</SegmentedControlItem>
          <SegmentedControlItem value="comfortable">
            Comfortable
          </SegmentedControlItem>
        </SegmentedControl>
      </div>
      <div className="flex items-center gap-3">
        <Button type="submit" size="sm">
          Save
        </Button>
        <Button type="reset" size="sm" variant="ghost">
          Reset
        </Button>
      </div>
      <p className="m-0 text-sm text-muted-foreground">
        {saved ? `Saved ${saved}` : "Nothing saved yet."}
      </p>
    </form>
  )
}

export { UiSdkSegmentedControlForm }

Salt okunur bir kontrol değerini korur ve yine gönderilir. Ok tuşları hiçbir şeyi seçmeden odağı taşır.

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlReadOnly() {
  return (
    <SegmentedControl aria-label="Plan" defaultValue="team" readOnly>
      <SegmentedControlItem value="solo">Solo</SegmentedControlItem>
      <SegmentedControlItem value="team">Team</SegmentedControlItem>
    </SegmentedControl>
  )
}

export { UiSdkSegmentedControlReadOnly }

Öğeler sağdan başlar ve gösterge onları izler.

import {
  SegmentedControl,
  SegmentedControlItem,
} from "@/components/ui/ui-sdk-segmented-control"

function UiSdkSegmentedControlRtl() {
  return (
    <div dir="rtl" lang="ar">
      <SegmentedControl aria-label="العرض" defaultValue="list">
        <SegmentedControlItem value="list">قائمة</SegmentedControlItem>
        <SegmentedControlItem value="grid">شبكة</SegmentedControlItem>
        <SegmentedControlItem value="board">لوحة</SegmentedControlItem>
      </SegmentedControl>
    </div>
  )
}

export { UiSdkSegmentedControlRtl }
TuşAction
TabKontrole, seçili öğeye ya da ilk etkin öğeye girer.
←→↑↓Sonraki veya önceki öğeye geçip onu seçer, devre dışı olanları atlar. loop false değilse başa döner.
SpaceOdaktaki öğeyi seçer.
EnterFormunu gönderir.

Kontrol bir radyo grubu, her öğe de bir radyo düğmesidir; bu yüzden ekran okuyucular seçimi ve konumunu duyurur. Gösterge yalnızca görseldir ve ekran okuyucular onu atlar.

Gösterge yalnızca sayfa etkileşimli olunca kayar; yüklenirken asla canlanmaz ve azaltılmış hareket açıkken hiç kaymaz. Zorlanmış renklerde seçili öğe görünür bir kenarlık korur.

Her parça aynı adlı UI SDK parçasını sarar ve render ile parçanın durumuna bağlı bir fonksiyon olabilen className dahil tüm prop’larını kabul eder.

PropTürVarsayılan
value
T | null–
defaultValue
T | null–
onValueChange
(value: T | null, details) => void–
size
"sm" | "default" | "lg""default"
orientation
"horizontal" | "vertical""horizontal"
loop
booleantrue
disabled
booleanfalse
readOnly
booleanfalse
required
booleanfalse
name
string–
form
string–
controllercreateSegmentedControlController() ile oluşturulur.
SegmentedControlController–
render
ReactElement | (props, state) => ReactElement–
ÖznitelikAçıklama
data-slot="segmented-control"CSS'te segmentli kontrolü hedeflemek için.
data-sizeBoyut: sm, default veya lg.
data-orientationhorizontal veya vertical.
data-disabledDevre dışıyken bulunur.
data-readonlySalt okunur olduğunda bulunur.
data-requiredZorunlu olduğunda bulunur.
PropTürVarsayılan
value
string–
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement–
ÖznitelikAçıklama
data-slot="segmented-control-item"CSS'te bir öğeyi hedeflemek için.
data-checkedSeçili öğede bulunur.
data-uncheckedDiğer öğelerde bulunur.
data-icon-onlyÖğe yalnızca bir simge içerdiğinde bulunur.
data-disabledDevre dışıyken bulunur.