Files
2024-02-15 17:01:50 +00:00

115 lines
2.6 KiB
TypeScript

import type {useSortable} from '@dnd-kit/sortable';
import styled from '@emotion/styled';
import {Button} from 'sentry/components/button';
import {IconCopy, IconDelete, IconEdit, IconGrabbable} from 'sentry/icons';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import {DRAG_HANDLE_CLASS} from '../dashboard';
type DraggableProps = Pick<ReturnType<typeof useSortable>, 'attributes' | 'listeners'>;
type ToolbarProps = {
draggableProps?: DraggableProps;
hideToolbar?: boolean;
isMobile?: boolean;
onDelete?: () => void;
onDuplicate?: () => void;
onEdit?: () => void;
};
export function Toolbar({
hideToolbar,
isMobile,
onEdit,
onDelete,
onDuplicate,
draggableProps,
}: ToolbarProps) {
return (
<ToolbarPanel>
<IconContainer style={{visibility: hideToolbar ? 'hidden' : 'visible'}}>
{!isMobile && (
<GrabbableButton
size="xs"
aria-label={t('Drag Widget')}
icon={<IconGrabbable />}
borderless
className={DRAG_HANDLE_CLASS}
{...draggableProps?.listeners}
{...draggableProps?.attributes}
/>
)}
{onEdit && (
<Button
data-test-id="widget-edit"
aria-label={t('Edit Widget')}
size="xs"
borderless
onClick={onEdit}
icon={<IconEdit />}
/>
)}
{onDuplicate && (
<Button
aria-label={t('Duplicate Widget')}
size="xs"
borderless
onClick={onDuplicate}
icon={<IconCopy />}
/>
)}
{onDelete && (
<Button
data-test-id="widget-delete"
aria-label={t('Delete Widget')}
borderless
size="xs"
onClick={onDelete}
icon={<IconDelete />}
/>
)}
</IconContainer>
</ToolbarPanel>
);
}
const ToolbarPanel = styled('div')`
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
justify-content: flex-end;
align-items: flex-start;
background-color: ${p => p.theme.overlayBackgroundAlpha};
border-radius: calc(${p => p.theme.panelBorderRadius} - 1px);
`;
const IconContainer = styled('div')`
display: flex;
margin: ${space(1)};
touch-action: none;
`;
const GrabbableButton = styled(Button)`
cursor: grab;
`;
export const WidgetTitleRow = styled('span')`
display: flex;
align-items: center;
gap: ${space(0.75)};
`;
export const WidgetDescription = styled('small')`
${p => p.theme.overflowEllipsis}
color: ${p => p.theme.gray300};
`;