
* Update to new design theme (#1631) * Update macaw to 0.3.0 (#1623) * Update macaw to 0.3 * Use proper pagination component * Fix type errors * Remove leftover import * Remove variant and color from confirm button * Remove alias * Update macaw * Fix button type * Random fixes (#1633) * Improve layout components * Use colored svgs * Minor fixes * Fix autocomplete loaders * Fix padding * Fix button variant * Remove codegen file * Fixes after bumping macaw to 0.3 part 2 (#1638) * Fix various visual bugs * Fix type errors * Bump macaw * Random fixes part 3 (#1647) * wip * Fix mismatched paddings * Fix actions container padding * Put story in the right directory * Fix shipping zone picker * Fix minor visual bugs * Remove unused imports * Move styles to separate file * Random fixes part 4 (#1641) * Fix various visual bugs * Fix type errors * Fix last table item padding * Add outline on hover * Fix spaces * Fix spaces * Remove dead code * Fix elevation * Remove dead code * Fix shadows * Add outline to expand button * Fix spacing * Fix spacings * Fix selectable tables hover * Use proper delete icon * Fix ConfirmButtonTransitionState imports * Update src/apps/components/CustomApps/CustomApps.tsx Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> * Rework error page (#1670) * Remake error page * Fix types * Update error id styles * Fix types * Login page rework (#1703) * Rework login page * Remove outline * Fix logo and footer placement * Sort imports * Random fixes part 5 (#1669) * Fix text color in dark mode * Update password reset pages (#1714) * Update password reset pages * Update src/auth/components/ResetPasswordPage/ResetPasswordPage.tsx Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com> Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com> * Fix collection page * Update dark mode logo * Bring back "create app" button * Fix spacings * Fix selects * Fix login e2e test * Fix not found page displaying * Update selector * Add missing package * Let dropdown overflow through card * Fix scroll * Fix scroll * Fix overflow on grid element * Fix e2e tests * Fix data-test-id * Update snapshots * Update messages * Update macaw * Update snapshots * Use stable macaw version Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com> * Update to new design theme (#1631) * Update macaw to 0.3.0 (#1623) * Update macaw to 0.3 * Use proper pagination component * Fix type errors * Remove leftover import * Remove variant and color from confirm button * Remove alias * Update macaw * Fix button type * Random fixes (#1633) * Improve layout components * Use colored svgs * Minor fixes * Fix autocomplete loaders * Fix padding * Fix button variant * Remove codegen file * Fixes after bumping macaw to 0.3 part 2 (#1638) * Fix various visual bugs * Fix type errors * Bump macaw * Random fixes part 3 (#1647) * wip * Fix mismatched paddings * Fix actions container padding * Put story in the right directory * Fix shipping zone picker * Fix minor visual bugs * Remove unused imports * Move styles to separate file * Random fixes part 4 (#1641) * Fix various visual bugs * Fix type errors * Fix last table item padding * Add outline on hover * Fix spaces * Fix spaces * Remove dead code * Fix elevation * Remove dead code * Fix shadows * Add outline to expand button * Fix spacing * Fix spacings * Fix selectable tables hover * Use proper delete icon * Fix ConfirmButtonTransitionState imports * Update src/apps/components/CustomApps/CustomApps.tsx Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> * Rework error page (#1670) * Remake error page * Fix types * Update error id styles * Fix types * Login page rework (#1703) * Rework login page * Remove outline * Fix logo and footer placement * Sort imports * Random fixes part 5 (#1669) * Fix text color in dark mode * Update password reset pages (#1714) * Update password reset pages * Update src/auth/components/ResetPasswordPage/ResetPasswordPage.tsx Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com> Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com> * Fix collection page * Update dark mode logo * Bring back "create app" button * Fix spacings * Fix selects * Fix login e2e test * Fix not found page displaying * Update selector * Add missing package * Let dropdown overflow through card * Fix scroll * Fix scroll * Fix overflow on grid element * Fix e2e tests * Fix data-test-id * Update snapshots * Update messages * Update macaw * Update snapshots * Use stable macaw version Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com> * Fix visual bugs and artifacts * Fix dropdown menus being clipped (#1762) * wip * Fix clipped select menus * Remove unused import * Fix spacing * Fix tests * Fix select content appearing under dialogs (#1777) * Fix type errors * Fix bulk delete button placement * Fix filter arrow buttons * Fix messages * Remove backling from pages list * Move status above events * Update messages and snapshots Co-authored-by: Wojciech Mista <wojciech.mista@saleor.io> Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com>
198 lines
5.2 KiB
TypeScript
198 lines
5.2 KiB
TypeScript
import {
|
|
CircularProgress,
|
|
ClickAwayListener,
|
|
Grow,
|
|
MenuItem,
|
|
MenuList,
|
|
Paper,
|
|
Popper,
|
|
Typography
|
|
} from "@material-ui/core";
|
|
import { IconButton, makeStyles, MoreIcon } from "@saleor/macaw-ui";
|
|
import classNames from "classnames";
|
|
import React, { useEffect, useRef, useState } from "react";
|
|
import { FormattedMessage } from "react-intl";
|
|
|
|
import { cardMenuMessages as messages } from "./messages";
|
|
|
|
const ITEM_HEIGHT = 48;
|
|
export interface CardMenuItem {
|
|
disabled?: boolean;
|
|
label: string;
|
|
testId?: string;
|
|
onSelect: () => void;
|
|
loading?: boolean;
|
|
withLoading?: boolean;
|
|
hasError?: boolean;
|
|
}
|
|
|
|
export interface CardMenuProps {
|
|
className?: string;
|
|
disabled?: boolean;
|
|
menuItems: CardMenuItem[];
|
|
outlined?: boolean;
|
|
}
|
|
|
|
const useStyles = makeStyles(
|
|
theme => ({
|
|
container: {
|
|
zIndex: 1
|
|
},
|
|
iconButton: {
|
|
background: theme.palette.background.paper,
|
|
borderRadius: "100%",
|
|
height: 32,
|
|
padding: 0,
|
|
width: 32
|
|
},
|
|
paper: {
|
|
marginTop: theme.spacing(2),
|
|
maxHeight: ITEM_HEIGHT * 4.5,
|
|
overflowY: "scroll"
|
|
},
|
|
loadingContent: {
|
|
width: "100%",
|
|
display: "grid",
|
|
gridTemplateColumns: "1fr 24px",
|
|
gap: theme.spacing(2),
|
|
alignItems: "center",
|
|
justifyContent: "flex-end"
|
|
}
|
|
}),
|
|
{ name: "CardMenu" }
|
|
);
|
|
|
|
const CardMenu: React.FC<CardMenuProps> = props => {
|
|
const { className, disabled, menuItems, outlined, ...rest } = props;
|
|
const classes = useStyles(props);
|
|
|
|
const anchorRef = useRef<HTMLButtonElement | null>(null);
|
|
const [open, setOpen] = useState(false);
|
|
|
|
const handleToggle = () => setOpen(prevOpen => !prevOpen);
|
|
|
|
const handleClose = (event: React.MouseEvent<EventTarget>) => {
|
|
if (
|
|
anchorRef.current &&
|
|
anchorRef.current.contains(event.target as HTMLElement)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
setOpen(false);
|
|
};
|
|
|
|
const handleListKeyDown = (event: React.KeyboardEvent) => {
|
|
if (event.key === "Tab") {
|
|
event.preventDefault();
|
|
setOpen(false);
|
|
}
|
|
};
|
|
|
|
const prevOpen = useRef(open);
|
|
useEffect(() => {
|
|
if (prevOpen.current === true && open === false) {
|
|
anchorRef.current!.focus();
|
|
}
|
|
|
|
prevOpen.current = open;
|
|
}, [open]);
|
|
|
|
useEffect(() => {
|
|
const hasAnyItemsLoadingOrWithError = menuItems
|
|
?.filter(({ withLoading }) => withLoading)
|
|
?.some(({ loading, hasError }) => loading || hasError);
|
|
|
|
if (!hasAnyItemsLoadingOrWithError) {
|
|
setOpen(false);
|
|
}
|
|
}, [menuItems]);
|
|
|
|
const handleMenuClick = (index: number) => {
|
|
const selectedItem = menuItems[index];
|
|
selectedItem.onSelect();
|
|
|
|
if (!selectedItem.withLoading) {
|
|
setOpen(false);
|
|
}
|
|
};
|
|
|
|
const isWithLoading = menuItems.some(({ withLoading }) => withLoading);
|
|
|
|
return (
|
|
<div className={className} {...rest}>
|
|
<IconButton
|
|
data-test-id="showMoreButton"
|
|
aria-label="More"
|
|
aria-owns={open ? "long-menu" : null}
|
|
aria-haspopup="true"
|
|
color="primary"
|
|
disabled={disabled}
|
|
ref={anchorRef}
|
|
onClick={handleToggle}
|
|
variant={outlined ? "primary" : "secondary"}
|
|
>
|
|
<MoreIcon />
|
|
</IconButton>
|
|
<Popper
|
|
placement="bottom-end"
|
|
className={classes.container}
|
|
open={open}
|
|
anchorEl={anchorRef.current}
|
|
transition
|
|
>
|
|
{({ TransitionProps, placement }) => (
|
|
<Grow
|
|
{...TransitionProps}
|
|
style={{
|
|
transformOrigin:
|
|
placement === "bottom" ? "right top" : "right bottom",
|
|
overflowY: "auto"
|
|
}}
|
|
>
|
|
<Paper className={classes.paper} elevation={8}>
|
|
<ClickAwayListener onClickAway={handleClose}>
|
|
<MenuList
|
|
autoFocusItem={open}
|
|
id="menu-list-grow"
|
|
onKeyDown={handleListKeyDown}
|
|
>
|
|
{menuItems.map((menuItem, menuItemIndex) => (
|
|
<MenuItem
|
|
data-test-id={menuItem.testId}
|
|
disabled={menuItem.loading || menuItem.disabled}
|
|
onClick={() => handleMenuClick(menuItemIndex)}
|
|
key={menuItem.label}
|
|
data-test={menuItem.testId}
|
|
>
|
|
<div
|
|
className={classNames(className, {
|
|
[classes.loadingContent]: isWithLoading
|
|
})}
|
|
>
|
|
{menuItem.loading ? (
|
|
<>
|
|
<Typography variant="subtitle1">
|
|
<FormattedMessage
|
|
{...messages.cardMenuItemLoading}
|
|
/>
|
|
</Typography>
|
|
<CircularProgress size={24} />
|
|
</>
|
|
) : (
|
|
<Typography>{menuItem.label}</Typography>
|
|
)}
|
|
</div>
|
|
</MenuItem>
|
|
))}
|
|
</MenuList>
|
|
</ClickAwayListener>
|
|
</Paper>
|
|
</Grow>
|
|
)}
|
|
</Popper>
|
|
</div>
|
|
);
|
|
};
|
|
CardMenu.displayName = "CardMenu";
|
|
export default CardMenu;
|