Skip to content
This repository was archived by the owner on Jan 20, 2022. It is now read-only.

Commit

Permalink
Add support for custom as components in modals (#306)
Browse files Browse the repository at this point in the history
* add support for custom as components in modals

* use the right type

* lint
  • Loading branch information
Jephuff authored Jan 29, 2021
1 parent 35ab672 commit 89f69f9
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
42 changes: 42 additions & 0 deletions src/Modal/Modal.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@ interface Props {
size: "small" | "medium" | "large";
}

const CustomComponent = React.forwardRef<HTMLDivElement, { an?: undefined }>(
(props, ref) => (
<div
{...props}
ref={ref}
css={css`
background: repeating-linear-gradient(
135deg,
${colors.white},
${colors.white} 10px,
rgb(255, 253, 253) 10px,
rgb(255, 253, 253) 20px
);
width: 80vw;
`}
/>
),
);

export function ModalStory({
title,
description,
Expand Down Expand Up @@ -103,6 +122,29 @@ storiesOf("Modal", module)
Inner text
</Modal>
))
.add("using as with custom component", () => (
<Modal
as={<CustomComponent />}
size="large"
title="Example Title"
primaryAction={
<Button
color={colors.red.base}
style={{ color: colors.white }}
type="button"
>
Accept
</Button>
}
secondaryAction={
<Button color={colors.white} type="button">
Cancel
</Button>
}
>
Inner text
</Modal>
))
.add(
"static (small) (✅ primaryAction, ✅ secondaryAction, ✅ bottomLeftText)",
() => (
Expand Down
11 changes: 8 additions & 3 deletions src/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,19 @@ export const Modal: React.FC<Props> = ({
return () => document.removeEventListener("keydown", handleKeyDown);
}, [onClose]);

const type: keyof typeof motion =
const type: keyof typeof motion | React.ComponentType =
as.props.__EMOTION_TYPE_PLEASE_DO_NOT_USE__ || as.type;
if (!type || type === "custom") {
// TypeScript will give us some protection here, but we need to guarantee
// that `as` is an element that `motion` supports
throw new TypeError(
"`as` must be an element with a corresponding element in `Framer.motion`",
);
} else if (!motion[type] && !React.isValidElement(as)) {
} else if (
typeof type === "string" &&
!motion[type] &&
!React.isValidElement(as)
) {
throw new TypeError(
"Could not determine the type of `as` to clone that element using Framer. This is most likely because it's a ref forwarding component and we don't have any way of determining what type it will render to.",
);
Expand All @@ -176,7 +180,8 @@ export const Modal: React.FC<Props> = ({
* We have to strip the type because we'll get an error about the union being
* too complex to model because `motion` has over 100 options.
*/
const MotionComponent: React.ComponentType<MotionProps> = motion[type];
const MotionComponent: React.ComponentType<MotionProps> =
typeof type === "string" ? motion[type] : motion.custom<MotionProps>(type);

return (
<ClassNames>
Expand Down

0 comments on commit 89f69f9

Please sign in to comment.