본문으로 건너뛰기
Amineslab UI

Component

Popover

PC에서는 trigger 옆 Popover, 모바일에서는 BottomSheet로 보조 컨트롤과 정보를 표시합니다.

Playground

옵션을 조절하며 화면과 사용 코드를 함께 확인하세요.

PC 1280px
Controls

본문 여백 · PC와 모바일 모두 적용, 목록은 sm

PC 표시 방향

PC 정렬

PC trigger와의 간격

false면 자식이 모바일 본문 스크롤을 소유

Code
import { Popover, PopoverTrigger, Button, PopoverContent, PopoverClose } from '@amineslab/ui'

export default function ExamplePreview() {
  return ((<Popover snappable={true} fullScreenOnMobile={false}>
      <PopoverTrigger asChild>
        <Button variant="outline">옵션</Button>
      </PopoverTrigger>
      <PopoverContent title={"작업 옵션"} padding={"md"} scrollable={true} align={"center"} side={"bottom"} sideOffset={8}>
        <p className="text-body-2">작업을 계속하기 전에 선택을 확인하세요.</p>
        <PopoverClose asChild>
          <Button>확인</Button>
        </PopoverClose>
      </PopoverContent>
    </Popover>))
}

Props

import {
  Popover,
  PopoverTrigger,
  PopoverContent,
  PopoverAnchor,
  PopoverClose,
  PopoverPortal,
  PopoverArrow,
} from '@amineslab/ui'

Popover

HTML <div> 요소의 표준 속성을 그대로 받습니다.

NameTypeDefaultDescription
PopoverTrigger / PopoverContentReactNode-PopoverTrigger asChild 안에 버튼을, PopoverContent 안에 메뉴·폼을 넣습니다. PopoverClose나 onOpenChange(false)로 닫습니다.
PopoverContent.title / aria-labelstring'선택'모바일 패널 제목입니다. title, aria-label 순서로 사용합니다.
Popover.open / defaultOpen / onOpenChangeboolean / (open: boolean) => void-제어 상태. 생략하면 내부 상태를 사용합니다.
PopoverContent.padding'none' | 'sm' | 'md''md'PC 표면과 모바일 본문 여백입니다. md는 PC·모바일 16px, 선택 목록용 sm은 PC 4px·모바일 8px, none은 여백이 없습니다.
PopoverContent.scrollablebooleantruefalse면 모바일 본문 스크롤 wrapper를 생략해 자식이 스크롤을 소유합니다. 자식에 min-h-0 flex-1 overflow-y-auto를 지정하고 이중 스크롤을 피합니다.
PopoverContent.confirmFooterReactNode-명시적 적용이 필요한 다중 선택의 모바일 고정 footer입니다. 단일 선택에는 넣지 않습니다. PC 작업 버튼은 children에 직접 배치합니다.
Popover.snappablebooleantrue내용 높이로 열고 위로 끌어 전체 높이로 확장합니다.
Popover.fullScreenOnMobilebooleanfalse모바일에서 처음부터 전체 높이로 엽니다.
PopoverContent.align / side / sideOffsetPopoverContentProps-PC Popover 위치. 모바일 Drawer에서는 사용하지 않습니다.
PopoverContent.className / mobileClassNamestring-className은 PC 표면, mobileClassName은 모바일 시트 표면에 적용합니다. 본문 여백은 padding으로 조절합니다.
sideOffsetnumber6trigger와 내용 사이의 간격입니다.

Examples

자주 쓰는 조합을 살펴보고, 필요한 예시의 코드를 펼쳐 확인하세요.

모바일 bottomsheet 메뉴

PC에서는 Popover, 모바일에서는 내용 높이의 Drawer로 열립니다. Drawer 안에서는 중첩 Drawer가 됩니다. 목록은 padding="sm" 여백을 사용합니다.

import { useState } from 'react'

import { Popover, PopoverTrigger, Button, PopoverContent } from '@amineslab/ui'

function ResponsiveMenuExample() {
    const [open, setOpen] = useState(false);
    const [selection, setSelection] = useState('최근 수정순');
    return (<Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button variant="outline">{selection}</Button>
      </PopoverTrigger>
      <PopoverContent title="정렬 기준" padding="sm">
        <div className="grid gap-1">
          {['최근 수정순', '이름순', '생성일순'].map((label) => (<Button key={label} variant="ghost" className="justify-start" onClick={() => {
                setSelection(label);
                setOpen(false);
            }}>
              {label}
            </Button>))}
        </div>
      </PopoverContent>
    </Popover>);
}

export default function ExamplePreview() {
  return (<ResponsiveMenuExample />)
}

Small form

import { Popover, PopoverTrigger, Button, PopoverContent, Input } from '@amineslab/ui'

export default function ExamplePreview() {
  return ((<Popover>
          <PopoverTrigger asChild>
            <Button variant="outline">이름 바꾸기</Button>
          </PopoverTrigger>
          <PopoverContent>
            <Input aria-label="새 이름" defaultValue="Amineslab UI"/>
            <Button>저장</Button>
          </PopoverContent>
        </Popover>))
}

사용 기준

권장하는 사용
  • 맥락을 유지한 채 짧게 끝나는 작업에 사용합니다.
피해야 할 사용
  • 겉모양만으로 사용을 결정하지 마세요.
  • 의미와 키보드 동작, 모바일에서의 흐름을 함께 확인하세요.

접근성

화면에 맞는 이름을 제공하고, 키보드만으로 작업을 마칠 수 있는지 확인하세요.

  • Enter 또는 Space: 열기
  • Escape: 닫고 trigger로 포커스 복귀