Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RM-30]다크모드 기능 구현 #80

Merged
merged 2 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions public/images/dark-to-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/github-logo-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
1 change: 1 addition & 0 deletions public/images/light-github-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/images/light-to-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/mypage-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/mypage-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
Loading