-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added color game! Will make some updates to this but this is a rough …
…start
- Loading branch information
Showing
21 changed files
with
667 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
build/ | ||
node_modules/ | ||
|
||
**/.DS_Store |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { memo, useCallback, useEffect, useRef, useState } from "react"; | ||
import cn from "./ColorGame.module.scss"; | ||
import { Text } from "app/components"; | ||
import { Section, Space } from "app/Symbols"; | ||
import clsx from "clsx"; | ||
import { Leaderboard } from "./components/Leaderboard/Leaderboard"; | ||
import { | ||
DIGITS, | ||
HexColorInput, | ||
} from "./components/HexColorInput/HexColorInput"; | ||
import { Results } from "./components/Results/Results"; | ||
import Auto from "react-animate-height"; | ||
const generateRandomHexString = () => { | ||
const randomHex = []; | ||
|
||
for (let i = 0; i < 6; i++) { | ||
randomHex.push(DIGITS[Math.floor(Math.random() * 16)]); | ||
} | ||
return randomHex; | ||
}; | ||
|
||
const PADDING = 40; | ||
|
||
export const ColorGame = memo(function ColorGame() { | ||
const [color, setColor] = useState(generateRandomHexString); | ||
const [report, setReport] = useState(); | ||
const [height, setHeight] = useState("auto"); | ||
|
||
const resetColor = useCallback( | ||
() => setColor(generateRandomHexString()), | ||
[] | ||
); | ||
|
||
useEffect(() => { | ||
const element = contentRef.current; | ||
|
||
const resizeObserver = new ResizeObserver(() => { | ||
setHeight(element.clientHeight + PADDING); | ||
}); | ||
|
||
resizeObserver.observe(element); | ||
|
||
return () => resizeObserver.disconnect(); | ||
}, []); | ||
const contentRef = useRef(null); | ||
|
||
return ( | ||
<div className={cn.page}> | ||
<Text | ||
size="XL" | ||
className={clsx(cn.centered, "wait dx bold color blue")} | ||
> | ||
Guess the color | ||
</Text> | ||
|
||
<Auto | ||
duration={500} | ||
height={height} | ||
className={clsx(cn.container, "slim")} | ||
contentRef={contentRef} | ||
> | ||
<div className={clsx(cn.split)}> | ||
<div | ||
className={cn.color} | ||
style={{ backgroundColor: "#" + color.join("") }} | ||
></div> | ||
<HexColorInput | ||
color={color} | ||
setReport={setReport} | ||
resetColor={resetColor} | ||
/> | ||
</div> | ||
{report && <Results report={report} />} | ||
</Auto> | ||
<Leaderboard report={report} /> | ||
</div> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
|
||
.centered { | ||
text-align: center; | ||
} | ||
.page { | ||
min-height: calc(100vh - 88px); | ||
display: grid; | ||
place-content: center; | ||
box-sizing: border-box; | ||
|
||
grid-auto-flow: row; | ||
gap: 20px; | ||
margin: 0 auto; | ||
|
||
padding: 20px; | ||
box-sizing: border-box; | ||
|
||
|
||
.container { | ||
padding: 20px; | ||
border: 2px solid var(--silver); | ||
border-radius: 18px; | ||
|
||
.split { | ||
display: grid; | ||
grid-template-columns: auto 1fr; | ||
gap: 20px; | ||
|
||
.color { | ||
height: 200px; | ||
width: 200px; | ||
border-radius: 8px; | ||
margin-bottom: 0px; | ||
} | ||
|
||
@media screen and (max-width: 900px) { | ||
grid-template-columns: auto; | ||
gap: 20px; | ||
|
||
.color { | ||
width: 100%; | ||
margin: 0 auto; | ||
} | ||
|
||
} | ||
} | ||
} | ||
} |
138 changes: 138 additions & 0 deletions
138
src/app/pages/ColorGame/components/HexColorInput/HexColorInput.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import { createRef, memo, useMemo, useState } from "react"; | ||
import cn from "./HexColorInput.module.scss"; | ||
import clsx from "clsx"; | ||
import { generateReport } from "./generateReport"; | ||
import REFRESH_ICON from "./refresh.png"; | ||
|
||
export const DIGITS = [ | ||
"0", | ||
"1", | ||
"2", | ||
"3", | ||
"4", | ||
"5", | ||
"6", | ||
"7", | ||
"8", | ||
"9", | ||
"A", | ||
"B", | ||
"C", | ||
"D", | ||
"E", | ||
"F", | ||
]; | ||
|
||
const EMPTY_GUESS = ["", "", "", "", "", ""]; | ||
|
||
const focusEndOfInput = (inputEl) => { | ||
inputEl.focus(); | ||
inputEl.setSelectionRange(-1, -1); | ||
}; | ||
|
||
export const HexColorInput = memo(function HexColorInput({ | ||
color, | ||
setReport, | ||
resetColor, | ||
}) { | ||
const [guess, setGuess] = useState(EMPTY_GUESS); | ||
const [input] = useState(() => Array.from({ length: 6 }, createRef)); | ||
|
||
const guessIsValid = useMemo(() => guess.join("").length === 6, [guess]); | ||
|
||
const ignoreEvent = (event) => { | ||
event.preventDefault(); | ||
}; | ||
|
||
const handleSubmit = (event) => { | ||
event.preventDefault(); | ||
if (!guessIsValid) return; | ||
|
||
setReport(generateReport(color, guess)); | ||
}; | ||
|
||
const refresh = () => { | ||
resetColor(); | ||
setGuess(EMPTY_GUESS); | ||
setReport(); | ||
focusEndOfInput(input[0].current); | ||
}; | ||
|
||
const handleChange = (index) => (event) => { | ||
const userKeyInput = event.key.toUpperCase(); | ||
|
||
switch (event.key) { | ||
case "Backspace": | ||
if (index > 0 && !guess[index].length) { | ||
focusEndOfInput(input[index - 1].current); | ||
} | ||
setGuess((prev) => { | ||
const next = [...prev]; | ||
next[!guess[index].length ? index - 1 : index] = ""; | ||
return next; | ||
}); | ||
return; | ||
|
||
case "ArrowLeft": | ||
if (index === 0) return; | ||
focusEndOfInput(input[index - 1].current); | ||
return; | ||
|
||
case "ArrowRight": | ||
if (index > 5) return; | ||
focusEndOfInput(input[index + 1].current); | ||
return; | ||
|
||
default: | ||
if (!DIGITS.includes(userKeyInput)) return; | ||
|
||
setGuess((prev) => { | ||
const next = [...prev]; | ||
next[index] = userKeyInput; | ||
return next; | ||
}); | ||
|
||
if (index > 4) return; | ||
focusEndOfInput(input[index + 1].current); | ||
} | ||
}; | ||
return ( | ||
<form className={cn.container} onSubmit={handleSubmit}> | ||
<div className={cn.input}> | ||
<input | ||
className={cn.underline} | ||
type="text" | ||
contentEditable={false} | ||
value="#" | ||
readOnly | ||
/> | ||
{guess.map((digit, index) => ( | ||
<input | ||
key={index} | ||
ref={input[index]} | ||
type="text" | ||
value={digit} | ||
onChange={ignoreEvent} | ||
onKeyDown={handleChange(index)} | ||
placeholder="F" | ||
/> | ||
))} | ||
</div> | ||
<div className={cn.actions}> | ||
<button | ||
className={clsx(cn.submit, guessIsValid && cn.allowed)} | ||
type="submit" | ||
> | ||
Submit | ||
</button> | ||
<button | ||
className={clsx(cn.retry)} | ||
type="button" | ||
onClick={refresh} | ||
> | ||
<img alt="refresh" src={REFRESH_ICON} /> | ||
</button> | ||
</div> | ||
</form> | ||
); | ||
}); |
Oops, something went wrong.