Refactor/new menu item (#1448)
* wip * finished * Added disabled * Fixed disabled * Finished cleaning * Minor fixes from merge * Added docs * Added PascalCase * Fix from review * Fixes from merge * Fix lint * Fixed storybook tests
This commit is contained in:
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { Tag } from '@/ui/tag/components/Tag';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
|
||||
import { BoardColumnHotkeyScope } from '../types/BoardColumnHotkeyScope';
|
||||
@ -52,7 +53,7 @@ const StyledNumChildren = styled.div`
|
||||
`;
|
||||
|
||||
export type BoardColumnProps = {
|
||||
color: string;
|
||||
color?: ThemeColor;
|
||||
title: string;
|
||||
onDelete?: (id: string) => void;
|
||||
onTitleEdit: (title: string, color: string) => void;
|
||||
@ -97,7 +98,7 @@ export function BoardColumn({
|
||||
return (
|
||||
<StyledColumn isFirstColumn={isFirstColumn}>
|
||||
<StyledHeader>
|
||||
<Tag onClick={handleTitleClick} color={color} text={title} />
|
||||
<Tag onClick={handleTitleClick} color={color ?? 'gray'} text={title} />
|
||||
{!!totalAmount && <StyledAmount>${totalAmount}</StyledAmount>}
|
||||
<StyledNumChildren>{numChildren}</StyledNumChildren>
|
||||
</StyledHeader>
|
||||
@ -107,7 +108,7 @@ export function BoardColumn({
|
||||
onDelete={onDelete}
|
||||
onTitleEdit={onTitleEdit}
|
||||
title={title}
|
||||
color={color}
|
||||
color={color ?? 'gray'}
|
||||
stageId={stageId}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { ChangeEvent, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { DropdownMenuSelectableItem } from '@/ui/dropdown/components/DropdownMenuSelectableItem';
|
||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||
import { MenuItemSelectColor } from '@/ui/menu-item/components/MenuItemSelectColor';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
import { textInputStyle } from '@/ui/theme/constants/effects';
|
||||
import { debounce } from '~/utils/debounce';
|
||||
|
||||
@ -32,21 +33,15 @@ export type BoardColumnEditTitleMenuProps = {
|
||||
onClose: () => void;
|
||||
title: string;
|
||||
onTitleEdit: (title: string, color: string) => void;
|
||||
color: string;
|
||||
color: ThemeColor;
|
||||
};
|
||||
|
||||
const StyledColorSample = styled.div<{ colorName: string }>`
|
||||
background-color: ${({ theme, colorName }) =>
|
||||
theme.tag.background[colorName]};
|
||||
border: 1px solid
|
||||
${({ theme, colorName }) =>
|
||||
theme.color[colorName as keyof typeof theme.color]};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
`;
|
||||
type ColumnColorOption = {
|
||||
name: string;
|
||||
id: ThemeColor;
|
||||
};
|
||||
|
||||
export const COLOR_OPTIONS = [
|
||||
export const COLUMN_COLOR_OPTIONS: ColumnColorOption[] = [
|
||||
{ name: 'Green', id: 'green' },
|
||||
{ name: 'Turquoise', id: 'turquoise' },
|
||||
{ name: 'Sky', id: 'sky' },
|
||||
@ -85,18 +80,17 @@ export function BoardColumnEditTitleMenu({
|
||||
/>
|
||||
</StyledEditTitleContainer>
|
||||
<StyledDropdownMenuSeparator />
|
||||
{COLOR_OPTIONS.map((colorOption) => (
|
||||
<DropdownMenuSelectableItem
|
||||
{COLUMN_COLOR_OPTIONS.map((colorOption) => (
|
||||
<MenuItemSelectColor
|
||||
key={colorOption.name}
|
||||
onClick={() => {
|
||||
onTitleEdit(title, colorOption.id);
|
||||
onClose();
|
||||
}}
|
||||
color={colorOption.id}
|
||||
selected={colorOption.id === color}
|
||||
>
|
||||
<StyledColorSample colorName={colorOption.id} />
|
||||
{colorOption.name}
|
||||
</DropdownMenuSelectableItem>
|
||||
text={colorOption.name}
|
||||
/>
|
||||
))}
|
||||
</StyledDropdownMenuItemsContainer>
|
||||
);
|
||||
|
||||
@ -5,7 +5,6 @@ import { Key } from 'ts-key-enum';
|
||||
|
||||
import { useCreateCompanyProgress } from '@/companies/hooks/useCreateCompanyProgress';
|
||||
import { useFilteredSearchCompanyQuery } from '@/companies/hooks/useFilteredSearchCompanyQuery';
|
||||
import { DropdownMenuSelectableItem } from '@/ui/dropdown/components/DropdownMenuSelectableItem';
|
||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||
import { IconPencil, IconPlus, IconTrash } from '@/ui/icon';
|
||||
@ -13,8 +12,9 @@ import { SingleEntitySelect } from '@/ui/input/relation-picker/components/Single
|
||||
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||
import { useSnackBar } from '@/ui/snack-bar/hooks/useSnackBar';
|
||||
import { icon } from '@/ui/theme/constants/icon';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
@ -32,7 +32,7 @@ const StyledMenuContainer = styled.div`
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
color: string;
|
||||
color: ThemeColor;
|
||||
onClose: () => void;
|
||||
onDelete?: (id: string) => void;
|
||||
onTitleEdit: (title: string, color: string) => void;
|
||||
@ -52,7 +52,7 @@ export function BoardColumnMenu({
|
||||
}: OwnProps) {
|
||||
const [currentMenu, setCurrentMenu] = useState('actions');
|
||||
|
||||
const [boardColumns, setBoardColumns] = useRecoilState(boardColumnsState);
|
||||
const [, setBoardColumns] = useRecoilState(boardColumnsState);
|
||||
|
||||
const boardColumnMenuRef = useRef(null);
|
||||
|
||||
@ -130,21 +130,21 @@ export function BoardColumnMenu({
|
||||
<StyledDropdownMenu>
|
||||
{currentMenu === 'actions' && (
|
||||
<StyledDropdownMenuItemsContainer>
|
||||
<DropdownMenuSelectableItem onClick={() => setMenu('title')}>
|
||||
<IconPencil size={icon.size.md} stroke={icon.stroke.sm} />
|
||||
Rename
|
||||
</DropdownMenuSelectableItem>
|
||||
<DropdownMenuSelectableItem
|
||||
disabled={boardColumns.length <= 1}
|
||||
<MenuItem
|
||||
onClick={() => setMenu('title')}
|
||||
LeftIcon={IconPencil}
|
||||
text="Rename"
|
||||
/>
|
||||
<MenuItem
|
||||
onClick={handleDelete}
|
||||
>
|
||||
<IconTrash size={icon.size.md} stroke={icon.stroke.sm} />
|
||||
Delete
|
||||
</DropdownMenuSelectableItem>
|
||||
<DropdownMenuSelectableItem onClick={() => setMenu('add')}>
|
||||
<IconPlus size={icon.size.md} stroke={icon.stroke.sm} />
|
||||
New opportunity
|
||||
</DropdownMenuSelectableItem>
|
||||
LeftIcon={IconTrash}
|
||||
text="Delete"
|
||||
/>
|
||||
<MenuItem
|
||||
onClick={() => setMenu('add')}
|
||||
LeftIcon={IconPlus}
|
||||
text="New opportunity"
|
||||
/>
|
||||
</StyledDropdownMenuItemsContainer>
|
||||
)}
|
||||
{currentMenu === 'title' && (
|
||||
|
||||
@ -7,18 +7,19 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
|
||||
import {
|
||||
IconChevronLeft,
|
||||
IconChevronRight,
|
||||
IconLayoutKanban,
|
||||
IconPlus,
|
||||
IconSettings,
|
||||
} from '@/ui/icon';
|
||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||
import { MenuItemNavigate } from '@/ui/menu-item/components/MenuItemNavigate';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
@ -35,16 +36,18 @@ const StyledIconSettings = styled(IconSettings)`
|
||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const StyledIconChevronRight = styled(IconChevronRight)`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
margin-left: auto;
|
||||
`;
|
||||
|
||||
enum BoardOptionsMenu {
|
||||
StageCreation = 'StageCreation',
|
||||
Stages = 'Stages',
|
||||
}
|
||||
|
||||
type ColumnForCreate = {
|
||||
id: string;
|
||||
colorCode: ThemeColor;
|
||||
index: number;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export function BoardOptionsDropdownContent({
|
||||
customHotkeyScope,
|
||||
onStageAdd,
|
||||
@ -68,7 +71,7 @@ export function BoardOptionsDropdownContent({
|
||||
)
|
||||
return;
|
||||
|
||||
const columnToCreate = {
|
||||
const columnToCreate: ColumnForCreate = {
|
||||
id: v4(),
|
||||
colorCode: 'gray',
|
||||
index: boardColumns.length,
|
||||
@ -113,32 +116,26 @@ export function BoardOptionsDropdownContent({
|
||||
</DropdownMenuHeader>
|
||||
<StyledDropdownMenuSeparator />
|
||||
<StyledDropdownMenuItemsContainer>
|
||||
<DropdownMenuItem
|
||||
<MenuItemNavigate
|
||||
onClick={() => setCurrentMenu(BoardOptionsMenu.Stages)}
|
||||
>
|
||||
<IconLayoutKanban size={theme.icon.size.md} />
|
||||
Stages
|
||||
<StyledIconChevronRight size={theme.icon.size.sm} />
|
||||
</DropdownMenuItem>
|
||||
LeftIcon={IconLayoutKanban}
|
||||
text="Stages"
|
||||
/>
|
||||
</StyledDropdownMenuItemsContainer>
|
||||
</>
|
||||
)}
|
||||
{currentMenu === BoardOptionsMenu.Stages && (
|
||||
<>
|
||||
<DropdownMenuHeader
|
||||
startIcon={<IconChevronLeft size={theme.icon.size.md} />}
|
||||
onClick={resetMenu}
|
||||
>
|
||||
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={resetMenu}>
|
||||
Stages
|
||||
</DropdownMenuHeader>
|
||||
<StyledDropdownMenuSeparator />
|
||||
<StyledDropdownMenuItemsContainer>
|
||||
<DropdownMenuItem
|
||||
<MenuItem
|
||||
onClick={() => setCurrentMenu(BoardOptionsMenu.StageCreation)}
|
||||
>
|
||||
<IconPlus size={theme.icon.size.md} />
|
||||
Add stage
|
||||
</DropdownMenuItem>
|
||||
LeftIcon={IconPlus}
|
||||
text="Add stage"
|
||||
/>
|
||||
</StyledDropdownMenuItemsContainer>
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -4,7 +4,7 @@ import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import {
|
||||
BoardColumnEditTitleMenu,
|
||||
COLOR_OPTIONS,
|
||||
COLUMN_COLOR_OPTIONS,
|
||||
} from '../BoardColumnEditTitleMenu';
|
||||
|
||||
const meta: Meta<typeof BoardColumnEditTitleMenu> = {
|
||||
@ -14,7 +14,7 @@ const meta: Meta<typeof BoardColumnEditTitleMenu> = {
|
||||
argTypes: {
|
||||
color: {
|
||||
control: 'select',
|
||||
options: COLOR_OPTIONS.map(({ id }) => id),
|
||||
options: COLUMN_COLOR_OPTIONS.map(({ id }) => id),
|
||||
},
|
||||
},
|
||||
args: { color: 'green', title: 'Column title' },
|
||||
|
||||
@ -16,7 +16,7 @@ export function useBoardContextMenuEntries() {
|
||||
setContextMenuEntries([
|
||||
<ContextMenuEntry
|
||||
label="Delete"
|
||||
icon={<IconTrash size={16} />}
|
||||
Icon={IconTrash}
|
||||
accent="danger"
|
||||
onClick={() => deleteSelectedBoardCards()}
|
||||
key="delete"
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
|
||||
export type BoardColumnDefinition = {
|
||||
id: string;
|
||||
title: string;
|
||||
index: number;
|
||||
colorCode: string;
|
||||
colorCode?: ThemeColor;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user