Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 0 additions & 17 deletions packages/propel/src/dialog/constants.ts

This file was deleted.

159 changes: 100 additions & 59 deletions packages/propel/src/dialog/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,75 +3,116 @@
import * as React from "react";
import { Dialog as BaseDialog } from "@base-ui-components/react";
import { cn } from "@plane/utils";
import { EDialogWidth } from "./constants";

function DialogPortal({ ...props }: React.ComponentProps<typeof BaseDialog.Portal>) {
return <BaseDialog.Portal data-slot="dialog-portal" {...props} />;
// enums

export enum EDialogWidth {
SM = "sm:max-w-sm",
MD = "sm:max-w-md",
LG = "sm:max-w-lg",
XL = "sm:max-w-xl",
XXL = "sm:max-w-2xl",
XXXL = "sm:max-w-3xl",
XXXXL = "sm:max-w-4xl",
VXL = "sm:max-w-5xl",
VIXL = "sm:max-w-6xl",
VIIXL = "sm:max-w-7xl",
}

function DialogOverlay({ className, ...props }: React.ComponentProps<typeof BaseDialog.Backdrop>) {
return (
<BaseDialog.Backdrop
data-slot="dialog-overlay"
className={cn(
"fixed inset-0 z-30 bg-custom-backdrop transition-all duration-200 [&[data-ending-style]]:opacity-0 [&[data-starting-style]]:opacity-0",
className
)}
{...props}
/>
);
// Types
export type DialogPosition = "center" | "top";

export interface DialogProps extends React.ComponentProps<typeof BaseDialog.Root> {
children: React.ReactNode;
}

function Dialog({ ...props }: React.ComponentProps<typeof BaseDialog.Root>) {
return <BaseDialog.Root data-slot="dialog" {...props} />;
export interface DialogPanelProps extends React.ComponentProps<typeof BaseDialog.Popup> {
width?: EDialogWidth;
position?: DialogPosition;
children: React.ReactNode;
}

function DialogTrigger({ ...props }: React.ComponentProps<typeof BaseDialog.Trigger>) {
return <BaseDialog.Trigger data-slot="dialog-trigger" {...props} />;
export interface DialogTitleProps extends React.ComponentProps<typeof BaseDialog.Title> {
children: React.ReactNode;
}

function DialogPanel({
className,
width = EDialogWidth.XXL,
children,
...props
}: React.ComponentProps<typeof BaseDialog.Popup> & { width?: EDialogWidth }) {
return (
<DialogPortal data-slot="dialog-portal">
<DialogOverlay />
<BaseDialog.Popup
data-slot="dialog-content"
className={cn(
"fixed flex justify-center top-0 left-0 w-full z-30 px-4 sm:py-20 overflow-y-auto overflow-hidden outline-none"
)}
{...props}
>
<div
className={cn(
"rounded-lg bg-custom-background-100 text-left shadow-custom-shadow-md transition-all w-full",
width,
className
)}
// Constants
const OVERLAY_CLASSNAME = cn("fixed inset-0 z-backdrop bg-custom-backdrop");
const BASE_CLASSNAME = "relative text-left bg-custom-background-100 rounded-lg shadow-md w-full z-modal";

// Utility functions
const getPositionClassNames = React.useCallback(
(position: DialogPosition) =>
cn("isolate fixed z-modal", {
"top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2": position === "center",
"top-8 left-1/2 -translate-x-1/2": position === "top",
}),
[]
);

const DialogPortal = React.memo<React.ComponentProps<typeof BaseDialog.Portal>>(({ children, ...props }) => (
<BaseDialog.Portal data-slot="dialog-portal" {...props}>
{children}
</BaseDialog.Portal>
));
DialogPortal.displayName = "DialogPortal";

const DialogOverlay = React.memo<React.ComponentProps<typeof BaseDialog.Backdrop>>(({ className, ...props }) => (
<BaseDialog.Backdrop data-slot="dialog-overlay" className={cn(OVERLAY_CLASSNAME, className)} {...props} />
));
DialogOverlay.displayName = "DialogOverlay";

const DialogComponent = React.memo<DialogProps>(({ children, ...props }) => (
<BaseDialog.Root data-slot="dialog" {...props}>
{children}
</BaseDialog.Root>
));
DialogComponent.displayName = "Dialog";

const DialogTrigger = React.memo<React.ComponentProps<typeof BaseDialog.Trigger>>(({ children, ...props }) => (
<BaseDialog.Trigger data-slot="dialog-trigger" {...props}>
{children}
</BaseDialog.Trigger>
));
DialogTrigger.displayName = "DialogTrigger";

const DialogPanel = React.forwardRef<React.ElementRef<typeof BaseDialog.Popup>, DialogPanelProps>(
({ className, width = EDialogWidth.XXL, children, position = "center", ...props }, ref) => {
const positionClassNames = React.useMemo(() => getPositionClassNames(position), [position]);
return (
<DialogPortal>
<DialogOverlay />
<BaseDialog.Popup
ref={ref}
data-slot="dialog-content"
className={cn(BASE_CLASSNAME, positionClassNames, width, className)}
role="dialog"
aria-modal="true"
{...props}
>
{children}
</div>
</BaseDialog.Popup>
</DialogPortal>
);
}
</BaseDialog.Popup>
</DialogPortal>
);
}
);
DialogPanel.displayName = "DialogPanel";

function DialogTitle({ className, ...props }: React.ComponentProps<typeof BaseDialog.Title>) {
return (
<BaseDialog.Title
data-slot="dialog-title"
className={cn("text-lg leading-none font-semibold", className)}
{...props}
/>
);
}
// compound components
Dialog.Trigger = DialogTrigger;
Dialog.Panel = DialogPanel;
Dialog.Title = DialogTitle;
const DialogTitle = React.memo<DialogTitleProps>(({ className, children, ...props }) => (
<BaseDialog.Title data-slot="dialog-title" className={cn("text-lg leading-none font-semibold", className)} {...props}>
{children}
</BaseDialog.Title>
));

DialogTitle.displayName = "DialogTitle";

// Create the compound Dialog component with proper typing
const Dialog = Object.assign(DialogComponent, {
Panel: DialogPanel,
Title: DialogTitle,
}) as typeof DialogComponent & {
Panel: typeof DialogPanel;
Title: typeof DialogTitle;
};

export { Dialog, DialogTitle, DialogTrigger, DialogPanel };
export { Dialog, DialogTitle, DialogPanel };
2 changes: 1 addition & 1 deletion packages/propel/src/popover/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./root";
export * from "./root";
10 changes: 6 additions & 4 deletions packages/propel/src/popover/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ const PopoverPortal = React.memo<React.ComponentProps<typeof BasePopover.Portal>
return <BasePopover.Portal data-slot="popover-portal" {...props} />;
});

const PopoverPositioner = React.memo<React.ComponentProps<typeof BasePopover.Positioner>>(function PopoverPositioner(props) {
return <BasePopover.Positioner data-slot="popover-positioner" {...props} />;
});
const PopoverPositioner = React.memo<React.ComponentProps<typeof BasePopover.Positioner>>(
function PopoverPositioner(props) {
return <BasePopover.Positioner data-slot="popover-positioner" {...props} />;
}
);

// compound components
const Popover = Object.assign(
Expand All @@ -119,4 +121,4 @@ PopoverPortal.displayName = "PopoverPortal";
PopoverTrigger.displayName = "PopoverTrigger";
PopoverPositioner.displayName = "PopoverPositioner";

export { Popover};
export { Popover };
14 changes: 14 additions & 0 deletions packages/tailwind-config/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,20 @@ module.exports = {
fontFamily: {
custom: ["Inter", "sans-serif"],
},
zIndex: {
base: 0 /* default content */,
header: 10 /* sticky headers, navbars */,
sidebar: 20 /* sidebars, drawers */,
dropdown: 30 /* dropdowns, select menus */,
popover: 40 /* popovers, hovercards */,
tooltip: 50 /* tooltips, hints */,
sticky: 60 /* sticky UI */,
backdrop: 90 /* backdrop / overlay */,
modal: 100 /* dialogs, modals */,
toast: 110 /* toast, alerts */,
loader: 120 /* blocking loader/spinner */,
max: 9999 /* emergency override (rare use) */,
},
},
},
plugins: [
Expand Down
Loading