import React, { useEffect, useRef, useState } from 'react'; import { css, cx } from '@leafygreen-ui/emotion'; import { spacing } from '@leafygreen-ui/tokens'; import { Button, Icon } from '../leafygreen'; import { Tooltip } from '../tooltip'; import type { Signal } from '../signal-popover'; import { SignalPopover } from '../signal-popover'; const actionsGroupContainer = css({ position: 'absolute', display: 'flex', alignItems: 'center', gap: spacing[2], width: '100%', top: spacing[2] + spacing[1], paddingLeft: spacing[3], paddingRight: spacing[3], pointerEvents: 'none', }); const actionsGroupItem = css({ flex: 'none', pointerEvents: 'all', }); const actionsGroupItemSeparator = css({ flex: '1 0 auto', pointerEvents: 'none', }); const actionsGroupIdle = css({ '& > [data-action-item]': { display: 'none', }, }); const actionsGroupHovered = css({ '& > [data-action-item]': { display: 'block', }, }); // Insight icon is always visible, even when action buttons are not const actionsGroupSignalPopover = css({ display: 'block !important', }); function useElementParentHoverState( ref: React.RefObject ): boolean { const [isHovered, setIsHovered] = useState(false); useEffect(() => { const node = ref.current?.parentElement; const onMouseEnter = () => { setIsHovered(true); }; const onMouseLeave = () => { setIsHovered(false); }; node?.addEventListener('mouseenter', onMouseEnter); node?.addEventListener('mouseleave', onMouseLeave); return () => { node?.removeEventListener('mouseenter', onMouseEnter); node?.removeEventListener('mouseleave', onMouseLeave); }; }, [ref]); return isHovered; } function ActionButton({ tooltipText, tooltipEnabled, ...props }: Partial> & { tooltipText: string; tooltipEnabled: boolean; }) { return ( { return (
); }} justify="middle" delay={200} // The copy and clone buttons look alike so we keep the delay short. > {tooltipText}
); } const DocumentActionsGroup: React.FunctionComponent< { onEdit?: () => void; onCopy?: () => void; onClone?: () => void; onRemove?: () => void; onlyShowOnHover?: boolean; insights?: Signal | Signal[]; } & ( | { onExpand?: never; expanded?: never } | { onExpand: () => void; expanded: boolean } ) > = ({ onEdit, onCopy, onClone, onRemove, onExpand, expanded, onlyShowOnHover = true, insights, }) => { const [signalOpened, setSignalOpened] = useState(false); const conatinerRef = useRef(null); const isHovered = useElementParentHoverState(conatinerRef); const [showCopyButtonTooltip, setShowCopyButtonTooltip] = useState(false); const isActive = isHovered || signalOpened; useEffect(() => { if (showCopyButtonTooltip === true) { const tid = setTimeout(() => { setShowCopyButtonTooltip(false); }, 1200); return () => { clearTimeout(tid); }; } }, [showCopyButtonTooltip]); return (
{onExpand && ( } aria-label={expanded ? 'Collapse all' : 'Expand all'} aria-pressed={expanded} data-testid="expand-document-button" onClick={onExpand} className={actionsGroupItem} tooltipText={expanded ? 'Collapse all' : 'Expand all'} /> )} {insights && (
)} {onEdit && ( } aria-label="Edit document" data-testid="edit-document-button" onClick={onEdit} className={actionsGroupItem} tooltipText="Edit document" /> )} {onCopy && ( (
} aria-label="Copy document to clipboard" data-testid="copy-document-button" onClick={() => { setShowCopyButtonTooltip(true); onCopy(); }} className={actionsGroupItem} tooltipText="Copy to clipboard" /> {children}
)} justify="middle" > Copied!
)} {onClone && ( } aria-label="Clone document" data-testid="clone-document-button" onClick={onClone} className={actionsGroupItem} tooltipText="Clone document" /> )} {onRemove && ( } aria-label="Remove document" data-testid="remove-document-button" onClick={onRemove} className={actionsGroupItem} tooltipText="Remove document" /> )}
); }; export default DocumentActionsGroup;