Add timed message modal component
This commit is contained in:
@@ -8,6 +8,7 @@ export default function Modal(props: ModalProps){
|
||||
display,
|
||||
backgroundType = "blur",
|
||||
backgroundClassName,
|
||||
top = false,
|
||||
close,
|
||||
className,
|
||||
children
|
||||
@@ -34,7 +35,11 @@ export default function Modal(props: ModalProps){
|
||||
<div
|
||||
{...divProps}
|
||||
className={clsx(
|
||||
"fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 max-w-(--breakpoint-sm) z-50",
|
||||
"fixed left-1/2 -translate-x-1/2 max-w-(--breakpoint-sm) z-50",
|
||||
{
|
||||
"top-1/2 -translate-y-1/2": !top,
|
||||
"top-0": top
|
||||
},
|
||||
"flex flex-col rounded-lg max-h-full shadow-lg shadow-[#00000066]",
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface ModalProps extends HTMLProps<HTMLDivElement>{
|
||||
display?: boolean;
|
||||
backgroundType?: ModalBackgroundType;
|
||||
backgroundClassName?: string;
|
||||
top?: boolean;
|
||||
close?: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import App from './App.tsx'
|
||||
import './index.css'
|
||||
import { AuthProvider } from './providers/AuthProvider.tsx'
|
||||
import { ThemeProvider } from './providers/ThemeProvider.tsx'
|
||||
import { TimedModalProvider } from "./providers/TimedModalProvider.tsx"
|
||||
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
@@ -17,12 +18,14 @@ createRoot(document.getElementById('root')!).render(
|
||||
defaultTheme="dark"
|
||||
storageKey="vite-ui-theme"
|
||||
>
|
||||
<TimedModalProvider>
|
||||
<AuthProvider
|
||||
jwtStorageKey="jwt"
|
||||
refreshTokenStorageKey="refreshToken"
|
||||
>
|
||||
<App />
|
||||
</AuthProvider>
|
||||
</TimedModalProvider>
|
||||
</ThemeProvider>
|
||||
</QueryClientProvider>
|
||||
</StrictMode>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
||||
|
||||
|
||||
type Theme = "dark" | "light" | "system";
|
||||
|
||||
type ThemeProviderProps = {
|
||||
|
||||
86
src/providers/TimedModalProvider.tsx
Normal file
86
src/providers/TimedModalProvider.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import Modal from "@/components/modal/Modal";
|
||||
import ModalBody from "@/components/modal/ModalBody";
|
||||
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
||||
|
||||
|
||||
type TimedModalProviderState = {
|
||||
addMessage: (timeout: number, message: React.ReactNode) => void;
|
||||
}
|
||||
|
||||
|
||||
const initialState: TimedModalProviderState = {
|
||||
addMessage: () => null
|
||||
}
|
||||
|
||||
const TimedModalProviderContext = createContext<TimedModalProviderState>(initialState);
|
||||
|
||||
|
||||
export function TimedModalProvider({
|
||||
children
|
||||
}:{
|
||||
children: React.ReactNode;
|
||||
}){
|
||||
const [ display, setDisplay ] = useState(false);
|
||||
const [ messages, setMessages ] = useState<React.ReactNode[]>([]);
|
||||
const messagesRef = useRef<React.ReactNode[]>(messages);
|
||||
messagesRef.current = messages;
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
console.log("effect");
|
||||
console.log(messages);
|
||||
if(messages.length > 0){
|
||||
setDisplay(true);
|
||||
}
|
||||
else{
|
||||
setDisplay(false);
|
||||
}
|
||||
}, [ messages ]);
|
||||
|
||||
|
||||
const addMessage = (timeout: number, message: React.ReactNode) => {
|
||||
setMessages([...messages, message]);
|
||||
setTimeout(() => {
|
||||
setMessages(messagesRef.current.filter((m) => m !== message));
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<TimedModalProviderContext.Provider value={{addMessage}}>
|
||||
<Modal
|
||||
display={display}
|
||||
backgroundType="none"
|
||||
className="bg-neutral-300 dark:bg-neutral-600"
|
||||
top={true}
|
||||
>
|
||||
<ModalBody>
|
||||
<div
|
||||
className="space-y-4"
|
||||
>
|
||||
{
|
||||
messages.map((message, index) => (
|
||||
<div
|
||||
key={index}
|
||||
>
|
||||
{message}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
{children}
|
||||
</TimedModalProviderContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useTimedModal = () => {
|
||||
const context = useContext(TimedModalProviderContext);
|
||||
|
||||
if(context === undefined){
|
||||
throw new Error("useTimeModal must be used within a TimedModalProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user