Skip to content

Commit

Permalink
Refactor theming of SplitButton (#1602)
Browse files Browse the repository at this point in the history
Added theming for SplitButton, ClassKey and styled elements

---------

Co-authored-by: Ricky James Smith <jamesricky@me.com>
  • Loading branch information
NataliaVizintini and jamesricky authored Jan 25, 2024
1 parent 96eb8fb commit 5e29232
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 24 deletions.
112 changes: 89 additions & 23 deletions packages/admin/admin/src/common/buttons/split/SplitButton.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,101 @@
import { ChevronDown } from "@comet/admin-icons";
import { Button, ButtonGroup, ButtonGroupProps, MenuItem, MenuList, Popover, PopoverProps } from "@mui/material";
import { withStyles } from "@mui/styles";
import {
Button,
ButtonGroup as MuiButtonGroup,
ButtonGroupProps,
MenuItem as MuiMenuItem,
MenuList as MuiMenuList,
Popover as MuiPopover,
PopoverProps,
} from "@mui/material";
import { styled, useThemeProps } from "@mui/material/styles";
import { ThemedComponentBaseProps } from "helpers/ThemedComponentBaseProps";
import * as React from "react";
import { PropsWithChildren } from "react";

import { useStoredState } from "../../../hooks/useStoredState";
import { SplitButtonContext } from "./SplitButtonContext";

export interface SplitButtonProps extends ButtonGroupProps<any> {
export type SplitButtonClassKey = "root" | "activeButton" | "popover" | "menuList" | "menuItem";

export interface SplitButtonProps
extends ButtonGroupProps<any>,
ThemedComponentBaseProps<{
root: typeof MuiButtonGroup;
activeButton: typeof Button;
popover: typeof MuiPopover;
menuList: typeof MuiMenuList;
menuItem: typeof MuiMenuItem;
}> {
selectIcon?: React.ReactNode;
selectedIndex?: number;
onSelectIndex?: (index: number, item: React.ReactElement) => void;
showSelectButton?: boolean;
localStorageKey?: string;
autoClickOnSelect?: boolean;
storage?: Storage;
/**
* @deprecated Use `slotProps` instead.
*/
popoverProps?: Partial<PopoverProps>;
}

const Root = styled(MuiButtonGroup, {
name: "CometAdminSplitButton",
slot: "root",
overridesResolver(_, styles) {
return [styles.root];
},
})();

const ActiveButton = styled(Button, {
name: "CometAdminSplitButton",
slot: "activeButton",
overridesResolver(_, styles) {
return [styles.activeButton];
},
})();

const Popover = styled(MuiPopover, {
name: "CometAdminSplitButton",
slot: "popover",
overridesResolver(_, styles) {
return [styles.popover];
},
})();

const MenuList = styled(MuiMenuList, {
name: "CometAdminSplitButton",
slot: "menuList",
overridesResolver(_, styles) {
return [styles.menuList];
},
})();

const MenuItem = styled(MuiMenuItem, {
name: "CometAdminSplitButton",
slot: "menuItem",
overridesResolver(_, styles) {
return [styles.menuItem];
},
})();

// Based on https://v4.mui.com/components/button-group/#split-button
const SplitBtn = ({
selectIcon = <ChevronDown />,
selectedIndex,
onSelectIndex,
children,
showSelectButton,
localStorageKey,
storage,
autoClickOnSelect = true,
popoverProps,
...restProps
}: PropsWithChildren<SplitButtonProps>) => {
export function SplitButton(inProps: PropsWithChildren<SplitButtonProps>) {
const {
selectIcon = <ChevronDown />,
selectedIndex,
onSelectIndex,
children,
showSelectButton,
localStorageKey,
storage,
autoClickOnSelect = true,
popoverProps,
slotProps,
...restProps
} = useThemeProps({ props: inProps, name: "CometAdminSplitButton" });

const [showSelectButtonState, setShowSelectButtonState] = React.useState<boolean | undefined>(undefined);

const childrenArray = React.Children.toArray(children);
Expand Down Expand Up @@ -76,36 +141,39 @@ const SplitBtn = ({
const showSelect = showSelectButtonState != null ? showSelectButtonState : showSelectButton;
return (
<SplitButtonContext.Provider value={{ setShowSelectButton: setShowSelectButtonState }}>
<ButtonGroup variant={activeChildVariant} color={activeChildColor} {...restProps} ref={anchorRef}>
<Root variant={activeChildVariant} color={activeChildColor} {...restProps} {...slotProps?.root} ref={anchorRef}>
{ActiveChild}
{(showSelect ?? childrenArray.length > 1) && (
<Button
<ActiveButton
variant={activeChildVariant}
color={activeChildColor}
size="small"
classes={ActiveChild.props.classes}
onClick={handleToggle}
{...slotProps?.activeButton}
>
{selectIcon}
</Button>
</ActiveButton>
)}
</ButtonGroup>
</Root>
<Popover
open={open}
anchorEl={anchorRef.current}
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
transformOrigin={{ vertical: "top", horizontal: "center" }}
onClose={handleClose}
{...popoverProps}
{...slotProps?.popover}
>
<MenuList>
<MenuList {...slotProps?.menuList}>
{childrenArray.map((child: React.ReactElement, index) => {
return (
<MenuItem
key={index}
selected={index === selectedIndex}
onClick={(event) => handleMenuItemClick(event, index, child)}
disabled={child.props.disabled}
{...slotProps?.menuItem}
>
{child.props.children}
</MenuItem>
Expand All @@ -115,9 +183,7 @@ const SplitBtn = ({
</Popover>
</SplitButtonContext.Provider>
);
};

export const SplitButton = withStyles({}, { name: "CometAdminSplitButton" })(SplitBtn);
}

declare module "@mui/material/styles" {
interface ComponentsPropsList {
Expand Down
2 changes: 1 addition & 1 deletion packages/admin/admin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export {
export { DeleteButton, DeleteButtonClassKey, DeleteButtonProps } from "./common/buttons/delete/DeleteButton";
export { OkayButton, OkayButtonClassKey, OkayButtonProps } from "./common/buttons/okay/OkayButton";
export { SaveButton, SaveButtonClassKey, SaveButtonProps } from "./common/buttons/save/SaveButton";
export { SplitButton, SplitButtonProps } from "./common/buttons/split/SplitButton";
export { SplitButton, SplitButtonClassKey, SplitButtonProps } from "./common/buttons/split/SplitButton";
export { SplitButtonContext, SplitButtonContextOptions } from "./common/buttons/split/SplitButtonContext";
export { useSplitButtonContext } from "./common/buttons/split/useSplitButtonContext";
export { ClearInputAdornment, ClearInputAdornmentProps } from "./common/ClearInputAdornment";
Expand Down

0 comments on commit 5e29232

Please sign in to comment.