-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
581 additions
and
129 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { GridCenter } from "../commonElement"; | ||
import { Text } from "../Typography/Text/Text"; | ||
import { Dialog } from "./Dialog"; | ||
import Separator from "../Separator/Separator"; | ||
import { Spacer } from "../Spacer/Spacer"; | ||
import { Button } from "../Button/Button"; | ||
import styled from "styled-components"; | ||
import { Link } from "../Link/Link"; | ||
|
||
const DialogComponent = ({ | ||
open, | ||
title, | ||
modal, | ||
showClose, | ||
forceMount, | ||
}: { | ||
open?: boolean; | ||
title: string; | ||
modal: boolean; | ||
showClose: boolean; | ||
forceMount?: boolean; | ||
}) => ( | ||
<GridCenter> | ||
<Dialog | ||
open={open} | ||
modal={modal} | ||
> | ||
<Dialog.Trigger> | ||
<Link>Open dialog</Link> | ||
</Dialog.Trigger> | ||
<Dialog.Content | ||
title={title} | ||
showClose={showClose} | ||
forceMount={forceMount ? true : undefined} | ||
> | ||
<Text color="muted"> | ||
Hello there, I'm a wonderful example of a modal dialog. You can close me by | ||
using the button in my top, left corner. | ||
</Text> | ||
<Spacer /> | ||
<Separator size="lg" /> | ||
<ActionArea> | ||
<Dialog.Close label="Close" /> | ||
<Button iconRight="arrow-right">Continue</Button> | ||
</ActionArea> | ||
</Dialog.Content> | ||
</Dialog> | ||
</GridCenter> | ||
); | ||
|
||
const ActionArea = styled.div` | ||
display: flex; | ||
justify-content: flex-end; | ||
gap: ${({ theme }) => theme.click.dialog.space.gap}; | ||
`; | ||
export default { | ||
component: DialogComponent, | ||
title: "Display/Dialog", | ||
tags: ["autodocs", "dialog"], | ||
argTypes: { | ||
open: { | ||
options: [true, false, undefined], | ||
control: { type: "radio" }, | ||
}, | ||
}, | ||
}; | ||
|
||
export const Playground = { | ||
args: { | ||
title: "Example dialog title", | ||
showClose: true, | ||
open: true, | ||
onOpenChange: () => { | ||
console.log("ignored"); | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { screen } from "@testing-library/react"; | ||
import { DialogProps } from "@radix-ui/react-dialog"; | ||
import { Dialog } from "./Dialog"; | ||
import { fireEvent } from "@testing-library/react"; | ||
import { renderCUI } from "@/utils/test-utils"; | ||
|
||
describe("Dialog Component", () => { | ||
const renderDialog = (props: DialogProps) => | ||
renderCUI( | ||
<Dialog {...props}> | ||
<Dialog.Trigger> | ||
<div>Open Dialog</div> | ||
</Dialog.Trigger> | ||
<Dialog.Close label="Close" /> | ||
<Dialog.Content title="Test Dialog">Test Content</Dialog.Content> | ||
</Dialog> | ||
); | ||
|
||
it("renders the dialog content with title", () => { | ||
const { getByText } = renderDialog({}); | ||
const dialogTrigger = getByText("Open Dialog"); | ||
expect(dialogTrigger).not.toBeNull(); | ||
fireEvent.click(dialogTrigger); | ||
|
||
const dialogTitle = screen.getByText("Test Dialog"); | ||
const dialogContent = screen.getByText("Test Content"); | ||
|
||
expect(dialogTitle).toBeTruthy(); | ||
expect(dialogContent).toBeTruthy(); | ||
}); | ||
|
||
it("closes the dialog when close button is clicked", () => { | ||
const { getByText } = renderDialog({}); | ||
const dialogTrigger = getByText("Open Dialog"); | ||
expect(dialogTrigger).not.toBeNull(); | ||
fireEvent.click(dialogTrigger); | ||
|
||
const DialogClose = screen.getByText("Close"); | ||
fireEvent.click(DialogClose); | ||
|
||
const dialogTitle = screen.queryByText("Test Dialog"); | ||
const dialogContent = screen.queryByText("Test Content"); | ||
|
||
expect(dialogTitle).toBeFalsy(); | ||
expect(dialogContent).toBeFalsy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import React, { ReactNode } from "react"; | ||
import * as RadixDialog from "@radix-ui/react-dialog"; | ||
import styled, { keyframes } from "styled-components"; | ||
import { Button, Icon, Spacer, Title } from "@/components"; | ||
import { EmptyButton } from "../commonElement"; | ||
|
||
export const Dialog = ({ children, ...props }: RadixDialog.DialogProps) => { | ||
return <RadixDialog.Root {...props}>{children}</RadixDialog.Root>; | ||
}; | ||
|
||
// Dialog Trigger | ||
const Trigger = styled(RadixDialog.Trigger)` | ||
width: fit-content; | ||
background: transparent; | ||
border: none; | ||
cursor: pointer; | ||
`; | ||
|
||
interface DialogTriggerProps extends RadixDialog.DialogTriggerProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
const DialogTrigger = ({ children, ...props }: DialogTriggerProps) => { | ||
return <Trigger {...props}>{children}</Trigger>; | ||
}; | ||
|
||
DialogTrigger.displayName = "DialogTrigger"; | ||
Dialog.Trigger = DialogTrigger; | ||
|
||
// Dialog Close | ||
interface DialogCloseProps extends RadixDialog.DialogCloseProps { | ||
label: string; | ||
} | ||
|
||
const DialogClose = ({ label }: DialogCloseProps) => { | ||
label = label ?? "Close"; | ||
return ( | ||
<RadixDialog.Close asChild> | ||
<Button type="secondary">{label}</Button> | ||
</RadixDialog.Close> | ||
); | ||
}; | ||
|
||
DialogClose.displayName = "DialogClose"; | ||
Dialog.Close = DialogClose; | ||
|
||
// Dialog Content | ||
const overlayShow = keyframes({ | ||
"0%": { opacity: 0 }, | ||
"100%": { opacity: 1 }, | ||
}); | ||
|
||
const contentShow = keyframes({ | ||
"0%": { opacity: 0, transform: "translate(-50%, -48%) scale(.96)" }, | ||
"100%": { opacity: 1, transform: "translate(-50%, -50%) scale(1)" }, | ||
}); | ||
|
||
const DialogOverlay = styled(RadixDialog.Overlay)` | ||
background-color: ${({ theme }) => theme.click.dialog.color.opaqueBackground.default}; | ||
position: fixed; | ||
inset: 0; | ||
animation: ${overlayShow} 150ms cubic-bezier(0.16, 1, 0.3, 1); | ||
`; | ||
|
||
const ContentArea = styled(RadixDialog.Content)` | ||
background: ${({ theme }) => theme.click.dialog.color.background.default}; | ||
border-radius: ${({ theme }) => theme.click.dialog.radii.all}; | ||
padding: ${({ theme }) => theme.click.dialog.space.y} | ||
${({ theme }) => theme.click.dialog.space.x}; | ||
box-shadow: ${({ theme }) => theme.click.dialog.shadow.default}; | ||
border: 1px solid ${({ theme }) => theme.click.global.color.stroke.default}; | ||
width: 75%; | ||
max-width: 670px; | ||
position: fixed; | ||
top: 25%; | ||
margin-top: 20%; | ||
left: 50%; | ||
max-height: 75%; | ||
overflow: auto; | ||
transform: translate(-50%, -50%); | ||
animation: ${contentShow} 150ms cubic-bezier(0.16, 1, 0.3, 1); | ||
outline: none; | ||
`; | ||
|
||
const TitleArea = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
min-height: ${({ theme }) => theme.sizes[9]}; // 32px | ||
`; | ||
|
||
const CrossButton = styled(EmptyButton)` | ||
padding: ${({ theme }) => theme.click.button.iconButton.sm.space.y} | ||
${({ theme }) => theme.click.button.iconButton.sm.space.x}; | ||
background: ${({ theme }) => | ||
theme.click.button.iconButton.color.primary.background.default}; | ||
border-radius: ${({ theme }) => theme.click.button.iconButton.radii.all}; | ||
&:hover { | ||
background: ${({ theme }) => | ||
theme.click.button.iconButton.color.primary.background.hover}; | ||
} | ||
`; | ||
|
||
const CloseButton = ({ onClose }: { onClose?: () => void }) => ( | ||
<RadixDialog.Close asChild> | ||
<CrossButton onClick={onClose}> | ||
<Icon | ||
name="cross" | ||
size="lg" | ||
/> | ||
</CrossButton> | ||
</RadixDialog.Close> | ||
); | ||
|
||
interface DialogContentProps extends RadixDialog.DialogContentProps { | ||
title: string; | ||
showClose?: boolean; | ||
forceMount?: true; | ||
container?: HTMLElement | null; | ||
children: ReactNode; | ||
onClose?: () => void; | ||
} | ||
|
||
const DialogContent = ({ | ||
title, | ||
children, | ||
showClose, | ||
onClose, | ||
forceMount, | ||
container, | ||
}: DialogContentProps) => { | ||
return ( | ||
<RadixDialog.Portal | ||
forceMount={forceMount} | ||
container={container} | ||
> | ||
<DialogOverlay /> | ||
<ContentArea> | ||
<TitleArea> | ||
<Title | ||
size="xl" | ||
type="h2" | ||
> | ||
{title} | ||
</Title> | ||
{showClose && <CloseButton onClose={onClose} />} | ||
</TitleArea> | ||
<Spacer /> | ||
{children} | ||
</ContentArea> | ||
</RadixDialog.Portal> | ||
); | ||
}; | ||
|
||
DialogContent.displayName = "DialogContent"; | ||
Dialog.Content = DialogContent; |
Oops, something went wrong.