컴포넌트

Popover

기준 요소 옆에 내용이나 작업을 표시합니다.

설치

pnpm dlx ply-ui add popover

공통 설치 설정을 먼저 적용합니다.

사용법

Positioner의 side/align/sideOffset으로 위치를 조절합니다.

Title/Description을 넣고, 사용자가 작업을 마치면 Close로 닫을 수 있습니다.

구성

구성 요소역할
Root열림 상태를 관리합니다.
Trigger클릭해서 내용을 여는 버튼입니다.
Portal / Positioner팝오버를 버튼 기준으로 배치합니다.
Popup내용을 담는 표면입니다. variant로 색상을 바꿉니다.
Title / Description제목과 설명입니다.
Arrow버튼 방향을 가리키는 표시입니다.
Close팝오버를 닫습니다.

Standard

Popup variant="standard"는 기본 표면 색상입니다.

Inverse

Popup variant="inverse"는 반전된 표면과 글자 색상입니다.

속성

이 프로젝트에서 추가하거나 제한한 속성입니다.

속성

타입

구현 코드

components/ui/popover.tsx
popover.tsx
"use client";

import type { ComponentProps } from "react";
import { Popover as Primitive } from "@base-ui/react/popover";
import { withClassName } from "../../lib/cx";
import "./popover.css";

// 동작과 접근성은 Base UI가 담당합니다. 이 파일은 스타일 연결만 담당합니다.
function PopoverTrigger({
  className,
  ...props
}: ComponentProps<typeof Primitive.Trigger>) {
  return (
    <Primitive.Trigger
      {...props}
      className={withClassName("rbx-button", className)}
    />
  );
}

export type PopoverPopupProps = ComponentProps<typeof Primitive.Popup> & {
  /** 표면과 글자 색상입니다. @defaultValue "standard" */
  variant?: "standard" | "inverse";
};
function PopoverPopup({
  variant = "standard",
  className,
  ...props
}: PopoverPopupProps) {
  return (
    <Primitive.Popup
      {...props}
      data-variant={variant}
      className={withClassName("rbx-popup rbx-padded", className)}
    />
  );
}

function PopoverPositioner({
  className,
  ...props
}: ComponentProps<typeof Primitive.Positioner>) {
  return (
    <Primitive.Positioner
      {...props}
      className={withClassName("rbx-positioner", className)}
    />
  );
}

function PopoverTitle({
  className,
  ...props
}: ComponentProps<typeof Primitive.Title>) {
  return (
    <Primitive.Title
      {...props}
      className={withClassName("rbx-dialog-title", className)}
    />
  );
}

function PopoverDescription({
  className,
  ...props
}: ComponentProps<typeof Primitive.Description>) {
  return (
    <Primitive.Description
      {...props}
      className={withClassName("rbx-description", className)}
    />
  );
}

function PopoverClose({
  className,
  ...props
}: ComponentProps<typeof Primitive.Close>) {
  return (
    <Primitive.Close
      {...props}
      className={withClassName("rbx-button", className)}
    />
  );
}

function PopoverArrow({
  className,
  ...props
}: ComponentProps<typeof Primitive.Arrow>) {
  return (
    <Primitive.Arrow
      {...props}
      className={withClassName("rbx-popup-arrow", className)}
    />
  );
}

// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const Popover = {
  ...Primitive,
  Trigger: PopoverTrigger,
  Popup: PopoverPopup,
  Positioner: PopoverPositioner,
  Title: PopoverTitle,
  Description: PopoverDescription,
  Close: PopoverClose,
  Arrow: PopoverArrow,
};
components/ui/popover.css
popover.css
@import "./button.css";
/* Community educational tooltip variant. Standard popovers retain the shared surface. */
.rbx-popup[data-variant="inverse"] {
  padding: 12px;
  border: 0;
  border-radius: 8px;
  background: var(--rbx-inverse-surface-0);
  color: var(--rbx-inverse-content-emphasis);
  box-shadow: none;
}
.rbx-popup[data-variant="inverse"] .rbx-description {
  color: var(--rbx-inverse-content-default);
}
.rbx-popup[data-variant="inverse"] .rbx-popup-arrow {
  fill: var(--rbx-inverse-surface-0);
}

목차