# 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의 제목과 액션은 형제 요소로 배치하세요.