Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 12, 2025

Linked Issue

Closes #3844

Description

Implements a Zag.js-based Menu component following the established architecture pattern used by RatingGroup, Accordion, and Popover. The community poll indicated 70.8% interest in this component (highest among niche components).

Changes

  • Common package: Added classesMenu with definitions for all anatomy parts
  • React package: Implemented composed Menu component with 15 anatomy parts:
    • State: Root, Provider, Context
    • Triggers: Trigger, ContextTrigger
    • Layout: Positioner, Content, Arrow, ArrowTip, Separator
    • Items: Item, OptionItem, TriggerItem, ItemGroup, ItemGroupLabel
  • Svelte package: Matching implementation for Svelte 5
  • Dependencies: Added @zag-js/[email protected] to catalog
  • Tests: 9 test suites per framework covering all major anatomy parts
  • Documentation: Complete documentation page with 4 examples per framework
    • Documentation page at framework-components/menu.mdx
    • Examples: Default menu, Grouped items, Option items (checkbox), Context menu
    • Added menu-item CSS utility class with hover, disabled, highlighted, and checked states

Implementation Notes

TriggerItem for Nested Menus: The TriggerItem component is designed for nested menus and accepts a childMenu API prop directly (not split props). This follows the Zag.js Menu API where getTriggerItemProps() takes a child menu API instance for creating nested menu structures.

Type Safety: Excluded aria-label and onSelect from HTMLAttributes in MenuRootProps to avoid type conflicts with Zag.js Menu props. Used internal createContext helper for proper null safety handling.

ItemGroup Context: Automatic ID generation for ItemGroup components, with context-based ID passing to ItemGroupLabel for proper accessibility.

Usage

// React
<Menu>
  <Menu.Trigger>Actions</Menu.Trigger>
  <Menu.Positioner>
    <Menu.Content>
      <Menu.Item value="edit">Edit</Menu.Item>
      <Menu.Separator />
      <Menu.ItemGroup>
        <Menu.ItemGroupLabel>View</Menu.ItemGroupLabel>
        <Menu.OptionItem value="grid" type="radio">Grid</Menu.OptionItem>
        <Menu.OptionItem value="list" type="radio">List</Menu.OptionItem>
      </Menu.ItemGroup>
    </Menu.Content>
  </Menu.Positioner>
</Menu>
<!-- Svelte -->
<Menu>
  <Menu.Trigger>Actions</Menu.Trigger>
  <Menu.Positioner>
    <Menu.Content>
      <Menu.Item value="edit">Edit</Menu.Item>
      <Menu.Separator />
      <Menu.ItemGroup>
        <Menu.ItemGroupLabel>View</Menu.ItemGroupLabel>
        <Menu.OptionItem value="grid" type="radio">Grid</Menu.OptionItem>
        <Menu.OptionItem value="list" type="radio">List</Menu.OptionItem>
      </Menu.ItemGroup>
    </Menu.Content>
  </Menu.Positioner>
</Menu>

Checklist

Please read and apply all contribution requirements.

  • Your branch should be prefixed with: docs/, feature/, chore/, bugfix/
  • Contributions should target the main branch
  • Documentation should be updated to describe all relevant changes
  • Run pnpm check in the root of the monorepo
  • Run pnpm format in the root of the monorepo
  • Run pnpm lint in the root of the monorepo
  • Run pnpm test in the root of the monorepo
  • If you modify /package projects, please supply a Changeset

Changesets

View our documentation to learn more about Changesets. To create a Changeset:

  1. Navigate to the root of the monorepo in your terminal
  2. Run pnpm changeset and follow the prompts
  3. Commit and push the changeset before flagging your PR review for review.
Original prompt

This section details on the original issue you should resolve

<issue_title>Add Menu Component</issue_title>
<issue_description>### Describe the feature in detail (code, mocks, or screenshots encouraged)

Hello,

Could Skeleton UI add a Menu component following the established Zag.js based architecture pattern used by existing components like TreeView .

What type of pull request would this be?

New Feature

Provide relevant links or additional information.

Thank you</issue_description>

<agent_instructions>Skeleton uses zag for component implementations, read our contributions docs to see how to author a component, see references.

Use our composed components style of authoring, reference other zag components we already implemented like RatingGroup, Accordion, Popover, etc. You are an expert software engineer and double check anything without making any assumptions. You write tests and learn from the codebase.

References:

Comments on the Issue (you are @copilot in this section)

@endigo9740 Hi @ibilux per our [recent announcement for the Skeleton v4 RC](https://github.com//discussions/3844), we are introducing a few new components. This includes the Portal, TreeView, DatePicker, and Listbox.

Once we launch v4 around mid-October the plan will be to send out a community poll and determine what components folks want the most. That will help inform our priority. Though we may not always take on the components verbatim.

That said, we have the process for contributing components down to a science now. If you're interested in seeing this component added sooner than later, I'd recommend considering to contribute this directly. We cover most everything you need here:

https://skeleton.dev/docs/resources/contribute

And of course we're always around if you have questions or need help.

I'll also recommend you check out the new and improved Popover component, which won't have all the a11y features built in for Menu, but will get you most of the way there. It might be a good temporary solution:

https://skeleton.dev/docs/components/popover/svelte

I'll keep this ticket open for now, as we will likely add this component. But cannot promise an exact ETA beyond the info above.</comment_new>
<comment_new>@endigo9740
Just a quick update to this - v4 has launched and our community poll has been sent and gathered a number of responses. Currently this is where the component requests stand:

Image

Menu is right at the top of the niche set, so we'll aim to prioritize this as we can.

We're currently ramping up on some big documentation updates, and plan to begin work on Skeleton v5 very soon. That said, we plan to drop new components about every 1-2 weeks, as time allows.

Currently Toggle Group looks to be the next component out the door:
#3929

But again, we will aim to jump on Menu soon. And again encourage contribution if you would like to see it even sooner.</comment_new>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@changeset-bot
Copy link

changeset-bot bot commented Nov 12, 2025

⚠️ No Changeset found

Latest commit: d542a72

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Nov 12, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
www.skeleton.dev Ready Ready Preview Nov 13, 2025 5:30pm

Copilot AI changed the title [WIP] Add menu component following Zag.js pattern Add Menu Component Nov 12, 2025
Copilot AI requested a review from Hugos68 November 12, 2025 13:33
Copilot finished work on behalf of Hugos68 November 12, 2025 13:33
Copy link
Contributor

@Hugos68 Hugos68 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Few things, see my comments, also, the build on Vercel is failing with: ../../packages/skeleton-svelte/dist/components/menu/anatomy/trigger-item.svelte (15:10): "splitTriggerItemProps" is not exported by "../../node_modules/.pnpm/@[email protected]/node_modules/@zag-js/menu/dist/index.mjs", imported by "../../packages/skeleton-svelte/dist/components/menu/anatomy/trigger-item.svelte".
file: /vercel/path0/packages/skeleton-svelte/dist/components/menu/anatomy/trigger-item.svelte:15:10

Please run cd sites/skeleton/dev + pnpm build to test wether the docsite will build, it will likely fail at the end because of the vercel adapter, but it shouldn't fail at the start, only the end.

import type { useMenu } from './provider.svelte.js';
import { createContext } from '@/internal/create-context.js';

export const MenuRootContext = createContext<ReturnType<typeof useMenu>>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename to RootContext like all the other components.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7eebd40. Renamed MenuRootContext to RootContext throughout the Svelte components to match the naming convention used by other components.

- Rename MenuRootContext to RootContext in Svelte (consistency with other components)
- Fix TriggerItem to not use splitTriggerItemProps (doesn't exist in @zag-js/menu)
- TriggerItem now accepts childMenu API directly for nested menus
- Verified docsite builds successfully

Co-authored-by: Hugos68 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 12, 2025

@copilot Few things, see my comments, also, the build on Vercel is failing with: ../../packages/skeleton-svelte/dist/components/menu/anatomy/trigger-item.svelte (15:10): "splitTriggerItemProps" is not...

Fixed in 7eebd40. The issue was that @zag-js/menu doesn't export splitTriggerItemProps - this function doesn't exist in the package.

The TriggerItem component is for nested menus and works differently than other item types. It now accepts a childMenu prop (the nested menu's API) instead of using split props. The getTriggerItemProps() method takes the child menu API directly.

Verified that cd sites/skeleton.dev && pnpm build now completes successfully.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • iojs.org
    • Triggering command: curl -q --fail --compressed -L -s REDACTED -o - (dns block)
  • telemetry.astro.build
    • Triggering command: node /home/REDACTED/work/skeleton/skeleton/sites/skeleton.dev/node_modules/.bin/../astro/astro.js build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

- Use internal createContext instead of React's (fixes null check issues)
- Remove PropTypes generic from Api type (not exported by @zag-js/menu)
- Exclude aria-label and onSelect from HTMLAttributes to avoid type conflicts
- Fix MenuRootContextProps naming to match component naming convention
- All TypeScript checks now pass

Co-authored-by: Hugos68 <[email protected]>
Copilot finished work on behalf of Hugos68 November 12, 2025 13:56
Copilot AI requested a review from Hugos68 November 12, 2025 13:56
@Hugos68
Copy link
Contributor

Hugos68 commented Nov 12, 2025

@copilot I just cleaned up whatever you did, you did a pretty good job except some small bits, I patched those up. The menu is a pretty special component and needed some extra stuff. Can you go ahead and implement the docs? See how other framework-components are docuemnted in sites/skeleton.dev/src

- Created documentation page at framework-components/menu.mdx
- Added example files for React and Svelte:
  - Default menu with basic items
  - Grouped items with ItemGroup and ItemGroupLabel
  - Option items with checkbox functionality
  - Context menu with right-click trigger
- Added menu-item CSS utility class with hover, disabled, highlighted, and checked states
- Fixed Svelte examples to use <Menu> instead of <Menu.Root> (correct pattern)
- Verified docsite builds successfully

Co-authored-by: Hugos68 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 12, 2025

@copilot I just cleaned up whatever you did, you did a pretty good job except some small bits, I patched those up. The menu is a pretty special component and needed some extra stuff. Can you go ahead ...

Implemented in 81975f2. Added complete documentation for the Menu component:

Documentation page: framework-components/menu.mdx

Examples created (React + Svelte):

  • Default menu with basic items and separator
  • Grouped items using ItemGroup and ItemGroupLabel
  • Option items with checkbox functionality
  • Context menu with right-click trigger

CSS: Added menu-item utility class with hover, disabled, highlighted, and checked states

Build status: Docsite builds successfully ✅

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • iojs.org
    • Triggering command: curl -q --fail --compressed -L -s REDACTED -o - (dns block)
  • telemetry.astro.build
    • Triggering command: node /home/REDACTED/work/skeleton/skeleton/sites/skeleton.dev/node_modules/.bin/../../../../node_modules/.pnpm/[email protected]_@types&#43;[email protected]_@vercel&#43;[email protected][email protected][email protected]._895223b23ea2c9b7d6cead1a3fda33f8/node_modules/astro/astro.js sync (dns block)
    • Triggering command: node /home/REDACTED/work/skeleton/skeleton/sites/skeleton.dev/node_modules/.bin/../astro/astro.js build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Menu Component

2 participants