섹션
컴포넌트
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"팝오버는 트리거에 고정된 플로팅 패널에 풍부한 콘텐츠를 보여 줍니다. 클릭으로 열고, 바깥 클릭이나 Esc로 닫습니다. Base UI Popover 프리미티브를 기반으로 하며, 네오브루탈리즘 공식(두꺼운 테두리, 선명한 그림자, 굵은 서체)에 맞춰 스타일을 입혔습니다.
다음과 같은 경우에 사용합니다.
- 인라인 폼 — 전체 다이얼로그 없이 항목 이름 바꾸기, 크기 설정, 단일 옵션 조정.
- 날짜·색 선택기 — 캘린더나 스와치 그리드를 입력에 바로 붙입니다.
- 툴바·테이블 필터 — 체크박스와 범위를 작은 트리거 뒤에 쌓습니다.
설치#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/popover.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/popover.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/popover.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/popover.json
다음 의존성을 설치합니다.
pnpm add @base-ui/reactnpm install @base-ui/reactyarn add @base-ui/reactbun add @base-ui/react
다음 코드를 복사해서 프로젝트에 붙여넣습니다.
"use client"
import * as React from "react"
import { Popover as PopoverPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Popover({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
return <PopoverPrimitive.Root data-slot="popover" {...props} />
}
function PopoverTrigger({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
}
function PopoverContent({
className,
align = "center",
sideOffset = 4,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
data-slot="popover-content"
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded border-2 bg-popover p-2.5 text-sm text-popover-foreground shadow-md outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
)
}
function PopoverAnchor({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
}
function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="popover-header"
className={cn("flex flex-col gap-0.5 text-sm", className)}
{...props}
/>
)
}
function PopoverTitle({ className, ...props }: React.ComponentProps<"h2">) {
return (
<div
data-slot="popover-title"
className={cn("font-medium", className)}
{...props}
/>
)
}
function PopoverDescription({
className,
...props
}: React.ComponentProps<"p">) {
return (
<p
data-slot="popover-description"
className={cn("text-muted-foreground", className)}
{...props}
/>
)
}
export {
Popover,
PopoverAnchor,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
}
import 경로를 프로젝트 구성에 맞게 수정합니다.
사용법#
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover"<Popover>
<PopoverTrigger render={<Button variant="outline" />}>
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Title</PopoverTitle>
<PopoverDescription>Description text here.</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>구성#
Popover를 만들려면 다음 구성을 사용합니다.
Popover
├── PopoverTrigger
└── PopoverContent예제#
기본#
헤더, 제목, 설명을 갖춘 간단한 팝오버입니다.
import { Button } from "@/components/ui/button"
import {
Popover,정렬#
PopoverContent의 align prop을 사용해서 수평 정렬을 제어합니다.
import { Button } from "@/components/ui/button"
import {
Popover,폼과 함께#
폼 필드를 내부에 배치한 팝오버입니다.
import { Button } from "@/components/ui/button"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"RTL#
Neobrutalism에서 RTL 지원을 활성화하는 방법은 RTL 설정 가이드를 참고하세요.
"use client"
import {접근성#
팝오버는 WAI-ARIA Dialog 패턴의 비모달 형태를 따릅니다. 트리거는 aria-haspopup="dialog", aria-expanded, aria-controls를 갖고, 패널은 role="dialog"로 렌더링됩니다. 열리면 포커스가 안으로 들어가고 닫히면 트리거로 돌아옵니다.
키보드 상호작용:
| 키 | 동작 |
|---|---|
Space / Enter | 트리거에서 팝오버 열기/닫기 |
Tab / Shift + Tab | 패널의 포커스 가능한 요소 사이로 이동 |
Esc | 팝오버를 닫고 트리거로 포커스 복귀 |
API 참조#
자세한 내용은 Base UI 문서를 참고하세요.