1 import type { ForwardRefRenderFunction } from 'react';
13 import { c } from 'ttag';
15 import { Button } from '@proton/atoms';
16 import type { IconName, PopperPlacement } from '@proton/components';
17 import { Dropdown, DropdownMenu, Icon, usePopperAnchor } from '@proton/components';
18 import type { Props as DropdownMenuButtonCoreProps } from '@proton/components/components/dropdown/DropdownMenuButton';
19 import { default as DropdownMenuButtonCore } from '@proton/components/components/dropdown/DropdownMenuButton';
20 import clsx from '@proton/utils/clsx';
22 type QuickActionChildProp = { onClick: (evt: MouseEvent) => void };
23 type QuickActionChild = ReactElement<QuickActionChildProp>;
24 type Props = { children: QuickActionChild[]; originalPlacement?: PopperPlacement };
26 const QuickActionsDropdown: FC<Props> = ({ children, originalPlacement }) => {
27 const { anchorRef, isOpen, toggle, close } = usePopperAnchor<HTMLButtonElement>();
29 const handleClick = (evt: MouseEvent) => {
30 evt.stopPropagation();
44 title={c('Action').t`More options`}
46 <Icon name="three-dots-vertical" alt={c('Action').t`More options`} color="var(--text-weak)" />
49 <Dropdown isOpen={isOpen} anchorRef={anchorRef} onClose={close} originalPlacement={originalPlacement}>
51 {Children.toArray(children).map((child) =>
52 isValidElement<QuickActionChildProp>(child)
53 ? cloneElement<QuickActionChildProp>(child, {
54 onClick: (evt: MouseEvent) => {
55 child.props.onClick?.(evt);
67 type DropdownMenuButtonLabelProps = {
69 labelClassname?: string;
70 icon?: IconName | ReactElement;
76 export const DropdownMenuButtonLabel: FC<DropdownMenuButtonLabelProps> = ({
84 const strLabel = typeof label === 'string';
87 <div className="flex justify-space-between items-center flex-nowrap gap-2 max-h-custom">
88 <div className={clsx(labelClassname, 'flex items-center flex-nowrap gap-2')}>
89 {typeof icon === 'string' ? (
90 <Icon name={icon} className={clsx(danger ? 'color-danger' : 'color-weak', 'shrink-0')} />
94 <div className={clsx('flex flex-nowrap flex-auto gap-1', danger && 'color-danger')}>
95 {strLabel ? <span className={clsx(ellipsis && 'text-ellipsis')}>{label}</span> : label}
103 interface DropdownMenuButtonProps extends DropdownMenuButtonCoreProps, DropdownMenuButtonLabelProps {
104 children?: ReactNode;
106 isSelected?: boolean;
107 parentClassName?: string;
108 quickActions?: QuickActionChild[];
109 quickActionsClassname?: string;
110 quickActionsPlacement?: PopperPlacement;
111 size?: 'small' | 'medium';
114 const DropdownMenuButtonRender: ForwardRefRenderFunction<HTMLDivElement, DropdownMenuButtonProps> = (
127 quickActionsClassname,
128 quickActionsPlacement,
135 const extraPadding = quickActions !== undefined ? 'pr-3' : '';
138 <div className={clsx('relative shrink-0', parentClassName)} style={style} ref={ref}>
139 <DropdownMenuButtonCore
140 className={clsx(size === 'small' && 'text-sm', className)}
141 // translator : "Selected" is singular only
142 title={isSelected ? c('Label').t`Selected` : undefined}
145 <DropdownMenuButtonLabel
150 labelClassname={clsx('text-left', labelClassname)}
152 <div className={clsx('flex items-center shrink-0 flex-nowrap color-weak', extraPadding)}>
154 <div className={clsx('ml-auto')}>
155 <Icon name="checkmark" color="var(--interaction-norm-major-1)" />
162 </DropdownMenuButtonCore>
164 <div className={clsx('absolute flex items-center h-full right-0 top-0', quickActionsClassname)}>
166 <QuickActionsDropdown originalPlacement={quickActionsPlacement}>
168 </QuickActionsDropdown>
175 export const DropdownMenuButton = forwardRef(DropdownMenuButtonRender);