CoreSelectPrim
컴파운드 패턴으로 구성된 Select 컴포넌트입니다. 단일 값에 대한 선택을 지원합니다.
Usage
기본 사용법
import { SelectPrim } from '@featuring-corp/components';
<SelectPrim.Root required width="240px">
<SelectPrim.Label tooltip="도움말">Label</SelectPrim.Label>
<SelectPrim.Trigger>
<SelectPrim.Value placeholder="옵션을 선택하세요" />
</SelectPrim.Trigger>
<SelectPrim.HelperText>Helper Text</SelectPrim.HelperText>
<SelectPrim.Portal>
<SelectPrim.Content>
<SelectPrim.Item value="option1">Option 1</SelectPrim.Item>
<SelectPrim.Item value="option2">Option 2</SelectPrim.Item>
<SelectPrim.Item value="option3" disabled>Option 3 (disabled)</SelectPrim.Item>
</SelectPrim.Content>
</SelectPrim.Portal>
</SelectPrim.Root>제어된 컴포넌트 (Controlled Component)
import { useState } from 'react';
import { SelectPrim } from '@featuring-corp/components';
const [selected, setSelected] = useState('option1');
<SelectPrim.Root
value={selected}
onValueChange={setSelected}
required
width="240px"
>
<SelectPrim.Label>Label</SelectPrim.Label>
<SelectPrim.Trigger>
<SelectPrim.Value />
</SelectPrim.Trigger>
<SelectPrim.Portal>
<SelectPrim.Content>
<SelectPrim.Item value="option1">Option 1</SelectPrim.Item>
<SelectPrim.Item value="option2">Option 2</SelectPrim.Item>
</SelectPrim.Content>
</SelectPrim.Portal>
</SelectPrim.Root>그룹과 구분선 사용
import { SelectPrim } from '@featuring-corp/components';
import { IconAccountFilled, IconTuneFilled } from '@featuring-corp/icons';
import { flex } from '@styles/utils';
<SelectPrim.Root required width="240px">
<SelectPrim.Label>Label</SelectPrim.Label>
<SelectPrim.Trigger>
<SelectPrim.Value />
</SelectPrim.Trigger>
<SelectPrim.Portal>
<SelectPrim.Content>
<SelectPrim.Group>
<SelectPrim.GroupLabel>옵션 그룹 1</SelectPrim.GroupLabel>
<SelectPrim.Item value="option1">
<div className={flex({ gap: 'spacing-200' })}>
<IconAccountFilled size="12px" />
Option 1
</div>
</SelectPrim.Item>
<SelectPrim.Item value="option2">
<div className={flex({ gap: 'spacing-200' })}>
<IconTuneFilled size="12px" />
Option 2
</div>
</SelectPrim.Item>
</SelectPrim.Group>
<SelectPrim.Separator />
<SelectPrim.Group>
<SelectPrim.GroupLabel>옵션 그룹 2</SelectPrim.GroupLabel>
<SelectPrim.Item value="option3">Option 3</SelectPrim.Item>
<SelectPrim.Item value="option4">Option 4</SelectPrim.Item>
</SelectPrim.Group>
<SelectPrim.Separator />
<SelectPrim.Item value="option5">Option 5</SelectPrim.Item>
</SelectPrim.Content>
</SelectPrim.Portal>
</SelectPrim.Root>함수형 children을 사용한 커스텀 아이템
import { SelectPrim } from '@featuring-corp/components';
import { CoreRadio } from '@featuring-corp/components';
<SelectPrim.Root required width="240px">
<SelectPrim.Label>Label</SelectPrim.Label>
<SelectPrim.Trigger>
<SelectPrim.Value />
</SelectPrim.Trigger>
<SelectPrim.Portal>
<SelectPrim.Content>
<SelectPrim.Item value="option1">
{(selected) => (
<CoreRadio
label="Option 1"
checked={selected}
onChange={() => {}}
/>
)}
</SelectPrim.Item>
<SelectPrim.Item value="option2">
{(selected) => (
<CoreRadio
label="Option 2"
checked={selected}
onChange={() => {}}
/>
)}
</SelectPrim.Item>
</SelectPrim.Content>
</SelectPrim.Portal>
</SelectPrim.Root>커스텀 Value 표시
import { useState } from 'react';
import { SelectPrim } from '@featuring-corp/components';
import { CoreTag } from '@featuring-corp/components';
const [selected, setSelected] = useState('option1');
const options = {
option1: { label: 'Option 1', display: <CoreTag text="Option 1" /> },
option2: { label: 'Option 2', display: <CoreTag text="Option 2" /> },
option3: { label: 'Option 3', display: <CoreTag text="Option 3" /> },
};
<SelectPrim.Root
value={selected}
onValueChange={setSelected}
required
width="240px"
>
<SelectPrim.Label tooltip="도움말">Label</SelectPrim.Label>
<SelectPrim.Trigger>
<SelectPrim.Value>
{options[selected]?.display}
</SelectPrim.Value>
</SelectPrim.Trigger>
<SelectPrim.Portal>
<SelectPrim.Content>
{Object.entries(options).map(([value, { label }]) => (
<SelectPrim.Item key={value} value={value}>
{label}
</SelectPrim.Item>
))}
</SelectPrim.Content>
</SelectPrim.Portal>
</SelectPrim.Root>상태와 크기 설정
import { SelectPrim } from '@featuring-corp/components';
<SelectPrim.Root
status="error"
size="lg"
width="300px"
required
disabled={false}
readonly={false}
>
<SelectPrim.Label>Label</SelectPrim.Label>
<SelectPrim.Trigger>
<SelectPrim.Value />
</SelectPrim.Trigger>
<SelectPrim.HelperText status="error">
에러 메시지가 표시됩니다
</SelectPrim.HelperText>
<SelectPrim.Portal>
<SelectPrim.Content height={200}>
<SelectPrim.Item value="option1">Option 1</SelectPrim.Item>
<SelectPrim.Item value="option2">Option 2</SelectPrim.Item>
</SelectPrim.Content>
</SelectPrim.Portal>
</SelectPrim.Root>Props
SelectPrim.Root
가장 상위 컴포넌트로, Select 전체를 감싸는 역할을 합니다.
해당 컴포넌트를 통해 내부적으로 많은 기능을 컨트롤하기 때문에, 반드시 포함되어야하는 컴포넌트입니다.
Root 컴포넌트에 주입된 status, size, width, readonly, required, disabled props는 하위 컴포넌트에 모두 전달됩니다.
Prop
Type
SelectPrim.Label
Select의 라벨을 표시합니다.
Prop
Type
SelectPrim.Trigger
Select의 선택된 값을 표시합니다. button element로 되어 있습니다.
Prop
Type
SelectPrim.Value
선택된 값을 표시합니다. Trigger 내부에서 사용합니다.
Prop
Type
SelectPrim.HelperText
Select의 헬퍼 텍스트를 표시합니다.
Prop
Type
SelectPrim.Portal
Select의 옵션 목록을 렌더링할 포탈입니다.
Select.SelectPortalProps 타입을 확장한 컴포넌트입니다.
SelectPrim.Content
Select의 옵션 목록을 표시합니다.
Prop
Type
SelectPrim.Item
옵션 목록 내부의 아이템입니다.
children에 작성한 내용이 선택 시에도 자동으로 적용됩니다.
Prop
Type
SelectPrim.Group
옵션 목록 내부의 그룹입니다.
Select.SelectGroupProps 타입을 확장한 컴포넌트입니다.
SelectPrim.GroupLabel
옵션 목록 내부의 그룹 라벨입니다.
Select.SelectLabelProps 타입을 확장한 컴포넌트입니다.
SelectPrim.Separator
옵션 목록 내부의 구분선입니다.
Select.SelectSeparatorProps 타입을 확장한 컴포넌트입니다.
SelectStatus
Prop
Type
SelectSize
Prop
Type
CoreTooltipProps
CoreTooltip 컴포넌트의 props를 참조하세요.스타일
기본 스타일 속성
Label:
display:flexjustify-content:flex-startalign-items:centermargin-bottom:spacing-150(6px)typography:heading[1]color:text-2(기본),text-4(disabled)
Label Required:
margin-left:spacing-50(2px)
Label Icon:
margin-left:spacing-100(4px)
Select Trigger:
display:flexjustify-content:space-betweengap:spacing-200(8px)padding-x:spacing-250(10px)border-radius:radius-100border:1px solid border[1]background-color:background-1(기본),background-2(hover)color:text-1(기본),text-5(placeholder)cursor:pointerwidth:auto(기본값)
Select Value:
display:blockflex-grow:1
Select Value Placeholder:
display:-webkit-box-webkit-box-orient:verticalword-wrap:break-wordtext-overflow:ellipsisoverflow:hiddenwhite-space:pre-wrapword-break:break-all-webkit-line-clamp:1
Content Container:
background-color:background-1padding:spacing-200(8px)border-radius:radius-100elevation:elevation-8width:auto(기본값)height:auto(기본값)overflow:auto
Select Item:
display:flexgap:spacing-150(6px)border-radius:radius-100min-height:28pxcursor:pointer(disabled: off),not-allowed(disabled: on)
Helper Text:
display:flexgap:spacing-100(4px)margin-top:spacing-100(4px)typography:body[1]
Group Label:
padding-x:spacing-200(8px)padding-y:spacing-100(4px)color:text-3typography:body[1]
Separator:
margin-y:spacing-300(12px)margin-x:spacing-200(8px)border-top:1px solid border-default
Size Variants (Trigger)
sm:typography: body[1],min-height: 28px,height: max-contentmd:typography: body[2],min-height: 32px,height: max-contentlg:typography: body[2],min-height: 40px,height: max-content
Size Variants (Item)
sm:typography: body[1],padding-y: spacing-50(2px)md:typography: body[2],padding-y: spacing-100(4px)lg:typography: body[2],padding-y: spacing-200(8px)
Status Variants (Trigger)
none:border-color: border[1]warning:border-color: support-warning[3]error:border-color: support-error[3]
Helper Text Status Variants
none:color: text-3warning:color: support-warning-3error:color: support-error-3
Select Item States
- Disabled (on):
background-color: toggle-disabled-bg,color: toggle-disabled-text,cursor: not-allowed - Disabled (off):
data-highlighted:background-color: primary[10],color: primary[100],cursor: pointer
States (상태별 토큰)
Select Trigger:
- Default:
background-color: background-1,border: 1px solid border[1],color: text-1 - Hover:
background-color: background-2,border-color: border-2 - Focus (not readonly, not disabled):
border-color: primary[50] - Data-state="open":
border-color: primary[50] - Readonly:
border-color: border[2],background-color: background[4],color: text[1],cursor: auto - Disabled:
border-color: border[2],background-color: background[4],color: text[4],cursor: not-allowed - Placeholder:
color: text[5]