histogram width divide by mode, not total #2

Merged
christofsteel merged 47 commits from honigle into main 2022-02-02 13:59:36 +01:00
11 changed files with 63 additions and 64 deletions
Showing only changes of commit ffca3337a8 - Show all commits

View file

@ -1,38 +1,3 @@
.App { html.dark {
text-align: center; background-color: rgb(15, 23, 42);
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
} }

View file

@ -1,5 +1,8 @@
import { InformationCircleIcon } from '@heroicons/react/outline' import {
import { ChartBarIcon } from '@heroicons/react/outline' InformationCircleIcon,
ChartBarIcon,
SunIcon,
} from '@heroicons/react/outline'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { Alert } from './components/alerts/Alert' import { Alert } from './components/alerts/Alert'
import { Grid } from './components/grid/Grid' import { Grid } from './components/grid/Grid'
@ -15,9 +18,15 @@ import {
saveGameStateToLocalStorage, saveGameStateToLocalStorage,
} from './lib/localStorage' } from './lib/localStorage'
import './App.css'
const ALERT_TIME_MS = 2000 const ALERT_TIME_MS = 2000
function App() { function App() {
const prefersDarkMode = window.matchMedia(
'(prefers-color-scheme: dark)'
).matches
const [currentGuess, setCurrentGuess] = useState('') const [currentGuess, setCurrentGuess] = useState('')
const [isGameWon, setIsGameWon] = useState(false) const [isGameWon, setIsGameWon] = useState(false)
const [isInfoModalOpen, setIsInfoModalOpen] = useState(false) const [isInfoModalOpen, setIsInfoModalOpen] = useState(false)
@ -26,6 +35,13 @@ function App() {
const [isStatsModalOpen, setIsStatsModalOpen] = useState(false) const [isStatsModalOpen, setIsStatsModalOpen] = useState(false)
const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false) const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false)
const [isGameLost, setIsGameLost] = useState(false) const [isGameLost, setIsGameLost] = useState(false)
const [isDarkMode, setIsDarkMode] = useState(
localStorage.getItem('theme')
? localStorage.getItem('theme') === 'dark'
: prefersDarkMode
? true
: false
)
const [successAlert, setSuccessAlert] = useState('') const [successAlert, setSuccessAlert] = useState('')
const [guesses, setGuesses] = useState<string[]>(() => { const [guesses, setGuesses] = useState<string[]>(() => {
const loaded = loadGameStateFromLocalStorage() const loaded = loadGameStateFromLocalStorage()
@ -44,6 +60,19 @@ function App() {
const [stats, setStats] = useState(() => loadStats()) const [stats, setStats] = useState(() => loadStats())
useEffect(() => {
if (isDarkMode) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
}, [isDarkMode])
const handleDarkMode = (isDark: boolean) => {
setIsDarkMode(isDark)
localStorage.setItem('theme', isDark ? 'dark' : 'light')
}
useEffect(() => { useEffect(() => {
saveGameStateToLocalStorage({ guesses, solution }) saveGameStateToLocalStorage({ guesses, solution })
}, [guesses]) }, [guesses])
@ -114,13 +143,17 @@ function App() {
return ( return (
<div className="py-8 max-w-7xl mx-auto sm:px-6 lg:px-8"> <div className="py-8 max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="flex w-80 mx-auto items-center mb-8"> <div className="flex w-80 mx-auto items-center mb-8">
<h1 className="text-xl grow font-bold">Not Wordle</h1> <h1 className="text-xl grow font-bold dark:text-white">Not Wordle</h1>
<SunIcon
className="h-6 w-6 cursor-pointer dark:stroke-white"
onClick={() => handleDarkMode(!isDarkMode)}
/>
<InformationCircleIcon <InformationCircleIcon
className="h-6 w-6 cursor-pointer" className="h-6 w-6 cursor-pointer dark:stroke-white"
onClick={() => setIsInfoModalOpen(true)} onClick={() => setIsInfoModalOpen(true)}
/> />
<ChartBarIcon <ChartBarIcon
className="h-6 w-6 cursor-pointer" className="h-6 w-6 cursor-pointer dark:stroke-white"
onClick={() => setIsStatsModalOpen(true)} onClick={() => setIsStatsModalOpen(true)}
/> />
</div> </div>

View file

@ -8,13 +8,13 @@ type Props = {
export const Cell = ({ value, status }: Props) => { export const Cell = ({ value, status }: Props) => {
const classes = classnames( const classes = classnames(
'w-14 h-14 border-solid border-2 flex items-center justify-center mx-0.5 text-lg font-bold rounded', 'w-14 h-14 border-solid border-2 flex items-center justify-center mx-0.5 text-lg font-bold rounded dark:text-white',
{ {
'bg-white border-slate-200': !status, 'bg-white dark:bg-slate-900 border-slate-200 dark:border-slate-600': !status,
'border-black': value && !status, 'border-black dark:border-slate-100': value && !status,
'bg-slate-400 text-white border-slate-400': status === 'absent', 'bg-slate-400 dark:bg-slate-700 text-white border-slate-400 dark:border-slate-700': status === 'absent',
'bg-green-500 text-white border-green-500': status === 'correct', 'bg-green-500 text-white border-green-500': status === 'correct',
'bg-yellow-500 text-white border-yellow-500': status === 'present', 'bg-yellow-500 dark:bg-yellow-700 text-white border-yellow-500 dark:border-yellow-700': status === 'present',
'cell-animation': !!value, 'cell-animation': !!value,
} }
) )

View file

@ -19,13 +19,13 @@ export const Key = ({
onClick, onClick,
}: Props) => { }: Props) => {
const classes = classnames( const classes = classnames(
'flex items-center justify-center rounded mx-0.5 text-xs font-bold cursor-pointer select-none', 'flex items-center justify-center rounded mx-0.5 text-xs font-bold cursor-pointer select-none dark:text-white',
{ {
'bg-slate-200 hover:bg-slate-300 active:bg-slate-400': !status, 'bg-slate-200 dark:bg-slate-600 hover:bg-slate-300 active:bg-slate-400': !status,
'bg-slate-400 text-white': status === 'absent', 'bg-slate-400 text-white': status === 'absent',
'bg-green-500 hover:bg-green-600 active:bg-green-700 text-white': 'bg-green-500 hover:bg-green-600 active:bg-green-700 text-white':
status === 'correct', status === 'correct',
'bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white': 'bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 dark:bg-yellow-700 text-white':
status === 'present', status === 'present',
} }
) )

View file

@ -8,7 +8,7 @@ type Props = {
export const AboutModal = ({ isOpen, handleClose }: Props) => { export const AboutModal = ({ isOpen, handleClose }: Props) => {
return ( return (
<BaseModal title="About" isOpen={isOpen} handleClose={handleClose}> <BaseModal title="About" isOpen={isOpen} handleClose={handleClose}>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500 dark:text-gray-300">
This is an open source clone of the game Wordle -{' '} This is an open source clone of the game Wordle -{' '}
<a <a
href="https://github.com/hannahcode/wordle" href="https://github.com/hannahcode/wordle"

View file

@ -46,10 +46,10 @@ export const BaseModal = ({ title, children, isOpen, handleClose }: Props) => {
leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
> >
<div className="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6"> <div className="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6 dark:bg-gray-800">
<div className="absolute right-4 top-4"> <div className="absolute right-4 top-4">
<XCircleIcon <XCircleIcon
className="h-6 w-6 cursor-pointer" className="h-6 w-6 cursor-pointer dark:stroke-white"
onClick={() => handleClose()} onClick={() => handleClose()}
/> />
</div> </div>
@ -57,7 +57,7 @@ export const BaseModal = ({ title, children, isOpen, handleClose }: Props) => {
<div className="text-center"> <div className="text-center">
<Dialog.Title <Dialog.Title
as="h3" as="h3"
className="text-lg leading-6 font-medium text-gray-900" className="text-lg leading-6 font-medium text-gray-900 dark:text-gray-100"
> >
{title} {title}
</Dialog.Title> </Dialog.Title>

View file

@ -9,7 +9,7 @@ type Props = {
export const InfoModal = ({ isOpen, handleClose }: Props) => { export const InfoModal = ({ isOpen, handleClose }: Props) => {
return ( return (
<BaseModal title="How to play" isOpen={isOpen} handleClose={handleClose}> <BaseModal title="How to play" isOpen={isOpen} handleClose={handleClose}>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500 dark:text-gray-300">
Guess the WORDLE in 6 tries. After each guess, the color of the tiles Guess the WORDLE in 6 tries. After each guess, the color of the tiles
will change to show how close your guess was to the word. will change to show how close your guess was to the word.
</p> </p>
@ -21,7 +21,7 @@ export const InfoModal = ({ isOpen, handleClose }: Props) => {
<Cell value="R" /> <Cell value="R" />
<Cell value="Y" /> <Cell value="Y" />
</div> </div>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500 dark:text-gray-300">
The letter W is in the word and in the correct spot. The letter W is in the word and in the correct spot.
</p> </p>
@ -32,7 +32,7 @@ export const InfoModal = ({ isOpen, handleClose }: Props) => {
<Cell value="O" /> <Cell value="O" />
<Cell value="T" /> <Cell value="T" />
</div> </div>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500 dark:text-gray-300">
The letter L is in the word but in the wrong spot. The letter L is in the word but in the wrong spot.
</p> </p>
@ -43,7 +43,7 @@ export const InfoModal = ({ isOpen, handleClose }: Props) => {
<Cell value="U" status="absent" /> <Cell value="U" status="absent" />
<Cell value="E" /> <Cell value="E" />
</div> </div>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500 dark:text-gray-300">
The letter U is not in the word in any spot. The letter U is not in the word in any spot.
</p> </p>
</BaseModal> </BaseModal>

View file

@ -35,16 +35,16 @@ export const StatsModal = ({
return ( return (
<BaseModal title="Statistics" isOpen={isOpen} handleClose={handleClose}> <BaseModal title="Statistics" isOpen={isOpen} handleClose={handleClose}>
<StatBar gameStats={gameStats} /> <StatBar gameStats={gameStats} />
<h4 className="text-lg leading-6 font-medium text-gray-900"> <h4 className="text-lg leading-6 font-medium text-gray-900 dark:text-gray-100">
Guess Distribution Guess Distribution
</h4> </h4>
<Histogram gameStats={gameStats} /> <Histogram gameStats={gameStats} />
{(isGameLost || isGameWon) && ( {(isGameLost || isGameWon) && (
<div className="mt-5 sm:mt-6 columns-2"> <div className="mt-5 sm:mt-6 columns-2 dark:text-white">
<div> <div>
<h5>New word in</h5> <h5>New word in</h5>
<Countdown <Countdown
className="text-lg font-medium text-gray-900" className="text-lg font-medium text-gray-900 dark:text-gray-100"
date={tomorrow} date={tomorrow}
daysInHours={true} daysInHours={true}
/> />

View file

@ -10,7 +10,7 @@ export const Histogram = ({ gameStats }: Props) => {
const maxValue = Math.max(...winDistribution) const maxValue = Math.max(...winDistribution)
return ( return (
<div className="columns-1 justify-left m-2 text-sm"> <div className="columns-1 justify-left m-2 text-sm dark:text-white">
{winDistribution.map((value, i) => ( {winDistribution.map((value, i) => (
<Progress <Progress
key={i} key={i}

View file

@ -12,7 +12,7 @@ const StatItem = ({
value: string | number value: string | number
}) => { }) => {
return ( return (
<div className="items-center justify-center m-1 w-1/4"> <div className="items-center justify-center m-1 w-1/4 dark:text-white">
<div className="text-3xl font-bold">{value}</div> <div className="text-3xl font-bold">{value}</div>
<div className="text-xs">{label}</div> <div className="text-xs">{label}</div>
</div> </div>

View file

@ -1,6 +1,7 @@
module.exports = { module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'], content: ['./src/**/*.{js,jsx,ts,tsx}'],
theme: { darkMode: 'class',
theme: {
extend: {}, extend: {},
}, },
plugins: [], plugins: [],