
Scene Menu Bar
FreeSimplify your scene's menu management with conventions.
Free · Opens the source repo
What Scene Menu Bar does
The Scene Menu Bar skill provides a structured approach to managing the menu bar in PostHog scenes, specifically designed to enhance usability and accessibility. It introduces conventions for adding, editing, and organizing menu items above the <SceneTitleSection>, making it easier for developers to create a consistent user experience. The skill outlines the components available for use, including top-level menus, sub-menus, and various item types such as checkboxes and radio groups, which help streamline user interactions.
This skill is particularly useful for developers working with PostHog who need to implement or modify scene menu bars. By adhering to the documented conventions, developers can ensure that their menus are not only functional but also intuitive. The skill provides guidance on how to gate the entire menu bar behind feature flags, allowing for controlled feature rollouts and testing. This is crucial in environments where features are frequently added or modified based on user feedback or testing phases.
The Scene Menu Bar skill also emphasizes the importance of keyboard navigation, making it easier for users to access menu items quickly. It includes components that facilitate rich inputs, like tags and comboboxes, ensuring that the menu can accommodate various user needs. By following the provided taxonomy and wiring rules, developers can create a cohesive and user-friendly interface that enhances the overall experience within PostHog scenes.
In summary, this skill is an essential resource for developers looking to implement a Mac-style menu bar in PostHog scenes, offering clear guidelines and components that promote best practices in menu design and functionality.
When to use it
Use this skill when you need to add or modify menu items in PostHog scenes, ensuring consistency and usability.
When not to use it
This skill is not suitable for projects outside of PostHog or for scenarios where menu management is not required.
What you can build with it
Adding New Menu Items
Use this skill to easily add new items to your scene's menu bar, following the established conventions for consistency.
Modifying Existing Menus
When you need to rearrange or edit existing menu items, this skill provides clear guidelines to ensure usability.
Implementing Feature Flags
Utilize the skill's conventions to gate menu items behind feature flags, allowing for controlled feature rollouts.
How to install Scene Menu Bar
View source1. Install with the skills CLI
npx skills add posthog/posthog/scene-menu-bar --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by posthogSceneMenuBar conventions
PostHog scenes render a Mac-style menu bar above <SceneTitleSection> that consolidates
ScenePanel actions into a discoverable, keyboard-navigable surface. This skill documents
the taxonomy, the available primitives, and the wiring rules.
The whole bar is gated by the SCENE_MENU_BAR feature flag (see lib/constants.tsx).
Components
All primitives live in frontend/src/layout/scenes/components/SceneMenuBar.tsx.
| Component | Use for |
|---|---|
<SceneMenuBar> | Top-level wrapper; renders above <SceneTitleSection>. Includes the universal right cluster (PostHog AI / Docs / Support). |
<SceneMenuBarMenu label> | Top-level menu (File / Edit / View / Metadata / Staff only). |
<SceneMenuBarSubMenu label> | Nested sub-menu inside a SceneMenuBarMenu (e.g. Create, Export, Add to notebook). Auto-prepends a blank icon slot to the trigger so the label aligns with icon-bearing siblings — pass withIconBlank={false} to opt out. |
<SceneMenuBarItem> | Standard menu item (action / navigation). |
<SceneMenuBarCheckboxItem> | Toggle item — reflects boolean state via checkmark. |
<SceneMenuBarRadioGroup> + <SceneMenuBarRadioItem> | One-of-many mutually-exclusive options. |
<SceneMenuBarSeparator> | Horizontal divider between groups. |
<SceneMenuBarShortcut> | Right-aligned keyboard shortcut hint. |
<SceneMenuBarPopover label> | Drop-in alternative to SceneMenuBarMenu when content needs rich form controls (text inputs, comboboxes). Uses Popover under the hood — Menu.Popup intercepts keystrokes and blocks inputs. Trigger does NOT participate in CompositeRoot keyboard nav. |
Canonical menu set (in order)
| Menu | Items |
|---|---|
| File | + Create sub-menu (top), ── , project tree items (Open / Move / Star), Copy to another project, Manage with Terraform, scene-specific file ops, Export sub-menu, ──, Delete / Archive / Restore (destructive at the very bottom) |
| Edit | Duplicate, Rename, Edit in SQL editor, scene-specific edits, state mutations (Pause/Resume, Activate/Deactivate), ──, toggle group (checkbox/radio items, separated by <SceneMenuBarSeparator> from regular items) |
| View (conditional) | Cross-resource viewing — View recordings, View metalytics, View related insights, etc. Anything that navigates to see something tangentially related to the current resource. Skip when empty. |
Metadata (use SceneMenuBarPopover) | Tags, Evaluation contexts, Stage, Activity indicator, External references, Comments, etc. |
| Staff only (conditional) | Debug panels, staff-only toggles. Only render for staff / superpowers / impersonated / non-cloud users. |
State lives in Edit. Pause/Resume, Activate/Deactivate, Favorite/Pin toggles and similar state mutations all live inside the Edit menu — usually at the bottom, after a
<SceneMenuBarSeparator>if there's a toggle group. Don't create a separateStatemenu.
Right cluster is fixed and universal: PostHog AI · Docs · Support. Do not add to it.
Rules
Destructive actions (Delete / Archive / Restore)
- Live at the bottom of File, separated from the file ops above by a
<SceneMenuBarSeparator>. - Pass
variant="destructive"for visual treatment (red text + icon). - Do not add
opensFloatingUito destructive items even when they open a confirmation dialog — the destructive variant + clear label are signal enough. - Wrap with
<AccessControlAction>where the resource has access control levels.
Toggle groups
- Group all
<SceneMenuBarCheckboxItem>and<SceneMenuBarRadioGroup>items together. - Separate them from regular action items with
<SceneMenuBarSeparator>above and (if more items follow) below. - Use stable labels — the checkmark conveys state:
PinnednotPin/Unpin,Show debug panelnotShow/Hide debug panel. - Radios for mutually-exclusive choices (
<SceneMenuBarRadioGroup value onValueChange>).
opensFloatingUi prop
Append … to the item label as a Mac-style affordance for items that open additional floating UI:
- ✅ Use for: modal, popover, dialog, side panel openers
- ❌ Skip for: same-page navigations, direct actions, destructive items (the destructive style already signals consequence), toggle items
+ Create cross-sells
- Nest inside a
<SceneMenuBarSubMenu label="Create">at the top of File. - Place a
<SceneMenuBarSeparator>between Create and the rest of File. - Cross-sells: Cohort, Survey, Dashboard, Notebook, Endpoint, Subscription, Alert, Share or embed.
Empty menus
SceneMenuBarMenu auto-disables its trigger when its children render nothing at compile
time — e.g. {false && <Item/>}, {null}, or an empty fragment. The trigger stays
visible (greyed out, cursor-not-allowed) so the menu set still communicates the bar's
capabilities to the user.
For menus whose children may render null at runtime (the most common case is
<SceneMenuBarFileItems>, which returns null when no project-tree entry is registered),
the parent cannot detect that the popup will be empty. You must either:
-
Pass
disabledexplicitly based on the same value the children depend on, e.g.:const { projectTreeRefEntry } = useValues(projectTreeDataLogic) const hasFileItems = !!projectTreeRefEntry <SceneMenuBarMenu label="File" disabled={!hasFileItems}> {hasFileItems && <SceneMenuBarFileItems dataAttrKey="…" />} </SceneMenuBarMenu> -
Gate the whole menu at the parent if it can't render anything useful:
{ hasAnyEditItem && <SceneMenuBarMenu label="Edit">…</SceneMenuBarMenu> }
Prefer (1) when the menu's presence is part of the scene's identity (File should always be visible even if disabled), and (2) when the menu is genuinely optional (View, Staff only).
Tags / Evaluation contexts / other rich inputs
- Must live inside a
<SceneMenuBarPopover>, not a<SceneMenuBarMenu>. Menu popups intercept keystrokes (typeahead, arrow nav) and prevent text inputs from receiving input. - Use
<TagsCombobox>(lib/components/Scenes/TagsCombobox.tsx) for multi-select chip inputs — selection-only by default; passallowCustomValuesto surface a "Create new {noun} '...'" item at the bottom. - Use
<SceneTagsCombobox>(lib/components/Scenes/SceneTagsCombobox.tsx) as the ready-made wrapper that swaps in for<SceneTags>underSCENE_MENU_BAR.
Optimistic saves with debounce
When autosaving from menubar inputs (tags, toggles), use a kea listener with:
- Optimistic update (
setX+updateX) immediately, before the API call. await breakpoint(250)to debounce rapid changes.breakpoint()after the API response to bail if a newer call has superseded this one.- Set-equality check before reconciling with server response to avoid re-ordering when the server returns differently-ordered values.
- Re-throw
error.isBreakpointso kea swallows it silently.
See saveTagsInline in frontend/src/scenes/feature-flags/featureFlagLogic.ts.
File menu — project tree items
Use <SceneMenuBarFileItems dataAttrKey={RESOURCE_TYPE} /> at the bottom of File
(before the destructive separator) to render Open in project tree, Move to folder,
Add/Remove starred. It auto-hides when no project-tree entry is registered.
Right cluster
Lives outside the <Menubar> wrapper to keep CompositeRoot keyboard nav working for
the actual menus. Do not add items here without UX review.
Layout-aware bleed
<SceneMenuBar> reads sceneLayoutLogic.sceneLayoutConfig.layout and bleeds past the
scene container's padding (-mx-4 -mt-4) only when the layout is padded:
app, app-container, or app-full-scene-height. For unpadded layouts (app-raw,
app-raw-no-header, plain) the negatives would overshoot and visually break the
header, so they're skipped. You don't need to do anything in your scene — just register
the right SceneConfig.layout and the bar adapts. Sentinel: a data-scene-layout
attribute is set on the wrapper for debugging.
Scenes already migrated
- Feature Flag —
frontend/src/scenes/feature-flags/FeatureFlag.tsx - Insight —
frontend/src/scenes/insights/SidePanel/InsightSceneMenuBar.tsx - Dashboard —
frontend/src/scenes/dashboard/DashboardSceneMenuBar.tsx
When migrating a new scene, follow the <Scene>SceneMenuBar.tsx pattern (component
that reads featureFlagLogic, early-returns null if the flag is off, otherwise renders
the bar). Mount it directly above <SceneTitleSection>.
Auditing a scene
When migrating a scene, take its existing ScenePanel and map every item to:
- Which menu it belongs to (File / Edit / View / Metadata / Staff only).
- Whether it needs
variant="destructive"(delete/archive/remove). - Whether it needs
opensFloatingUi(opens modal/popover/dialog/side panel). - Whether it's a toggle (use
SceneMenuBarCheckboxItem). - What gates apply (saved state, FF, AccessControl, multi-project).
See /Users/adamleithp/Desktop/scene-menu-bar-grouping.md for the running inventory of
all ScenePanel items across PostHog and their proposed menu placement.
Frequently asked questions about Scene Menu Bar
Similar skills
Playwright Component Testing
Test React and Vue components in isolation with Playwright.
Fluent UI Blazor
Integrate Fluent UI components in Blazor applications effortlessly.
Build MCP App
Create interactive UI widgets for MCP servers.
Web Design Reviewer
Identify and fix design issues in websites efficiently.
Markstream Install
Seamlessly integrate Markstream for Markdown rendering.
GSAP & Framer Scroll Animation
Create advanced scroll animations effortlessly.
