Add timed message modal component
This commit is contained in:
@@ -8,6 +8,7 @@ export default function Modal(props: ModalProps){
|
|||||||
display,
|
display,
|
||||||
backgroundType = "blur",
|
backgroundType = "blur",
|
||||||
backgroundClassName,
|
backgroundClassName,
|
||||||
|
top = false,
|
||||||
close,
|
close,
|
||||||
className,
|
className,
|
||||||
children
|
children
|
||||||
@@ -34,7 +35,11 @@ export default function Modal(props: ModalProps){
|
|||||||
<div
|
<div
|
||||||
{...divProps}
|
{...divProps}
|
||||||
className={clsx(
|
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]",
|
"flex flex-col rounded-lg max-h-full shadow-lg shadow-[#00000066]",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export interface ModalProps extends HTMLProps<HTMLDivElement>{
|
|||||||
display?: boolean;
|
display?: boolean;
|
||||||
backgroundType?: ModalBackgroundType;
|
backgroundType?: ModalBackgroundType;
|
||||||
backgroundClassName?: string;
|
backgroundClassName?: string;
|
||||||
|
top?: boolean;
|
||||||
close?: () => void;
|
close?: () => void;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import App from './App.tsx'
|
|||||||
import './index.css'
|
import './index.css'
|
||||||
import { AuthProvider } from './providers/AuthProvider.tsx'
|
import { AuthProvider } from './providers/AuthProvider.tsx'
|
||||||
import { ThemeProvider } from './providers/ThemeProvider.tsx'
|
import { ThemeProvider } from './providers/ThemeProvider.tsx'
|
||||||
|
import { TimedModalProvider } from "./providers/TimedModalProvider.tsx"
|
||||||
|
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
@@ -17,12 +18,14 @@ createRoot(document.getElementById('root')!).render(
|
|||||||
defaultTheme="dark"
|
defaultTheme="dark"
|
||||||
storageKey="vite-ui-theme"
|
storageKey="vite-ui-theme"
|
||||||
>
|
>
|
||||||
|
<TimedModalProvider>
|
||||||
<AuthProvider
|
<AuthProvider
|
||||||
jwtStorageKey="jwt"
|
jwtStorageKey="jwt"
|
||||||
refreshTokenStorageKey="refreshToken"
|
refreshTokenStorageKey="refreshToken"
|
||||||
>
|
>
|
||||||
<App />
|
<App />
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
|
</TimedModalProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
type Theme = "dark" | "light" | "system";
|
type Theme = "dark" | "light" | "system";
|
||||||
|
|
||||||
type ThemeProviderProps = {
|
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