Skip to content

Commit

Permalink
add theme toggler
Browse files Browse the repository at this point in the history
  • Loading branch information
Davi de Medeiros authored and davilima6 committed Sep 20, 2023
1 parent 5b9a220 commit bd16650
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 13 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jigsawer - A Quiz Game</title>
</head>
<body>
<body data-theme="light">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
Expand Down
5 changes: 4 additions & 1 deletion src/components/Answer/Answer.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
}

.answer-wrapper input {
background-color: var(--text-bg);
border: 1px solid var(--text-fg);
color: var(--text-fg);
padding: 0.25rem 0.5rem;
}

.answer-wrapper button {
background-color: var(--text-bg);
border: 1px solid var(--text-fg);
color: var(--text-fg);
color: var(--color-secondary);
padding: 0.25rem 1rem;
}

Expand Down
4 changes: 3 additions & 1 deletion src/components/Challenge/Challenge.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.challenge-wrapper {
align-items: center;
background-color: var(--text-bg);
border: 1px solid var(--text-fg);
border-radius: 5px;
border-radius: 5px 0 0 5px;
color: var(--text-fg);
display: flex;
flex-direction: column;
flex-grow: 3;
Expand Down
1 change: 0 additions & 1 deletion src/components/ChancesLeft/ChancesLeft.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
display: flex;
flex-direction: column;
justify-content: center;
padding-top: 1rem;
}

.chances-left-wrapper h3 {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Score/Score.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
.score-wrapper {
align-items: center;
border-bottom: 1px dashed var(--text-fg);
display: flex;
flex-direction: column;
justify-content: center;
padding-bottom: 1rem;
}

.score-wrapper h3 {
color: var(--text-fg);
font-size: 1rem;
margin: 0;
}

.score-wrapper span {
color: var(--text-fg);
font-size: 4rem;
}
14 changes: 13 additions & 1 deletion src/components/Status/Status.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
.status-wrapper {
background-color: var(--text-bg);
border: 1px solid var(--text-fg);
border-radius: 5px;
border-radius: 0 5px 5px 0;
display: flex;
flex-basis: 200px;
flex-direction: column;
flex-grow: 0;
flex-shrink: 0;
justify-content: space-evenly;
padding: 1rem;
}

.status-wrapper hr {
border: 0;
border-bottom: 1px dashed var(--text-fg);
width: 100%;
}

.status-wrapper span {
color: var(--text-fg);
}
1 change: 1 addition & 0 deletions src/components/Status/Status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function Status({ chancesLeft, points }: Props) {
return (
<aside className="status-wrapper">
<Score amount={points} />
<hr />
<ChancesLeft amount={chancesLeft} />
</aside>
);
Expand Down
36 changes: 36 additions & 0 deletions src/components/ThemeToggler/ThemeToggler.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.theme-toggler-wrapper {
position: fixed;
right: 1rem;
top: 0.5rem;
}

.theme-toggler-wrapper input {
appearance: none;
background-color: var(--text-fg);
border: 1px solid var(--text-bg);
border-radius: 1rem;
cursor: pointer;
display: block;
height: 1rem;
margin: 0;
width: 2.5rem;
}

.theme-toggler-wrapper input::before {
background-color: var(--text-bg);
border: 1px solid var(--text-fg);
border-radius: 50%;
box-shadow: var(--text-bg) 0 1px 4px;
content: "";
height: 1rem;
left: 0;
position: absolute;
top: -1px;
width: 1rem;
}

.theme-toggler-wrapper input:checked::before {
background-color: var(--text-bg);
box-shadow: var(--text-fg) 0 1px 4px;
transform: translateX(1.5rem);
}
43 changes: 43 additions & 0 deletions src/components/ThemeToggler/ThemeToggler.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useEffect, useRef, useState } from 'react';

import './ThemeToggler.css';

type Props = {
onToggle: () => void;
};

const INPUT_NAME = 'theme-toggler';
const ENABLE_LIGHT_MODE_LABEL = 'Enable day mode';
const ENABLE_DARK_MODE_LABEL = 'Enable night mode';

function ThemeToggler({ onToggle }: Props) {
const inputRef = useRef<HTMLInputElement>(null);
const [inputLabel, setInputLabel] = useState(ENABLE_DARK_MODE_LABEL);

useEffect(() => {
if (!window?.matchMedia) {
return;
}

const isSystemDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;

if (isSystemDarkMode) {
inputRef.current?.click();
}
}, []);

function handleClick(): void {
onToggle();
setInputLabel(inputLabel === ENABLE_LIGHT_MODE_LABEL ? ENABLE_DARK_MODE_LABEL : ENABLE_LIGHT_MODE_LABEL);
}

return (
<div className="theme-toggler-wrapper" role="button" tabIndex={0} onClick={handleClick}>
<label htmlFor={INPUT_NAME} aria-label={inputLabel} title={inputLabel}>
<input type="checkbox" id={INPUT_NAME} name={INPUT_NAME} ref={inputRef} />
</label>
</div>
);
}

export default ThemeToggler;
1 change: 1 addition & 0 deletions src/components/ThemeToggler/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ThemeToggler'
20 changes: 17 additions & 3 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,33 @@
}

:root {
background-color: var(--text-bg);
color: var(--text-fg);
color-scheme: light dark;
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: 400;
line-height: 1.5;
}

html,
body {
height: 100%;
}

body {
background-color: var(--text-bg);
margin: 0;
}

body[data-theme='light'] {
--text-bg: var(--color-secondary);
--text-fg: var(--color-primary);
}

body[data-theme='dark'] {
--text-bg: var(--color-primary);
--text-fg: var(--color-secondary);
}

a {
color: #646cff;
}
Expand All @@ -38,7 +52,7 @@ button {
}

@media (prefers-color-scheme: dark) {
:root {
body {
--text-bg: var(--color-primary);
--text-fg: var(--color-secondary);
}
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export type ChallengesData = {
};

export type ChallengesMap = Map<Digest, Challenge>;

export type Theme = "light" | "dark"
2 changes: 2 additions & 0 deletions src/views/App/App.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#root {
display: flex;
height: 100%;
margin: 0 auto;
max-width: 1280px;
padding: 2rem;
Expand All @@ -10,6 +11,7 @@
display: flex;
gap: 2rem;
justify-content: center;
height: 100%;
margin: 0 auto;
min-width: 100%;
}
13 changes: 10 additions & 3 deletions src/views/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from 'react';

import Challenge from '../../components/Challenge';
import Status from '../../components/Status';
import ThemeToggler from '../../components/ThemeToggler';
import './App.css';

const INITIAL_POINTS = 0;
Expand All @@ -11,27 +12,33 @@ function App() {
const [points, setPoints] = useState(INITIAL_POINTS);
const [chancesLeft, setChancesLeft] = useState(INITIAL_CHANCES_LEFT);

function handleHit() {
function handleHit(): void {
setPoints((pointsCur) => pointsCur + 1);
}

function handleMiss() {
function handleMiss(): void {
if (chancesLeft === 0) {
return;
}

setChancesLeft((chancesLeftCur) => chancesLeftCur - 1);
}

function handleGameOver() {
function handleGameOver(): void {
setPoints(INITIAL_POINTS);
setChancesLeft(INITIAL_CHANCES_LEFT);
}

function handleThemeToggle(): void {
const { theme } = document.body.dataset;
document.body.dataset.theme = theme === 'light' ? 'dark' : 'light';
}

const disabled = chancesLeft === 0;

return (
<div className="app-wrapper">
<ThemeToggler onToggle={handleThemeToggle} />
<Challenge onHit={handleHit} onMiss={handleMiss} onGameOver={handleGameOver} disabled={disabled} />
<Status chancesLeft={chancesLeft} points={points} />
</div>
Expand Down

0 comments on commit bd16650

Please sign in to comment.