# List
URL: /lynx/components/list
Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/list.mdx
가로 행으로 구성된 콘텐츠를 표현하는 컴포넌트입니다.
사용 가능 버전: @seed-design/lynx-react@0.7.0, @seed-design/lynx-css@0.11.0
## Preview
```tsx
import "./styles";
import IconILowercaseSerifCircleLine from "@karrotmarket/lynx-monochrome-icon/IconILowercaseSerifCircleLine";
import IconPersonCircleLine from "@karrotmarket/lynx-monochrome-icon/IconPersonCircleLine";
import { PrefixIcon, SuffixIcon } from "@seed-design/lynx-react";
import { ListHeader } from "@/components/ui/list-header";
import { List, ListDivider, ListItem } from "@/components/ui/list";
export default function Example() {
return (
리스트 헤더
} />}
title="아이콘이 있는 리스트 아이템"
detail="부가 정보가 포함된 설명"
suffix={} />}
/>
);
}
```
## Installation
- npm: npx @seed-design/cli@latest add ui:list
- pnpm: pnpm dlx @seed-design/cli@latest add ui:list
- yarn: yarn dlx @seed-design/cli@latest add ui:list
- bun: bun x @seed-design/cli@latest add ui:list
## Usage
```tsx
import { ListHeader } from "@/components/ui/list-header";
import { List, ListDivider, ListItem } from "@/components/ui/list";
리스트 헤더
```
## Props
### `ListHeader`
### `List`
고유 prop이 없습니다. `className`, `style`, `children`을 받습니다.
### List Items
Lynx에는 HTML anchor에 해당하는 기본 요소가 없습니다. 링크 이동은 `ListButtonItem`의 `bindtap`에서 앱 라우터를 호출해 처리합니다.
## Examples
### Using `ListHeader`
`ListHeader`는 `List` 밖에 둡니다. 헤더에 액션이 필요하면 형제 요소로 배치하세요.
```tsx
import "./styles";
import IconChevronRightLine from "@karrotmarket/lynx-monochrome-icon/IconChevronRightLine";
import IconLockLine from "@karrotmarket/lynx-monochrome-icon/IconLockLine";
import IconPersonCircleLine from "@karrotmarket/lynx-monochrome-icon/IconPersonCircleLine";
import IconQuestionmarkCircleFill from "@karrotmarket/lynx-monochrome-icon/IconQuestionmarkCircleFill";
import { ActionButton, PrefixIcon, SuffixIcon } from "@seed-design/lynx-react";
import { List, ListButtonItem, ListDivider } from "@/components/ui/list";
import { ListHeader } from "@/components/ui/list-header";
function AccountList() {
return (
} />}
suffix={} />}
/>
} />}
suffix={} />}
/>
);
}
export default function Example() {
return (
variant="mediumWeak"
variant="boldSolid"
List Header with Action Button
} />
도움말
);
}
```
### Affixes (Prefix/Suffix)
```tsx
import "./styles";
import IconArrowUpBracketDownFill from "@karrotmarket/lynx-monochrome-icon/IconArrowUpBracketDownFill";
import IconILowercaseSerifCircleLine from "@karrotmarket/lynx-monochrome-icon/IconILowercaseSerifCircleLine";
import { useState } from "@lynx-js/react";
import { ActionButton, Icon, PrefixIcon } from "@seed-design/lynx-react";
import { List, ListDivider, ListItem } from "@/components/ui/list";
export default function Example() {
const [pressed, setPressed] = useState(false);
return (
A
}
title="Prefix에 Avatar 넣기"
detail="Amet elit ullamco magna."
/>
} />}
/>
액션 버튼
}
/>
} />
}
/>
{
"background only";
setPressed((value) => !value);
}}
>
{pressed ? "선택됨" : "토글 버튼"}
}
/>
);
}
```
### Clickable List Items
`ListButtonItem`을 사용하면 리스트 항목 전체를 탭할 수 있습니다. Lynx에는 `ListLinkItem`이 없으므로 화면 이동은 `bindtap`에서 앱 라우터를 호출합니다.
```tsx
import "./styles";
import IconArrowUpRightLine from "@karrotmarket/lynx-monochrome-icon/IconArrowUpRightLine";
import IconCheckmarkFill from "@karrotmarket/lynx-monochrome-icon/IconCheckmarkFill";
import IconChevronRightLine from "@karrotmarket/lynx-monochrome-icon/IconChevronRightLine";
import IconPenHorizlineFill from "@karrotmarket/lynx-monochrome-icon/IconPenHorizlineFill";
import IconPlusFill from "@karrotmarket/lynx-monochrome-icon/IconPlusFill";
import IconSquare2StackedFill from "@karrotmarket/lynx-monochrome-icon/IconSquare2StackedFill";
import { useState } from "@lynx-js/react";
import { ActionButton, PrefixIcon, SuffixIcon } from "@seed-design/lynx-react";
import { List, ListButtonItem, ListDivider, ListItem } from "@/components/ui/list";
export default function Example() {
const [status, setStatus] = useState("아직 탭하지 않았어요");
const [subscribed, setSubscribed] = useState(false);
const [copied, setCopied] = useState(false);
return (
{
"background only";
setStatus("편집 클릭됨");
}}
>
} />
편집
}
/>
{
"background only";
setStatus("리스트 아이템 클릭됨");
}}
suffix={
{}}>
{
"background only";
setSubscribed((value) => !value);
setStatus("모아보기 상태 변경됨");
}}
>
: } />
{subscribed ? "모아보는 중" : "모아보기"}
} />
}
/>
{
"background only";
setStatus("리스트 아이템 클릭됨");
}}
suffix={
{
"background only";
setStatus("커스텀 버튼 클릭됨");
}}
>
커스텀 버튼
} />
}
/>
{
"background only";
setStatus("링크 이동 요청됨");
}}
suffix={
{}}>
{
"background only";
setCopied(true);
setStatus("URL 복사됨");
}}
>
: } />
{copied ? "복사됨" : "URL 복사"}
} />
}
/>
{status}
);
}
```
### `input`s in List Items
`ListSwitchItem`, `ListCheckItem`, `ListRadioItem`을 사용하면 항목 전체를 탭해 값을 바꿀 수 있습니다. snippet은 각 컨트롤을 기본 suffix로 렌더링합니다. `suffix={null}`을 전달하면 기본 컨트롤을 숨길 수 있습니다.
```tsx
import "./styles";
import IconTrashcanLine from "@karrotmarket/lynx-monochrome-icon/IconTrashcanLine";
import { PrefixIcon } from "@seed-design/lynx-react";
import { List, ListDivider, ListSwitchItem } from "@/components/ui/list";
export default function Example() {
return (
} />}
/>
);
}
```
```tsx
import "./styles";
import { HStack } from "@seed-design/lynx-react";
import { Badge } from "@/components/ui/badge";
import { Checkmark } from "@/components/ui/checkbox";
import { List, ListCheckItem, ListDivider } from "@/components/ui/list";
export default function Example() {
return (
알림 수신 동의
권장
}
detail="푸시 알림을 받으시겠습니까?"
defaultChecked
/>
}
suffix={null}
defaultChecked
/>
}
suffix={null}
title="Ghost Variant"
/>
);
}
```
```tsx
import "./styles";
import { List, ListDivider, ListRadioItem } from "@/components/ui/list";
import { RadioGroup, Radiomark } from "@/components/ui/radio-group";
export default function Example() {
return (
}
/>
}
suffix={null}
/>
}
suffix={null}
/>
);
}
```
### Accessibility
`ListButtonItem`은 `title`에서 접근성 이름을 만듭니다. 제목에 ``나 ``를 직접 넣거나 부가 텍스트가 섞이면 `accessibility-label`을 지정하세요.
선택 항목은 행 전체를 하나의 접근성 요소로 노출하고 선택 상태를 전달합니다. `ListRadioItem`은 Registry snippet의 `RadioGroup` 안에 두고 그룹의 접근성 이름을 지정하세요.
```tsx
import { List, ListRadioItem } from "@/components/ui/list";
import { RadioGroup } from "@/components/ui/radio-group";
```
### Disabled
```tsx
import "./styles";
import IconChevronRightLine from "@karrotmarket/lynx-monochrome-icon/IconChevronRightLine";
import IconPersonCircleLine from "@karrotmarket/lynx-monochrome-icon/IconPersonCircleLine";
import IconSlashCircleLine from "@karrotmarket/lynx-monochrome-icon/IconSlashCircleLine";
import { PrefixIcon, SuffixIcon } from "@seed-design/lynx-react";
import { List, ListButtonItem, ListCheckItem, ListRadioItem } from "@/components/ui/list";
import { RadioGroup } from "@/components/ui/radio-group";
export default function Example() {
return (
} />}
title="활성화된 ListButtonItem"
detail="Cupidatat et pariatur amet."
suffix={} />}
/>
} />}
title="활성화된 ListCheckItem"
/>
} />}
title="활성화된 ListRadioItem"
value="enabled"
/>
} />}
title="비활성화된 ListButtonItem"
detail="Cupidatat et pariatur amet."
suffix={} />}
/>
} />}
title="비활성화된 ListCheckItem"
/>
} />}
title="비활성화된 ListRadioItem"
value="disabled"
/>
);
}
```
### Variants
#### Highlighted
```tsx
import "./styles";
import IconPersonCircleLine from "@karrotmarket/lynx-monochrome-icon/IconPersonCircleLine";
import { useState } from "@lynx-js/react";
import { PrefixIcon } from "@seed-design/lynx-react";
import { List, ListButtonItem, ListDivider, ListItem } from "@/components/ui/list";
import { Switch } from "@/components/ui/switch";
export default function Example() {
const [highlighted, setHighlighted] = useState(true);
return (
} />}
title="버튼"
detail="Enim aute duis magna mollit aute sit aliquip duis ut tempor sunt."
/>
} />}
title="하이라이트된 버튼"
detail="Enim aute duis magna mollit aute sit aliquip duis ut tempor sunt."
/>
} />}
title="하이라이트 및 비활성화된 버튼"
detail="Enim aute duis magna mollit aute sit aliquip duis ut tempor sunt."
/>
} />}
title="하이라이트"
highlighted={highlighted}
/>
highlight
);
}
```
### With Bottom Sheet
```tsx
import "./styles";
import IconArrowClockwiseCircularFill from "@karrotmarket/lynx-monochrome-icon/IconArrowClockwiseCircularFill";
import { useRef, useState } from "@lynx-js/react";
import { ActionButton, PrefixIcon } from "@seed-design/lynx-react";
import {
BottomSheetBody,
BottomSheetContent,
BottomSheetFooter,
BottomSheetRoot,
type BottomSheetRootRef,
BottomSheetTrigger,
} from "@/components/ui/bottom-sheet";
import { List, ListCheckItem } from "@/components/ui/list";
const TYPES = ["버스", "지하철", "택시", "자전거", "도보"] as const;
export default function Example() {
const sheetRef = useRef(null);
const [selectedTypes, setSelectedTypes] = useState<(typeof TYPES)[number][]>([]);
return (
BottomSheet 열기
{TYPES.map((type) => (
{
setSelectedTypes((previous) =>
previous.includes(type)
? previous.filter((item) => item !== type)
: [...previous, type],
);
}}
/>
))}
{
"background only";
sheetRef.current?.close();
}}
>
경로 찾기
{
"background only";
setSelectedTypes([]);
}}
>
} />
초기화
);
}
```
### Alignment
React의 `alignItems` prop은 Lynx List에서 지원하지 않습니다. 상단 정렬이 필요하면 슬롯을 직접 배치한 별도 레이아웃을 사용하세요.
### Border Radius
React의 `itemBorderRadius` prop은 Lynx List에서 지원하지 않습니다. Lynx 항목의 눌림 반경은 Recipe가 정한 값을 사용합니다. 둥근 카드 안에서는 바깥 컨테이너에 `border-radius`와 `overflow: hidden`을 적용하세요.
## 웹 버전과의 차이
- 항목을 탭할 때는 `onClick` 대신 `bindtap`을 사용합니다.
- 링크 항목은 `ListButtonItem`의 `bindtap`에서 앱 라우터를 호출합니다.
- 선택 항목은 행 전체가 컨트롤의 상태와 접근성 값을 가집니다.
## Lynx 미지원 기능
- `as`와 `asChild`를 지원하지 않습니다.
- `itemBorderRadius` 대신 바깥 컨테이너에 반경과 clipping을 적용하세요.
- `alignItems` 대신 별도 레이아웃을 구성하세요.
- Header의 제목과 액션은 형제 요소로 배치하세요.