Collapsible

Collapsible은 콘텐츠를 접었다 펼칠 수 있는 대화형 컴포넌트입니다. 아코디언이나 확장 가능한 섹션을 구현할 때 사용합니다.
import * as React from 'react';

import { Collapsible, Text, VStack } from '@vapor-ui/core';
import { ChevronRightOutlineIcon } from '@vapor-ui/icons';

export default function DefaultCollapsible() {
    return (
        <Collapsible.Root className="flex min-h-36 w-64 flex-col justify-center text-v-gray-900">
            <Collapsible.Trigger className="group flex items-center gap-2 rounded-sm bg-v-blue-100 px-3 py-2 text-sm font-medium hover:bg-v-blue-200 focus-visible:outline-2 focus-visible:outline-v-blue-600 active:bg-v-blue-200">
                <ChevronRightOutlineIcon className="size-3 transition-all ease-out group-data-[panel-open]:rotate-90" />
                프로젝트 메뉴
            </Collapsible.Trigger>
            <Collapsible.Panel className="flex h-[var(--collapsible-panel-height)] flex-col justify-end overflow-hidden text-sm transition-all ease-out data-[ending-style]:h-0 data-[starting-style]:h-0">
                <VStack
                    gap="$050"
                    backgroundColor="$blue-050"
                    paddingY="$150"
                    paddingLeft="$300"
                    marginTop="$050"
                    className="cursor-text rounded-sm"
                >
                    <Text foreground="normal-200">• 대시보드</Text>
                    <Text foreground="normal-200">• 작업 관리</Text>
                    <Text foreground="normal-200">• 팀원 초대</Text>
                </VStack>
            </Collapsible.Panel>
        </Collapsible.Root>
    );
}

Property


Open State

Collapsible의 열림/닫힘 상태를 제어할 수 있습니다. defaultOpen으로 초기 상태를 설정하거나, openonOpenChange로 완전히 제어할 수 있습니다.

import { useState } from 'react';

import { Button, Collapsible, HStack } from '@vapor-ui/core';

export default function CollapsibleOpenState() {
    const [open, setOpen] = useState(false);

    return (
        <HStack gap="$300">
            <Collapsible.Root defaultOpen className="w-72 h-48">
                <h4 className="text-lg font-medium mb-3">Uncontrolled (defaultOpen)</h4>
                <Collapsible.Trigger className="px-4 py-2 bg-v-green-500 text-v-white rounded hover:bg-v-green-600 transition-colors">
                    기본적으로 열려있음
                </Collapsible.Trigger>
                <Collapsible.Panel>
                    <div className="p-4 border border-v-gray-200 rounded bg-v-green-50 mt-2">
                        이 패널은 처음에 열린 상태로 시작합니다.
                    </div>
                </Collapsible.Panel>
            </Collapsible.Root>

            <Collapsible.Root open={open} onOpenChange={setOpen} className="w-72 h-48">
                <h4 className="text-lg font-medium mb-3">Controlled</h4>

                <Collapsible.Trigger className="px-4 py-2 bg-v-blue-500 text-v-white rounded hover:bg-v-blue-600 transition-colors">
                    제어되는 Collapsible
                </Collapsible.Trigger>
                <Collapsible.Panel className=" ">
                    <div className="p-4 border border-v-gray-200 rounded mt-2 bg-v-blue-50">
                        이 패널의 상태는 외부에서 제어됩니다.
                    </div>
                </Collapsible.Panel>

                <div className="flex gap-2 mt-3">
                    <Button size="sm" onClick={() => setOpen(true)}>
                        열기
                    </Button>
                    <Button size="sm" onClick={() => setOpen(false)}>
                        닫기
                    </Button>
                    <span className="text-sm text-v-gray-600 flex items-center">
                        현재 상태: {open ? '열림' : '닫힘'}
                    </span>
                </div>
            </Collapsible.Root>
        </HStack>
    );
}

Keep Mounted

keepMounted 속성을 사용하여 패널이 닫힌 상태에서도 DOM에 유지할 수 있습니다.

import { Button, Collapsible, HStack } from '@vapor-ui/core';

export default function CollapsibleKeepMounted() {
    return (
        <HStack gap="$500">
            <Collapsible.Root className="w-72 h-36">
                <h4 className="text-lg font-medium mb-3">기본 (DOM에서 제거됨)</h4>
                <Collapsible.Trigger render={<Button color="secondary" />}>
                    기본 동작
                </Collapsible.Trigger>
                <Collapsible.Panel>
                    <div className="mt-2 p-4 border border-v-gray-200 rounded bg-v-purple-50">
                        닫힌 상태에서는 DOM에서 제거됩니다.
                    </div>
                </Collapsible.Panel>
            </Collapsible.Root>

            <Collapsible.Root className="w-72 h-36">
                <h4 className="text-lg font-medium mb-3">keepMounted (DOM에 유지됨)</h4>
                <Collapsible.Trigger render={<Button color="warning" variant="outline" />}>
                    keepMounted 사용
                </Collapsible.Trigger>
                <Collapsible.Panel keepMounted>
                    <div className="mt-2 p-4 border border-v-gray-200 rounded bg-v-orange-50">
                        닫힌 상태에서도 DOM에 유지됩니다.
                    </div>
                </Collapsible.Panel>
            </Collapsible.Root>
        </HStack>
    );
}

Disabled

Collapsible을 비활성화하여 사용자 상호작용을 막을 수 있습니다.

import { Button, Collapsible } from '@vapor-ui/core';

export default function CollapsibleDisabled() {
    return (
        <Collapsible.Root disabled>
            <Collapsible.Trigger render={<Button color="danger" />}>
                비활성화된 Collapsible
            </Collapsible.Trigger>
            <Collapsible.Panel>이 콘텐츠는 토글할 수 없습니다.</Collapsible.Panel>
        </Collapsible.Root>
    );
}

Props Table


Collapsible.Root

이 컴포넌트는 div 요소를 기반으로, 표준 HTML 속성(className, style 등)을 지원합니다.

PropDefaultType
open?
-
boolean
defaultOpen?
false
boolean
onOpenChange?
-
function
disabled?
false
boolean
render?
-
ReactElementnull
className?
-
string
children?
-
ReactNode

Collapsible.Trigger

이 컴포넌트는 button 요소를 기반으로, 표준 HTML 속성(onClick, disabled 등)을 지원합니다.

PropDefaultType
render?
-
ReactElementnull
className?
-
string
disabled?
false
boolean
children?
-
ReactNode

Collapsible.Panel

이 컴포넌트는 div 요소를 기반으로, 표준 HTML 속성(className, style 등)을 지원합니다.

PropDefaultType
keepMounted?
false
boolean
hiddenUntilFound?
false
boolean
className?
-
string
children?
-
ReactNode
render?
-
ReactElementnull