# Quantity Picker
URL: /lynx/components/quantity-picker
Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/quantity-picker.mdx
정수 단위의 수량을 늘리거나 줄일 때 사용하는 컴포넌트입니다.
Lynx Engine 최소 버전: 3.6
사용 가능 버전: @seed-design/lynx-react@0.8.0, @seed-design/lynx-css@0.12.0
## Preview
```tsx
import "./styles";
import { QuantityPicker } from "@/components/ui/quantity-picker";
export default function Example() {
return ;
}
```
## Installation
- npm: npx @seed-design/cli@latest add ui:quantity-picker
- pnpm: pnpm dlx @seed-design/cli@latest add ui:quantity-picker
- yarn: yarn dlx @seed-design/cli@latest add ui:quantity-picker
- bun: bun x @seed-design/cli@latest add ui:quantity-picker
## Props
### `QuantityPicker`
Registry의 `QuantityPicker`는 수량 선택에 필요한 감소 버튼, 값, 증가 버튼을 함께 제공합니다.
`min`과 `max`는 필수이며 안전한 정수여야 합니다. `step`의 기본값은 `1`이고, `defaultValue`를 생략하면 `min`에서 시작합니다. `value`와 `onValueChange`를 함께 사용하면 값을 외부 상태로 제어할 수 있습니다.
## Examples
### Layout
`layout="hug"`는 콘텐츠에 맞는 너비를 유지합니다. 부모가 Flex 레이아웃이고 남은 공간을 채워야 한다면 `layout="fill"`을 사용하세요. 양쪽 버튼 크기는 유지되고 Value Display 영역만 늘어납니다.
```tsx
import "./styles";
import { QuantityPicker } from "@/components/ui/quantity-picker";
export default function Example() {
return (
Layout
Hug (기본)
Fill
);
}
```
이 예제에서 사용하는 Quantity Picker recipe는 `display: grid`를 사용합니다. Android/iOS Lynx engine 2.1 이상과 HarmonyOS Lynx engine 3.4 이상에서 호환됩니다.
### Value Text
`getValueText`를 사용하면 표시되는 수량에 단위나 보조 설명을 덧붙일 수 있습니다. 반환한 값은 Value Display와 접근성 값에 사용할 표시 텍스트이며, 내부 수량 상태나 증감 단위에는 영향을 주지 않습니다.
```tsx
import "./styles";
import { QuantityPicker } from "@/components/ui/quantity-picker";
export default function Example() {
return (
Value text
`${valueText}개`}
/>
);
}
```
### Controlled
`value`와 `onValueChange`를 사용해 수량 상태를 앱의 상태로 제어할 수 있습니다. 변경 콜백에서 새 숫자를 저장하고, 저장한 값을 다시 `value`로 전달하세요.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { QuantityPicker } from "@/components/ui/quantity-picker";
export default function Example() {
const [quantity, setQuantity] = useState(2);
function handleValueChange(nextQuantity: number) {
"background only";
setQuantity(nextQuantity);
}
return (
Controlled
현재 수량: {quantity}개
);
}
```
### Removable
`removable`을 사용하면 값이 `min`에 도달했을 때 Decrement 버튼이 Remove 버튼으로 전환됩니다. 이때 Decrement를 누르면 수량을 변경하지 않고 `onRemove`만 호출합니다. 삭제나 목록에서 제거하는 동작은 `onRemove`에서 처리하세요.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { ActionButton, VStack } from "@seed-design/lynx-react";
import { QuantityPicker } from "@/components/ui/quantity-picker";
export default function Example() {
const [removed, setRemoved] = useState(false);
function handleRemove() {
"background only";
setRemoved(true);
}
function handleRestore() {
"background only";
setRemoved(false);
}
return (
Removable
{removed ? (
상품을 삭제했습니다.
되돌리기
) : (
<>
최솟값에서 감소 버튼을 누르면 수량 선택기가 제거됩니다.
>
)}
);
}
```
### Loading
`loading`으로 모든 action 또는 특정 action의 실행을 일시적으로 막고 loading indicator를 표시할 수 있습니다. `loading={true}`는 Decrement와 Increment 모두에 적용되며, `loading={{ increment: true }}`처럼 객체를 전달하면 해당 action만 막습니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { ActionButton } from "@seed-design/lynx-react";
import { QuantityPicker } from "@/components/ui/quantity-picker";
export default function Example() {
const [decrementLoading, setDecrementLoading] = useState(false);
const [incrementLoading, setIncrementLoading] = useState(false);
const allLoading = decrementLoading && incrementLoading;
function toggleAllLoading() {
"background only";
const nextLoading = !allLoading;
setDecrementLoading(nextLoading);
setIncrementLoading(nextLoading);
}
function toggleDecrementLoading() {
"background only";
setDecrementLoading((current) => !current);
}
function toggleIncrementLoading() {
"background only";
setIncrementLoading((current) => !current);
}
return (
Loading
전체 {allLoading ? "끄기" : "켜기"}
감소 {decrementLoading ? "끄기" : "켜기"}
증가 {incrementLoading ? "끄기" : "켜기"}
감소: {decrementLoading ? "loading" : "준비"} · 증가:{" "}
{incrementLoading ? "loading" : "준비"}
);
}
```
`disabled`, `readOnly`, `loading`은 모두 action을 실행하지 못하게 합니다. `disabled`는 두 action을 비활성화하고 접근성 상태에도 disabled를 전달합니다. `readOnly`는 수량 변경과 Remove 콜백 호출을 막지만 값을 다른 상태로 바꾸지는 않습니다. `loading`은 지정된 action만 일시적으로 막으며, 해당 action의 indicator를 표시합니다. 따라서 `removable`의 최솟값에서도 Decrement가 disabled, readOnly 또는 decrement loading이면 `onRemove`가 호출되지 않습니다.
### Form
Lynx에는 HTML `