Tiro
Tiro Design
Components

Popover

Non-modal 플로팅 패널. 짧은 맥락 설명, 간단한 설정, 보조 액션에 사용.

Mobile

모바일에서 Popover는 두 갈래로 분기된다:

  • Inline Popover — 트리거 근처에 좁고 짧은 패널을 인라인으로 표시 (예: 색상 피커, 작은 메뉴, FolderScreen 상단 + 액션 메뉴). 트리거 기준으로 정렬, 화면을 가리지 않음. 데스크탑 Popover에 가장 가까운 형태.
  • BottomSheet 변환 — 패널 콘텐츠가 길거나(폼·리스트), 트리거 주변 공간이 부족하거나, 인터랙션이 모달성을 띠는 경우 BottomSheet로 승격. 컨테이너 anatomy(detents, grabber, swipe-to-dismiss, safe area)는 Dialog → Mobile Presentation 참조.

판단 기준: 화면 면적의 1/3 이상을 차지하거나 사용자 입력이 필요하면 BottomSheet로. 그렇지 않으면 Inline.

FolderScreen 상단 +처럼 trigger 주변에서 1–3개 짧은 액션을 선택하는 UI는 Dialog popup이 아니라 Inline Popover로 분류한다.

Preview

preview-mobile

preview-mobile

Inline Popover — FolderScreen create menu

Anatomy

Popover는 trigger 클릭으로 열리는 작은 floating 패널. Tooltip처럼 맥락 가까이에 붙지만, 텍스트 설명을 넘어 버튼·토글·짧은 입력 같은 인터랙션을 담을 수 있다. 순수 옵션 목록은 DropdownMenu/Select를 우선한다.

PopoverRoot
├─ PopoverTrigger             (외부 element — Button·Chip 등)
└─ PopoverContent             (floating 컨테이너)
   ├─ PopoverArrow            (optional, trigger 방향 화살표)
   ├─ PopoverHeader           (optional)
   │  ├─ PopoverTitle         (Text · label1Medium)
   │  └─ PopoverClose         (optional, Button ghost icon-only)
   ├─ PopoverBody             (자유 콘텐츠)
   └─ PopoverFooter           (optional, Button 1~2개)

슬롯 규칙

SlotRequiredPrimitive비고
PopoverTriggeralways(외부)Trigger element는 popover 외부 — anatomy에는 reference만
PopoverContentalwaysbg-white, 1px solid stone-100/200, rounded-lg, shadow-md (Level 2)
PopoverArrowoptionaltrigger 방향 8px 삼각, content와 동일 색·border
PopoverTitleoptionalTextlabel1Medium, color stone-700
PopoverCloseoptionalButton (ghost icon-only, size='sm')header 우측 끝, aria-label="닫기"
PopoverBodyalways(자유)min-width 200px, max-width 360px. 설명, 컨트롤 그룹, 보조 액션 조합 가능
PopoverFooteroptionalButton최대 2개, 가로 right-align

Layout invariants

  • max-width 360px — 콘텐츠 길어지면 Sheet 또는 Dialog로 승격
  • PopoverArrow는 trigger 중심을 가리키도록 자동 위치 (Radix Popper 자동)
  • Trigger 외 영역 클릭 시 close (dismissOnOutsideClick=true default)
  • Esc로 close, focus는 trigger로 복귀
  • Trigger가 disabled면 popover 열리지 않음

Token Mapping

TokenValue (web)Value (mobile)Description
presentationfloating popover (트리거 근처)Inline popover 또는 BottomSheet (콘텐츠 크기에 따라)Popover Mobile 판단 기준 참조
bg#FFFFFF#FFFFFF
border1px solid stone-100/200inline: 동일 / BottomSheet: 없음
elevationLevel 2 (shadow-md)inline: 동일 / BottomSheet: native sheet elevation
radiusrounded-lg (8px)inline: 동일 / BottomSheet: top corners r4 (16px)
padding12–16px동일 (px-5 py-4 BottomSheet 본문)
max-width320pxinline: 화면 폭에서 인셋 16pt / BottomSheet: 100vw모바일 inline은 트리거 폭 기준 정렬
inner interactive row heighth-8 (32px)≥44pt (iOS HIG) — inline·BottomSheet 모두옵션·메뉴 항목 높이
titlelabel1Medium text-stone-700동일
descriptionbody2Regular text-stone-500동일
control labellabel1Medium text-stone-600동일
section labelcaption1Medium text-stone-400동일

Inline Popover 실제 값 — FolderScreen create menu

TokenValue
libraryreact-native-popup-menu
triggerheader right Plus icon button, 32×32
popover width200
popover radius10
popover padding10
popover border1px, stone-200
popover backgroundDesignColors.semantic.surface
popover shadowshadowOpacity: 0.08, shadowRadius: 8, elevation: 6
popover offsetmarginTop: 32
item layoutflex-row items-center justify-between p-1
item textTypography.body1_16, stone-950
item iconFolderPlus size={20}, stone-950

Props

type PopoverProps = {
  open?: boolean
  onOpenChange?: (v: boolean) => void
  side?: 'top' | 'right' | 'bottom' | 'left'
  align?: 'start' | 'center' | 'end'
}

Usage

<Popover>
  <PopoverTrigger asChild>
    <Button type="ghost" layout="icon-only" aria-label="보기 설정"><SettingsIcon /></Button>
  </PopoverTrigger>
  <PopoverContent>
    <Text className="label1Medium text-stone-700">노트 보기 설정</Text>
    <Text className="body2Regular text-stone-500">현재 노트에서만 표시 방식을 조정합니다.</Text>
  </PopoverContent>
</Popover>

A11y

  • Non-modal — body 인터랙션 차단하지 않음
  • Trigger의 aria-expanded 자동 전달
  • 키보드 탐색 가능

Do / Don't

  • Do: 짧은 정보 표시, 간단한 컨트롤 그룹, 맥락 액션
  • Do: 포털 렌더 — 부모 stacking context 탈출
  • Don't: hover-only 설명에는 Tooltip 사용
  • Don't: 긴 폼 입력은 Dialog 또는 Sheet로 승격
  • Don't: 옵션 목록만 있으면 DropdownMenu, 선택값이 남으면 Select

On this page