Sheet

Sheet는 화면의 가장자리에서 슬라이드되어 나타나는 오버레이 컴포넌트입니다. 사이드바, 메뉴, 폼, 상세 정보 등을 표시할 때 사용합니다.
'use client';

import { Button, Sheet } from '@vapor-ui/core';
import { CloseOutlineIcon } from '@vapor-ui/icons';

export default function DefaultSheet() {
    return (
        <Sheet.Root>
            <Sheet.Trigger render={<Button variant="outline" />}>Open Sheet</Sheet.Trigger>
            <Sheet.Popup>
                <div className="absolute top-4 right-4">
                    <Sheet.Close aria-label="Close sheet" className="flex">
                        <CloseOutlineIcon />
                    </Sheet.Close>
                </div>
                <Sheet.Header>
                    <Sheet.Title>알림</Sheet.Title>
                </Sheet.Header>
                <Sheet.Body>
                    <Sheet.Description>
                        Sheet는 화면 가장자리에서 슬라이드되어 나타나는 오버레이 컴포넌트입니다.
                        추가 정보나 작업을 위한 공간을 제공합니다.
                    </Sheet.Description>
                </Sheet.Body>
                <Sheet.Footer>
                    <Sheet.Close render={<Button variant="ghost" />}>닫기</Sheet.Close>
                    <Button colorPalette="primary">확인</Button>
                </Sheet.Footer>
            </Sheet.Popup>
        </Sheet.Root>
    );
}

Property


Side

Sheet가 나타날 위치를 설정합니다. 기본값은 'right'입니다.

'use client';

import { Button, Sheet } from '@vapor-ui/core';
import { CloseOutlineIcon } from '@vapor-ui/icons';

export default function SheetSide() {
    return (
        <div className="flex flex-wrap gap-4">
            {/* Right Side (Default) */}
            <Sheet.Root>
                <Sheet.Trigger render={<Button variant="outline" />}>Right</Sheet.Trigger>
                <Sheet.Popup positionerElement={<Sheet.PositionerPrimitive side="right" />}>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>우측 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>
                            화면 우측에서 슬라이드됩니다. (기본값)
                        </Sheet.Description>
                    </Sheet.Body>
                </Sheet.Popup>
            </Sheet.Root>

            {/* Left Side */}
            <Sheet.Root>
                <Sheet.Trigger render={<Button variant="outline" />}>Left</Sheet.Trigger>
                <Sheet.Popup positionerElement={<Sheet.PositionerPrimitive side="left" />}>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>좌측 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>화면 좌측에서 슬라이드됩니다.</Sheet.Description>
                    </Sheet.Body>
                </Sheet.Popup>
            </Sheet.Root>

            {/* Top Side */}
            <Sheet.Root>
                <Sheet.Trigger render={<Button variant="outline" />}>Top</Sheet.Trigger>
                <Sheet.Popup positionerElement={<Sheet.PositionerPrimitive side="top" />}>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>상단 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>화면 상단에서 슬라이드됩니다.</Sheet.Description>
                    </Sheet.Body>
                </Sheet.Popup>
            </Sheet.Root>

            {/* Bottom Side */}
            <Sheet.Root>
                <Sheet.Trigger render={<Button variant="outline" />}>Bottom</Sheet.Trigger>
                <Sheet.Popup positionerElement={<Sheet.PositionerPrimitive side="bottom" />}>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>하단 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>화면 하단에서 슬라이드됩니다.</Sheet.Description>
                    </Sheet.Body>
                </Sheet.Popup>
            </Sheet.Root>
        </div>
    );
}

Controlled State

Sheet의 열림/닫힘 상태를 외부에서 제어합니다.

'use client';

import { useState } from 'react';

import { Button, Sheet } from '@vapor-ui/core';
import { CloseOutlineIcon } from '@vapor-ui/icons';

export default function SheetControlled() {
    const [isOpen, setIsOpen] = useState(false);

    return (
        <div className="space-y-4">
            <div className="flex gap-2">
                <Button onClick={() => setIsOpen(true)} colorPalette="primary">
                    Sheet 열기
                </Button>
                <Button onClick={() => setIsOpen(false)} colorPalette="danger" variant="outline">
                    Sheet 닫기
                </Button>
            </div>

            <p className="text-sm text-gray-600">
                현재 상태: <strong>{isOpen ? '열림' : '닫힘'}</strong>
            </p>

            <Sheet.Root open={isOpen} onOpenChange={setIsOpen}>
                <Sheet.Popup>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>제어된 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>
                            이 Sheet는 외부 버튼으로 상태가 제어됩니다. 프로그래밍 방식으로
                            열림/닫힘을 관리할 수 있습니다.
                        </Sheet.Description>
                    </Sheet.Body>
                    <Sheet.Footer>
                        <Sheet.Close render={<Button variant="ghost" />}>닫기</Sheet.Close>
                    </Sheet.Footer>
                </Sheet.Popup>
            </Sheet.Root>
        </div>
    );
}

Keep Mounted

Sheet가 닫혀도 DOM에서 제거되지 않고 유지되도록 설정합니다.

'use client';

import { Button, Sheet, TextInput } from '@vapor-ui/core';
import { CloseOutlineIcon } from '@vapor-ui/icons';

export default function SheetKeepMounted() {
    return (
        <div className="flex gap-4">
            {/* Normal Sheet */}
            <Sheet.Root>
                <Sheet.Trigger render={<Button variant="outline" />}>일반 Sheet</Sheet.Trigger>
                <Sheet.Popup>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>일반 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>
                            이 Sheet는 닫힐 때 DOM에서 제거됩니다. 다시 열 때마다 내용이 새로
                            생성됩니다.
                        </Sheet.Description>
                        <div className="mt-4">
                            <TextInput placeholder="입력해보세요..." />
                        </div>
                    </Sheet.Body>
                </Sheet.Popup>
            </Sheet.Root>

            {/* Keep Mounted Sheet */}
            <Sheet.Root>
                <Sheet.Trigger render={<Button variant="outline" colorPalette="success" />}>
                    유지 Sheet
                </Sheet.Trigger>
                <Sheet.Popup portalElement={<Sheet.PortalPrimitive keepMounted />}>
                    <div className="absolute top-4 right-4">
                        <Sheet.Close aria-label="Close sheet" className="flex">
                            <CloseOutlineIcon />
                        </Sheet.Close>
                    </div>
                    <Sheet.Header>
                        <Sheet.Title>유지되는 Sheet</Sheet.Title>
                    </Sheet.Header>
                    <Sheet.Body>
                        <Sheet.Description>
                            이 Sheet는 닫혀도 DOM에 유지됩니다. 입력한 내용이 보존되는 것을
                            확인해보세요.
                        </Sheet.Description>
                        <div className="mt-4">
                            <TextInput placeholder="상태 보존 테스트..." />
                        </div>
                    </Sheet.Body>
                </Sheet.Popup>
            </Sheet.Root>
        </div>
    );
}

Examples


Custom Usage

유연하게 Sheet를 사용합니다.

'use client';

import { Button, Sheet } from '@vapor-ui/core';
import { CloseOutlineIcon } from '@vapor-ui/icons';

export default function Flexible() {
    return (
        <Sheet.Root>
            <Sheet.Trigger render={<Button variant="outline" />}>유연한 Sheet</Sheet.Trigger>
            <Sheet.PortalPrimitive>
                <Sheet.OverlayPrimitive />
                <Sheet.PositionerPrimitive>
                    <Sheet.PopupPrimitive>
                        <div className="absolute top-4 right-4">
                            <Sheet.Close aria-label="Close sheet" className="flex">
                                <CloseOutlineIcon />
                            </Sheet.Close>
                        </div>
                        <Sheet.Header>
                            <Sheet.Title>간단한 Sheet</Sheet.Title>
                        </Sheet.Header>
                        <Sheet.Body>
                            <Sheet.Description>
                                이 Sheet는 Vapor UI의 Primitive 컴포넌트를 사용하여 유연하게
                                구성되었습니다.
                            </Sheet.Description>
                        </Sheet.Body>
                    </Sheet.PopupPrimitive>
                </Sheet.PositionerPrimitive>
            </Sheet.PortalPrimitive>
        </Sheet.Root>
    );
}

Props Table


Sheet.Root

Loading component documentation...

Sheet.Trigger

Loading component documentation...

Sheet.Popup

Loading component documentation...

Sheet.PortalPrimitive

Loading component documentation...

Sheet.OverlayPrimitive

Loading component documentation...

Sheet.PopupPrimitive

Loading component documentation...

Sheet.PositionerPrimitive

Loading component documentation...

Sheet.Header

Loading component documentation...

Sheet.Body

Loading component documentation...

Sheet.Footer

Loading component documentation...

Sheet.Title

Loading component documentation...

Sheet.Description

Loading component documentation...

Sheet.Close

Loading component documentation...