Eva Marco e705b6e12c
🎉 Add components library (#10675)
* 🎉 Install react-aria-components

* 🎉 Create modal component in TS using react-aria-component

* 🎉 Create modal ds component

* 🎉 Separate header content and footer components

* 🐛 Remove mf/html macros when not needed

* 🎉 Solve little problems

* ♻️ Format files

* ♻️ Remove ModalCloseBtn

* 🐛 Fix CI

* ♻️ Remove unused files

* 🎉 Make close button not dependant on the modal header

* 🎉 Add footer with two slots

* 🎉 Improvements on modal

* 🐛 Fix package imports and remove login example code

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-07-30 13:05:28 +02:00

67 lines
1.5 KiB
TypeScript

import {
DialogTrigger,
ModalOverlay,
Modal as RACModal,
Dialog,
} from 'react-aria-components';
import {
createContext,
useContext,
type ReactNode,
} from 'react';
import styles from './Modal.module.scss';
const ModalCloseContext = createContext<(() => void) | null>(null);
export function useModalClose(): (() => void) | null {
return useContext(ModalCloseContext);
}
interface ModalProps {
isOpen?: boolean;
onOpenChange?: (isOpen: boolean) => void;
children: ReactNode;
trigger?: ReactNode;
isDismissable?: boolean;
size?: 'small' | 'medium' | 'large' | 'xlarge';
className?: string;
}
export function Modal({
isOpen,
onOpenChange,
children,
trigger,
isDismissable = true,
size = 'medium',
className,
}: ModalProps) {
const sizeClass =
size === 'small'
? styles.modalSmall
: size === 'large'
? styles.modalLarge
: size === 'xlarge'
? styles.modalXlarge
: styles.modalMedium;
return (
<DialogTrigger isOpen={isOpen} onOpenChange={onOpenChange}>
{trigger}
<ModalOverlay className={styles.overlay} isDismissable={isDismissable}>
<RACModal
className={`${styles.modal} ${sizeClass} ${className ?? ''}`}
>
<Dialog className={styles.dialog}>
{({ close }) => (
<ModalCloseContext.Provider value={close}>
{children}
</ModalCloseContext.Provider>
)}
</Dialog>
</RACModal>
</ModalOverlay>
</DialogTrigger>
);
}