refactor: modal component

This commit is contained in:
emirsassan 2025-07-21 00:09:59 +03:00
parent 8e6ffdccf6
commit 4e60aefc9d
2 changed files with 85 additions and 28 deletions

View file

@ -41,6 +41,7 @@ interface FormValidation {
export function NewClusterCreate() {
const queryClient = useQueryClient();
const [currentStepIndex, setCurrentStepIndex] = useState(0);
const [isModalOpen, setIsModalOpen] = useState(false);
const [formData, setFormData] = useState<ClusterFormData>({
loader: 'vanilla',
clusterName: '',
@ -63,6 +64,15 @@ export function NewClusterCreate() {
}), {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['getClusters'] });
// Modal'ı kapat ve formu sıfırla
setIsModalOpen(false);
setCurrentStepIndex(0);
setFormData({
loader: 'vanilla',
clusterName: '',
clusterVersion: '',
clusterProvider: '',
});
},
});
@ -154,32 +164,30 @@ export function NewClusterCreate() {
/>
</div>
<Modal.Trigger>
<Button>
<PlusIcon className="stroke-width-[2.2] size-5" />
New cluster
</Button>
<Button onPress={() => setIsModalOpen(true)}>
<PlusIcon className="stroke-width-[2.2] size-5" />
New cluster
</Button>
<Modal>
<div className="min-w-sm flex flex-col rounded-lg bg-page text-center">
<ModalHeader currentStep={currentStepConfig} />
<Modal isDismissable isOpen={isModalOpen} onOpenChange={setIsModalOpen}>
<div className="min-w-sm flex flex-col rounded-lg bg-page text-center">
<ModalHeader currentStep={currentStepConfig} />
<div className="flex flex-col rounded-b-lg border border-white/5">
<div className="p-3">
{stepContent}
</div>
<ModalFooter
isFirstStep={isFirstStep}
isNextDisabled={isNextDisabled}
nextButtonText={nextButtonText}
onBack={handleBack}
onNext={handleNext}
/>
<div className="flex flex-col rounded-b-lg border border-white/5">
<div className="p-3">
{stepContent}
</div>
<ModalFooter
isFirstStep={isFirstStep}
isNextDisabled={isNextDisabled}
nextButtonText={nextButtonText}
onBack={handleBack}
onNext={handleNext}
/>
</div>
</Modal>
</Modal.Trigger>
</div>
</Modal>
</div>
);
}

View file

@ -1,19 +1,68 @@
import type { DialogProps } from 'react-aria-components';
import type { VariantProps } from 'tailwind-variants';
import {
Dialog as AriaDialog,
Modal as AriaModal,
DialogTrigger,
ModalOverlay,
} from 'react-aria-components';
import { twMerge } from 'tailwind-merge';
import { tv } from 'tailwind-variants';
interface ModalProps extends DialogProps { }
const modalVariants = tv({
slots: {
overlay: [
'fixed inset-0 z-50',
'flex items-center justify-center',
'bg-black/50 p-4',
'data-[entering]:animate-in data-[entering]:fade-in data-[entering]:duration-200',
'data-[exiting]:animate-out data-[exiting]:fade-out data-[exiting]:duration-150',
],
modal: [
'data-[entering]:animate-in data-[entering]:zoom-in-95 data-[entering]:duration-200',
'data-[exiting]:animate-out data-[exiting]:zoom-out-95 data-[exiting]:duration-150',
],
dialog: [
'outline-none',
],
},
});
export interface ModalProps extends DialogProps, VariantProps<typeof modalVariants> {
isOpen?: boolean;
onOpenChange?: (isOpen: boolean) => void;
isDismissable?: boolean;
overlayClassName?: string;
modalClassName?: string;
}
function Modal({
className,
isOpen,
onOpenChange,
isDismissable = true,
overlayClassName,
modalClassName,
...props
}: ModalProps) {
const { overlay, modal, dialog } = modalVariants();
const isControlled = isOpen !== undefined || onOpenChange !== undefined;
const overlayProps = {
className: twMerge(overlay(), overlayClassName),
isDismissable,
...(isControlled && { isOpen, onOpenChange }),
};
function Modal({ className, ...props }: ModalProps) {
return (
<ModalOverlay className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4" isDismissable>
<AriaModal>
<AriaDialog className="" {...props} />
<ModalOverlay {...overlayProps}>
<AriaModal className={twMerge(modal(), modalClassName)}>
<AriaDialog
className={twMerge(dialog(), className)}
{...props}
/>
</AriaModal>
</ModalOverlay>
);