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
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
┌─ 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.json→popover· 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
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:
Escapecloses, 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
{/* 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>