Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add modal dialog to Storybook #5496

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions src/app/components/client/stories/ModalDialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import type { Meta, StoryObj } from "@storybook/react";

import { useOverlayTriggerState } from "react-stately";
import { useOverlayTrigger } from "react-aria";
import Image from "next/image";
import Illustration from "../assets/modal-default-img.svg";
import { ModalOverlay } from "../dialog/ModalOverlay";
import { Dialog } from "../dialog/Dialog";
import { Button } from "../Button";

export type ModalDialogProps = {
withDialog?: boolean;
withTitle?: boolean;
withIllustration?: boolean;
};

const ModalDialog = (props: ModalDialogProps) => {
const modalState = useOverlayTriggerState({ defaultOpen: true });
const modalTrigger = useOverlayTrigger({ type: "dialog" }, modalState);
return (
<>
<Button {...modalTrigger.triggerProps} variant="primary">
Open modal {props.withDialog && " dialog"}
</Button>
{modalState.isOpen && (
<ModalOverlay
state={modalState}
{...modalTrigger.overlayProps}
isDismissable={true}
>
{props.withDialog ? (
<Dialog
title={props.withTitle ? "Here's a dialog for you" : undefined}
illustration={
props.withIllustration ? (
<Image src={Illustration} alt="" />
) : undefined
}
onDismiss={() => modalState.close()}
>
<p>Some dialog content.</p>
</Dialog>
) : (
<>
<p>
This is modal content; note that it&apos;s not possible to
interact with the content behind the modal overlay. Here&apos;s
a button to close the modal: &nbsp;
</p>
<Button variant="primary" onPress={() => modalState.close()}>
Close modal
</Button>
</>
)}
</ModalOverlay>
)}
</>
);
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious why we have a modal without dialog variant here, I don't think we're using this in the app?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not, but I wanted to make sure people understood what you get if you use just the modal overlay, to clarify what the dialog is and what the modal is.

Copy link
Collaborator

@codemist codemist Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. Could we add a comment somewhere that this isn't being used in the app, since it is a UI library we wouldn't want to give off the assumption that it's an intentional FE component.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good callout, I added 7a94a77 which calls it out right in the story, what do you think?

I'll see if I get another E2E failure, they seem to be flaky today - I wouldn't expect this PR to affect the appsAndSerices button 😅


// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
const meta: Meta<typeof ModalDialog> = {
title: "Design Systems/Molecules/Modal dialog",
component: ModalDialog,
argTypes: {
withDialog: {
control: "boolean",
name: "With dialog",
},
withTitle: {
control: "boolean",
name: "With title",
},
withIllustration: {
control: "boolean",
name: "With illustration",
},
},
};
export default meta;
type Story = StoryObj<typeof ModalDialog>;

export const Modal: Story = {
name: "Modal without a dialog",
args: {},
};

export const ModalWithDialog: Story = {
name: "Modal dialog",
args: {
withDialog: true,
},
};

export const ModalDialogWithTitle: Story = {
name: "With title",
args: {
withDialog: true,
withTitle: true,
},
};

export const ModalDialogWithIllustration: Story = {
name: "With title and illustration",
args: {
withDialog: true,
withTitle: true,
withIllustration: true,
},
};
Loading