Skip to content

Commit

Permalink
feat(sparkle): add Modal component
Browse files Browse the repository at this point in the history
  • Loading branch information
fontanierh committed Sep 8, 2023
1 parent bbb3f97 commit 783e81f
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 1 deletion.
2 changes: 1 addition & 1 deletion sparkle/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dust-tt/sparkle",
"version": "0.1.47",
"version": "0.1.48",
"scripts": {
"build": "rm -rf dist && rollup -c",
"build:with-tw-base": "rollup -c --environment INCLUDE_TW_BASE:true",
Expand Down
3 changes: 3 additions & 0 deletions sparkle/src/_index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export { Avatar };
import Spinner from "./components/Spinner";
export { Spinner };

import { Modal } from "./components/Modal";
export { Modal };

import {
LogoHorizontalColor as LogoHorizontalColorLogo,
LogoHorizontalDark as LogoHorizontalDarkLogo,
Expand Down
87 changes: 87 additions & 0 deletions sparkle/src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Dialog, Transition } from "@headlessui/react";
import React, { Fragment } from "react";

import { XCircleIcon } from "..";
import { Button, ButtonProps } from "./Button";

interface ModalProps {
isOpen: boolean;
onClose: () => void;
action?: ButtonProps;
children: React.ReactNode;
hasChanged: boolean;
onSave?: () => void;
}

export function Modal({
isOpen,
onClose,
action,
children,
hasChanged,
onSave,
}: ModalProps) {
return (
<Transition.Root show={isOpen} as={Fragment}>
<Dialog as="div" className="s-relative s-z-50" onClose={onClose}>
<Transition.Child
as={Fragment}
enter="s-ease-out s-duration-300"
enterFrom="s-opacity-0"
enterTo="s-opacity-100"
leave="s-ease-in s-duration-200"
leaveFrom="s-opacity-100"
leaveTo="s-opacity-0"
>
<div className="s-fixed s-inset-0 s-bg-gray-500 s-bg-opacity-75 s-transition-opacity" />
</Transition.Child>

<div className="s-h-5/5 s-fixed s-inset-0 s-z-50 s-overflow-y-auto">
<div className="s-flex s-min-h-full s-items-end s-justify-center s-p-4 s-text-center sm:s-items-center sm:s-p-0">
<Transition.Child
as={Fragment}
enter="s-ease-out s-duration-300"
enterFrom="s-opacity-0 s-translate-y-4 sm:s-translate-y-0 sm:s-scale-95"
enterTo="s-opacity-100 s-translate-y-0 sm:s-scale-100"
leave="s-ease-in s-duration-200"
leaveFrom="s-opacity-100 s-translate-y-0 sm:s-scale-100"
leaveTo="s-opacity-0 s-translate-y-4 sm:s-translate-y-0 sm:s-scale-95"
>
<Dialog.Panel className="s-relative s-max-w-2xl s-transform s-overflow-hidden s-rounded-lg s-bg-white s-px-4 s-pb-4 s-text-left s-shadow-xl s-transition-all sm:s-p-6 lg:s-w-1/2">
<div className="s-flex s-items-start s-justify-between sm:s-mt-0">
<div>{action && <Button {...action} />}</div>
{hasChanged ? (
<div className="s-flex s-justify-end s-gap-1">
<Button
labelVisible={true}
onClick={onClose}
label="Cancel"
variant="secondary"
size="xs"
/>
<Button
labelVisible={true}
onClick={onSave}
label="Save"
variant="primary"
size="xs"
/>
</div>
) : (
<div
onClick={onClose}
className="s-cursor-pointer s-self-center"
>
<XCircleIcon className="s-h-6 s-w-6 s-text-gray-500" />
</div>
)}
</div>
{children}
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}
55 changes: 55 additions & 0 deletions sparkle/src/stories/Modal.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { Meta } from "@storybook/react";
import React, { useState } from "react";

import {
Button,
ChatBubbleBottomCenterTextIcon,
Modal,
} from "../index_with_tw_base";

const meta = {
title: "Atoms/Modal",
component: Modal,
} satisfies Meta<typeof Modal>;

export default meta;

export const ModalExample = () => {
const [isOpenNoActionNoChange, setIsOpenNoActionNoChange] = useState(false);
const [isOpenWithActionAndChange, setIsOpenWithActionAndChange] =
useState(false);

return (
<>
<Modal
isOpen={isOpenNoActionNoChange}
onClose={() => setIsOpenNoActionNoChange(false)}
hasChanged={false}
>
<div className="s-mt-4 s-h-72 " />
</Modal>
<Modal
isOpen={isOpenWithActionAndChange}
onClose={() => setIsOpenWithActionAndChange(false)}
hasChanged={true}
action={{
icon: ChatBubbleBottomCenterTextIcon,
label: "Contact an agent",
labelVisible: true,
variant: "tertiary",
size: "xs",
}}
>
<div className="s-mt-4 s-h-72 " />
</Modal>
<Button
label="Modal without action and without changes"
onClick={() => setIsOpenNoActionNoChange(true)}
/>
<Button
label="Modal with action and changes"
onClick={() => setIsOpenWithActionAndChange(true)}
/>
</>
);
};

0 comments on commit 783e81f

Please sign in to comment.