first commit

This commit is contained in:
Hydra
2024-04-18 08:46:06 +01:00
commit f1bdec484e
165 changed files with 20993 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
import { keyframes, style } from "@vanilla-extract/css";
import { recipe } from "@vanilla-extract/recipes";
import { SPACING_UNIT, vars } from "../../theme.css";
export const backdropFadeIn = keyframes({
"0%": { backdropFilter: "blur(0px)", backgroundColor: "rgba(0, 0, 0, 0.5)" },
"100%": {
backdropFilter: "blur(2px)",
backgroundColor: "rgba(0, 0, 0, 0.7)",
},
});
export const backdropFadeOut = keyframes({
"0%": { backdropFilter: "blur(2px)", backgroundColor: "rgba(0, 0, 0, 0.7)" },
"100%": {
backdropFilter: "blur(0px)",
backgroundColor: "rgba(0, 0, 0, 0)",
},
});
export const modalSlideIn = keyframes({
"0%": { opacity: 0 },
"100%": {
opacity: 1,
},
});
export const modalSlideOut = keyframes({
"0%": { opacity: 1 },
"100%": {
opacity: 0,
},
});
export const backdrop = recipe({
base: {
animationName: backdropFadeIn,
animationDuration: "0.4s",
backgroundColor: "rgba(0, 0, 0, 0.7)",
position: "absolute",
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
zIndex: 1,
top: 0,
padding: `${SPACING_UNIT * 3}px`,
backdropFilter: "blur(2px)",
transition: "all ease 0.2s",
},
variants: {
closing: {
true: {
animationName: backdropFadeOut,
backdropFilter: "blur(0px)",
backgroundColor: "rgba(0, 0, 0, 0)",
},
},
},
});
export const modal = recipe({
base: {
animationName: modalSlideIn,
animationDuration: "0.3s",
backgroundColor: vars.color.background,
borderRadius: "5px",
maxWidth: "600px",
color: vars.color.bodyText,
maxHeight: "100%",
border: `solid 1px ${vars.color.borderColor}`,
overflow: "hidden",
display: "flex",
flexDirection: "column",
},
variants: {
closing: {
true: {
animationName: modalSlideOut,
opacity: 0,
},
},
},
});
export const modalContent = style({
height: "100%",
overflow: "auto",
padding: `${SPACING_UNIT * 3}px ${SPACING_UNIT * 2}px`,
});
export const modalHeader = style({
display: "flex",
gap: `${SPACING_UNIT}px`,
padding: `${SPACING_UNIT * 2}px`,
borderBottom: `solid 1px ${vars.color.borderColor}`,
justifyContent: "space-between",
alignItems: "flex-start",
});
export const closeModalButton = style({
cursor: "pointer",
});
export const closeModalButtonIcon = style({
color: vars.color.bodyText,
});

View File

@@ -0,0 +1,69 @@
import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { XIcon } from "@primer/octicons-react";
import * as styles from "./modal.css";
import { useAppDispatch } from "@renderer/hooks";
import { toggleDragging } from "@renderer/features";
export interface ModalProps {
visible: boolean;
title: string;
description: string;
onClose: () => void;
children: React.ReactNode;
}
export function Modal({
visible,
title,
description,
onClose,
children,
}: ModalProps) {
const [isClosing, setIsClosing] = useState(false);
const dispatch = useAppDispatch();
const handleCloseClick = () => {
setIsClosing(true);
const zero = performance.now();
requestAnimationFrame(function animateClosing(time) {
if (time - zero <= 400) {
requestAnimationFrame(animateClosing);
} else {
onClose();
setIsClosing(false);
}
});
};
useEffect(() => {
dispatch(toggleDragging(visible));
}, [dispatch, visible]);
if (!visible) return null;
return createPortal(
<div className={styles.backdrop({ closing: isClosing })}>
<div className={styles.modal({ closing: isClosing })}>
<div className={styles.modalHeader}>
<div style={{ display: "flex", gap: 4, flexDirection: "column" }}>
<h3>{title}</h3>
<p style={{ fontSize: 14 }}>{description}</p>
</div>
<button
type="button"
onClick={handleCloseClick}
className={styles.closeModalButton}
>
<XIcon className={styles.closeModalButtonIcon} size={24} />
</button>
</div>
<div className={styles.modalContent}>{children}</div>
</div>
</div>,
document.body
);
}