mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
Migrate Guide.tsx from Reakit to Radix Dialog (#9752)
* Migrate Guide.tsx from Reakit to Radix Dialog - Replace Reakit Dialog imports with @radix-ui/react-dialog - Update component structure to use Dialog.Root, Dialog.Portal, Dialog.Overlay, and Dialog.Content - Remove useDialogState hook in favor of direct open/onOpenChange props - Preserve identical styling and animations using data-state attributes - Maintain slide-in animation from right side with 250ms transition - Keep all existing props and behavior intact * stash * fix animations --------- Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com> Co-authored-by: Tom Moor <tom@getoutline.com>
This commit is contained in:
+42
-59
@@ -1,9 +1,14 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Dialog, DialogBackdrop, useDialogState } from "reakit/Dialog";
|
import * as Dialog from "@radix-ui/react-dialog";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { depths, s } from "@shared/styles";
|
import { depths, s } from "@shared/styles";
|
||||||
import Scrollable from "~/components/Scrollable";
|
import Scrollable from "~/components/Scrollable";
|
||||||
import usePrevious from "~/hooks/usePrevious";
|
import {
|
||||||
|
fadeIn,
|
||||||
|
fadeOut,
|
||||||
|
fadeInAndSlideLeft,
|
||||||
|
fadeOutAndSlideRight,
|
||||||
|
} from "~/styles/animations";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@@ -18,55 +23,33 @@ const Guide: React.FC<Props> = ({
|
|||||||
title = "Untitled",
|
title = "Untitled",
|
||||||
onRequestClose,
|
onRequestClose,
|
||||||
...rest
|
...rest
|
||||||
}: Props) => {
|
}: Props) => (
|
||||||
const dialog = useDialogState({
|
<Dialog.Root open={isOpen} onOpenChange={(open) => !open && onRequestClose()}>
|
||||||
animated: 250,
|
<Dialog.Portal>
|
||||||
});
|
<StyledOverlay>
|
||||||
const wasOpen = usePrevious(isOpen);
|
<Scene
|
||||||
|
onEscapeKeyDown={onRequestClose}
|
||||||
|
onPointerDownOutside={onRequestClose}
|
||||||
|
aria-describedby={undefined}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
<Content>
|
||||||
|
{title && <Header>{title}</Header>}
|
||||||
|
{children}
|
||||||
|
</Content>
|
||||||
|
</Scene>
|
||||||
|
</StyledOverlay>
|
||||||
|
</Dialog.Portal>
|
||||||
|
</Dialog.Root>
|
||||||
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
const Header = styled(Dialog.Title)`
|
||||||
if (!wasOpen && isOpen) {
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wasOpen && !isOpen) {
|
|
||||||
dialog.hide();
|
|
||||||
}
|
|
||||||
}, [dialog, wasOpen, isOpen]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DialogBackdrop {...dialog}>
|
|
||||||
{(backdropProps) => (
|
|
||||||
<Backdrop {...backdropProps}>
|
|
||||||
<Dialog
|
|
||||||
{...dialog}
|
|
||||||
aria-label={title}
|
|
||||||
preventBodyScroll
|
|
||||||
hideOnEsc
|
|
||||||
hide={onRequestClose}
|
|
||||||
>
|
|
||||||
{(dialogProps) => (
|
|
||||||
<Scene {...dialogProps} {...rest}>
|
|
||||||
<Content>
|
|
||||||
{title && <Header>{title}</Header>}
|
|
||||||
{children}
|
|
||||||
</Content>
|
|
||||||
</Scene>
|
|
||||||
)}
|
|
||||||
</Dialog>
|
|
||||||
</Backdrop>
|
|
||||||
)}
|
|
||||||
</DialogBackdrop>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Header = styled.h1`
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Backdrop = styled.div`
|
const StyledOverlay = styled(Dialog.Overlay)`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -74,37 +57,37 @@ const Backdrop = styled.div`
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: ${s("backdrop")} !important;
|
background-color: ${s("backdrop")} !important;
|
||||||
z-index: ${depths.overlay};
|
z-index: ${depths.overlay};
|
||||||
transition: opacity 200ms ease-in-out;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
&[data-enter] {
|
&[data-state="open"] {
|
||||||
opacity: 1;
|
animation: ${fadeIn} 200ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-state="closed"] {
|
||||||
|
animation: ${fadeOut} 200ms ease;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Scene = styled.div`
|
const Scene = styled(Dialog.Content)`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
z-index: ${depths.modal};
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
z-index: ${depths.modal};
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
width: 350px;
|
width: 350px;
|
||||||
background: ${s("background")};
|
background: ${s("background")};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
outline: none;
|
outline: none;
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(16px);
|
|
||||||
transition:
|
|
||||||
transform 250ms ease,
|
|
||||||
opacity 250ms ease;
|
|
||||||
|
|
||||||
&[data-enter] {
|
&[data-state="open"] {
|
||||||
opacity: 1;
|
animation: ${fadeInAndSlideLeft} 200ms ease;
|
||||||
transform: translateX(0px);
|
}
|
||||||
|
|
||||||
|
&[data-state="closed"] {
|
||||||
|
animation: ${fadeOutAndSlideRight} 200ms ease;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export const fadeIn = keyframes`
|
|||||||
to { opacity: 1; }
|
to { opacity: 1; }
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const fadeOut = keyframes`
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
`;
|
||||||
|
|
||||||
export const fadeOutCursor = keyframes`
|
export const fadeOutCursor = keyframes`
|
||||||
0% { opacity: 1; }
|
0% { opacity: 1; }
|
||||||
90% { opacity: 1; }
|
90% { opacity: 1; }
|
||||||
@@ -47,6 +52,30 @@ export const fadeAndSlideUp = keyframes`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const fadeInAndSlideLeft = keyframes`
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0px);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const fadeOutAndSlideRight = keyframes`
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(10px);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const mobileContextMenu = keyframes`
|
export const mobileContextMenu = keyframes`
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user