Skip to content

Commit

Permalink
Feat: "다크모드 구현"
Browse files Browse the repository at this point in the history
  • Loading branch information
lee-ji-hong committed May 9, 2024
1 parent a466fa1 commit 2b55c5e
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 42 deletions.
36 changes: 24 additions & 12 deletions src/components/Common/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ import { toast } from "react-toastify";
import Button from "react-bootstrap/Button";
import Overlay from "react-bootstrap/Overlay";
import { useNavigate, Link } from "react-router-dom";

import ThemeContext from "context/ThemeContext";
import { app } from "../../../firebaseApp";

const Header = () => {
const auth = getAuth(app);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(!!auth?.currentUser);
const [show, setShow] = useState(false);
const context = useContext(ThemeContext);
const target = useRef(null);
const navigate = useNavigate();

useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
const unsubscribe = onAuthStateChanged(auth, user => {
if (user) {
setIsAuthenticated(true);
} else {
Expand All @@ -28,7 +29,6 @@ const Header = () => {
return () => unsubscribe();
}, [auth]);


const onSignOut = async () => {
try {
await signOut(auth);
Expand All @@ -49,15 +49,27 @@ const Header = () => {
</Link>
</div>
<div className="flex justify-center items-center">
<Link to="https://github.com/">
<img src="/images/github-logo.svg" alt="github" className="h-8 w-8 mr-3" />
</Link>
<img src="/images/light-to-dark.svg" alt="dark" className="h-8 w-8 mr-3" />

<Button variant="transparent" ref={target} onClick={() => setShow(!show)} className="p-0">
{/* Click me to see */}
<img src="/images/mypage.svg" alt="mypage" className="h-8 w-8" />
</Button>
{context.theme === "light" ? (
<>
<Link to="https://github.com/">
<img src="/images/github-logo-light.svg" alt="github" className="h-9 w-9 mr-3" />
</Link>
<img onClick={context.toggleMode} src="/images/light-to-dark.svg" alt="light" className="h-9 w-9 mr-3" />
<Button variant="transparent" ref={target} onClick={() => setShow(!show)} className="p-0">
<img src="/images/mypage-light.svg" alt="mypage" className="h-9 w-9" />
</Button>
</>
) : (
<>
<Link to="https://github.com/">
<img src="/images/github-logo-dark.svg" alt="github" className="h-9 w-9 mr-3" />
</Link>
<img onClick={context.toggleMode} src="/images/dark-to-light.svg" alt="dark" className="h-8 w-8 mr-3" />
<Button variant="transparent" ref={target} onClick={() => setShow(!show)} className="p-0">
<img src="/images/mypage-dark.svg" alt="mypage" className="h-9 w-9" />
</Button>
</>
)}
<Overlay target={target.current} show={show} placement="bottom">
{({
placement: _placement,
Expand Down
29 changes: 29 additions & 0 deletions src/context/ThemeContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { ReactNode, createContext, useState } from "react";

const ThemeContext = createContext({
theme: "light",
toggleMode: () => {},
});

interface ThemeProps {
children: ReactNode;
}

export const ThemeContextProvider = ({ children }: ThemeProps) => {
const [theme, setTheme] = useState(
window.localStorage.getItem("theme") || "light"
);

const toggleMode = () => {
setTheme((prev) => (prev === "light" ? "dark" : "light"));
window.localStorage.setItem("theme", theme === "light" ? "dark" : "light");
};

return (
<ThemeContext.Provider value={{ theme, toggleMode }}>
{children}
</ThemeContext.Provider>
);
};

export default ThemeContext;
16 changes: 10 additions & 6 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter as Router } from "react-router-dom";
import { AuthContextProvider } from "context/AuthContext";

import App from "./pages/App";
import firebase from "./firebaseApp";
import "../src/styles/global.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { SectionProvider } from "context/SectionContext";
import { ThemeContextProvider } from "context/ThemeContext";
import { AuthContextProvider } from "context/AuthContext";

const rootElement = document.getElementById("root");

Expand All @@ -17,11 +19,13 @@ if (rootElement) {
root.render(
<React.StrictMode>
<AuthContextProvider>
<SectionProvider>
<Router>
<App />
</Router>
</SectionProvider>
<ThemeContextProvider>
<SectionProvider>
<Router>
<App />
</Router>
</SectionProvider>
</ThemeContextProvider>
</AuthContextProvider>
</React.StrictMode>,
);
Expand Down
32 changes: 18 additions & 14 deletions src/pages/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { ToastContainer } from "react-toastify";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import React, { useEffect, useState } from "react";
import React, { useEffect, useState, useContext } from "react";
import { Routes } from "./Routes";
import { app } from "../firebaseApp";
import ThemeContext from "context/ThemeContext";
import LoadingSpinner from "../components/Common/LoadingSpinner/LoadingSpinner";
import "react-toastify/dist/ReactToastify.css";

function App() {
const auth = getAuth(app);
const context = useContext(ThemeContext);
const [init, setInit] = useState<boolean>(false);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(!!auth?.currentUser);

Expand All @@ -24,19 +26,21 @@ function App() {

return (
<>
<ToastContainer
position="top-center"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="light"
/>
{init ? <Routes isAuthenticated={isAuthenticated} /> : <LoadingSpinner/>}
<div className={context.theme === "light" ? "white" : "dark"}>
<ToastContainer
position="top-center"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme={context.theme === "light" ? "white" : "dark"}
/>
{init ? <Routes isAuthenticated={isAuthenticated} /> : <LoadingSpinner/>}
</div>
</>
);
}
Expand Down
12 changes: 8 additions & 4 deletions src/pages/HomePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ interface ButtonProps {
backgroundColor: string;
description: string;
hover: string;
dark: string;
testId: string;
}

function HomePage() {
return (
<div className="w-full h-[calc(100vh-80px)] flex flex-col items-center justify-center gap-[20px]">
<div className="dark:bg-gradient-dark w-full h-[calc(100vh-80px)] flex flex-col items-center justify-center gap-[20px]">
<div className="flex-Center flex-col" data-testid="home">
<img alt="로고" src="/images/rm-logo.png" width="150" height="150" data-testid="logo" />
<span className="text-textPrimary text-3xl md:text-6xl sm:text-5xl font-bold line-lg" data-testid="title">
<span className="text-textPrimary dark:text-textWhite text-3xl md:text-6xl sm:text-5xl font-bold line-lg" data-testid="title">
README-MONSTER
</span>
<p
Expand All @@ -32,6 +33,7 @@ function HomePage() {
url="/editor"
color="text-white"
backgroundColor="bg-textBlue"
dark="bg-darkSecondary"
hover="hover:bg-textBlueHover"
description="시작하기"
testId="firstButton"
Expand All @@ -40,6 +42,7 @@ function HomePage() {
url="/signup"
color="text-textPrimary"
backgroundColor="bg-gray-200"
dark="bg-gray-200"
hover="hover:bg-textgreyHover"
description="더 알아보기"
testId="secondButton"
Expand All @@ -52,7 +55,7 @@ function HomePage() {

export default HomePage;

export function Button({ url, color, backgroundColor, description, hover, testId }: ButtonProps) {
export function Button({ url, color, backgroundColor, description, hover, dark, testId }: ButtonProps) {
const router = useRouter();
const handleClick = () => {
router.push(url);
Expand All @@ -67,7 +70,8 @@ export function Button({ url, color, backgroundColor, description, hover, testId
font-medium text-xl
${backgroundColor}
${hover}
border border-transparent rounded-lg
border-transparent rounded-lg
dark:${dark}
${color}
w-[250px] h-[54px]
justify-center
Expand Down
6 changes: 3 additions & 3 deletions src/pages/LoginPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ const LoginPage = () => {
return (
<div className="mx-auto max-w-screen-xl px-4 py-16 sm:px-6 lg:px-8" data-testid="login">
<div className="mx-auto max-w-lg">
<h1 className="text-center text-2xl font-bold sm:text-3xl h-1px">로그인</h1>
<h1 className="text-center text-2xl dark:text-textWhite font-bold sm:text-3xl h-1px">로그인</h1>

<p className="text-center text-sm text-gray-300 bg-gray-300 mx-4 mt-5 leading-none h-px">
<span className="bg-white p-3">또는</span>
<span className="bg-textWhite dark:bg-darkPrimary p-3">또는</span>
</p>

<form className="mb-0 mt-6 space-y-4 p-4 sm:p-6 lg:p-8" onSubmit={handleSubmit}>
Expand All @@ -113,7 +113,7 @@ const LoginPage = () => {

<button
type="submit"
className="block w-full rounded-lg bg-textBlue px-5 py-3 text-sm font-medium text-white cursor-pointer"
className="block w-full rounded-lg bg-textBlue dark:bg-darkSecondary px-5 py-3 text-sm font-medium text-white cursor-pointer"
data-testid="login-button"
// disabled={Object.keys(errors).length > 0}
>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/SignupPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ function SignupPage() {
return (
<div className="mx-auto max-w-screen-xl px-4 py-16 sm:px-6 lg:px-8" data-testid="signup">
<div className="mx-auto max-w-lg">
<h1 className="text-center text-2xl font-bold sm:text-3xl h-1px">회원가입</h1>
<h1 className="text-center text-2xl dark:text-textWhite font-bold sm:text-3xl h-1px">회원가입</h1>

<p className="text-center text-sm text-gray-300 bg-gray-300 mx-4 mt-5 leading-none h-px">
<span className="bg-white p-3">또는</span>
<span className="bg-textWhite dark:bg-darkPrimary p-3">또는</span>
</p>

<form className="mb-0 mt-6 space-y-4 p-4 sm:p-6 lg:p-8" onSubmit={handleSubmit}>
Expand Down Expand Up @@ -167,7 +167,7 @@ function SignupPage() {

<button
type="submit"
className="block w-full rounded-lg bg-textBlue px-5 py-3 text-sm font-medium text-white cursor-pointer"
className="block w-full rounded-lg bg-textBlue dark:bg-darkSecondary px-5 py-3 text-sm font-medium text-white cursor-pointer"
data-testid="signup-button"
// disabled={Object.keys(errors).length > 0}
>
Expand Down
12 changes: 12 additions & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,16 @@
.editor .w-md-editor-content {
padding: 5px
}

.white {
transition: all 0.25s linear;
background-color: white;
}

.dark {
transition: all 0.25s linear;
background-color: #1e2937;
min-height: 100vh;
}

}
6 changes: 6 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
darkMode: 'class',
theme: {
extend: {
colors: {
Expand All @@ -12,6 +13,11 @@ module.exports = {
textgreyHover: "#E0DEDE",
textWhite: "#FFFFFF",
textBlack: "#000000",
darkPrimary: "#1e2937",
darkSecondary: "#374152",
},
backgroundImage: {
'gradient-dark': 'linear-gradient(#1e2937, #556274) !important', // 새 그라데이션 추가
},
screens: {
mobile: "768px",
Expand Down

0 comments on commit 2b55c5e

Please sign in to comment.