Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 253 additions & 0 deletions components/retroui/ContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
"use client";

import * as React from "react";
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";

import { cn } from "@/lib/utils";

function ContextMenu({
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;
}

function ContextMenuTrigger({
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
return (
<ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} />
);
}

function ContextMenuGroup({
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
return (
<ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
);
}

function ContextMenuPortal({
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
return (
<ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
);
}

function ContextMenuSub({
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />;
}

function ContextMenuRadioGroup({
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
return (
<ContextMenuPrimitive.RadioGroup
data-slot="context-menu-radio-group"
{...props}
/>
);
}

function ContextMenuSubTrigger({
className,
inset,
children,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
inset?: boolean;
}) {
return (
<ContextMenuPrimitive.SubTrigger
data-slot="context-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-primary focus:text-primary-foreground data-[state=open]:bg-primary data-[state=open]:text-primary-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
className,
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto" />
</ContextMenuPrimitive.SubTrigger>
);
}

function ContextMenuSubContent({
className,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
return (
<ContextMenuPrimitive.SubContent
data-slot="context-menu-sub-content"
className={cn(
"bg-background text-foreground border-2 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[--radix-context-menu-content-transform-origin] overflow-hidden rounded-sm p-1",
className,
)}
{...props}
/>
);
}

function ContextMenuContent({
className,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {
return (
<ContextMenuPrimitive.Portal>
<ContextMenuPrimitive.Content
data-slot="context-menu-content"
className={cn(
"bg-background text-foreground border-2 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-context-menu-content-available-height)] min-w-[8rem] origin-[--radix-context-menu-content-transform-origin] overflow-x-hidden overflow-y-auto rounded-sm p-1",
className,
)}
{...props}
/>
</ContextMenuPrimitive.Portal>
);
}

function ContextMenuItem({
className,
inset,
variant = "default",
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
inset?: boolean;
variant?: "default" | "destructive";
}) {
return (
<ContextMenuPrimitive.Item
data-slot="context-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-primary focus:text-primary-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
className,
)}
{...props}
/>
);
}
Comment on lines +114 to +135
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix likely-invalid Tailwind selector for destructive icons + forwardRef Item

The selector data-[variant=destructive]:*:[svg]:!text-destructive is likely not recognized by Tailwind. Use the established arbitrary selector form with a descendant: data-[variant=destructive]:[&_svg]:!text-destructive. Also forward the ref.

Apply this diff:

-function ContextMenuItem({
-  className,
-  inset,
-  variant = "default",
-  ...props
-}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
-  inset?: boolean;
-  variant?: "default" | "destructive";
-}) {
-  return (
-    <ContextMenuPrimitive.Item
-      data-slot="context-menu-item"
-      data-inset={inset}
-      data-variant={variant}
-      className={cn(
-        "focus:bg-primary focus:text-primary-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
-        className,
-      )}
-      {...props}
-    />
-  );
-}
+const ContextMenuItem = React.forwardRef<
+  React.ElementRef<typeof ContextMenuPrimitive.Item>,
+  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
+    inset?: boolean;
+    variant?: "default" | "destructive";
+  }
+>(({ className, inset, variant = "default", ...props }, ref) => (
+  <ContextMenuPrimitive.Item
+    ref={ref}
+    data-slot="context-menu-item"
+    data-inset={inset}
+    data-variant={variant}
+    className={cn(
+      "focus:bg-primary focus:text-primary-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:[&_svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
+      className,
+    )}
+    {...props}
+  />
+));
+ContextMenuItem.displayName = "ContextMenuItem";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function ContextMenuItem({
className,
inset,
variant = "default",
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
inset?: boolean;
variant?: "default" | "destructive";
}) {
return (
<ContextMenuPrimitive.Item
data-slot="context-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-primary focus:text-primary-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
className,
)}
{...props}
/>
);
}
const ContextMenuItem = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
inset?: boolean;
variant?: "default" | "destructive";
}
>(({ className, inset, variant = "default", ...props }, ref) => (
<ContextMenuPrimitive.Item
ref={ref}
data-slot="context-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-primary focus:text-primary-foreground " +
"data-[variant=destructive]:text-destructive " +
"data-[variant=destructive]:focus:bg-destructive/10 " +
"dark:data-[variant=destructive]:focus:bg-destructive/20 " +
"data-[variant=destructive]:focus:text-destructive " +
"data-[variant=destructive]:[&_svg]:!text-destructive " +
"[&_svg:not([class*='text-'])]:text-muted-foreground " +
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none " +
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 " +
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
className,
)}
{...props}
/>
));
ContextMenuItem.displayName = "ContextMenuItem";
🤖 Prompt for AI Agents
components/retroui/ContextMenu.tsx around lines 114 to 135: the Tailwind
selector `data-[variant=destructive]:*:[svg]:!text-destructive` is invalid and
the component doesn't forward refs; replace the selector with the correct
arbitrary descendant form `data-[variant=destructive]:[&_svg]:!text-destructive`
in the cn list, and convert ContextMenuItem to a forwardRef component that
accepts the same props and passes the ref through to ContextMenuPrimitive.Item
(ensure proper React.forwardRef typing and spread props).


function ContextMenuCheckboxItem({
className,
children,
checked,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {
return (
<ContextMenuPrimitive.CheckboxItem
data-slot="context-menu-checkbox-item"
className={cn(
"focus:bg-primary focus:text-primary-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
className,
)}
checked={checked}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<ContextMenuPrimitive.ItemIndicator>
<CheckIcon className="size-4" />
</ContextMenuPrimitive.ItemIndicator>
</span>
{children}
</ContextMenuPrimitive.CheckboxItem>
);
}

function ContextMenuRadioItem({
className,
children,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {
return (
<ContextMenuPrimitive.RadioItem
data-slot="context-menu-radio-item"
className={cn(
"focus:bg-primary focus:text-primary-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors",
className,
)}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<ContextMenuPrimitive.ItemIndicator>
<CircleIcon className="size-2 fill-current" />
</ContextMenuPrimitive.ItemIndicator>
</span>
{children}
</ContextMenuPrimitive.RadioItem>
);
}

function ContextMenuLabel({
className,
inset,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
inset?: boolean;
}) {
return (
<ContextMenuPrimitive.Label
data-slot="context-menu-label"
data-inset={inset}
className={cn(
"text-foreground px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
className,
)}
{...props}
/>
);
}

function ContextMenuSeparator({
className,
...props
}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
return (
<ContextMenuPrimitive.Separator
data-slot="context-menu-separator"
className={cn("bg-border -mx-1 my-1 h-px", className)}
{...props}
/>
);
}

function ContextMenuShortcut({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="context-menu-shortcut"
className={cn(
"text-muted-foreground ml-auto text-xs tracking-widest",
className,
)}
{...props}
/>
);
}

const ContextMenuComponent = Object.assign(ContextMenu, {
Trigger: ContextMenuTrigger,
Content: ContextMenuContent,
Item: ContextMenuItem,
CheckboxItem: ContextMenuCheckboxItem,
RadioItem: ContextMenuRadioItem,
Label: ContextMenuLabel,
Separator: ContextMenuSeparator,
Shortcut: ContextMenuShortcut,
Group: ContextMenuGroup,
Portal: ContextMenuPortal,
Sub: ContextMenuSub,
SubContent: ContextMenuSubContent,
SubTrigger: ContextMenuSubTrigger,
RadioGroup: ContextMenuRadioGroup,
});

export { ContextMenuComponent as ContextMenu };
1 change: 1 addition & 0 deletions components/retroui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export * from "./Sonner";
export * from "./Tooltip";
export * from "./Breadcrumb";
export * from "./CommandDisplay";
export * from "./ContextMenu";
export * from "./Loader";
11 changes: 11 additions & 0 deletions config/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ export const componentConfig: {
name: "breadcrumb",
filePath: "components/retroui/Breadcrumb.tsx",
},
"context-menu": {
name: "context-menu",
filePath: "components/retroui/ContextMenu.tsx",
},
},
examples: {
"accordion-style-default": {
Expand Down Expand Up @@ -600,6 +604,13 @@ export const componentConfig: {
() => import("@/preview/components/breadcrumb-link-component"),
),
},
"context-menu-style-default": {
name: "context-menu-style-default",
filePath: "preview/components/context-menu-style-default.tsx",
preview: lazy(
() => import("@/preview/components/context-menu-style-default"),
),
},
"loader-style-default": {
name: "loader-style-default",
filePath: "preview/components/loader-style-default.tsx",
Expand Down
3 changes: 2 additions & 1 deletion config/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const navConfig: INavigationConfig = {
title: "Figma Kit",
href: "https://pro.retroui.dev/figma",
tag: "Pro",
}
},
],
},
{
Expand All @@ -55,6 +55,7 @@ export const navConfig: INavigationConfig = {
{ title: "Input", href: `${componentsRoute}/input` },
{ title: "Label", href: `${componentsRoute}/label` },
{ title: "Menu", href: `${componentsRoute}/menu` },
{ title: "Context Menu", href: `${componentsRoute}/context-menu` },
{
title: "Popover",
href: `${componentsRoute}/popover`,
Expand Down
32 changes: 32 additions & 0 deletions content/docs/components/context-menu.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: Context Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
lastUpdated: 21 Aug, 2025
links:
source: https://github.com/Logging-Stuff/RetroUI/blob/main/components/retroui/ContextMenu.tsx
---

<ComponentShowcase name="context-menu-style-default" />
<br />
<br />

<ComponentInstall>
<ComponentInstall.Cli npmCommand="npx shadcn@latest add 'https://retroui.dev/r/context-menu.json'" />
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify CLI snippet resolves to a valid recipe URL

Sanity‑check that the JSON is reachable to avoid broken “Add” flows.


🏁 Script executed:

#!/bin/bash
# Expect: HTTP 200 and a small JSON body
curl -sI https://retroui.dev/r/context-menu.json | head -n 1
curl -s https://retroui.dev/r/context-menu.json | jq 'keys' | head

Length of output: 199


🏁 Script executed:

#!/bin/bash
# Follow redirects and check the HTTP status after redirects
curl -sI -L https://retroui.dev/r/context-menu.json | head -n 1
# Fetch the content and list top-level keys to verify valid JSON
curl -sL https://retroui.dev/r/context-menu.json | jq 'keys' | head

Length of output: 204


🏁 Script executed:

#!/bin/bash
# Show the full redirect chain and headers, dropping body
curl -sL -D - https://retroui.dev/r/context-menu.json -o /dev/null
echo "------- BODY PREVIEW -------"
# Print the first 20 lines of the response body
curl -sL https://retroui.dev/r/context-menu.json | head -n 20

Length of output: 20098


Broken Recipe URL in CLI Snippet
The recipe URL in content/docs/components/context-menu.mdx (line 14) currently points to https://retroui.dev/r/context-menu.json, but following the redirect yields a 404, which will break the npx shadcn@latest add … flow:

curl -sI -L https://retroui.dev/r/context-menu.json | head -n1
→ HTTP/2 307 (redirect)
curl -sI -L https://www.retroui.dev/r/context-menu.json | head -n1
→ HTTP/2 404

Please update the snippet to reference a valid, reachable JSON recipe URL (or publish the recipe at /r/context-menu.json) so that the “Add” command succeeds.

🤖 Prompt for AI Agents
In content/docs/components/context-menu.mdx around line 14, the CLI snippet
references https://retroui.dev/r/context-menu.json which redirects to a 404;
update the ComponentInstall.Cli npmCommand to point to a valid, reachable JSON
recipe URL (or publish the recipe at /r/context-menu.json) so the npx
shadcn@latest add command succeeds — replace the broken URL with the correct
hosted recipe URL and verify with aHEAD request or curl that it returns 200
before committing.

<ComponentInstall.Manual>
#### 1. Install dependencies:

```sh
npm install class-variance-authority
```
Comment on lines +19 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Manual install misses the required Radix dependency

Copy‑pasting the component without installing @radix-ui/react-context-menu will break builds.

- npm install class-variance-authority
+ npm install class-variance-authority @radix-ui/react-context-menu
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
npm install class-variance-authority
```
🤖 Prompt for AI Agents
In content/docs/components/context-menu.mdx around lines 19 to 20, the docs list
installing class-variance-authority but omit the required Radix dependency;
update the installation instructions to also include
@radix-ui/react-context-menu so users install both packages (e.g., add a second
install command or a combined npm/yarn install line) and mention that
@radix-ui/react-context-menu is required for the context menu component to build
correctly.


<br />

#### 2. Copy the code 👇 into your project:

<ComponentSource name="context-menu" />

</ComponentInstall.Manual>
</ComponentInstall>

<br />
<br />
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-context-menu": "^2.2.16",
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify Radix context menu version and peer alignment

The added dependency looks right, but please verify:

  • Version compatibility with Next 14.2.x and React 18.x (peers).
  • No duplicate Radix versions pulled in (dedupe if needed).

Run locally:


🏁 Script executed:

#!/bin/bash
pnpm why @radix-ui/react-context-menu
pnpm ls @radix-ui/react-context-menu @radix-ui/react-dropdown-menu @radix-ui/react-slot
pnpm dedupe
pnpm -s exec tsc -p .

Length of output: 6890


🏁 Script executed:

#!/bin/bash
# Inspect peerDependencies of the newly added Radix context-menu package
grep -R '"peerDependencies"' -A5 node_modules/@radix-ui/react-context-menu/package.json

# Verify why this package is present and ensure no unexpected duplicates
pnpm why @radix-ui/react-context-menu

Length of output: 492


Radix Context Menu OK – Project Peers & Build Are Broken

Context-menu v2.2.16 itself aligns with React’s peer requirement (supports React ≥16.8 and ≤19.x) and pnpm only pulls in one version of @radix-ui/react-context-menu (2.2.16) as expected. However, two critical issues surfaced when verifying:

• Next.js peer-dependency mismatch

  • next@14.2.7 requires react@^18.2.0 and react-dom@^18.2.0, but package.json is pinned to 18.0.0 → fail pnpm dedupe & peer info

• TypeScript build errors

  • Numerous “Cannot find module 'contentlayer/generated'” and implicit-any errors indicate that contentlayer types aren’t generated before tscfail tsc output

Action items (critical fixes required):

  • Upgrade react and react-dom to at least 18.2.0 in package.json so Next.js peers are satisfied.
  • Ensure contentlayer’s generated types exist:
    • Add or update the contentlayer build step in your prebuild or CI scripts.
    • Confirm imports reference the correct output path.
  • Re-run:
    pnpm dedupe
    pnpm -s exec tsc -p .
    to verify no peer warnings or type errors remain.
🤖 Prompt for AI Agents
In package.json around line 17, the project currently pins react and react-dom
to 18.0.0 which conflicts with Next.js 14.2.7 peers and the build fails plus
Contentlayer types are missing before tsc runs; update package.json to bump
react and react-dom to at least 18.2.0, add/update scripts so contentlayer types
are generated before TypeScript compilation (e.g., run contentlayer build in
prebuild/prepare or CI before tsc), verify all imports reference the generated
output path (contentlayer/generated), and after changes run pnpm dedupe and pnpm
-s exec tsc -p . to confirm no peer warnings or type errors remain.

"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.2",
Expand Down
Loading