infoalloggi-monorepo/apps/infoalloggi/src/components/custom_ui/credenza.tsx

230 lines
5.4 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
"use client";
import { useMediaQuery } from "~/hooks/use-media-query";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
//DrawerNested,
DrawerTitle,
DrawerTrigger,
} from "~/components/ui/drawer";
import { type Drawer as DrawerPrimitive } from "vaul";
import { cn } from "~/lib/utils";
import { createContext, useContext, type ReactNode } from "react";
interface BaseProps {
children: ReactNode;
}
interface RootCredenzaProps extends BaseProps {
open?: boolean;
onOpenChange?: (open: boolean) => void;
drawerProps?: React.ComponentProps<typeof DrawerPrimitive.Root>;
}
interface CredenzaProps extends BaseProps {
className?: string;
asChild?: true;
}
const CredenzaContext = createContext<{ isDesktop: boolean }>({
isDesktop: false,
});
const useCredenzaContext = () => {
const context = useContext(CredenzaContext);
if (!context) {
throw new Error(
"Credenza components cannot be rendered outside the Credenza Context",
);
}
return context;
};
/**
* Drawer-Dialog component
* @example
* import {
* Credenza,
* CredenzaTrigger,
* CredenzaContent,
* CredenzaHeader,
* CredenzaTitle,
* CredenzaDescription,
* CredenzaBody,
* CredenzaFooter,
* CredenzaClose,
* } from "~/components/custom_ui/credenza";
*
* <Credenza>
* <CredenzaTrigger asChild>
* <button>Open modal</button>
* </CredenzaTrigger>
* <CredenzaContent>
* <CredenzaHeader>
* <CredenzaTitle>Credenza</CredenzaTitle>
* <CredenzaDescription>
* Description of the component.
* </CredenzaDescription>
* </CredenzaHeader>
* <CredenzaBody>
* This component body.
* </CredenzaBody>
* <CredenzaFooter>
* <CredenzaClose asChild>
* <button>Close</button>
* </CredenzaClose>
* </CredenzaFooter>
* </CredenzaContent>
* </Credenza>
*/
const Credenza = ({ children, drawerProps, ...props }: RootCredenzaProps) => {
const isDesktop = useMediaQuery("(min-width: 768px)");
const Credenza = isDesktop ? Dialog : Drawer;
return (
<CredenzaContext.Provider value={{ isDesktop }}>
<Credenza
{...props}
{...(!isDesktop && { ...drawerProps, autoFocus: true })}
>
{children}
</Credenza>
</CredenzaContext.Provider>
);
};
/*const CredenzaNested = ({
children,
drawerProps,
...props
}: RootCredenzaProps) => {
const isDesktop = useMediaQuery("(min-width: 768px)");
const Credenza = isDesktop ? Dialog : DrawerNested;
return (
<CredenzaContext.Provider value={{ isDesktop }}>
<Credenza
{...props}
{...(!isDesktop && { ...drawerProps, autoFocus: true })}
>
{children}
</Credenza>
</CredenzaContext.Provider>
);
};*/
const CredenzaTrigger = ({ className, children, ...props }: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaTrigger = isDesktop ? DialogTrigger : DrawerTrigger;
return (
<CredenzaTrigger className={className} {...props}>
{children}
</CredenzaTrigger>
);
};
const CredenzaClose = ({ className, children, ...props }: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaClose = isDesktop ? DialogClose : DrawerClose;
return (
<CredenzaClose className={className} {...props}>
{children}
</CredenzaClose>
);
};
const CredenzaContent = ({ className, children, ...props }: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaContent = isDesktop ? DialogContent : DrawerContent;
return (
<CredenzaContent className={className} {...props}>
{children}
</CredenzaContent>
);
};
const CredenzaDescription = ({
className,
children,
...props
}: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaDescription = isDesktop ? DialogDescription : DrawerDescription;
return (
<CredenzaDescription className={className} {...props}>
{children}
</CredenzaDescription>
);
};
const CredenzaHeader = ({ className, children, ...props }: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaHeader = isDesktop ? DialogHeader : DrawerHeader;
return (
<CredenzaHeader className={className} {...props}>
{children}
</CredenzaHeader>
);
};
const CredenzaTitle = ({ className, children, ...props }: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaTitle = isDesktop ? DialogTitle : DrawerTitle;
return (
<CredenzaTitle className={className} {...props}>
{children}
</CredenzaTitle>
);
};
const CredenzaBody = ({ className, children, ...props }: CredenzaProps) => {
return (
<div className={cn("px-4 md:px-0", className)} {...props}>
{children}
</div>
);
};
const CredenzaFooter = ({ className, children, ...props }: CredenzaProps) => {
const { isDesktop } = useCredenzaContext();
const CredenzaFooter = isDesktop ? DialogFooter : DrawerFooter;
return (
<CredenzaFooter className={className} {...props}>
{children}
</CredenzaFooter>
);
};
export {
Credenza,
//CredenzaNested,
CredenzaTrigger,
CredenzaClose,
CredenzaContent,
CredenzaDescription,
CredenzaHeader,
CredenzaTitle,
CredenzaBody,
CredenzaFooter,
};