Skip to content

Commit

Permalink
Allow extending slots from Admin components
Browse files Browse the repository at this point in the history
Extending a Comet Admin component using `styled()` requires the
`className` prop to be passed through to the components `root` slot.

Also added the `ThemedComponentBaseProps` type to use as a base for
components props. This abstracts away the need to manually define the
`sx`, `className` and `slotProps` props in every component.
  • Loading branch information
jamesricky committed Nov 28, 2023
1 parent 92eae2b commit 1c6694d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ E.g.: in this instance of `MyComponent`, the root should have a red border, and
## Example component

```tsx
import { SlotProps } from "@comet/admin";
import { ThemedComponentBaseProps } from "@comet/admin";
import { CometColor } from "@comet/admin-icons";
import { ComponentsOverrides, Typography } from "@mui/material";
import { css, styled, SxProps, Theme, useThemeProps } from "@mui/material/styles";
import { css, styled, Theme, useThemeProps } from "@mui/material/styles";
import React from "react";

/**
Expand Down Expand Up @@ -162,38 +162,40 @@ const Children = styled("div", {
);

/**
* The `{ComponentName}Props` type defines all of the component's props.
* The following props are required by all Comet Admin components:
* - `sx`: Used to override the styles of the root slot of a component.
* - `slotProps`: Used to override the props and the styling (through the slot's `sx` prop) of each slot of a component.
* The `{ComponentName}Props` type defines all of the component's props and should extend `ThemedComponentBaseProps`.
* `ThemedComponentBaseProps` adds the props necessary for overriding the component's styles by adding the `sx`, `className` and `slotProps` props.
* If the component has multiple slots, pass in a generic/object with the slots as keys and their types as values.
*/
export interface MyComponentProps {
export interface MyComponentProps
extends ThemedComponentBaseProps<{
root: "div";
header: "div";
title: typeof Typography;
icon: typeof CometColor;
children: "div";
}> {
title: React.ReactNode;
children?: React.ReactNode;
shadow?: boolean;
sx?: SxProps<Theme>;
slotProps?: {
root?: SlotProps<"div">;
header?: SlotProps<"div">;
title?: SlotProps<typeof Typography>;
icon?: SlotProps<typeof CometColor>;
children?: SlotProps<"div">;
};
}

export function MyComponent(inProps: MyComponentProps) {
/**
* A component should never use the passed-in props directly but get them through the `useThemeProps` hook.
* This merges the components `defaultProps` from the theme with the passed-in props.
*/
const { title, children, shadow, slotProps = {}, sx } = useThemeProps({ props: inProps, name: "CometAdminMyComponent" });
const { title, children, shadow, slotProps, ...restProps } = useThemeProps({ props: inProps, name: "CometAdminMyComponent" });

const ownerState: OwnerState = {
shadow,
};

/**
* Ensure the `sx` and `className` props are passed into the root slot.
* In this case, this is done with `...restProps`.
*/
return (
<Root ownerState={ownerState} sx={sx} {...slotProps?.root}>
<Root ownerState={ownerState} {...restProps} {...slotProps?.root}>
<Header {...slotProps?.header}>
<Title ownerState={ownerState} variant="h4" {...slotProps?.title}>
{title}
Expand Down
13 changes: 13 additions & 0 deletions packages/admin/admin/src/helpers/RootSlotProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Theme } from "@mui/material/styles";
import { MUIStyledCommonProps, SxProps } from "@mui/system";
import React from "react";

type SlotProps<Component extends React.ElementType> = Partial<React.ComponentProps<Component>> & MUIStyledCommonProps<Theme>;

export type ThemedComponentBaseProps<Slots extends Record<string, React.ElementType> = never> = {
sx?: SxProps<Theme>;
className?: string;
slotProps?: {
[K in keyof Slots]?: SlotProps<Slots[K]>;
};
};
5 changes: 0 additions & 5 deletions packages/admin/admin/src/helpers/SlotProps.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/admin/admin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export { FinalFormRadio, FinalFormRadioProps } from "./form/Radio";
export { FinalFormSwitch, FinalFormSwitchProps } from "./form/Switch";
export { FormMutation } from "./FormMutation";
export { PrettyBytes } from "./helpers/PrettyBytes";
export { SlotProps } from "./helpers/SlotProps";
export { ThemedComponentBaseProps } from "./helpers/ThemedComponentBaseProps";
export { IWindowSize, useWindowSize } from "./helpers/useWindowSize";
export { AsyncOptionsProps, useAsyncOptionsProps } from "./hooks/useAsyncOptionsProps";
export { useStoredState } from "./hooks/useStoredState";
Expand Down

0 comments on commit 1c6694d

Please sign in to comment.