Prisma
Live Preview
Dimensions

Set the dimensions for this layer. These values will be applied when you save.

--- description: Hướng dẫn Agent tạo Popover — floating interactive content panel

Popover Component

Skill này hướng dẫn tạo component Popover — floating panel chứa interactive content. Khác Tooltip (hover info) và khác Dropdown Menu (menu items).

1. Mục tiêu (Objective)

Tạo Popover — floating panel chứa interactive content (forms, menus, cards). Khác Tooltip: popover cho click interaction, tooltip cho hover info.

2. AI Context & Intent (Ngữ cảnh cho AI)

Khi nào dùng Popover?

  • User menu: Profile dropdown với avatar, settings, logout
  • Inline editor: Edit field in-place (rename, change color)
  • Rich tooltip: Info panel với links, buttons (upgrade CTA)
  • Filter panel: Multi-filter popup cho tables

⚠️ Phân biệt Popover vs Tooltip vs Dropdown Menu vs Modal (QUAN TRỌNG)

Tiêu chí Popover Tooltip Dropdown Menu Modal
Trigger Click Hover Click Programmatic
Content Interactive (buttons, forms) Read-only text Menu items Complex forms
Dismiss Click outside Move mouse away Click item/outside Close button
Arrow ✅ Points to trigger ✅ Points to trigger ❌ No arrow ❌ No arrow
Blocking Non-blocking Non-blocking Non-blocking Blocking (backdrop)
Ví dụ User profile card "Copy link" hint Right-click menu Edit user form

Decision Tree cho AI

text
Cần floating content?
├─ Hover only, read-only text → Tooltip
├─ Menu items (list of actions) → Dropdown Menu
├─ Complex form / data → Modal
├─ Interactive content, non-blocking → Popover
│   ├─ User profile card → Popover (click trigger)
│   ├─ Color picker → Popover (click trigger)
│   ├─ Rich info card → Popover (hover trigger)
│   └─ Filter controls → Popover (click trigger)
└─ System feedback → Dialog

3. Anatomy

text
                    ┌─ trigger element ─┐
                    │   [ Settings ⚙ ]  │
                    └────────┬──────────┘
                             │
                        ┌────▼─────┐ ← Arrow (pointing to trigger)
                    ┌───┤          ├───────────┐
                    │   └──────────┘           │
                    │                          │ ← Panel: --surface bg
                    │   Content here           │    --border
                    │   [Button] [Link]        │    --section-radius-default
                    │                          │    level-3 shadow
                    └──────────────────────────┘

4. Platform Mapping

Platform Component Key Difference
Web Popover (custom floating) Arrow, click trigger, focus trap
iOS UIPopoverPresentationController Native popover with arrow
Android (M3) ❌ (use Menu or Dialog) No dedicated popover
Fluent Popover Click/hover trigger, positioning
Carbon Popover With caret, interactive content

5. Positions

top | bottom | left | right — auto-flip on collision.

5.4. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsonpopover · Layer: surface

Figma Slot data-slot CSS Class Required Accepts
Root popover .popover
Trigger popover-trigger button, icon-button, text-link
Content popover-content .slot-body typography, list, input-group, *

6. Token Mapping

📦 Atomic Mapping: Xem ATOMIC-MAPPING.md → mục popover — UI Layer: Surface, Density Tier: section.

Panel dùng --surface / --surface-foreground, border --border, radius --section-radius-default, elevation level-3. Component token JSON files đã deprecated.

7. Props & API

typescript
interface PopoverProps {
  trigger: ReactNode;
  triggerType?: 'click' | 'hover';
  position?: 'top' | 'bottom' | 'left' | 'right';
  showArrow?: boolean;
  closeOnOutsideClick?: boolean;
  focusTrap?: boolean;
  offset?: number;
  children: ReactNode;
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}

8. Accessibility (a11y)

  • Trigger: aria-haspopup="dialog", aria-expanded.
  • Panel: role="dialog", aria-label.
  • Focus trap: Tab cycling within popover when open.
  • Dismiss: Escape closes, return focus to trigger.

9. Best Practices & Rules

  • vs Tooltip: Tooltip = hover info, read-only. Popover = click, interactive content.
  • vs Modal: Modal = blocks page. Popover = contextual, non-blocking.
  • Arrow: Always point to trigger element for visual connection.
  • Auto-flip: Change position when near viewport edge.
  • Không Hardcode: Mọi giá trị từ Token.

10. Example Usage

jsx
{/* User profile popover */}
<Popover trigger={<Avatar src={user.avatar} />} position="bottom">
  <div className="user-card">
    <h4>{user.name}</h4>
    <p>{user.email}</p>
    <Button variant="outline" size="sm">View Profile</Button>
    <Button variant="ghost" size="sm">Sign Out</Button>
  </div>
</Popover>

{/* Color picker */}
<Popover trigger={<Button variant="outline">Pick Color</Button>} position="bottom">
  <ColorGrid colors={palette} onSelect={handleColorSelect} />
</Popover>

{/* Filter panel */}
<Popover trigger={<Button leftIcon="filter">Filters</Button>} position="bottom">
  <FilterForm
    filters={activeFilters}
    onChange={setFilters}
    onApply={handleApply}
    onReset={handleReset}
  />
</Popover>