React
Segmented Control
여러 옵션 중 하나를 선택하여 관련 콘텐츠를 즉시 필터링하거나 전환할 때 사용하는 컴포넌트입니다.
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
export default function SegmentedControlPreview() {
return (
<SegmentedControl defaultValue="Hot" aria-label="Sort by">
<SegmentedControlItem value="Hot">Hot</SegmentedControlItem>
<SegmentedControlItem value="New">New</SegmentedControlItem>
</SegmentedControl>
);
}Installation
npx @seed-design/cli@latest add ui:segmented-controlpnpm dlx @seed-design/cli@latest add ui:segmented-controlyarn dlx @seed-design/cli@latest add ui:segmented-controlbun x @seed-design/cli@latest add ui:segmented-control의존성 설치
npm install @seed-design/reactyarn add @seed-design/reactpnpm add @seed-design/reactbun add @seed-design/react아래 코드를 복사 후 붙여넣고 사용하세요
/**
* @file ui:segmented-control
* @requires @seed-design/react@^2.0.0
* @requires @seed-design/css@^2.0.0
**/
"use client";
import { HStack, SegmentedControl as SeedSegmentedControl } from "@seed-design/react";
import { NotificationBadgePositioner, NotificationBadge } from "@seed-design/react";
import * as React from "react";
export interface SegmentedControlProps extends SeedSegmentedControl.RootProps {}
/**
* @see https://seed-design.io/react/components/segmented-control
*/
export const SegmentedControl = React.forwardRef<HTMLDivElement, SegmentedControlProps>(
({ children, ...otherProps }, ref) => {
if (!otherProps["aria-label"] && !otherProps["aria-labelledby"]) {
console.warn(
"SegmentedControl component requires either an `aria-label` or `aria-labelledby` attribute.",
);
}
if (otherProps.value === undefined && otherProps.defaultValue === undefined) {
console.warn(
"SegmentedControl component requires either a `value` or `defaultValue` attribute.",
);
}
return (
<SeedSegmentedControl.Root ref={ref} {...otherProps}>
{children}
<SeedSegmentedControl.Indicator />
</SeedSegmentedControl.Root>
);
},
);
SegmentedControl.displayName = "SegmentedControl";
export interface SegmentedControlItemProps extends SeedSegmentedControl.ItemProps {
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
rootRef?: React.Ref<HTMLLabelElement>;
notification?: boolean;
}
/**
* @see https://seed-design.io/react/components/segmented-control#segmentedcontrolitem
*/
export const SegmentedControlItem = React.forwardRef<HTMLInputElement, SegmentedControlItemProps>(
({ children, inputProps, rootRef, notification, ...otherProps }, ref) => {
return (
<SeedSegmentedControl.Item ref={rootRef} {...otherProps}>
<SeedSegmentedControl.ItemHiddenInput ref={ref} {...inputProps} />
{notification ? (
<HStack position="relative" align="flex-start">
{children}
<NotificationBadgePositioner size="small" attach="text">
<NotificationBadge />
</NotificationBadgePositioner>
</HStack>
) : (
children
)}
</SeedSegmentedControl.Item>
);
},
);
SegmentedControlItem.displayName = "SegmentedControlItem";
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
Props
SegmentedControl
value와 defaultValue 중 적어도 하나를 제공해야 합니다.
Prop
Type
disabled?boolean | undefinedname?string | undefinedform?string | undefinedvalue?string | undefineddefaultValue?string | undefinedonValueChange?((value: string) => void) | undefinedSegmentedControlItem
Prop
Type
inputProps?React.InputHTMLAttributes<HTMLInputElement> | undefinedrootRef?React.Ref<HTMLLabelElement> | undefinednotification?boolean | undefinedvaluestringdisabled?boolean | undefinedinvalid?boolean | undefinedExamples
Disabled
import { VStack } from "@seed-design/react";
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
export default function SegmentedControlPreview() {
return (
<VStack align="center" gap="spacingY.componentDefault">
<SegmentedControl defaultValue="Hot" disabled aria-label="Sort by">
<SegmentedControlItem value="Hot">Hot</SegmentedControlItem>
<SegmentedControlItem value="New">New</SegmentedControlItem>
</SegmentedControl>
<SegmentedControl defaultValue="Marinara" aria-label="Pasta">
<SegmentedControlItem value="Marinara">Marinara</SegmentedControlItem>
<SegmentedControlItem value="Alfredo" disabled>
Alfredo
</SegmentedControlItem>
<SegmentedControlItem value="Pesto" disabled>
Pesto
</SegmentedControlItem>
<SegmentedControlItem value="Carbonara">Carbonara</SegmentedControlItem>
<SegmentedControlItem value="Bolognese">Bolognese</SegmentedControlItem>
</SegmentedControl>
</VStack>
);
}Notification
import { ActionButton, VStack } from "@seed-design/react";
import { useState } from "react";
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
export default function SegmentedControlNotification() {
const [sortBy, setSortBy] = useState("monthly");
const [hasSeenAnnual, setHasSeenAnnual] = useState(false);
return (
<VStack align="center" gap="spacingY.componentDefault">
<SegmentedControl
aria-label="Billing Method"
value={sortBy}
onValueChange={(value) => {
setSortBy(value);
if (value === "annual") setHasSeenAnnual(true);
}}
>
<SegmentedControlItem value="monthly">Monthly</SegmentedControlItem>
<SegmentedControlItem value="annual" notification={!hasSeenAnnual}>
Annual
</SegmentedControlItem>
<SegmentedControlItem value="enterprise">Enterprise Custom</SegmentedControlItem>
</SegmentedControl>
<ActionButton
size="xsmall"
variant="neutralSolid"
disabled={!hasSeenAnnual}
onClick={() => setHasSeenAnnual(false)}
>
Reset Notification
</ActionButton>
</VStack>
);
}Long Label
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
export default function SegmentedControlLongLabel() {
return (
<SegmentedControl defaultValue="price" aria-label="정렬 기준">
<SegmentedControlItem value="price">가격 높은 순</SegmentedControlItem>
<SegmentedControlItem value="discount">할인율 높은 순</SegmentedControlItem>
<SegmentedControlItem value="popularity">인기 많은 순</SegmentedControlItem>
</SegmentedControl>
);
}Fixed Width
SegmentedControl의 style prop에 width를 제공해서 직접 너비를 설정할 수 있습니다.
import { VStack } from "@seed-design/react";
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
export default function SegmentedControlFixedWidth() {
return (
<VStack align="center" gap="spacingY.componentDefault">
<SegmentedControl defaultValue="new" style={{ width: "500px" }} aria-label="Sort by">
<SegmentedControlItem value="new">New</SegmentedControlItem>
<SegmentedControlItem value="hot">Hot</SegmentedControlItem>
</SegmentedControl>
<SegmentedControl defaultValue="oneway" style={{ width: "400px" }} aria-label="Trip Type">
<SegmentedControlItem value="oneway">One Way Trip</SegmentedControlItem>
<SegmentedControlItem notification value="round">
Round Trip
</SegmentedControlItem>
<SegmentedControlItem notification value="multi">
Multi-City Journey
</SegmentedControlItem>
</SegmentedControl>
</VStack>
);
}Listening to Value Changes
SegmentedControl의 onValueChange prop을 사용하여 선택 값 변경을 감지할 수 있습니다.
이벤트를 활용해야 하는 경우 SegmentedControlItem의 inputProps를 통해 내부 <input> 요소에 직접 이벤트 핸들러를 추가할 수 있습니다.
import { VStack, Text } from "@seed-design/react";
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
import { useState } from "react";
export default function SegmentedControlValueChanges() {
const [count, setCount] = useState(0);
const [lastValue, setLastValue] = useState<string | null>(null);
return (
<VStack gap="x4" align="center">
<SegmentedControl
defaultValue="hot"
aria-label="Sort by"
onValueChange={(value) => {
setCount((prev) => prev + 1);
setLastValue(value);
}}
>
<SegmentedControlItem value="hot">Hot</SegmentedControlItem>
<SegmentedControlItem value="new">New</SegmentedControlItem>
</SegmentedControl>
<Text>
onValueChange called: {count} times, last value: {lastValue ?? "-"}
</Text>
</VStack>
);
}Last updated on