Chip Tabs
Chip 형태로 표현된 탭 컴포넌트입니다. 카테고리나 필터를 선택하여 콘텐츠를 전환할 때 사용됩니다.
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsPreview() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Installation
npx @seed-design/cli@latest add ui:chip-tabspnpm dlx @seed-design/cli@latest add ui:chip-tabsyarn dlx @seed-design/cli@latest add ui:chip-tabsbun x @seed-design/cli@latest add ui:chip-tabs의존성 설치
npm install @seed-design/reactyarn add @seed-design/reactpnpm add @seed-design/reactbun add @seed-design/react아래 코드를 복사 후 붙여넣고 사용하세요
/**
* @file ui:chip-tabs
* @requires @seed-design/react@^2.0.0 || ^3.0.0
**/
"use client";
import { HStack, NotificationBadge, ChipTabs as SeedChipTabs } from "@seed-design/react";
import { forwardRef } from "react";
export interface ChipTabsRootProps extends SeedChipTabs.RootProps {}
export const ChipTabsRoot = SeedChipTabs.Root;
export interface ChipTabsListProps extends SeedChipTabs.ListProps {}
export const ChipTabsList = SeedChipTabs.List;
export interface ChipTabsTriggerProps extends Omit<SeedChipTabs.TriggerProps, "asChild"> {
notification?: boolean;
}
export const ChipTabsTrigger = forwardRef<HTMLButtonElement, ChipTabsTriggerProps>((props, ref) => {
const { children, notification, ...otherProps } = props;
return (
<SeedChipTabs.Trigger ref={ref} {...otherProps}>
{notification ? (
<HStack as="span" gap="x1_5">
{children}
<NotificationBadge size="small" />
</HStack>
) : (
children
)}
</SeedChipTabs.Trigger>
);
});
ChipTabsTrigger.displayName = "ChipTabsTrigger";
export interface ChipTabsCarouselProps extends Omit<SeedChipTabs.CarouselProps, "asChild"> {}
export const ChipTabsCarousel = (props: ChipTabsCarouselProps) => {
const { children, ...otherProps } = props;
return (
<SeedChipTabs.Carousel {...otherProps}>
<SeedChipTabs.CarouselCamera>{children}</SeedChipTabs.CarouselCamera>
</SeedChipTabs.Carousel>
);
};
ChipTabsCarousel.displayName = "ChipTabsCarousel";
export interface ChipTabsContentProps extends SeedChipTabs.ContentProps {}
export const ChipTabsContent = SeedChipTabs.Content;
/**
* 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
ChipTabsRoot
Prop
Type
orientation?"horizontal" | "vertical" | undefinedvalue?string | undefineddefaultValue?string | undefinedonValueChange?((value: string) => void) | undefinedChipTabsList
Prop
Type
ChipTabsTrigger
Prop
Type
notification?boolean | undefinedvaluestringdisabled?boolean | undefinedChipTabsCarousel
Prop
Type
swipeable?boolean | undefinedautoHeight?boolean | undefinedloop?boolean | undefineddragThreshold?number | undefinedonSettle?(() => void) | undefinedChipTabsContent
Prop
Type
valuestringUsage
Content
탭 선택으로만 콘텐츠를 전환할 때는 ChipTabsContent를 ChipTabsRoot 안에 배치합니다. Trigger와 Content의 value를 맞추면 선택된 패널만 표시됩니다. 이 구성은 전환 애니메이션과 좌우 스와이프를 제공하지 않습니다.
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export function App() {
return (
<ChipTabsRoot defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">첫 번째 콘텐츠</ChipTabsContent>
<ChipTabsContent value="2">두 번째 콘텐츠</ChipTabsContent>
<ChipTabsContent value="3">세 번째 콘텐츠</ChipTabsContent>
</ChipTabsRoot>
);
}ChipTabsRoot는 value와 onValueChange로 제어하거나 defaultValue로 초기 선택 값을 지정합니다. ChipTabsTrigger의 notification은 label 옆에 작은 NotificationBadge를 표시합니다.
Swipeable
ChipTabsContent를 ChipTabsCarousel 안에 배치하면 탭을 바꿀 때 콘텐츠가 가로로 전환되고, swipeable을 설정하면 콘텐츠를 좌우로 밀어 탭을 바꿀 수 있습니다. Registry의 ChipTabsCarousel은 내부에서 Camera를 조립하므로 ChipTabsCarouselCamera를 따로 추가할 필요가 없습니다.
아래 예제에서 Trigger를 누르거나 콘텐츠를 좌우로 밀면 선택된 chip과 콘텐츠가 함께 바뀝니다. 스와이프 시작·종료·정착은 ChipTabsCarousel의 onSwipeStart, onSwipeEnd, onSettle로 처리할 수 있습니다.
import {
ChipTabsCarousel,
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsSwipeable() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot defaultValue="2">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsCarousel swipeable>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsCarousel>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Examples
Size=Medium
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsSizeMedium() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot variant="neutralSolid" size="medium" defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Size=Large
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsSizeLarge() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot variant="neutralSolid" size="large" defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Variant=Neutral Solid
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsVariantNeutralSolid() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot variant="neutralSolid" defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Variant=Neutral Outline
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsVariantNeutralOutline() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot variant="neutralOutline" defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger value="1">라벨1</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Notification
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
export default function ChipTabsNotification() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot variant="neutralOutline" size="medium" defaultValue="1">
<ChipTabsList>
<ChipTabsTrigger notification value="1">
라벨1
</ChipTabsTrigger>
<ChipTabsTrigger value="2">라벨2</ChipTabsTrigger>
<ChipTabsTrigger value="3">라벨3</ChipTabsTrigger>
</ChipTabsList>
<ChipTabsContent value="1">
<Content>Content 1</Content>
</ChipTabsContent>
<ChipTabsContent value="2">
<Content>Content 2</Content>
</ChipTabsContent>
<ChipTabsContent value="3">
<Content>Content 3</Content>
</ChipTabsContent>
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};With Scroll Fog
탭이 많아 가로 스크롤이 필요한 경우 Scroll Fog를 적용하여 좌우 스크롤 힌트를 제공할 수 있습니다.
권장 padding인 20px을 유지해야 합니다.
import { ScrollFog } from "@seed-design/react";
import {
ChipTabsContent,
ChipTabsList,
ChipTabsRoot,
ChipTabsTrigger,
} from "seed-design/ui/chip-tabs";
const tabs = Array.from({ length: 15 }, (_, i) => String(i + 1));
export default function ChipTabsWithScrollFog() {
return (
<div style={{ width: "100%", maxWidth: "360px" }}>
<ChipTabsRoot variant="neutralSolid" defaultValue="1">
<ScrollFog placement={["left", "right"]}>
<ChipTabsList style={{ paddingLeft: "20px", paddingRight: "20px" }}>
{tabs.map((value) => (
<ChipTabsTrigger key={value} value={value}>
라벨{value}
</ChipTabsTrigger>
))}
</ChipTabsList>
</ScrollFog>
{tabs.map((value) => (
<ChipTabsContent key={value} value={value}>
<Content>Content {value}</Content>
</ChipTabsContent>
))}
</ChipTabsRoot>
</div>
);
}
const Content = (props: React.PropsWithChildren) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "180px",
backgroundColor: "var(--seed-color-bg-layer-default)",
}}
>
{props.children}
</div>
);
};Last updated on