mirror of
https://github.com/detleph/components.git
synced 2026-09-04 08:36:03 +02:00
Add support for "outside elements" (Popups, Drawers, ...)
+ Add Drawer + Add new root in the HTML (should be included in production)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<div id="detleph-fg-context"></div>
|
||||
@@ -1,3 +1,22 @@
|
||||
<script>
|
||||
window.global = window;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#detleph-fg-context {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#detleph-fg-context:empty {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
|
||||
import { ComponentStory, ComponentMeta } from "@storybook/react";
|
||||
|
||||
import Drawer from "../util/Drawer";
|
||||
|
||||
export default { title: "Drawer", component: Drawer } as ComponentMeta<typeof Drawer>;
|
||||
|
||||
const Template: ComponentStory<typeof Drawer> = (args) => <Drawer {...args} />;
|
||||
|
||||
export const DefaultDrawer = Template.bind({});
|
||||
|
||||
DefaultDrawer.args = {
|
||||
children: "Test",
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
.drawer {
|
||||
background: white;
|
||||
border-top-left-radius: 30px;
|
||||
border-top-right-radius: 30px;
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
bottom: 0;
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
|
||||
import styles from "./Drawer.module.scss";
|
||||
import { OutsideElement } from "../OutsideElement/OutsideElement";
|
||||
|
||||
interface DrawerProps {
|
||||
open: boolean;
|
||||
children: React.ReactNode;
|
||||
onClose?: () => unknown;
|
||||
}
|
||||
|
||||
const Drawer: React.FC<DrawerProps> = ({ open, children, onClose }) => {
|
||||
return (
|
||||
<OutsideElement open={open} onClose={onClose}>
|
||||
<UIDrawer>{children}</UIDrawer>
|
||||
</OutsideElement>
|
||||
);
|
||||
};
|
||||
|
||||
const UIDrawer: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
return (
|
||||
<motion.div
|
||||
className={styles.drawer}
|
||||
initial={{ y: "100vh" }}
|
||||
animate={{ y: "0%" }}
|
||||
exit={{ y: "100vh" }}
|
||||
transition={{ type: "tween" }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Drawer;
|
||||
@@ -0,0 +1,3 @@
|
||||
import Drawer from "./Drawer";
|
||||
|
||||
export default Drawer;
|
||||
@@ -0,0 +1,9 @@
|
||||
.backdrop {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
position: absolute;
|
||||
background: #0000003f;
|
||||
|
||||
top: 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
|
||||
import styles from "./OutsideElement.module.scss";
|
||||
|
||||
interface OutsideElementProps {
|
||||
children: React.ReactNode;
|
||||
open: boolean;
|
||||
onClose?: () => unknown;
|
||||
}
|
||||
|
||||
export const OutsideElement: React.FC<OutsideElementProps> = ({ children, open, onClose }) => {
|
||||
return ReactDOM.createPortal(
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className={styles.backdrop}
|
||||
key="backdrop"
|
||||
onClick={() => onClose?.()}
|
||||
></motion.div>
|
||||
|
||||
{children}
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>,
|
||||
document.querySelector("#detleph-fg-context")!
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user