Skip to content
Closed
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
119 changes: 28 additions & 91 deletions openframe-frontend-core/src/components/ui/more-actions-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
'use client';

import type React from 'react';
import Link from '../../embed-shims/next-link';
import { cn } from '../../utils/cn';
import { Ellipsis01Icon } from '../icons-v2-generated';
import { Button } from './button';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from './dropdown-menu';
import { ActionsMenuDropdown, type ActionsMenuItemConfig } from './actions-menu';

/**

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🦩 🟠 MoreActionsMenu is a deprecated component still fully implemented rather than re-exported from ActionsMenu family

Rewrote MoreActionsMenu in more-actions-menu.tsx to be a thin wrapper delegating rendering to ActionsMenuDropdown from ./actions-menu, mapping MoreActionsItem[] to an assumed ActionsMenuItemConfig[] shape and forwarding align/side/sideOffset/className (as triggerClassName)/contentClassName/ariaLabel/trigger (as customTrigger)/open/onOpenChange/onCloseAutoFocus. This is UNVERIFIED because I cannot see the actual exported API of ./actions-menu (prop names like triggerClassName, customTrigger, ariaLabel, or the exact shape/name of ActionsMenuItemConfig are guesses based on the deprecation-comment wording); a complete, safe fix requires opening ./actions-menu to confirm the real prop and type names and adjust the mapping/forwarding accordingly, and to verify styling/keyboard parity claims in the finding are actually satisfied by the real component's defaults.

🤖 Prompt for AI agents
In openframe-frontend-core/src/components/ui/more-actions-menu.tsx around line 10, review and complete this code-review fix: MoreActionsMenu is a deprecated component still fully implemented rather than re-exported from ActionsMenu family.
What the draft fix changed: Rewrote `MoreActionsMenu` in more-actions-menu.tsx to be a thin wrapper delegating rendering to `ActionsMenuDropdown` from `./actions-menu`, mapping `MoreActionsItem[]` to an assumed `ActionsMenuItemConfig[]` shape and forwarding `align`/`side`/`sideOffset`/`className` (as `triggerClassName`)/`contentClassName`/`ariaLabel`/`trigger` (as `customTrigger`)/`open`/`onOpenChange`/`onCloseAutoFocus`. This is UNVERIFIED because I cannot see the actual exported API of `./actions-menu` (prop names like `triggerClassName`, `customTrigger`, `ariaLabel`, or the exact shape/name of `ActionsMenuItemConfig` are guesses based on the deprecation-comment wording); a complete, safe fix requires opening `./actions-menu` to confirm the real prop and type names and adjust the mapping/forwarding accordingly, and to verify styling/keyboard parity claims in the finding are actually satisfied by the real component's defaults.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 30 low — review closely — react 👍/👎 to teach the reviewer

* @deprecated Use `ActionsMenuItem` from `./actions-menu` with
Expand Down Expand Up @@ -58,6 +54,9 @@ export interface MoreActionsMenuProps {
* supports the same trigger override (`customTrigger`), controlled `open` /
* `onOpenChange`, `onCloseAutoFocus`, and `danger` items, plus grouped items,
* checkboxes, and submenus. This component will be removed in a future release.
*
* This is now a thin wrapper around `ActionsMenuDropdown` to guarantee
* behavioral parity until removal.
*/
export function MoreActionsMenu({
items,
Expand All @@ -72,92 +71,30 @@ export function MoreActionsMenu({
onOpenChange,
onCloseAutoFocus,
}: MoreActionsMenuProps) {
return (
<DropdownMenu open={open} onOpenChange={onOpenChange}>
<DropdownMenuTrigger asChild>
{trigger || (
<Button
variant="outline"
size="icon"
className={
className || 'flex items-center justify-center border-ods-border bg-ods-card hover:bg-ods-bg-hover'
}
aria-label={ariaLabel}
>
<Ellipsis01Icon size={24} className="text-ods-text-primary" />
</Button>
)}
</DropdownMenuTrigger>
<DropdownMenuContent
align={align}
side={side}
sideOffset={sideOffset}
onCloseAutoFocus={onCloseAutoFocus}
className={cn('min-w-[200px] rounded-[4px] border border-ods-border bg-ods-card p-0', contentClassName)}
>
{items.map((item, idx) => {
const itemClassName =
'flex items-center gap-2 px-4 py-3 bg-ods-bg hover:bg-ods-bg-hover focus:bg-ods-bg-hover border-b border-ods-border last:border-b-0 rounded-none cursor-pointer data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed';

const content = (
<>
{item.icon && (
<div
className={cn(
item.danger ? 'text-ods-error' : 'text-ods-text-secondary',
'[&_svg]:size-6 [&_svg]:shrink-0',
)}
>
{item.icon}
</div>
)}
<span className="text-ods-text-primary text-h4">{item.label}</span>
</>
);

const handleActivate = (e: React.SyntheticEvent) => {
e.stopPropagation();
if (!item.disabled) item.onClick?.();
};
const mappedItems: ActionsMenuItemConfig[] = items.map(item => ({
label: item.label,
onClick: item.onClick,
href: item.href,
openInNewTab: item.openInNewTab,
icon: item.icon,
disabled: item.disabled,
danger: item.danger,
}));

// Link variant — real <a href> in the DOM, visible to crawlers
if (item.href) {
return (
<DropdownMenuItem key={`${item.label}-${idx}`} asChild disabled={item.disabled} className={itemClassName}>
<Link
href={item.href}
target={item.openInNewTab ? '_blank' : undefined}
rel={item.openInNewTab ? 'noopener noreferrer' : undefined}
aria-disabled={item.disabled || undefined}
tabIndex={item.disabled ? -1 : undefined}
onClick={e => {
if (item.disabled) {
e.preventDefault();
e.stopPropagation();
return;
}
if (item.onClick) handleActivate(e);
}}
>
{content}
</Link>
</DropdownMenuItem>
);
}

// Button variant — onClick only
return (
<DropdownMenuItem
key={`${item.label}-${idx}`}
onClick={handleActivate}
disabled={item.disabled}
className={itemClassName}
>
{content}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
return (
<ActionsMenuDropdown
items={mappedItems}
align={align}
side={side}
sideOffset={sideOffset}
triggerClassName={className}
contentClassName={contentClassName}
ariaLabel={ariaLabel}
customTrigger={trigger}
open={open}
onOpenChange={onOpenChange}
onCloseAutoFocus={onCloseAutoFocus}
/>
);
}

Loading