# Accordion
URL: /lynx/components/accordion
Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/accordion.mdx
관련된 정보 섹션을 접고 펼쳐 화면을 간결하게 구성하는 컴포넌트입니다.
Lynx Engine 최소 버전: 3.6
사용 가능 버전: @seed-design/lynx-react@0.5.0, @seed-design/lynx-css@0.9.0
## Preview
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
첫 번째 항목의 내용입니다.
두 번째 항목의 내용입니다.
세 번째 항목의 내용입니다.
);
}
```
## Installation
- npm: npx @seed-design/cli@latest add ui:accordion
- pnpm: pnpm dlx @seed-design/cli@latest add ui:accordion
- yarn: yarn dlx @seed-design/cli@latest add ui:accordion
- bun: bun x @seed-design/cli@latest add ui:accordion
## Props
### `Accordion`
### `AccordionItem`
### `AccordionTrigger`
### `AccordionContent`
## Examples
### Inline Variant
기본 variant입니다. 아이템이 연속된 흐름으로 제공되며, 아이템 사이에 구분선이 표시됩니다.
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
첫 번째 항목의 내용입니다.
두 번째 항목의 내용입니다.
세 번째 항목의 내용입니다.
);
}
```
### Separated
`variant="separated"` 를 사용하면 각 항목이 분리된 카드 형태로 표시됩니다.
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
첫 번째 항목의 내용입니다.
두 번째 항목의 내용입니다.
세 번째 항목의 내용입니다.
);
}
```
### Multiple
기본적으로 한 번에 하나의 항목만 펼칠 수 있습니다. `multiple` prop을 사용하면 여러 항목을 동시에 펼칠 수 있습니다.
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
여러 항목을 동시에 펼칠 수 있습니다.
각 항목은 다른 항목과 독립적으로 열고 닫힙니다.
세 번째 항목의 내용입니다.
);
}
```
### Always one open
`values`와 `onValuesChange`를 사용해 controlled 패턴으로 운영하면, 빈 배열이 들어올 때 setter를 호출하지 않는 가드만 추가하여 항상 하나의 항목이 열려 있도록 강제할 수 있습니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [values, setValues] = useState(["item-1"]);
function handleValuesChange(nextValues: string[]) {
"background only";
if (nextValues.length === 0) return;
setValues(nextValues);
}
return (
현재 항목은 다시 눌러도 닫히지 않고, 다른 항목을 선택할 때만 전환됩니다.
평일 오후 2시 이전 주문은 당일 출고되며, 주말 주문은 다음 영업일에 출고됩니다.
수령 후 7일 이내에 교환 또는 반품을 요청할 수 있습니다.
);
}
```
### Size
`size`로 Accordion의 크기를 정합니다. (default: `medium`)
Lynx에서는 `medium`과 `large`를 사용할 수 있습니다. 화면 너비에 따라 자동으로 바뀌는 `responsive`는 지원하지 않으므로, 필요하면 앱에서 화면 너비에 따라 두 값 중 하나를 선택해 주세요.
```tsx
import "./styles";
import { Box, Text, VStack, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
항목의 내용입니다.
항목의 내용입니다.
);
}
```
### Prefix
`prefix` prop에 아이콘 같은 앞쪽 요소를 전달할 수 있습니다.
```tsx
import "./styles";
import IconCardLine from "@karrotmarket/lynx-monochrome-icon/IconCardLine";
import IconQuestionmarkCircleLine from "@karrotmarket/lynx-monochrome-icon/IconQuestionmarkCircleLine";
import IconTruckLine from "@karrotmarket/lynx-monochrome-icon/IconTruckLine";
import { Box, Icon, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
} size="full" />}
title="배송 방법"
/>
일반 배송, 빠른 배송, 방문 수령 중 주문 상황에 맞는 방법을 선택할 수 있습니다.
} size="full" />}
title="결제 및 쿠폰"
/>
카드, 간편결제, 보유 쿠폰을 한 번에 확인하고 결제에 적용할 수 있습니다.
} size="full" />}
title="문의와 환불"
/>
주문 취소 가능 시간, 환불 소요 기간, 고객센터 문의 방법을 확인할 수 있습니다.
);
}
```
### Description
`description` prop으로 트리거에 부가 설명을 추가할 수 있습니다.
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
첫 번째 항목의 내용입니다.
두 번째 항목의 내용입니다.
세 번째 항목의 내용입니다.
);
}
```
### Disabled
`disabled` prop으로 전체 또는 개별 항목을 비활성화할 수 있습니다.
- `Accordion`에 `disabled`를 설정하면 모든 항목이 비활성화됩니다.
- `AccordionItem`에 `disabled`를 설정하면 해당 항목만 비활성화됩니다.
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
이 항목은 활성화 상태입니다.
이 항목은 비활성화 상태입니다.
이 항목은 활성화 상태입니다.
);
}
```
### Controlled
`values`와 `onValuesChange`를 사용하여 열림 상태를 직접 제어할 수 있습니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [values, setValues] = useState(["item-1"]);
function handleValuesChange(nextValues: string[]) {
"background only";
setValues(nextValues);
}
return (
첫 번째 항목의 내용입니다.
두 번째 항목의 내용입니다.
세 번째 항목의 내용입니다.
);
}
```
### Value Array Changes
controlled 모드에서는 현재 열려 있는 항목이 `values` 배열로 전달됩니다. 아래 예시는 트리거를 누를 때마다 최신 `values`와 최근 `onValuesChange` 결과를 함께 보여줍니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { Box, HStack, Text, VStack, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
const DEFAULT_VALUES = ["shipping"];
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [values, setValues] = useState(DEFAULT_VALUES);
const [history, setHistory] = useState([DEFAULT_VALUES]);
function handleValuesChange(nextValues: string[]) {
"background only";
setValues(nextValues);
setHistory((previous) => [nextValues, ...previous].slice(0, 5));
}
return (
빠른 배송, 새벽 배송, 방문 수령 옵션을 비교할 수 있습니다.
카드, 계좌이체, 간편결제 중에서 원하는 결제 수단을 선택할 수 있습니다.
주문 취소 가능 시간과 환불 소요 기간을 확인할 수 있습니다.
values: {JSON.stringify(values)}
onValuesChange history:
{history.map((snapshot, index) => (
{index + 1}. {JSON.stringify(snapshot)}
))}
);
}
```
### Default Expanded
`defaultValues`를 사용하여 초기 열림 상태를 지정할 수 있습니다.
```tsx
import "./styles";
import { Box, Text, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
첫 번째 항목은 기본으로 펼쳐진 상태입니다.
두 번째 항목의 내용입니다.
세 번째 항목의 내용입니다.
);
}
```
### Custom Content
`AccordionContent`는 열림/닫힘 애니메이션 컨테이너 역할만 합니다. 기본 패딩, 배경색, 테두리, 타이포그래피 스타일은 제공하지 않으므로 내부 콘텐츠에서 직접 구성해야 합니다. 아래 예시처럼 `Box`로 패딩과 배경을 명시적으로 주는 패턴을 권장합니다.
```tsx
import "./styles";
import { Box, Text, VStack, useSeedClassName } from "@seed-design/lynx-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
일반 배송
주문 후 영업일 기준 2-3일 내에 배송됩니다.
제주 및 도서산간 지역은 1-2일이 추가 소요될 수 있습니다.
1. 고객센터로 반품/교환 요청
2. 상품 수거 (택배 방문 수거)
3. 검수 후 환불 또는 교환 처리
);
}
```
## Web Version Differences
Lynx `Accordion`은 React 버전과 다음 차이가 있습니다.
- **Native elements**: HTML heading, button, region 대신 Lynx ``와 ``를 렌더링합니다.
- **Interaction**: 키보드 탐색 대신 Trigger의 native tap 이벤트로 항목을 열고 닫습니다.
- **Accessibility**: DOM ARIA 대신 `accessibility-heading`, `accessibility-role-description`, `accessibility-value`를 사용합니다.
- **Responsive size**: Lynx preset은 viewport media query를 지원하지 않아 `size="responsive"`를 제공하지 않습니다.
- **Content transition**: React 버전은 CSS custom property로 높이를 전달하고, Lynx 버전은 `layoutchange`로 콘텐츠 높이를 측정해 같은 duration과 easing의 transition을 적용합니다.
## Unsupported Lynx Features
| 기능 | 설명 |
| ----------------------- | --------------------------------------------------------------------------------- |
| `asChild` | Lynx에는 Slot 기반 polymorphic 렌더링이 없습니다. |
| `headingLevel` | Lynx의 heading 접근성 속성은 HTML heading level을 받지 않습니다. |
| DOM ARIA 연결 | `aria-controls`, `aria-labelledby`, `role="region"` 대신 Lynx native 접근성 속성을 사용합니다. |
| Arrow / Home / End 키 탐색 | Lynx native 화면에는 웹과 같은 키보드 포커스 모델이 없습니다. |
| `size="responsive"` | Lynx preset은 viewport media query를 지원하지 않습니다. |