Skip to content

Commit fbeb9b5

Browse files
committed
Add Theme Switcher
1 parent 72a7b94 commit fbeb9b5

File tree

14 files changed

+168
-72
lines changed

14 files changed

+168
-72
lines changed

src/app/App.css

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
.App {
2-
text-align: center;
2+
text-align: center;
33
}
44

55
.App-logo {
6-
height: 40vmin;
7-
pointer-events: none;
6+
height: 40vmin;
7+
pointer-events: none;
88
}
99

1010
@media (prefers-reduced-motion: no-preference) {
11-
.App-logo {
12-
animation: App-logo-spin infinite 20s linear;
13-
}
11+
.App-logo {
12+
animation: App-logo-spin infinite 20s linear;
13+
}
1414
}
1515

1616
.App-header {
17-
background-color: #282c34;
18-
min-height: 100vh;
19-
display: flex;
20-
flex-direction: column;
21-
align-items: center;
22-
justify-content: center;
23-
font-size: calc(10px + 2vmin);
24-
color: white;
17+
background-color: var(--background-color);
18+
min-height: 100vh;
19+
display: flex;
20+
flex-direction: column;
21+
align-items: center;
22+
justify-content: center;
23+
font-size: calc(10px + 2vmin);
24+
color: var(--color);
2525
}
2626

2727
.App-link {
28-
color: #61dafb;
28+
color: #61dafb;
2929
}
3030

3131
@keyframes App-logo-spin {
32-
from {
33-
transform: rotate(0deg);
34-
}
35-
to {
36-
transform: rotate(360deg);
37-
}
32+
from {
33+
transform: rotate(0deg);
34+
}
35+
to {
36+
transform: rotate(360deg);
37+
}
3838
}

src/app/App.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,26 @@ import React from 'react';
22
import logo from './logo.svg';
33
import './App.css';
44

5+
import { ThemeProvider } from '../shared/providers/ThemeProvider';
6+
import { ThemeSwitcher } from '../shared/theme-switcher/ThemeSwitcher';
7+
58
function App() {
69
return (
7-
<div className="App">
8-
<header className="App-header">
9-
<img src={logo} className="App-logo" alt="logo" />
10-
<p>
10+
<ThemeProvider>
11+
<div className="App">
12+
<header className="App-header">
13+
<ThemeSwitcher />
14+
<img src={logo} className="App-logo" alt="logo" />
1115
<h1>Игорь Аралов ([email protected])</h1>
1216
<p>Научиться разрабатывать веб-приложения при помощи React</p>
1317
<p>
1418
Профессионально работаю SQL разработчиком уже 10 лет и принимаю участие в разработке десктопного приложения
1519
на Delphi
1620
</p>
1721
<p>Интересуюсь фронтенд и фуллстек разработкой на js/ts</p>
18-
</p>
19-
</header>
20-
</div>
22+
</header>
23+
</div>
24+
</ThemeProvider>
2125
);
2226
}
2327

src/app/index.css

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1+
[data-theme='light'] {
2+
--background-color: #fff;
3+
--color: #000;
4+
--logo-bg-color: #f4f4f4;
5+
--logo-text-color: #333;
6+
}
7+
8+
[data-theme='dark'] {
9+
--background-color: #333;
10+
--color: #fff;
11+
--logo-bg-color: #333;
12+
--logo-text-color: #f4f4f4;
13+
}
14+
115
body {
2-
margin: 0;
3-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto',
4-
'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
5-
'Helvetica Neue', sans-serif;
6-
-webkit-font-smoothing: antialiased;
7-
-moz-osx-font-smoothing: grayscale;
16+
margin: 0;
17+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
18+
'Droid Sans', 'Helvetica Neue', sans-serif;
19+
-webkit-font-smoothing: antialiased;
20+
-moz-osx-font-smoothing: grayscale;
821
}
922

1023
code {
11-
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12-
monospace;
24+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
1325
}

src/shared/header/Header.module.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
.header {
2+
display:flex;
3+
justify-content: space-between;
24
position: -webkit-sticky;
35
position: sticky;
46
top: 0;
5-
background-color: #333;
7+
background-color: var(--header-bg-color);
68
color: white;
79
padding: 10px;
810
min-height: 50px;

src/shared/header/Header.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import React from 'react';
22
import { Logo } from '../logo/Logo';
3+
import { ThemeSwitcher } from '../theme-switcher/ThemeSwitcher';
34
import s from './Header.module.scss';
45

5-
type HeaderProps = {
6+
export type HeaderProps = {
67
showLogo: boolean;
78
};
89

9-
export const Header = ({ showLogo = true }: HeaderProps) => <div className={s.header}>{showLogo && <Logo />}</div>;
10+
export const Header = ({ showLogo = true }: HeaderProps) => (
11+
<div className={s.header}>
12+
{showLogo && <Logo />}
13+
<ThemeSwitcher />
14+
</div>
15+
);
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.content {
22
margin: 0;
33
padding: 20px;
4-
background-color: #f4f4f4;
4+
background-color: var(--layout-bg-color);
5+
color: var(--color);
56
}

src/shared/logo/Logo.module.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
.logo {
22
width: 80px;
33
height: 50px;
4-
background-color: #f4f4f4;
4+
background-color: var(--logo-bg-color);
55
border-radius: 50%;
66
display: flex;
77
justify-content: center;
88
align-items: center;
9-
color: #333;
9+
color: var(--logo-text-color);
1010
font-family: 'Courier New', Courier, monospace;
1111
font-size: 1.35rem;
1212
font-weight: bold;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react';
2+
3+
type Theme = 'dark' | 'light';
4+
5+
type ThemeContextType = { theme: Theme; toggleTheme: () => void };
6+
7+
type ThemeProviderProps = {
8+
children: ReactNode;
9+
};
10+
11+
const ThemeContext = createContext<ThemeContextType>(null);
12+
13+
export const useTheme = () => useContext(ThemeContext);
14+
15+
export const ThemeProvider = ({ children }: ThemeProviderProps) => {
16+
const [theme, setTheme] = useState<Theme>('light');
17+
18+
useEffect(() => {
19+
document.documentElement.setAttribute('data-theme', theme);
20+
}, [theme]);
21+
22+
const toggleTheme = () => {
23+
setTheme((prevTheme) => (prevTheme === 'dark' ? 'light' : 'dark'));
24+
};
25+
26+
return <ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>;
27+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
import { useTheme } from '../providers/ThemeProvider';
3+
import { Button } from '../button/Button';
4+
5+
export const ThemeSwitcher = () => {
6+
const { theme, toggleTheme } = useTheme();
7+
8+
return <Button onClick={toggleTheme}>Switch to {theme === 'light' ? 'Dark' : 'Light'} Theme</Button>;
9+
};

src/stories/Header.stories.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)