mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-09 22:35:54 -05:00
## Changes 🏗️ Makes changes to use [Sonner for Toasts](https://sonner.emilkowal.ski/) rather than the [Radix UI primitive](https://www.radix-ui.com/primitives/docs/components/toast). <img width="431" alt="Screenshot 2025-07-09 at 15 49 47" src="https://github.com/user-attachments/assets/c09c3c1e-fd80-44d2-9336-c955c2d4f288" /> <img width="444" alt="Screenshot 2025-07-09 at 15 51 05" src="https://github.com/user-attachments/assets/cc2a3491-7b76-44e2-8bec-3ad0ac917148" /> <img width="450" alt="Screenshot 2025-07-09 at 15 51 50" src="https://github.com/user-attachments/assets/e8ede05d-3488-43f4-aa43-7d3cba92a050" /> https://github.com/user-attachments/assets/deb4ce1c-13bb-4f69-890e-9b8680c848e7 <img width="500" alt="Screenshot 2025-07-09 at 15 59 09" src="https://github.com/user-attachments/assets/5636969d-4c9a-41e6-acd1-afa49b8e70c6" /> Sonner is [the one used in shadcn](https://ui.shadcn.com/docs/components/toast) nowadays, because it brings great UX on touch devices: - allows to swipe to dismiss - they can stack nicely if multiple toasts appear ( see video 📹 ) - when stack, hovering over them reveals them all nicely ( see video 📹 ) I kept the existing `useToast()` API used on the pages, so I had to only refactor the hook not the calls 🏁 ## Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Login - [x] Click around the app and trigger toasts - [x] Toasts look good ### For configuration changes Nope
108 lines
2.8 KiB
TypeScript
108 lines
2.8 KiB
TypeScript
import React, { FC, useEffect, useState } from "react";
|
|
import { Button } from "./ui/button";
|
|
import { Textarea } from "./ui/textarea";
|
|
import { Maximize2, Minimize2, Clipboard } from "lucide-react";
|
|
import { createPortal } from "react-dom";
|
|
import { toast } from "./molecules/Toast/use-toast";
|
|
|
|
interface ModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onSave: (value: string) => void;
|
|
title?: string;
|
|
defaultValue: string;
|
|
}
|
|
|
|
const InputModalComponent: FC<ModalProps> = ({
|
|
isOpen,
|
|
onClose,
|
|
onSave,
|
|
title,
|
|
defaultValue,
|
|
}) => {
|
|
const [tempValue, setTempValue] = useState(defaultValue);
|
|
const [isMaximized, setIsMaximized] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
setTempValue(defaultValue);
|
|
setIsMaximized(false);
|
|
}
|
|
}, [isOpen, defaultValue]);
|
|
|
|
const handleSave = () => {
|
|
onSave(tempValue);
|
|
onClose();
|
|
};
|
|
|
|
const toggleSize = () => {
|
|
setIsMaximized(!isMaximized);
|
|
};
|
|
|
|
const copyValue = () => {
|
|
navigator.clipboard.writeText(tempValue).then(() => {
|
|
toast({
|
|
title: "Input value copied to clipboard!",
|
|
duration: 2000,
|
|
});
|
|
});
|
|
};
|
|
|
|
if (!isOpen) {
|
|
return null;
|
|
}
|
|
|
|
const modalContent = (
|
|
<div
|
|
id="modal-content"
|
|
className={`fixed rounded-lg border-[1.5px] bg-white p-5 ${
|
|
isMaximized ? "inset-[128px] flex flex-col" : `w-[90%] max-w-[800px]`
|
|
}`}
|
|
>
|
|
<h2 className="mb-4 text-center text-lg font-semibold">
|
|
{title || "Enter input text"}
|
|
</h2>
|
|
<div className="nowheel relative flex-grow">
|
|
<Textarea
|
|
className="h-full min-h-[200px] w-full resize-none"
|
|
value={tempValue}
|
|
onChange={(e) => setTempValue(e.target.value)}
|
|
/>
|
|
<div className="absolute bottom-2 right-2 flex space-x-2">
|
|
<Button onClick={copyValue} size="icon" variant="outline">
|
|
<Clipboard size={18} />
|
|
</Button>
|
|
<Button onClick={toggleSize} size="icon" variant="outline">
|
|
{isMaximized ? <Minimize2 size={18} /> : <Maximize2 size={18} />}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex justify-end space-x-2">
|
|
<Button onClick={onClose} variant="outline">
|
|
Cancel
|
|
</Button>
|
|
<Button onClick={handleSave}>Save</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
{isMaximized ? (
|
|
createPortal(
|
|
<div className="fixed inset-0 flex items-center justify-center bg-white bg-opacity-60">
|
|
{modalContent}
|
|
</div>,
|
|
document.body,
|
|
)
|
|
) : (
|
|
<div className="nodrag fixed inset-0 flex items-center justify-center bg-white bg-opacity-60">
|
|
{modalContent}
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default InputModalComponent;
|