diff --git a/packages/propel/package.json b/packages/propel/package.json index 9de16d76e..739df2385 100644 --- a/packages/propel/package.json +++ b/packages/propel/package.json @@ -25,6 +25,7 @@ "./collapsible": "./dist/collapsible/index.js", "./combobox": "./dist/combobox/index.js", "./command": "./dist/command/index.js", + "./context-menu": "./dist/context-menu/index.js", "./dialog": "./dist/dialog/index.js", "./emoji-icon-picker": "./dist/emoji-icon-picker/index.js", "./icons": "./dist/icons/index.js", diff --git a/packages/propel/src/context-menu/context-menu.stories.tsx b/packages/propel/src/context-menu/context-menu.stories.tsx new file mode 100644 index 000000000..bc33a304d --- /dev/null +++ b/packages/propel/src/context-menu/context-menu.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { ContextMenu } from "./context-menu"; + +const meta: Meta = { + title: "Components/ContextMenu", + component: ContextMenu, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => ( + + +
+ Right click here +
+
+ + + Back + Forward + Reload + + More Tools + + +
+ ), +}; diff --git a/packages/propel/src/context-menu/context-menu.tsx b/packages/propel/src/context-menu/context-menu.tsx new file mode 100644 index 000000000..60e05f1ba --- /dev/null +++ b/packages/propel/src/context-menu/context-menu.tsx @@ -0,0 +1,128 @@ +import * as React from "react"; +import { ContextMenu as ContextMenuPrimitive } from "@base-ui-components/react/context-menu"; +import { cn } from "../utils"; + +export interface ContextMenuProps extends React.ComponentProps { + children: React.ReactNode; +} + +export interface ContextMenuTriggerProps extends React.ComponentProps { + children: React.ReactNode; + className?: string; +} + +export interface ContextMenuContentProps extends React.ComponentProps { + children: React.ReactNode; + className?: string; + side?: "top" | "right" | "bottom" | "left"; + sideOffset?: number; +} + +export interface ContextMenuItemProps extends React.ComponentProps { + children: React.ReactNode; + className?: string; + disabled?: boolean; +} + +const ContextMenuRoot = React.forwardRef, ContextMenuProps>( + ({ children, ...props }, _ref) => {children} +); + +const ContextMenuTrigger = React.forwardRef< + React.ElementRef, + ContextMenuTriggerProps +>(({ className, children, ...props }, ref) => ( + + {children} + +)); + +const ContextMenuPortal = ContextMenuPrimitive.Portal; + +const ContextMenuContent = React.forwardRef< + React.ElementRef, + ContextMenuContentProps +>(({ className, children, side = "bottom", sideOffset = 4, ...props }, ref) => ( + + + {children} + + +)); + +const ContextMenuItem = React.forwardRef, ContextMenuItemProps>( + ({ className, disabled, children, ...props }, ref) => ( + + {children} + + ) +); + +const ContextMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentProps +>(({ className, ...props }, ref) => ( + +)); + +const ContextMenuSubmenu = ContextMenuPrimitive.SubmenuRoot; + +const ContextMenuSubmenuTrigger = React.forwardRef< + React.ElementRef, + React.ComponentProps +>(({ className, children, ...props }, ref) => ( + + {children} + +)); + +ContextMenuRoot.displayName = "ContextMenu"; +ContextMenuTrigger.displayName = "ContextMenuTrigger"; +ContextMenuContent.displayName = "ContextMenuContent"; +ContextMenuItem.displayName = "ContextMenuItem"; +ContextMenuSeparator.displayName = "ContextMenuSeparator"; +ContextMenuSubmenuTrigger.displayName = "ContextMenuSubmenuTrigger"; + +// compound components +const ContextMenu = Object.assign(ContextMenuRoot, { + Trigger: ContextMenuTrigger, + Portal: ContextMenuPortal, + Content: ContextMenuContent, + Item: ContextMenuItem, + Separator: ContextMenuSeparator, + Submenu: ContextMenuSubmenu, + SubmenuTrigger: ContextMenuSubmenuTrigger, +}); + +export { ContextMenu }; diff --git a/packages/propel/src/context-menu/index.ts b/packages/propel/src/context-menu/index.ts new file mode 100644 index 000000000..7a0cbc670 --- /dev/null +++ b/packages/propel/src/context-menu/index.ts @@ -0,0 +1,7 @@ +export { ContextMenu } from "./context-menu"; +export type { + ContextMenuProps, + ContextMenuTriggerProps, + ContextMenuContentProps, + ContextMenuItemProps, +} from "./context-menu"; diff --git a/packages/propel/tsdown.config.ts b/packages/propel/tsdown.config.ts index 71d201641..b571adb31 100644 --- a/packages/propel/tsdown.config.ts +++ b/packages/propel/tsdown.config.ts @@ -11,6 +11,7 @@ export default defineConfig({ "src/collapsible/index.ts", "src/combobox/index.ts", "src/command/index.ts", + "src/context-menu/index.ts", "src/dialog/index.ts", "src/emoji-icon-picker/index.ts", "src/icons/index.ts",