Skip to content
Merged
Show file tree
Hide file tree
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
46 changes: 29 additions & 17 deletions src/components/ui/alert-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"use client";

import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
import * as React from "react";

import { cn } from "@/lib/utils";
import { Button } from "./button";
import { useThemeOptional, defaultCssVariables } from "@/providers";
import { useThemeOptional } from "@/providers";

function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
Expand All @@ -15,9 +17,14 @@ function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
);
}

function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
function AlertDialogPortal({
children,
...props
}: AlertDialogPrimitive.Portal.Props) {
return (
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props}>
{children}
</AlertDialogPrimitive.Portal>
);
}

Expand All @@ -40,25 +47,30 @@ function AlertDialogOverlay({
function AlertDialogContent({
className,
size = "default",
children,
...props
}: AlertDialogPrimitive.Popup.Props & {
size?: "default" | "sm";
}) {
const theme = useThemeOptional();
const mode = theme?.mode ?? 'light';
const cssVariables = theme?.cssVariables ?? defaultCssVariables;
const { resolvedMode, cssVariables, className: themeClassName } = useThemeOptional();

return (
<AlertDialogPortal className={ cn('pui-root', mode, theme?.className) } style={cssVariables}>
<AlertDialogOverlay />
<AlertDialogPrimitive.Popup
data-slot="alert-dialog-content"
data-size={size}
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-6 rounded-xl p-6 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg group/alert-dialog-content fixed top-1/2 start-1/2 z-50 grid w-full -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 outline-none",
className
)}
{...props}
/>
<AlertDialogPortal>
<div className={ cn('pui-root', resolvedMode, themeClassName) } style={cssVariables}>

<AlertDialogOverlay />
<AlertDialogPrimitive.Popup
data-slot="alert-dialog-content"
data-size={size}
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-6 rounded-xl p-6 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg group/alert-dialog-content fixed top-1/2 start-1/2 z-50 grid w-full -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 outline-none",
className
)}
{...props}
>
{children}
</AlertDialogPrimitive.Popup>
</div>
</AlertDialogPortal>
);
}
Expand Down
59 changes: 36 additions & 23 deletions src/components/ui/combobox.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { Combobox as ComboboxPrimitive } from "@base-ui/react";
import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react";
import * as React from "react";
Expand All @@ -5,7 +7,7 @@
import { cn } from "@/lib/utils";
import { Button } from "./button";
import { Input } from "./input";
import { useThemeOptional, defaultCssVariables } from "@/providers";

Check warning on line 10 in src/components/ui/combobox.tsx

View workflow job for this annotation

GitHub Actions / build-and-test

'defaultCssVariables' is defined but never used

const Combobox = ComboboxPrimitive.Root;

Expand Down Expand Up @@ -103,6 +105,17 @@
);
ComboboxInput.displayName = "ComboboxInput";

function ComboboxPortal({
children,
...props
}: ComboboxPrimitive.Portal.Props) {
return (
<ComboboxPrimitive.Portal data-slot="combobox-portal" {...props}>
{children}
</ComboboxPrimitive.Portal>
);
}

function ComboboxContent({
className,
side = "bottom",
Expand All @@ -116,30 +129,30 @@
ComboboxPrimitive.Positioner.Props,
"side" | "align" | "sideOffset" | "alignOffset" | "anchor"
>) {
const theme = useThemeOptional();
const mode = theme?.mode ?? 'light';
const cssVariables = theme?.cssVariables ?? defaultCssVariables;
const { resolvedMode, cssVariables, className: themeClassName } = useThemeOptional();
return (
<ComboboxPrimitive.Portal className={ cn('pui-root', mode, theme?.className) } style={cssVariables}>
<ComboboxPrimitive.Positioner
side={side}
sideOffset={sideOffset}
align={align}
alignOffset={alignOffset}
anchor={anchor}
className="isolate z-50"
>
<ComboboxPrimitive.Popup
data-slot="combobox-content"
data-chips={!!anchor}
className={cn(
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 max-h-72 min-w-36 overflow-hidden rounded-md shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) data-[chips=true]:min-w-(--anchor-width)",
className
)}
{...props}
/>
</ComboboxPrimitive.Positioner>
</ComboboxPrimitive.Portal>
<ComboboxPortal>
<div className={ cn('pui-root', resolvedMode, themeClassName) } style={cssVariables}>
<ComboboxPrimitive.Positioner
side={side}
sideOffset={sideOffset}
align={align}
alignOffset={alignOffset}
anchor={anchor}
className="isolate z-50"
>
<ComboboxPrimitive.Popup
data-slot="combobox-content"
data-chips={!!anchor}
className={cn(
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 max-h-72 min-w-36 overflow-hidden rounded-md shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) data-[chips=true]:min-w-(--anchor-width)",
className
)}
{...props}
/>
</ComboboxPrimitive.Positioner>
</div>
</ComboboxPortal>
);
}

Expand Down
71 changes: 39 additions & 32 deletions src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { XIcon } from "lucide-react"
import { useThemeOptional, defaultCssVariables } from "@/providers"

Check warning on line 9 in src/components/ui/dialog.tsx

View workflow job for this annotation

GitHub Actions / build-and-test

'defaultCssVariables' is defined but never used

function Dialog({ ...props }: DialogPrimitive.Root.Props) {
return <DialogPrimitive.Root data-slot="dialog" {...props} />
Expand All @@ -20,8 +20,15 @@
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
}

function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
function DialogPortal({
children,
...props
}: DialogPrimitive.Portal.Props) {
return (
<DialogPrimitive.Portal data-slot="dialog-portal" {...props}>
{children}
</DialogPrimitive.Portal>
)
}

function DialogOverlay({
Expand All @@ -48,37 +55,37 @@
}: DialogPrimitive.Popup.Props & {
showCloseButton?: boolean
}) {
const theme = useThemeOptional()
const mode = theme?.mode ?? "light"
const cssVariables = theme?.cssVariables ?? defaultCssVariables
const { resolvedMode, cssVariables, className: themeClassName } = useThemeOptional()
return (
<DialogPortal className={cn("pui-root", mode, theme?.className)} style={cssVariables}>
<DialogOverlay />
<DialogPrimitive.Popup
data-slot="dialog-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-4 rounded-lg border border-border p-6 shadow-lg duration-150 fixed top-1/2 start-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 outline-none",
className
)}
{...props}
>
{children}
{showCloseButton && (
<DialogPrimitive.Close
data-slot="dialog-close"
render={
<Button
variant="ghost"
className="absolute top-4 end-4"
size="icon-sm"
/>
}
>
<XIcon />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}
</DialogPrimitive.Popup>
<DialogPortal>
<div className={cn("pui-root", resolvedMode, themeClassName)} style={cssVariables}>
<DialogOverlay />
<DialogPrimitive.Popup
data-slot="dialog-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-4 rounded-lg border border-border p-6 shadow-lg duration-150 fixed top-1/2 start-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 outline-none",
className
)}
{...props}
>
{children}
{showCloseButton && (
<DialogPrimitive.Close
data-slot="dialog-close"
render={
<Button
variant="ghost"
className="absolute top-4 end-4"
size="icon-sm"
/>
}
>
<XIcon />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}
</DialogPrimitive.Popup>
</div>
</DialogPortal>
)
}
Expand Down
55 changes: 32 additions & 23 deletions src/components/ui/dropdown-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
"use client";

import { Menu as MenuPrimitive } from "@base-ui/react/menu";
import { CheckIcon, ChevronRightIcon } from "lucide-react";
import * as React from "react";

import { cn } from "@/lib/utils";
import { useThemeOptional, defaultCssVariables } from "@/providers";

Check warning on line 8 in src/components/ui/dropdown-menu.tsx

View workflow job for this annotation

GitHub Actions / build-and-test

'defaultCssVariables' is defined but never used

function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
}

function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />;
function DropdownMenuPortal({
children,
...props
}: MenuPrimitive.Portal.Props) {
return (
<MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props}>
{children}
</MenuPrimitive.Portal>
);
}

function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
Expand All @@ -29,28 +38,28 @@
MenuPrimitive.Positioner.Props,
"align" | "alignOffset" | "side" | "sideOffset"
>) {
const theme = useThemeOptional();
const mode = theme?.mode ?? 'light';
const cssVariables = theme?.cssVariables ?? defaultCssVariables;
const { resolvedMode, cssVariables, className: themeClassName } = useThemeOptional();
return (
<MenuPrimitive.Portal className={ cn('pui-root', mode, theme?.className) } style={cssVariables}>
<MenuPrimitive.Positioner
className="isolate z-50 outline-none"
align={align}
alignOffset={alignOffset}
side={side}
sideOffset={sideOffset}
>
<MenuPrimitive.Popup
data-slot="dropdown-menu-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-md p-1 shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden",
className
)}
{...props}
/>
</MenuPrimitive.Positioner>
</MenuPrimitive.Portal>
<DropdownMenuPortal>
<div className={ cn('pui-root', resolvedMode, themeClassName) } style={cssVariables}>
<MenuPrimitive.Positioner
className="isolate z-50 outline-none"
align={align}
alignOffset={alignOffset}
side={side}
sideOffset={sideOffset}
>
<MenuPrimitive.Popup
data-slot="dropdown-menu-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-md p-1 shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden",
className
)}
{...props}
/>
</MenuPrimitive.Positioner>
</div>
</DropdownMenuPortal>
);
}

Expand Down
12 changes: 5 additions & 7 deletions src/components/ui/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
} from "react";
import { createPortal } from "react-dom";
import { cn } from "@/lib/utils";
import { useThemeOptional, defaultCssVariables } from "@/providers";

Check warning on line 11 in src/components/ui/modal.tsx

View workflow job for this annotation

GitHub Actions / build-and-test

'defaultCssVariables' is defined but never used

/* ============================================
Modal Overlay
Expand Down Expand Up @@ -296,9 +296,7 @@
className,
size = "default",
}: ModalProps) {
const theme = useThemeOptional();
const mode = theme?.mode ?? 'light';
const cssVariables = theme?.cssVariables ?? defaultCssVariables;
const { resolvedMode, cssVariables, className: themeClassName } = useThemeOptional();
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
null,
);
Expand All @@ -314,7 +312,7 @@

const container = document.createElement("div");
container.setAttribute("data-pui-modal-root", "true");
container.className = cn("pui-root", mode, theme?.className);
container.className = cn("pui-root", resolvedMode, themeClassName);
Object.assign(container.style, cssVariables);

document.body.appendChild(container);
Expand All @@ -331,15 +329,15 @@
previousActiveElement.current.focus();
}
};
}, [open, mode, cssVariables, theme?.className]);
}, [open, resolvedMode, cssVariables, themeClassName]);

// Keep portal container class and CSS variables in sync with theme
useEffect(() => {
if (portalContainer) {
portalContainer.className = cn("pui-root", mode, theme?.className);
portalContainer.className = cn("pui-root", resolvedMode, themeClassName);
Object.assign(portalContainer.style, cssVariables);
}
}, [mode, cssVariables, portalContainer, theme?.className]);
}, [resolvedMode, cssVariables, portalContainer, themeClassName]);

// Handle escape key
useEffect(() => {
Expand Down
Loading
Loading