Files
Checkmate/client/src/components/inputs/ButtonGroup.tsx
T
2025-11-26 21:37:12 +00:00

130 lines
3.4 KiB
TypeScript

import React from "react";
import ButtonGroup from "@mui/material/ButtonGroup";
import { Button } from "@/components/inputs";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import type { ButtonGroupProps } from "@mui/material/ButtonGroup";
import { ChevronDown } from "lucide-react";
import { useTheme } from "@mui/material/styles";
export const ButtonGroupInput: React.FC<ButtonGroupProps> = ({
orientation,
children,
sx,
...props
}) => {
const isVertical = orientation === "vertical";
const theme = useTheme();
if (!isVertical) {
return (
<ButtonGroup
orientation={orientation}
{...props}
sx={{
height: 34,
boxShadow: "none",
...sx,
}}
>
{children}
</ButtonGroup>
);
}
const items = React.Children.toArray(children).filter(
Boolean
) as React.ReactElement<any>[];
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [selectedIndex, setSelectedIndex] = React.useState(0);
const open = Boolean(anchorEl);
const handleToggleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => setAnchorEl(null);
const handleItemClick = (el: React.ReactElement, idx: number) => {
setSelectedIndex(idx);
const onClick = (el.props as any)?.onClick;
if (typeof onClick === "function") onClick();
handleClose();
};
const selected = items[selectedIndex];
const selectedLabel = (selected?.props as any)?.children ?? "Actions";
const selectedOnClick = (selected?.props as any)?.onClick as
| (() => void)
| undefined;
const selectedLoading = Boolean((selected?.props as any)?.loading);
return (
<>
<ButtonGroup
orientation="horizontal"
{...props}
sx={{
boxShadow: "none",
width: "100%",
"& .MuiButtonGroup-grouped": {
borderColor: theme.palette.divider,
},
...sx,
}}
>
<Button
onClick={() => {
if (typeof selectedOnClick === "function") selectedOnClick();
}}
loading={selectedLoading}
size="small"
variant="contained"
color="secondary"
>
{selectedLabel}
</Button>
<Button
onClick={handleToggleClick}
size="small"
variant="contained"
color="secondary"
sx={{
minWidth: 44,
width: 44,
}}
>
<ChevronDown
size={14}
style={{
transition: "transform 150ms ease",
transform: open ? "rotate(180deg)" : "rotate(0deg)",
}}
/>
</Button>
</ButtonGroup>
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleClose}
keepMounted
slotProps={{ list: { dense: true } }}
>
{items.length === 0 ? (
<MenuItem disabled>No actions</MenuItem>
) : (
items.map((el, idx) => (
<MenuItem
key={idx}
selected={idx === selectedIndex}
disabled={(el.props as any)?.disabled}
onClick={() => handleItemClick(el, idx)}
>
{(el.props as any)?.children}
</MenuItem>
))
)}
</Menu>
</>
);
};