diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx
index 101b076c..608a4b46 100644
--- a/frontend/src/router.tsx
+++ b/frontend/src/router.tsx
@@ -12,14 +12,17 @@ import SongDetailListPage from './pages/SongDetailListPage';
import AuthLayout from './shared/components/Layout/AuthLayout';
import Layout from './shared/components/Layout/Layout';
import ROUTE_PATH from './shared/constants/path';
+import { OverlayProvider } from './shared/hooks/useOverlay';
const router = createBrowserRouter([
{
path: ROUTE_PATH.ROOT,
element: (
-
-
-
+
+
+
+
+
),
children: [
{
diff --git a/frontend/src/shared/hooks/useOverlay/OverlayController.tsx b/frontend/src/shared/hooks/useOverlay/OverlayController.tsx
new file mode 100644
index 00000000..5dab659f
--- /dev/null
+++ b/frontend/src/shared/hooks/useOverlay/OverlayController.tsx
@@ -0,0 +1,37 @@
+import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react';
+import type { CreateOverlayElement } from './types';
+import type { Ref } from 'react';
+
+interface OverlayControllerProps {
+ overlayElement: CreateOverlayElement;
+ onExit: () => void;
+}
+
+export interface OverlayControlRef {
+ close: () => void;
+}
+
+export const OverlayController = forwardRef(function OverlayController(
+ { overlayElement: OverlayElement, onExit }: OverlayControllerProps,
+ ref: Ref
+) {
+ const [isOpenOverlay, setIsOpenOverlay] = useState(false);
+
+ const handleOverlayClose = useCallback(() => setIsOpenOverlay(false), []);
+
+ useImperativeHandle(
+ ref,
+ () => {
+ return { close: handleOverlayClose };
+ },
+ [handleOverlayClose]
+ );
+
+ useEffect(() => {
+ requestAnimationFrame(() => {
+ setIsOpenOverlay(true);
+ });
+ }, []);
+
+ return ;
+});
diff --git a/frontend/src/shared/hooks/useOverlay/OverlayProvider.tsx b/frontend/src/shared/hooks/useOverlay/OverlayProvider.tsx
new file mode 100644
index 00000000..d9de553f
--- /dev/null
+++ b/frontend/src/shared/hooks/useOverlay/OverlayProvider.tsx
@@ -0,0 +1,42 @@
+import React, { createContext, useCallback, useMemo, useRef, useState } from 'react';
+import type { Mount, Unmount } from './types';
+import type { MutableRefObject, PropsWithChildren, ReactNode } from 'react';
+
+export const OverlayContext = createContext<{
+ mount: Mount;
+ unmount: Unmount;
+ elementIdRef: MutableRefObject;
+} | null>(null);
+
+export function OverlayProvider({ children }: PropsWithChildren<{ containerId?: string }>) {
+ const [overlayById, setOverlayById] = useState