Once UI Handbook
Beginner Guides
What is Once UI?
Install & config
Page skeleton
Your first page
Build And Launch
How to launch a portfolio site that actually gets you hired
How to build a documentation site with MDX and Next.js
How to ship a landing page and dashboard with authentication in Next.js
How to launch a social app with Next.js and Supabase
Vibe Coding
Introduction to vibe coding
Set up your local dev environment
Essential tools for vibe coding
Build your first Once UI app
Common Patterns
Hero section
Static panel
Form layout
Highlighted card
Responsive stacking
Decoration layers
Dialog & modal
Toast & feedback
Tables & lists
Loading states
App shell navigation
Dashboard & charts
Chat & messaging
Auth & verification
Settings & split panels
Data filters & toolbar
Command palette
Pricing & plans
Accordion & FAQ
Media & uploads
Empty & error states
SEO, Open Graph, and structured data
Documentation code blocks with live preview
Carousels, galleries, and before/after comparisons
Date pickers and scheduling
Context menus and dropdown actions
Tags, chips, and multi-value inputs
Roadmap & kanban
Form inputs & controls
Progress, status & badges
Scrolling & feeds
Profile, avatars & identity
Social proof & logo clouds
Masonry & media grids
Table pagination, search & bulk selection
Banners & announcements
Footer layouts
Onboarding & first run
Waitlist & coming soon
Design Tips
Color & surfaces
Harness overview
Row, Column & Grid
Spacing & rhythm
Icons & buttons
Reveal & motion
Theme tokens, FOUC-free init, and runtime style controls
Tooltips and hover cards
Block updates
Block updates changelog
Agent Resources
Column, not Flex
Semantics over CSS
Typography scale
Common gotchas
Block anchors
Validate generated code
Pro block registry
Match task bundles
TrademarkTrademark
Ctrl k
Search...
Sign up
Once UI Handbook
Beginner Guides
What is Once UI?
Install & config
Page skeleton
Your first page
Build And Launch
How to launch a portfolio site that actually gets you hired
How to build a documentation site with MDX and Next.js
How to ship a landing page and dashboard with authentication in Next.js
How to launch a social app with Next.js and Supabase
Vibe Coding
Introduction to vibe coding
Set up your local dev environment
Essential tools for vibe coding
Build your first Once UI app
Common Patterns
Hero section
Static panel
Form layout
Highlighted card
Responsive stacking
Decoration layers
Dialog & modal
Toast & feedback
Tables & lists
Loading states
App shell navigation
Dashboard & charts
Chat & messaging
Auth & verification
Settings & split panels
Data filters & toolbar
Command palette
Pricing & plans
Accordion & FAQ
Media & uploads
Empty & error states
SEO, Open Graph, and structured data
Documentation code blocks with live preview
Carousels, galleries, and before/after comparisons
Date pickers and scheduling
Context menus and dropdown actions
Tags, chips, and multi-value inputs
Roadmap & kanban
Form inputs & controls
Progress, status & badges
Scrolling & feeds
Profile, avatars & identity
Social proof & logo clouds
Masonry & media grids
Table pagination, search & bulk selection
Banners & announcements
Footer layouts
Onboarding & first run
Waitlist & coming soon
Design Tips
Color & surfaces
Harness overview
Row, Column & Grid
Spacing & rhythm
Icons & buttons
Reveal & motion
Theme tokens, FOUC-free init, and runtime style controls
Tooltips and hover cards
Block updates
Block updates changelog
Agent Resources
Column, not Flex
Semantics over CSS
Typography scale
Common gotchas
Block anchors
Validate generated code
Pro block registry
Match task bundles
TrademarkTrademark
Once UIDocumentationBlog
© Once UI. All rights reserved.
Built with Aveiro
Common patterns

Context menus and dropdown actions

Right-click ContextMenu and click Dropdown patterns for contextual actions without cluttering the UI.
Updated 19d ago
Date pickers and scheduling
Tags, chips, and multi-value inputs
5 min · Pattern
The context menu opens on right-click at the cursor. The dropdown opens on click from a trigger. Both use option rows inside a Column — share one menu-content pattern across the app.

Context menu vs dropdown

Pattern
Trigger
Best for
Context menuRight-click (or long-press)Tables, canvases, file lists
DropdownClick on button or rowToolbars, row actions, sort menus
Dropdown wrapperCustom trigger elementComposed inputs (date picker, tag field)
The context menu portals the menu to the click position. The dropdown anchors to the trigger with floating-ui placement. Both support keyboard navigation and close on outside click.

Context menu structure

Wrap the interactive surface (a table row, card, or canvas) as children. Pass menu content via the dropdown prop. Build the menu as a Column with padding, then list option rows with label and value props. Wire onSelect to route action values. closeAfterClick defaults to true so the menu dismisses after a choice.
Column gap="2" padding="4" minWidth={10}
  Option label="Edit" value="edit"
  Option label="Duplicate" value="duplicate"
  Option danger label="Delete" value="delete"
Wrap the target surface in a Row with surface background and border so users know the area is interactive.

Prefix icons and danger actions

Add hasPrefix with an Icon on each option row for scanability. Mark destructive actions with the danger prop — it tints the label and icon toward the danger palette. Group related actions with spacing; separate Delete from safe actions with extra vertical gap.

Controlled open state

For programmatic open/close (e.g. after an async delete), pass isOpen and onOpenChange. Leave uncontrolled for standard right-click behavior.

Dropdown for click actions

The dropdown follows the same option list pattern but attaches to a visible trigger — typically a Button or IconButton.
IconButton icon="more" variant="ghost" aria-label="Row actions"
  → opens Column of Option rows
Tune placement (bottom-start, bottom-end, top) when the trigger sits near viewport edges. Use minWidth so short labels do not collapse the menu.

Shared menu content

Extract a reusable menu Column when the same actions appear in both a context menu and a toolbar dropdown:
  • Define a small function that returns the Column of option rows
  • Pass it to the context menu dropdown on the file row
  • Pass the same block to the dropdown on the row overflow button
Keep action handlers in the parent — the menu component only renders labels and values.

Accessibility

  • Context menu restores focus to the previously focused element on close
  • Arrow keys move between options when the menu is open
  • Every IconButton trigger needs aria-label (no visible text)
  • Do not rely on right-click alone — offer an equivalent overflow dropdown

Write this / not this

✅ Once UI way
❌ Common mistake
Option rows with value + onSelectInline onClick on random divs
Danger prop on destructive actionsRed text styled with custom CSS
Overflow dropdown + context menuRight-click as the only action path
Extracted shared menu contentCopy-pasted menu blocks per row

Check yourself

  • Destructive actions use danger on option rows
  • Icon-only triggers have aria-label
  • onSelect handles all menu values in one place
  • Click-based overflow exists wherever context menu is offered
  • Menu width fits the longest label (minWidth)

Related

→ Tables & lists → App shell navigation → Full reference: docs.once-ui.com — ContextMenu