Unify workspace dropdowns; Update layouts (#458)

Unified Account and Workspace drop-downs; Layout updates, now header lives within the PageBody component; Sidebars now use floating variant
This commit is contained in:
Giancarlo Buomprisco
2026-03-11 14:45:42 +08:00
committed by GitHub
parent ca585e09be
commit 4bc8448a1d
530 changed files with 14398 additions and 11198 deletions

View File

@@ -2,128 +2,129 @@
import * as React from 'react';
import { Cross2Icon } from '@radix-ui/react-icons';
import { type VariantProps, cva } from 'class-variance-authority';
import { Dialog as SheetPrimitive } from 'radix-ui';
import { cn } from '#lib/utils';
import { Dialog as SheetPrimitive } from '@base-ui/react/dialog';
import { XIcon } from 'lucide-react';
import { cn } from '../lib/utils';
import { Button } from './button';
const Sheet = SheetPrimitive.Root;
function Sheet({ ...props }: SheetPrimitive.Root.Props) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />;
}
const SheetTrigger = SheetPrimitive.Trigger;
function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
}
const SheetClose = SheetPrimitive.Close;
function SheetClose({ ...props }: SheetPrimitive.Close.Props) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
}
const SheetPortal = SheetPrimitive.Portal;
function SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
}
const SheetOverlay: React.FC<
React.ComponentPropsWithRef<typeof SheetPrimitive.Overlay>
> = ({ className, ...props }) => (
<SheetPrimitive.Overlay
className={cn(
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
className,
)}
{...props}
/>
);
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
return (
<SheetPrimitive.Backdrop
data-slot="sheet-overlay"
className={cn(
'data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0 fixed inset-0 z-50 bg-black/10 duration-100 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs',
className,
)}
{...props}
/>
);
}
const sheetVariants = cva(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 gap-4 p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
{
variants: {
side: {
top: 'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b',
bottom:
'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t',
left: 'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
right:
'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
},
},
defaultVariants: {
side: 'right',
},
},
);
interface SheetContentProps
extends
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent: React.FC<SheetContentProps> = ({
side = 'right',
function SheetContent({
className,
children,
side = 'right',
showCloseButton = true,
...props
}) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
className={cn(sheetVariants({ side }), className)}
}: SheetPrimitive.Popup.Props & {
side?: 'top' | 'right' | 'bottom' | 'left';
showCloseButton?: boolean;
}) {
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Popup
data-slot="sheet-content"
data-side={side}
className={cn(
'bg-background data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10 fixed z-50 flex flex-col gap-4 bg-clip-padding text-sm shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm',
className,
)}
{...props}
>
{children}
{showCloseButton && (
<SheetPrimitive.Close
data-slot="sheet-close"
render={
<Button
variant="ghost"
className="absolute top-3 right-3"
size="icon-sm"
/>
}
>
<XIcon />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
)}
</SheetPrimitive.Popup>
</SheetPortal>
);
}
function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="sheet-header"
className={cn('flex flex-col gap-0.5 p-4', className)}
{...props}
>
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
{children}
</SheetPrimitive.Content>
</SheetPortal>
);
SheetContent.displayName = SheetPrimitive.Content.displayName;
/>
);
}
const SheetHeader = ({
function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="sheet-footer"
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
{...props}
/>
);
}
function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn('text-foreground text-base font-medium', className)}
{...props}
/>
);
}
function SheetDescription({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn('flex flex-col gap-y-3 text-center sm:text-left', className)}
{...props}
/>
);
SheetHeader.displayName = 'SheetHeader';
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
className,
)}
{...props}
/>
);
SheetFooter.displayName = 'SheetFooter';
const SheetTitle: React.FC<
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
> = ({ className, ...props }) => (
<SheetPrimitive.Title
className={cn('text-foreground text-lg font-semibold', className)}
{...props}
/>
);
SheetTitle.displayName = SheetPrimitive.Title.displayName;
const SheetDescription: React.FC<
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
> = ({ className, ...props }) => (
<SheetPrimitive.Description
className={cn('text-muted-foreground text-sm', className)}
{...props}
/>
);
SheetDescription.displayName = SheetPrimitive.Description.displayName;
}: SheetPrimitive.Description.Props) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"
className={cn('text-muted-foreground text-sm', className)}
{...props}
/>
);
}
export {
Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose,
SheetContent,