Files
outline/app/components/Guide.tsx
忽如寄 396836dedd refactor: ♻️ del children type (#3283)
* refactor: 🔧 del unnecessary children type

Change-Id: I3dea5e07f5401bdbdd168eb959fe361c57784167

* feat: 💄 eslint

Change-Id: Ie173adeca9e3112d8cdfc1f85964332105dcb424

* feat: 🔧 add css type

Change-Id: I8850c4d09b152f4d9c4d98e6eebca58bd9eecd37

* fix: 💄 ci lint

Change-Id: I69ff89c7a30e2bdcd26475ec83f3f5ec143121b6
2022-03-24 17:45:36 -07:00

115 lines
2.4 KiB
TypeScript

import { observer } from "mobx-react";
import * as React from "react";
import { Dialog, DialogBackdrop, useDialogState } from "reakit/Dialog";
import styled from "styled-components";
import Scrollable from "~/components/Scrollable";
import usePrevious from "~/hooks/usePrevious";
type Props = {
isOpen: boolean;
title?: string;
onRequestClose: () => void;
};
const Guide: React.FC<Props> = ({
children,
isOpen,
title = "Untitled",
onRequestClose,
...rest
}) => {
const dialog = useDialogState({
animated: 250,
});
const wasOpen = usePrevious(isOpen);
React.useEffect(() => {
if (!wasOpen && isOpen) {
dialog.show();
}
if (wasOpen && !isOpen) {
dialog.hide();
}
}, [dialog, wasOpen, isOpen]);
return (
<DialogBackdrop {...dialog}>
{(props) => (
<Backdrop {...props}>
<Dialog
{...dialog}
aria-label={title}
preventBodyScroll
hideOnEsc
hide={onRequestClose}
>
{(props) => (
<Scene {...props} {...rest}>
<Content>
{title && <Header>{title}</Header>}
{children}
</Content>
</Scene>
)}
</Dialog>
</Backdrop>
)}
</DialogBackdrop>
);
};
const Header = styled.h1`
font-size: 18px;
margin-top: 0;
margin-bottom: 1em;
`;
const Backdrop = styled.div`
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: ${(props) => props.theme.backdrop} !important;
z-index: ${(props) => props.theme.depths.modalOverlay};
transition: opacity 200ms ease-in-out;
opacity: 0;
&[data-enter] {
opacity: 1;
}
`;
const Scene = styled.div`
position: absolute;
top: 0;
right: 0;
bottom: 0;
margin: 12px;
z-index: ${(props) => props.theme.depths.modal};
display: flex;
justify-content: center;
align-items: flex-start;
width: 350px;
background: ${(props) => props.theme.background};
transition: ${(props) => props.theme.backgroundTransition};
border-radius: 8px;
outline: none;
opacity: 0;
transform: translateX(16px);
transition: transform 250ms ease, opacity 250ms ease;
&[data-enter] {
opacity: 1;
transform: translateX(0px);
}
`;
const Content = styled(Scrollable)`
width: 100%;
padding: 16px;
`;
export default observer(Guide);