Skip to content

Commit

Permalink
New modal (#2493)
Browse files Browse the repository at this point in the history
* Some love for the modals

* Polish

* Bumping Sparkle version

* Cleaning config

* Cleaning config

---------

Co-authored-by: édouard wautier <[email protected]>
  • Loading branch information
Duncid and édouard wautier authored Nov 13, 2023
1 parent bdf352a commit 57546af
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 157 deletions.
9 changes: 9 additions & 0 deletions front/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ module.exports = {
objektiv: ["'objektiv-mk1'", "sans-serif"],
},
extend: {
scale: {
99: ".99",
},
dropShadow: {
md: "0 4px 3px rgba(0, 0, 0, 0.25)",
lg: "0 10px 15px rgba(0, 0, 0, 0.16)",
xl: "0 20px 25px rgba(0, 0, 0, 0.14)",
"2xl": "0 25px 50px rgba(0, 0, 0, 0.12)",
},
zIndex: {
60: "60",
},
Expand Down
4 changes: 2 additions & 2 deletions sparkle/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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.2.36",
"version": "0.2.37",
"scripts": {
"build": "rm -rf dist && rollup -c",
"build:with-tw-base": "rollup -c --environment INCLUDE_TW_BASE:true",
Expand Down
186 changes: 80 additions & 106 deletions sparkle/src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,64 @@
import { Dialog, Transition } from "@headlessui/react";
import React, { Fragment } from "react";

import { assertNever, classNames } from "@sparkle/lib/utils";
import { classNames } from "@sparkle/lib/utils";

import { BarHeader, BarHeaderButtonBarProps } from "./BarHeader";
import { Button, ButtonProps } from "./Button";

const RIGHT_SIDE_MODAL_WIDTH = {
normal: "sm:s-w-[448px]",
wide: "sm:s-w-[50rem]",
"ultra-wide": "sm:s-w-[80rem]",
} as const;
export enum ModalType {
Dialogue = "dialogue",
FullScreen = "full-screen",
Side = "side",
}

const variantToType = {
"full-screen": ModalType.FullScreen,
"side-md": ModalType.Side,
dialogue: ModalType.Dialogue,
"side-sm": ModalType.Side,
};
const variantSize = {
"full-screen": "",
"side-md": "sm:s-w-[50rem]",
dialogue: "",
"side-sm": "sm:s-w-[448px]",
};

const modalStyles = {
[ModalType.Side]: {
containerClasses: "s-flex s-h-full s-p-0 s-justify-end sm:s-p-2",
panelClasses:
"s-m-0 s-h-full s-max-h-full s-w-full s-max-w-full s-r-0 sm:s-rounded-xl s-drop-shadow-xl s-border s-border-structure-100",
transitionEnterFrom: "s-opacity-0 -s-translate-x-20 s-scale-99",
transitionEnterTo: "s-opacity-100 s-translate-x-0 s-scale-100",
transitionLeaveFrom: "s-opacity-100 s-translate-x-0 s-scale-100",
transitionLeaveTo: "s-opacity-0 s-translate-x-20 s-scale-99",
innerContainerClasses: "s-h-full s-overflow-y-auto",
},
[ModalType.FullScreen]: {
containerClasses:
"s-flex s-items-center s-justify-center s-h-full s-p-0 s-drop-shadow-xl",
panelClasses: "s-m-0 s-h-full s-max-h-full s-w-full s-max-w-full s-r-0",
transitionEnterFrom: "s-opacity-0 s-translate-y-4 s-scale-95 s-rounded-xl",
transitionEnterTo: "s-opacity-100 s-translate-y-0 s-scale-100 s-rounded-0",
transitionLeaveFrom:
"s-opacity-100 s-translate-y-0 s-scale-100 s-rounded-0",
transitionLeaveTo: "s-opacity-0 s-translate-y-4 s-scale-95 s-rounded-xl",
innerContainerClasses: "s-h-full s-overflow-y-auto",
},
[ModalType.Dialogue]: {
containerClasses:
"s-flex s-items-center s-justify-center s-min-h-full s-p-4",
panelClasses:
"s-w-full sm:s-w-[448px] overflow-hidden s-drop-shadow-2xl s-rounded-xl s-border s-border-structure-100",
transitionEnterFrom: "s-opacity-0 s-translate-y-4 s-scale-95",
transitionEnterTo: "s-opacity-100 s-translate-y-0 s-scale-100",
transitionLeaveFrom: "s-opacity-100 s-translate-y-0 s-scale-100",
transitionLeaveTo: "s-opacity-0 s-translate-y-4 s-scale-95",
innerContainerClasses: "",
},
};

type ModalProps = {
isOpen: boolean;
Expand All @@ -23,15 +71,10 @@ type ModalProps = {
isSaving?: boolean;
savingLabel?: string;
title?: string;
} & (
| {
type: "right-side";
width?: keyof typeof RIGHT_SIDE_MODAL_WIDTH;
}
| {
type: "full-screen" | "default";
}
);
variant?: "full-screen" | "side-sm" | "side-md" | "dialogue";
};

const getModalClasses = (type: ModalType) => modalStyles[type] || {};

export function Modal({
isOpen,
Expand All @@ -44,8 +87,9 @@ export function Modal({
isSaving,
savingLabel,
title,
...props
variant = "side-sm",
}: ModalProps) {
const type = variantToType[variant];
const buttonBarProps: BarHeaderButtonBarProps = hasChanged
? {
variant: "validate",
Expand All @@ -60,117 +104,47 @@ export function Modal({
onClose: onClose,
};

const justifyClass = (() => {
switch (props.type) {
case "right-side":
return "s-justify-end";

case "full-screen":
case "default":
return "s-justify-center";

default:
throw assertNever(props);
}
})();

const outerContainerClasses = (() => {
switch (props.type) {
case "right-side":
case "full-screen":
return "s-h-full s-p-0";

case "default":
return "s-min-h-full s-p-4";

default:
throw assertNever(props);
}
})();

const transitionEnterLeaveClasses = (() => {
switch (props.type) {
case "right-side":
return "s-translate-x-full";

case "full-screen":
case "default":
return "s-translate-y-4 sm:s-translate-y-0 sm:s-scale-95";

default:
throw assertNever(props);
}
})();

const panelClasses = (() => {
switch (props.type) {
case "right-side":
return classNames(
"s-m-0 s-h-full s-max-h-full s-w-full s-max-w-full",
RIGHT_SIDE_MODAL_WIDTH[props.width || "normal"]
);

case "full-screen":
return "s-m-0 s-h-full s-max-h-full s-w-full s-max-w-full";

case "default":
return "s-max-w-2xl s-rounded-lg s-shadow-xl lg:s-w-1/2";

default:
throw assertNever(props);
}
})();

const innerContainerClasses = (() => {
switch (props.type) {
case "right-side":
case "full-screen":
return "s-h-full s-overflow-y-auto";

case "default":
return "";

default:
throw assertNever(props);
}
})();
const {
containerClasses,
transitionEnterFrom,
transitionLeaveFrom,
transitionEnterTo,
transitionLeaveTo,
panelClasses,
innerContainerClasses,
} = getModalClasses(type);

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"
enter="s-ease-out s-duration-150"
enterFrom="s-opacity-0"
enterTo="s-opacity-100"
leave="s-ease-in s-duration-200"
leave="s-ease-in s-duration-150"
leaveFrom="s-opacity-100"
leaveTo="s-opacity-0"
>
<div className="s-fixed s-inset-0 s-bg-slate-800/70 s-transition-opacity" />
<div className="s-fixed s-inset-0 s-bg-white/80 s-backdrop-blur-sm s-transition-opacity" />
</Transition.Child>

<div className="s-fixed s-inset-0 s-z-50 s-overflow-y-auto">
<div
className={classNames(
"s-flex s-items-center",
justifyClass,
outerContainerClasses
)}
>
<div className={containerClasses}>
<Transition.Child
as={Fragment}
enter="s-ease-out s-duration-300"
enterFrom={classNames("s-opacity-0", transitionEnterLeaveClasses)}
enterTo="s-opacity-100 s-translate-y-0 sm:s-scale-100"
enterFrom={transitionEnterFrom}
enterTo={transitionEnterTo}
leave="s-ease-in s-duration-200"
leaveFrom="s-opacity-100 s-translate-y-0 sm:s-scale-100"
leaveTo={classNames("s-opacity-0", transitionEnterLeaveClasses)}
leaveFrom={transitionLeaveFrom}
leaveTo={transitionLeaveTo}
>
<Dialog.Panel
className={classNames(
"s-relative s-transform s-overflow-hidden s-bg-white s-px-3 s-transition-all sm:s-px-4",
panelClasses
"s-relative s-transform s-overflow-hidden s-bg-structure-0 s-px-3 s-transition-all sm:s-px-4",
panelClasses,
variantSize[variant]
)}
>
<BarHeader
Expand Down
Loading

0 comments on commit 57546af

Please sign in to comment.