Challenge mode functionality complete; layout updates

This commit is contained in:
Gene Mecija 2020-02-10 17:51:09 -08:00
parent dd077e6d12
commit 113e4a2348
20 changed files with 1100 additions and 272 deletions

View file

@ -40,8 +40,8 @@ export default React.memo(function App() {
<MorseBufferContextProvider> <MorseBufferContextProvider>
<WordListPickerContextProvider> <WordListPickerContextProvider>
<WordFeederContextProvider> <WordFeederContextProvider>
<GameClockContextProvider>
<ChallengeContextProvider> <ChallengeContextProvider>
<GameClockContextProvider>
<SidebarLeft /> <SidebarLeft />
<div id="main-interface"> <div id="main-interface">
<div id="mainOptions"> <div id="mainOptions">
@ -82,8 +82,8 @@ export default React.memo(function App() {
<div id="settings-icon" onClick={toggleRight}><i class="ri-settings-3-line"></i></div> <div id="settings-icon" onClick={toggleRight}><i class="ri-settings-3-line"></i></div>
</div> */} </div> */}
</ChallengeContextProvider>
</GameClockContextProvider> </GameClockContextProvider>
</ChallengeContextProvider>
</WordFeederContextProvider> </WordFeederContextProvider>
</WordListPickerContextProvider> </WordListPickerContextProvider>
</MorseBufferContextProvider> </MorseBufferContextProvider>

View file

@ -1,12 +1,8 @@
import React, {useContext} from 'react'; import React, {useContext} from 'react';
import '../css/App.css'; import '../css/App.css';
import morseCode from '../data/morse-reverse.json'
import ChallengeWord from '../components/ChallengeWord' import ChallengeWord from '../components/ChallengeWord'
import ChallengeBufferDisplay from '../components/ChallengeBufferDisplay'; import ChallengeBufferDisplay from '../components/ChallengeBufferDisplay';
import { MorseBufferContext } from '../contexts/morseBufferContext';
import { WordFeederContext } from '../contexts/wordFeederContext';
import GameClock from '../components/GameClock'; import GameClock from '../components/GameClock';
import { GameClockContext } from '../contexts/gameClockContext';
import { KeyTypeContext } from '../contexts/keyTypeContext'; import { KeyTypeContext } from '../contexts/keyTypeContext';
import StraightKey from '../components/StraightKey'; import StraightKey from '../components/StraightKey';
import ElectronicKey from '../components/ElectronicKey'; import ElectronicKey from '../components/ElectronicKey';
@ -14,102 +10,21 @@ import ChallengeControls from '../components/ChallengeControls';
import { ChallengeContext } from '../contexts/challengeContext'; import { ChallengeContext } from '../contexts/challengeContext';
export default React.memo(function ChallengeMode(props) { export default React.memo(function ChallengeMode() {
console.log('CHALLENGE MODE');
const {word, getNextWord} = useContext(WordFeederContext)
const {clockIsRunning} = useContext(GameClockContext)
const {morseCharBuffer, setMorseCharBuffer} = useContext(MorseBufferContext)
const {keyType} = useContext(KeyTypeContext) const {keyType} = useContext(KeyTypeContext)
const {completeChallenge, cancelChallenge} = useContext(ChallengeContext) const {challengeState, cancelChallenge, morseArray, incorrectMorseIndexes, challengeWordClass} = useContext(ChallengeContext)
let morseArray = morseCharBuffer.split('_').filter(l => l !== '')
let challengeWordClass = ''
let correctCharIndexes = [] // Indexes of correct letters in Challenge Word
let incorrectMorseIndexes = [] // Indexes of incorrect morse characters in morse character buffer
let offset = 0
let challengeLetters
// If no more words in wordlist, feeder returns first word in an array
if (typeof word === 'object') {
completeChallenge()
challengeLetters = word[0].split('')
}
else {
challengeLetters = word.split('')
}
// Iterate through the morse character buffer and compare with each letter of challenge word
morseArray.forEach((item, index) => {
if (morseCharBuffer.slice(-1) === '_') { // If end of morse character
let morseLetter = morseCode[morseArray[index]] || '[?]'
let challengeLetter = challengeLetters[index-offset].toLowerCase()
if (morseLetter === challengeLetter) {
correctCharIndexes.push(index-offset)
document.getElementById('challengeWord').childNodes[index-offset].classList.add('correct')
// incorrectCharIndex = null
}
else {
// incorrectCharIndex = index-offset
incorrectMorseIndexes.push(index)
if (incorrectMorseIndexes.length > 0) {
setMorseCharBuffer(prev => {
let newState = prev.split('_').filter(l => l !== '')
newState.splice(incorrectMorseIndexes[0], 1)
newState = newState.join('_') + '_'
return newState
})
incorrectMorseIndexes.splice(1,incorrectMorseIndexes.length)
}
offset = incorrectMorseIndexes.length
}
}
})
function timeout(delay) {
new Promise((resolve) => {
setTimeout(() => {
resolve()
}, delay)
})
}
// Next word once all correct
if (correctCharIndexes.length === challengeLetters.length) {
//
challengeWordClass = 'correct'
setTimeout(() => {
setMorseCharBuffer('')
morseArray = []
incorrectMorseIndexes = []
correctCharIndexes = []
offset = 0
}, 800)
setTimeout(() => {
getNextWord()
if (document.getElementById('challengeWord') !== null) {
document.getElementById('challengeWord').childNodes.forEach(node => {
node.classList = "cLetter"
})
}
}, 1000)
}
return ( return (
<> <>
{clockIsRunning ? (keyType === "straight" ? {challengeState === 'started' ? (keyType === "straight" ?
<StraightKey /> : <ElectronicKey />) : <></> <StraightKey /> : <ElectronicKey />) : <></>
} }
<ChallengeControls cancelChallenge={cancelChallenge} /> <div id="challenge-header">
<GameClock /> <GameClock />
<ChallengeWord className={challengeWordClass} word={word} /> <ChallengeControls cancelChallenge={cancelChallenge} />
</div>
<ChallengeWord challengeWordClass={challengeWordClass} />
<ChallengeBufferDisplay morseArray={morseArray} incorrectMorseIndexes={incorrectMorseIndexes} /> <ChallengeBufferDisplay morseArray={morseArray} incorrectMorseIndexes={incorrectMorseIndexes} />
</> </>
) )

View file

@ -5,18 +5,18 @@ import { ChallengeContext } from "../contexts/challengeContext"
export default (function ChallengeComplete(props) { export default (function ChallengeComplete(props) {
const {gameClockTime} = useContext(GameClockContext) const {gameClockTime} = useContext(GameClockContext)
const {cancelChallenge} = useContext(ChallengeContext) const {setChallengeState} = useContext(ChallengeContext)
function _continue() { function _continue() {
// setGameClockTime(0) // setGameClockTime(0)
// props.setChallengeState('ready') // props.setChallengeState('ready')
cancelChallenge() setChallengeState('ready')
} }
return ( return (
<div id="challengeComplete" className="notify"> <div id="challengeComplete" className="notify">
<h2>Challenge Complete</h2> <span id="notify-title">Challenge Complete</span>
Challenge completed in {gameClockTime} seconds! <span id="message">Challenge completed in {gameClockTime} seconds!</span>
<button id="continue" onClick={_continue}>Continue</button> <button id="continue" onClick={_continue}>Continue</button>
</div> </div>

View file

@ -4,7 +4,7 @@ export default (function ChallengeControls(props) {
return ( return (
<div id="challengeControls"> <div id="challengeControls">
<button onClick={props.cancelChallenge}>Exit</button> <button onClick={props.cancelChallenge}>Exit Challenge</button>
</div> </div>
) )
}) })

View file

@ -8,7 +8,7 @@ export default (function ChallengeReady() {
return ( return (
<div id="challengeReady" className="notify"> <div id="challengeReady" className="notify">
<h2>Challenge Options</h2> <span id="notify-title">Challenge Options</span>
<WordListPicker /> <WordListPicker />
<button id="startChallenge" onClick={startChallenge}>Start Challenge</button> <button id="startChallenge" onClick={startChallenge}>Start Challenge</button>
</div> </div>

View file

@ -1,9 +1,9 @@
import React, { useContext } from "react" import React, { useContext } from "react"
import { WordFeederContext } from "../contexts/wordFeederContext" import { WordFeederContext } from "../contexts/wordFeederContext"
import { ChallengeContext } from "../contexts/challengeContext"
export default React.memo(function ChallengeWord(props) { export default React.memo(function ChallengeWord(props) {
let challengeWordClass= props.className
const {word} = useContext(WordFeederContext) const {word} = useContext(WordFeederContext)
let challengeLetters let challengeLetters
@ -21,6 +21,6 @@ export default React.memo(function ChallengeWord(props) {
}) })
return ( return (
<div id="challengeWord" className={challengeWordClass}>{spannedWord}</div> <div id="challengeWord" className={props.challengeWordClass}>{spannedWord}</div>
) )
}) })

View file

@ -1,13 +1,14 @@
import React, {useContext} from "react" import React, {useContext} from "react"
import { GameClockContext } from "../contexts/gameClockContext"; import { GameClockContext } from "../contexts/gameClockContext";
function GameClock(props) { export default (function GameClock(props) {
const {gameClockTime} = useContext(GameClockContext) const {gameClockTime} = useContext(GameClockContext)
return ( const minutes = Math.floor(gameClockTime / 60)
<div id="gameClock">{gameClockTime}</div> const seconds = gameClockTime % 60
)
}
export default GameClock return (
<div id="gameClock">Time Elapsed: <span id="clockTime">{minutes} minutes {seconds} seconds</span></div>
)
})

View file

@ -16,20 +16,15 @@ export default React.memo(function Info() {
<h2>Dits and Dahs</h2> <h2>Dits and Dahs</h2>
<p> <p>
<span className="bold">Dit</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('.')}></i><br /> <span className="bold">Dit</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('.')}></i> Denoted as a dot (.), dits are short tones and are base unit of morse code.<br />
Denoted as a dot (.), dits are short tones and are base unit of morse code.<br /> <span className="bold">Dah</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('-')}></i> Denoted as a dash (-), dahs are long tones the length of three dits.
<span className="bold">Dah</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('-')}></i><br />
Denoted as a dash (-), dahs are long tones the length of three dits.
</p> </p>
<h2>Spacing</h2 > <h2>Spacing</h2 >
<p> <p>
<span className="bold">Intra-character Spacing</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('...')}></i><br /> <span className="bold">Intra-character Spacing</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('...')}></i> Silence between dits and dahs the length of one dit. Three dits separated by one-dit-long spaces is an "S".<br />
Silence between dits and dahs the length of one dit. Three dits separated by one-dit-long spaces is an "S".<br /> <span className="bold">Inter-character Spacing</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('. . .')}></i> Silence the length of three dits. Three dits separated by three-dit-long spaces is "EEE".<br />
<span className="bold">Inter-character Spacing</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('. . .')}></i><br /> <span className="bold">Inter-word Spacing</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('././.')}></i> Silence the length of seven dits. Three dits separated by seven-dit-long spaces is "E E E".
Silence the length of three dits. Three dits separated by three-dit-long spaces is "EEE".<br />
<span className="bold">Inter-word Spacing</span> <i className="ri-volume-up-fill" onClick={() => playMorseWord('. /. /.')}></i><br />
Silence the length of seven dits. Three dits separated by seven-dit-long spaces is "E E E".
</p> </p>
<h2>Speed</h2> <h2>Speed</h2>

View file

@ -41,9 +41,9 @@ export default (function MorseHistoryTextBox() {
// } catch {} // } catch {}
return ( return (
<> <div id="morse-history">
<div id="morseHistory-textbox">{text}</div> <div id="morseHistory-textbox">{text}</div>
<button onClick={clearHistory}>Clear History</button> <button id="clear-history" onClick={clearHistory}>Clear History</button>
</> </div>
) )
}) })

View file

@ -50,7 +50,8 @@ export default (function PlayMorseInput() {
<h2>Translate To Morse</h2> <h2>Translate To Morse</h2>
</div> </div>
<div id="input"> <div id="input">
<input type="text" id='morseInput' value={inputValue} onChange={handleChange} placeholder="Type here." maxLength="25"/> <i className="ri-volume-up-fill" onClick={handlePlay}></i> <input type="text" id='morseInput' value={inputValue} onChange={handleChange} placeholder="Type here." maxLength="25"/> <i className="ri-play-fill" onClick={handlePlay}></i>
<i class="ri-stop-fill" onClick={() => playMorseWord('')}></i>
</div> </div>
<div id="morseTranslation"> <div id="morseTranslation">
<span id="morseTrans"> <span id="morseTrans">

View file

@ -18,7 +18,7 @@ export default (function SidebarLeft() {
} else if (e.target.id === 'nav-legend') { } else if (e.target.id === 'nav-legend') {
setSidebarContent('nav-legend') setSidebarContent('nav-legend')
} else { } else {
setSidebarContent('nav-options') setSidebarContent('nav-play')
} }
let navItems = document.querySelector(".navbar").childNodes let navItems = document.querySelector(".navbar").childNodes
@ -35,6 +35,9 @@ export default (function SidebarLeft() {
<div className="sidebar" id="left"> <div className="sidebar" id="left">
<div id="sidebar-container"> <div id="sidebar-container">
<div className="navbar"> <div className="navbar">
<div id="nav-play" className="nav-item" onClick={navClicked}>
Play
</div>
<div id="nav-learn" className="nav-item selected" onClick={navClicked}> <div id="nav-learn" className="nav-item selected" onClick={navClicked}>
Learn Learn
</div> </div>

View file

@ -29,12 +29,19 @@ export default React.memo(function WordListPicker() {
let wordLists = ['alphabet', 'numbers', 'common100', 'test', 'short'] let wordLists = ['alphabet', 'numbers', 'common100', 'test', 'short']
let options = wordLists.map((wl, index) => (<option value={wl} key={index}>{wl.substr(0,1).toUpperCase() + wl.substr(1)}</option>)) let options = wordLists.map((wl, index) => (<option value={wl} key={index}>{wl.substr(0,1).toUpperCase() + wl.substr(1)}</option>))
const metadata = {
'alphabet': {description: 'Each letter of the alphabet', count: 26},
'numbers': {description: '0-9', count: 10},
'common100': {description: '100 most common words', count: 100},
'test': {description: 'A test list', count: 5},
'short': {description: 'A short list', count: 1}
}
return ( return (
<div id="challengeOptions"> <div id="challengeOptions">
<div id="wordListPicker" className="mode-picker"> <div id="wordListPicker" className="mode-picker">
<div id="title"> <div id="title">
Word List Word List:
</div> </div>
<div id="input"> <div id="input">
<select id="wordlist-picker" defaultValue={wordListCategory} onChange={handleClick}> <select id="wordlist-picker" defaultValue={wordListCategory} onChange={handleClick}>
@ -42,9 +49,10 @@ export default React.memo(function WordListPicker() {
</select> </select>
</div> </div>
</div> </div>
<div id="wordOrderPicker" className="mode-picker"> <div id="wordOrderPicker" className="mode-picker">
<div id="title"> <div id="title">
Word Order Word Order:
</div> </div>
<div id="buttons"> <div id="buttons">
<button id="sequential" className="selected" onClick={handleClick}> <button id="sequential" className="selected" onClick={handleClick}>
@ -55,6 +63,23 @@ export default React.memo(function WordListPicker() {
</button> </button>
</div> </div>
</div> </div>
<div id="wordlist-description" className="mode-picker">
<div id="title">
Description:
</div>
<div id="info">
{metadata[wordListCategory]['description']}
</div>
</div>
<div id="wordlist-count" className="mode-picker">
<div id="title">
# of List Items:
</div>
<div id="info">
{metadata[wordListCategory]['count']}
</div>
</div>
</div> </div>
) )
}) })

View file

@ -1,22 +1,42 @@
import React, {useState, useContext} from "react" import React, {useState, useContext} from "react"
import { GameClockContext } from "./gameClockContext" import { GameClockContext } from "./gameClockContext"
import { WordFeederContext } from "./wordFeederContext" import { WordFeederContext } from "./wordFeederContext"
// import { KeyTypeContext } from "./keyTypeContext" import { KeyTypeContext } from "./keyTypeContext";
import { MorseBufferContext } from "./morseBufferContext";
import morseCode from '../data/morse-reverse.json'
const ChallengeContext = React.createContext() const ChallengeContext = React.createContext()
function ChallengeContextProvider(props) { function ChallengeContextProvider(props) {
console.log('ChallengeContextProvider');
const [challengeState, setChallengeState] = useState('ready') const [challengeState, setChallengeState] = useState('ready')
const {startGameClock, stopGameClock, setGameClockTime, intervals} = useContext(GameClockContext)
const {resetFeeder} = useContext(WordFeederContext) const {resetFeeder} = useContext(WordFeederContext)
const {word, getNextWord} = useContext(WordFeederContext)
const {morseCharBuffer, setMorseCharBuffer} = useContext(MorseBufferContext)
let morseArray = morseCharBuffer.split('_').filter(l => l !== '')
let challengeWordClass = ''
let correctCharIndexes = [] // Indexes of correct letters in Challenge Word
let incorrectMorseIndexes = [] // Indexes of incorrect morse characters in morse character buffer
let offset = 0
let challengeLetters
function startChallenge() { function startChallenge() {
setGameClockTime(0) console.log('STARTCHALLENGE');
let countdown let countdown
let count = 3 let count = 3
// Challenge countdown setup
document.getElementById('challengeReady').classList.add('starting') document.getElementById('challengeReady').classList.add('starting')
document.getElementById('challengeReady').innerHTML = `<span id="message">Challenge starting in</span><span id="count">${count}</span>` document.getElementById('challengeReady').innerHTML = `<span id="message">Challenge starting in</span><span id="count">${count}</span>`
// Start Challenge countdown
countdown = setInterval(() => { countdown = setInterval(() => {
count-- count--
if (count === 0) { if (count === 0) {
@ -25,7 +45,7 @@ function ChallengeContextProvider(props) {
clearInterval(countdown) clearInterval(countdown)
setTimeout(() => { setTimeout(() => {
document.getElementById('challenge-overlay').classList.add('hide') document.getElementById('challenge-overlay').classList.add('hide')
startGameClock() // Start Challenge
setChallengeState('started') setChallengeState('started')
}, 900); }, 900);
} }
@ -34,31 +54,92 @@ function ChallengeContextProvider(props) {
} }
function completeChallenge() { function completeChallenge() {
stopGameClock() if (challengeState !== 'completed') {
setChallengeState('completed') setChallengeState('completed')
for (let i = 0; i < intervals.length; i++) { resetFeeder()
clearInterval(intervals[i]); showOverlay()
} }
resetFeeder()
const challengeOverlay = document.getElementById('challenge-overlay')
challengeOverlay.classList.remove('fade')
challengeOverlay.classList.remove('hide')
} }
function cancelChallenge() { function cancelChallenge() {
stopGameClock() if (challengeState !== 'cancelled') {
for (let i = 0; i < intervals.length; i++) { setChallengeState('cancelled')
clearInterval(intervals[i]); resetFeeder()
showOverlay()
} }
setChallengeState('ready') }
resetFeeder()
setGameClockTime(0)
function showOverlay() {
const challengeOverlay = document.getElementById('challenge-overlay') const challengeOverlay = document.getElementById('challenge-overlay')
challengeOverlay.classList.remove('fade') challengeOverlay.classList.remove('fade')
challengeOverlay.classList.remove('hide') challengeOverlay.classList.remove('hide')
} }
// If no more words in wordlist, feeder returns first word in an array
if (typeof word === 'object') {
completeChallenge()
challengeLetters = word[0].split('')
}
else {
challengeLetters = word.split('')
}
// Iterate through the morse character buffer and compare with each letter of challenge word
morseArray.forEach((item, index) => {
if (morseCharBuffer.slice(-1) === '_') { // If end of morse character
let morseLetter = morseCode[morseArray[index]] || '[?]'
let challengeLetter = challengeLetters[index-offset].toLowerCase()
if (morseLetter === challengeLetter) {
correctCharIndexes.push(index-offset)
console.log('morseCharBuffer', morseCharBuffer);
document.getElementById('challengeWord').childNodes[index-offset].classList.add('correct')
// incorrectCharIndex = null
}
else {
// incorrectCharIndex = index-offset
incorrectMorseIndexes.push(index)
if (incorrectMorseIndexes.length > 0) {
setMorseCharBuffer(prev => {
let newState = prev.split('_').filter(l => l !== '')
newState.splice(incorrectMorseIndexes[0], 1)
newState = newState.join('_') + '_'
return newState
})
incorrectMorseIndexes.splice(1,incorrectMorseIndexes.length)
}
offset = incorrectMorseIndexes.length
}
}
})
// Next word once all correct
if (correctCharIndexes.length === challengeLetters.length) {
challengeWordClass = 'correct'
setTimeout(() => {
setMorseCharBuffer('')
morseArray = []
incorrectMorseIndexes = []
offset = 0
if (document.getElementById('challengeWord') !== null) {
document.getElementById('challengeWord').childNodes.forEach(node => {
node.classList = "cLetter"
})
}
}, 800)
setTimeout(() => {
if (correctCharIndexes.length > 0) {
correctCharIndexes = []
getNextWord()
}
}, 1000)
}
return ( return (
<ChallengeContext.Provider value={{ <ChallengeContext.Provider value={{
@ -66,7 +147,10 @@ function ChallengeContextProvider(props) {
setChallengeState: setChallengeState, setChallengeState: setChallengeState,
startChallenge: startChallenge, startChallenge: startChallenge,
completeChallenge: completeChallenge, completeChallenge: completeChallenge,
cancelChallenge: cancelChallenge cancelChallenge: cancelChallenge,
challengeWordClass: challengeWordClass,
morseArray: morseArray,
incorrectMorseIndexes: incorrectMorseIndexes
}}> }}>
{props.children} {props.children}
</ChallengeContext.Provider> </ChallengeContext.Provider>

View file

@ -1,19 +1,20 @@
import React, {useState} from "react" import React, {useState, useContext, useEffect} from "react"
import { ChallengeContext } from "./challengeContext"
// import { KeyTypeContext } from "./keyTypeContext" // import { KeyTypeContext } from "./keyTypeContext"
const GameClockContext = React.createContext() const GameClockContext = React.createContext()
function GameClockContextProvider(props) { function GameClockContextProvider(props) {
const [gameClockTime, setGameClockTime] = useState(0) const [gameClockTime, setGameClockTime] = useState(0)
const [clockIsRunning, setClockIsRunning] = useState(false) const [clockIsRunning, setClockIsRunning] = useState(false)
// const [gameClockTimer, setGameClockTimer] = useState(0)
// let intervals = []
const [intervals, setIntervals] = useState([]) const [intervals, setIntervals] = useState([])
const {challengeState, setChallengeState} = useContext(ChallengeContext)
function startGameClock() { function startGameClock() {
console.log('before clock');
if (!clockIsRunning) { if (!clockIsRunning) {
console.log('after clock');
setClockIsRunning(true) setClockIsRunning(true)
setIntervals(prev => [...prev, (setInterval(() => { setIntervals(prev => [...prev, (setInterval(() => {
if (document.getElementById('gameClock') === null) { if (document.getElementById('gameClock') === null) {
@ -40,6 +41,27 @@ function GameClockContextProvider(props) {
clearInterval(intervals[i]); clearInterval(intervals[i]);
} }
} }
useEffect(() => {
switch (challengeState) {
case 'ready':
setGameClockTime(0)
cleanup()
break
case 'started':
startGameClock()
break
case 'completed':
stopGameClock()
break
case 'cancelled':
stopGameClock()
setChallengeState('ready')
break
default:
return
}
}, [challengeState])
return ( return (

View file

@ -3,6 +3,7 @@ import React, {useState} from "react"
const KeyTypeContext = React.createContext() const KeyTypeContext = React.createContext()
function KeyTypeContextProvider(props) { function KeyTypeContextProvider(props) {
console.log('KeyTypeContextProvider');
const [keyType, setKeyType] = useState('straight') const [keyType, setKeyType] = useState('straight')

View file

@ -3,6 +3,7 @@ import { WordListPickerContext } from "./wordListPickerContext"
const WordFeederContext = React.createContext() const WordFeederContext = React.createContext()
function WordFeederContextProvider(props) { function WordFeederContextProvider(props) {
// let wordList = ['hi', 'morse', 'code', 'hello', 'gene'] // let wordList = ['hi', 'morse', 'code', 'hello', 'gene']
const {wordList, wordListShuffled} = useContext(WordListPickerContext) const {wordList, wordListShuffled} = useContext(WordListPickerContext)

View file

@ -160,6 +160,10 @@ html, body {
border-color: #508090; border-color: #508090;
} }
#main-content .sidebar#left #sidebar-container .navbar .nav-item#nav-play {
display: none;
}
#main-content .sidebar#left #sidebar-container #info-icon { #main-content .sidebar#left #sidebar-container #info-icon {
width: -webkit-fit-content; width: -webkit-fit-content;
width: -moz-fit-content; width: -moz-fit-content;
@ -239,7 +243,7 @@ html, body {
height: fit-content; height: fit-content;
padding: 2.5em; padding: 2.5em;
font-family: "Roboto", sans-serif; font-family: "Roboto", sans-serif;
font-size: 0.9rem; font-size: 1.2rem;
line-height: 1.5em; line-height: 1.5em;
opacity: 100%; opacity: 100%;
-webkit-transition: all 500ms ease-in-out; -webkit-transition: all 500ms ease-in-out;
@ -481,7 +485,22 @@ i[class*="ri-"] {
margin-bottom: 45px; margin-bottom: 45px;
} }
#playMorseInput i:hover { #playMorseInput #input {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: auto;
}
#playMorseInput #input i {
font-size: 1.3em;
display: inline-block;
}
#playMorseInput #input i:hover {
color: goldenrod; color: goldenrod;
} }
@ -491,7 +510,7 @@ i[class*="ri-"] {
border: 1px solid #ddd; border: 1px solid #ddd;
height: 1.5rem; height: 1.5rem;
font-size: 0.9em; font-size: 0.9em;
width: 70%; width: auto;
} }
#playMorseInput #morseTrans { #playMorseInput #morseTrans {
@ -614,6 +633,8 @@ i[class*="ri-"] {
} }
#morseButton { #morseButton {
-ms-touch-action: manipulation;
touch-action: manipulation;
width: 100px; width: 100px;
height: 100px; height: 100px;
margin-top: 30px; margin-top: 30px;
@ -781,18 +802,26 @@ i[class*="ri-"] {
-webkit-box-align: center; -webkit-box-align: center;
-ms-flex-align: center; -ms-flex-align: center;
align-items: center; align-items: center;
padding: 1.5rem; width: 45%;
height: 250px; padding: 1.7em;
background: #fefefe; height: 40%;
margin-top: 30%; background: #eee;
margin-top: 25%;
border-radius: 5px; border-radius: 5px;
-webkit-box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.5); box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.5);
border: 3px solid #666;
}
#challenge-overlay #challengeReady #notify-title, #challenge-overlay #challengeComplete #notify-title {
font-size: 2.5em;
font-weight: bold;
} }
#challenge-overlay #challengeReady #message, #challenge-overlay #challengeComplete #message { #challenge-overlay #challengeReady #message, #challenge-overlay #challengeComplete #message {
font-size: 2em; display: inline-block;
font-weight: bold; text-align: center;
font-size: 1.7em;
} }
#challenge-overlay #challengeReady #count, #challenge-overlay #challengeComplete #count { #challenge-overlay #challengeReady #count, #challenge-overlay #challengeComplete #count {
@ -817,13 +846,24 @@ i[class*="ri-"] {
margin-right: 10px; margin-right: 10px;
font-size: 0.75em; font-size: 0.75em;
color: #333; color: #333;
max-width: 250px;
} }
#challenge-overlay #challengeReady button#startChallenge, #challenge-overlay #challengeReady button#continue, #challenge-overlay #challengeComplete button#startChallenge, #challenge-overlay #challengeComplete button#continue { #challenge-overlay #challengeReady button#startChallenge, #challenge-overlay #challengeReady button#continue, #challenge-overlay #challengeComplete button#startChallenge, #challenge-overlay #challengeComplete button#continue {
font-size: 1.2em; width: 100%;
font-size: 1.7em;
font-weight: bold; font-weight: bold;
padding: 0.3em; padding: 0.3em;
background: #666;
color: goldenrod;
text-transform: uppercase;
letter-spacing: 0.3rem;
}
#challenge-overlay #challengeReady button#startChallenge:active, #challenge-overlay #challengeReady button#continue:active, #challenge-overlay #challengeComplete button#startChallenge:active, #challenge-overlay #challengeComplete button#continue:active {
-webkit-transform: translateY(3px);
transform: translateY(3px);
-webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.2);
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.2);
} }
#challenge-overlay #challengeReady button.selected, #challenge-overlay #challengeComplete button.selected { #challenge-overlay #challengeReady button.selected, #challenge-overlay #challengeComplete button.selected {
@ -832,6 +872,7 @@ i[class*="ri-"] {
} }
#challenge-overlay #challengeReady #challengeOptions, #challenge-overlay #challengeComplete #challengeOptions { #challenge-overlay #challengeReady #challengeOptions, #challenge-overlay #challengeComplete #challengeOptions {
width: 100%;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
@ -842,12 +883,13 @@ i[class*="ri-"] {
-webkit-box-pack: start; -webkit-box-pack: start;
-ms-flex-pack: start; -ms-flex-pack: start;
justify-content: flex-start; justify-content: flex-start;
-webkit-box-align: start; -webkit-box-align: center;
-ms-flex-align: start; -ms-flex-align: center;
align-items: flex-start; align-items: center;
} }
#challenge-overlay #challengeReady #challengeOptions .mode-picker, #challenge-overlay #challengeComplete #challengeOptions .mode-picker { #challenge-overlay #challengeReady #challengeOptions .mode-picker, #challenge-overlay #challengeComplete #challengeOptions .mode-picker {
width: 90%;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
@ -865,7 +907,7 @@ i[class*="ri-"] {
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#title, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#title { #challenge-overlay #challengeReady #challengeOptions .mode-picker div#title, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#title {
font-weight: bold; font-weight: bold;
font-size: 1.08em; font-size: 1.4em;
height: 100%; height: 100%;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
@ -889,45 +931,68 @@ i[class*="ri-"] {
-webkit-box-align: center; -webkit-box-align: center;
-ms-flex-align: center; -ms-flex-align: center;
align-items: center; align-items: center;
height: 100%;
} }
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input { #challenge-overlay #challengeReady #challengeOptions .mode-picker div#buttons button, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#buttons button {
margin-left: 10px; font-size: 1rem;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#info, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#info {
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
-webkit-box-align: center; -webkit-box-align: center;
-ms-flex-align: center; -ms-flex-align: center;
align-items: center; align-items: center;
font-size: 1.2em;
height: 100%;
} }
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input input, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input input { #challenge-overlay #challengeReady #challengeOptions .mode-picker div#input, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input {
width: 50px; margin-left: 10px;
-webkit-appearance: textfield; margin-top: 0.25em;
-moz-appearance: textfield; display: -webkit-box;
appearance: textfield; display: -ms-flexbox;
text-align: center; display: flex;
border-radius: 3px; -webkit-box-align: center;
border: 1px solid #ddd; -ms-flex-align: center;
height: 1.3rem; align-items: center;
font-size: 0.75em; -webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
} }
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input select, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input select { #challenge-overlay #challengeReady #challengeOptions .mode-picker div#input select, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input select {
height: 1.4rem; height: auto;
font-size: 1rem;
} }
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input button, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input button { #challenge-header {
width: 20px; width: 100%;
height: 20px; padding: 1em;
border-radius: 3px; display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
} }
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input button i, #challenge-overlay #challengeComplete #challengeOptions .mode-picker div#input button i { #challenge-header #gameClock {
position: relative; font-size: 1.3em;
left: -1px; }
font-size: 1.1em;
font-weight: bold; #challenge-header #challengeControls button {
border: 0px;
border-radius: 5px;
padding: 0.3em;
font-size: 1.2em;
color: #555;
}
#challenge-header #challengeControls button:hover {
color: maroon;
} }
#challengeWord { #challengeWord {
@ -1209,12 +1274,29 @@ i[class*="ri-"] {
border-radius: 3px; border-radius: 3px;
} }
#morseHistory-textbox { #morse-history {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: end;
-ms-flex-align: end;
align-items: flex-end;
width: 80%;
max-width: 500px;
}
#morse-history #morseHistory-textbox {
background: #f8f8f8; background: #f8f8f8;
border-radius: 5px; border-radius: 5px;
min-height: 4em; min-height: 4em;
width: 80%; width: 100%;
max-width: 500px;
padding: 0.5em; padding: 0.5em;
font-family: Courier; font-family: Courier;
font-size: 1.5rem; font-size: 1.5rem;
@ -1227,7 +1309,7 @@ i[class*="ri-"] {
flex-wrap: wrap; flex-wrap: wrap;
} }
#morseHistory-textbox span { #morse-history #morseHistory-textbox span {
margin: 5px; margin: 5px;
background: #fdfdfd; background: #fdfdfd;
height: 1.5rem; height: 1.5rem;
@ -1347,4 +1429,284 @@ i[class*="ri-"] {
margin-left: 4px; margin-left: 4px;
margin-right: 4px; margin-right: 4px;
} }
@media only screen and (max-width: 415px) {
html, body, #root, #main-interface {
width: 100vw;
overflow: hidden;
}
#header {
font-size: 2.1em;
line-height: 1.2em;
height: auto;
}
#playerAndLegend {
padding: 0 !important;
overflow-x: hidden;
width: 100vw;
}
#playerAndLegend #legend {
width: 100vw;
}
#legend {
margin-top: 0px;
background: #eee;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: space-evenly;
-ms-flex-pack: space-evenly;
justify-content: space-evenly;
}
#legend #legend-title {
margin-left: 0em;
font-size: 1.5em;
font-weight: bold;
margin-bottom: 0.3em;
}
#legend #legend-items {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
height: -webkit-fit-content;
height: -moz-fit-content;
height: fit-content;
margin-bottom: 10px;
}
#legend #legend-items .item, #legend #legend-items span {
cursor: pointer;
}
#legend #legend-items .item {
font-family: "Courier", monospace;
font-size: 0.7em;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 20%;
margin: 5px;
padding: 0.3em;
border: 1px solid #ccc;
border-radius: 3px;
-webkit-transition: all 50ms ease-in-out;
transition: all 50ms ease-in-out;
background: #ddd;
border: 0px;
background: #eee;
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.35), 0px -1px 1px white;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.35), 0px -1px 1px white;
}
#legend #legend-items .item span {
-webkit-transition: all 50ms ease-in-out;
transition: all 50ms ease-in-out;
}
#legend #legend-items .item:active {
-webkit-transform: scale(0.95);
transform: scale(0.95);
border-color: rgba(112, 128, 144, 0.6);
background: #ddd;
}
#legend #legend-items .item:active span:first-child {
background: rgba(112, 128, 144, 0.6);
}
#legend #legend-items .item:hover {
border-color: rgba(112, 128, 144, 0.6);
background: #ddd;
}
#legend #legend-items .item:hover span:first-child {
background: rgba(112, 128, 144, 0.6);
}
#legend #legend-items .item span:first-child {
display: inline-block;
padding: 1px;
width: 1.5em;
background: #d6d6d6;
border-radius: 2px;
font-size: 1.5em;
-webkit-transition: all 75ms ease-in-out;
transition: all 75ms ease-in-out;
}
#legend #legend-items .item span:last-child {
font-weight: bold;
font-size: 1em;
display: inline-block;
padding-left: 5px;
width: 100%;
}
#main-content {
top: 2.5em;
width: 100vw;
}
#main-content .sidebar#left {
min-width: 100vw;
-webkit-transition: all 500ms ease-in-out;
transition: all 500ms ease-in-out;
}
#main-content .sidebar#left.hide {
left: calc(-100vw + 40px);
top: 50px;
overflow-y: hidden;
background: transparent;
-webkit-box-shadow: 0px 0px 0px transparent;
box-shadow: 0px 0px 0px transparent;
}
#main-content .sidebar#left.hide #sidebar-container #sidebar-content #info {
opacity: 0%;
overflow-y: hidden;
}
#main-content .sidebar#left.hide #sidebar-container #info-icon {
background: white;
}
#main-content .sidebar#left.hide #sidebar-container #info-icon::after {
content: ">";
}
#main-content .sidebar#left #sidebar-container {
width: 100%;
padding: 0em;
}
#main-content .sidebar#left #sidebar-container .navbar {
width: 100%;
}
#main-content .sidebar#left #sidebar-container .navbar .nav-item {
width: 25%;
}
#main-content .sidebar#left #sidebar-container .navbar .nav-item#nav-play {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
#main-content .sidebar#left #sidebar-container #info-icon {
display: none;
}
#main-content .sidebar#left #sidebar-container #sidebar-content #info {
width: 100%;
padding: 1em;
}
#main-content #main-interface {
width: 100vw;
left: 0;
}
#main-content #main-interface #morseBufferDisplay {
margin-bottom: 0px;
height: -webkit-fit-content;
height: -moz-fit-content;
height: fit-content;
}
#main-content #main-interface #morseBufferDisplay #overlay {
-webkit-box-shadow: inset 20px 0px 20px -5px #eee;
box-shadow: inset 20px 0px 20px -5px #eee;
}
#main-content #main-interface #morseBufferDisplay #alphanumeric-container {
text-align: center;
max-width: 75%;
display: inline-block;
overflow: hidden;
padding-top: 0px;
}
#main-content #main-interface #morseBufferDisplay #alphanumeric-container #alphanumeric {
height: 4rem;
padding-top: 0.45rem;
font-size: 3rem;
margin-bottom: 0px;
border-radius: 3px;
float: right;
}
#main-content #main-interface * {
z-index: 1000;
}
#main-content #main-interface.expandLeft {
left: 0;
width: 100vw;
}
#main-content #main-interface #morse-history {
width: 95%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
}
#main-content #main-interface #morse-history #morseHistory-textbox {
width: 100%;
overflow-y: scroll;
padding: 5px;
margin: 0px;
min-height: 2.3em;
}
#main-content #main-interface #morse-history #clear-history {
border: 0px;
}
#main-content #main-interface #morseButton {
margin-top: 5px;
}
#main-content #main-interface #mainOptions {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
height: 10em;
width: 100vw;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #title, #main-content #main-interface #mainOptions #options-right .mode-picker #title {
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
width: 5em;
font-weight: bold;
font-size: 1em;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #title span#range, #main-content #main-interface #mainOptions #options-right .mode-picker #title span#range {
display: none;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #buttons button, #main-content #main-interface #mainOptions #options-right .mode-picker #buttons button {
margin: 5px;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #input, #main-content #main-interface #mainOptions #options-right .mode-picker #input {
font-size: 0.8em;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #input input, #main-content #main-interface #mainOptions #options-right .mode-picker #input input {
height: 1.1rem;
font-size: 0.8rem;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #input select, #main-content #main-interface #mainOptions #options-right .mode-picker #input select {
height: 1.4rem;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #input button, #main-content #main-interface #mainOptions #options-right .mode-picker #input button {
width: 1.2em;
height: 1.2em;
border-radius: 3px;
font-size: 1em;
}
#main-content #main-interface #mainOptions #options-left .mode-picker #input button i, #main-content #main-interface #mainOptions #options-right .mode-picker #input button i {
left: -7px;
top: -3px;
font-size: 1rem;
}
#main-content #main-interface #mainOptions #options-left .mode-picker button, #main-content #main-interface #mainOptions #options-right .mode-picker button {
font-size: 0.8em;
color: #333;
}
}
/*# sourceMappingURL=App.css.map */ /*# sourceMappingURL=App.css.map */

File diff suppressed because one or more lines are too long

View file

@ -113,12 +113,12 @@ function useMorsePlayer() {
timeouts.push(setTimeout(() => { timeouts.push(setTimeout(() => {
}, delay)) }, delay))
delay += ditMaxTime*3 delay += ditMaxTime*2
} else if (char === '/') { } else if (char === '/') {
timeouts.push(setTimeout(() => { timeouts.push(setTimeout(() => {
}, delay)) }, delay))
delay += ditMaxTime*7 delay += ditMaxTime*6
} }
} }

View file

@ -141,6 +141,7 @@ html, body {
// margin-top: 450px; // margin-top: 450px;
// box-shadow: inset 0px 3px 3px rgba(0,0,0,0.3); // box-shadow: inset 0px 3px 3px rgba(0,0,0,0.3);
.nav-item { .nav-item {
// border: 1px solid black; // border: 1px solid black;
padding: 10px; padding: 10px;
@ -162,6 +163,9 @@ html, body {
&.selected { &.selected {
border-color: rgb(80, 128, 144); border-color: rgb(80, 128, 144);
} }
&#nav-play {
display: none;
}
} }
} }
@ -220,7 +224,7 @@ html, body {
height: fit-content; height: fit-content;
padding: 2.5em; padding: 2.5em;
font-family: $main-font; font-family: $main-font;
font-size: 0.9rem; font-size: 1.2rem;
line-height: 1.5em; line-height: 1.5em;
opacity: 100%; opacity: 100%;
// overflow-y: scroll; // overflow-y: scroll;
@ -545,30 +549,44 @@ i[class*="ri-"] {
} }
#playMorseInput { #playMorseInput {
// border: 1px solid #bbb;
background: #ddd; background: #ddd;
width: 400px; width: 400px;
height: 10em; height: 10em;
padding: 1em; padding: 1em;
// border: 1px solid #bbb;
border-radius: 5px; border-radius: 5px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
// justify-content: center;
margin-bottom: 45px; margin-bottom: 45px;
// overflow: hidden; // overflow: hidden;
i:hover {
color: goldenrod; #input {
} // border: 1px solid red;
#input input { display: flex;
padding-left: 3px; align-items: center;
border-radius: 3px; width: auto;
border: 1px solid #ddd;
height: 1.5rem; i {
font-size: 0.9em; // background: blue;
width: 70%; font-size: 1.3em;
display: inline-block;
&:hover {
color: goldenrod;
}
}
input {
padding-left: 3px;
border-radius: 3px;
border: 1px solid #ddd;
height: 1.5rem;
font-size: 0.9em;
width: auto;
}
} }
#morseTrans { #morseTrans {
@ -692,6 +710,9 @@ i[class*="ri-"] {
$button-diameter: 100px; $button-diameter: 100px;
$button-radius: 50px; $button-radius: 50px;
#morseButton { #morseButton {
touch-action: manipulation; // Disable double-tap to zoom on mobile devices
width: $button-diameter; width: $button-diameter;
height: $button-diameter; height: $button-diameter;
margin-top: 30px; margin-top: 30px;
@ -886,19 +907,25 @@ $button-radius: 50px;
justify-content: space-evenly; justify-content: space-evenly;
align-items: center; align-items: center;
// width: 400px; width: 45%;
padding: 1.5rem; padding: 1.7em;
height: 250px; height: 40%;
// background: $main-bg-color-light; background: $main-bg-color-light;
background: #fefefe; // background: #fefefe;
margin-top: 30%; margin-top: 25%;
border-radius: 5px; border-radius: 5px;
box-shadow: 0px 5px 15px rgba(0,0,0,0.5); box-shadow: 0px 5px 15px rgba(0,0,0,0.5);
border: 3px solid #666;
#message { #notify-title {
font-size: 2em; font-size: 2.5em;
font-weight: bold; font-weight: bold;
} }
#message {
display: inline-block;
text-align: center;
font-size: 1.7em;
}
#count { #count {
font-size: 4.5em; font-size: 4.5em;
font-weight: bold; font-weight: bold;
@ -917,41 +944,55 @@ $button-radius: 50px;
font-size: 0.75em; font-size: 0.75em;
color: $main-font-color-light; color: $main-font-color-light;
max-width: 250px; // max-width: 250px;
&#startChallenge, &#continue { &#startChallenge, &#continue {
font-size: 1.2em; width: 100%;
font-size: 1.7em;
font-weight: bold; font-weight: bold;
padding: 0.3em; padding: 0.3em;
background: #666;
color: goldenrod;
text-transform: uppercase;
letter-spacing: 0.3rem;
// &:hover {
// text-shadow: 0px 0px 7px rgba(255,255,255,0.3);
// }
&:active {
transform: translateY(3px);
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.2);
}
} }
&.selected { &.selected {
box-shadow: $main-box-shadow-light-selected; box-shadow: $main-box-shadow-light-selected;
} }
} }
#challengeOptions { #challengeOptions {
// border: 1px solid blue;
width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
align-items: flex-start; align-items: center;
// border: 1px solid blue;
.mode-picker { .mode-picker {
// border: 1px solid green; // border: 1px solid green;
// width: 300px; width: 90%;
display: flex; display: flex;
// align-self: flex-start;s
align-content: center; align-content: center;
justify-content: flex-start; justify-content: flex-start;
div { div {
padding: 5px; padding: 5px;
height: 2.4em; height: 2.4em;
} }
div#title { div#title {
font-weight: bold;
font-size: 1.08em;
// border: 1px solid red; // border: 1px solid red;
font-weight: bold;
font-size: 1.4em;
height: 100%; height: 100%;
// width: 40%;
display: flex; display: flex;
padding-left: 0px; padding-left: 0px;
justify-content: flex-start; justify-content: flex-start;
@ -962,36 +1003,61 @@ $button-radius: 50px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
height: 100%;
button {
font-size: 1rem;
// &:hover {
// color: goldenrod;
// }
// &:active {
// box-shadow: $main-box-shadow-light-selected;
// }
}
}
div#info {
// border: 1px solid black;
display: flex;
align-items: center;
font-size: 1.2em;
height: 100%;
} }
div#input { div#input {
margin-left: 10px; margin-left: 10px;
margin-top: 0.25em;
display: flex; display: flex;
align-items: center; align-items: center;
input { justify-content: center;
width: 50px;
appearance: textfield;
text-align: center;
border-radius: 3px;
border: 1px solid #ddd;
height: 1.3rem;
font-size: 0.75em;
}
select { select {
height: 1.4rem; height: auto;
} // padding: 5px;
button { font-size: 1rem;
width: 20px;
height: 20px;
border-radius: 3px;
// line-height: 10px;
i {
position: relative;
left: -1px;
// top: -2px;
font-size: 1.1em;
font-weight: bold;
}
} }
// input {
// width: 50px;
// appearance: textfield;
// text-align: center;
// border-radius: 3px;
// border: 1px solid #ddd;
// height: 1.3rem;
// font-size: 0.75em;
// }
// button {
// width: 20px;
// height: 20px;
// border-radius: 3px;
// // line-height: 10px;
// i {
// position: relative;
// left: -1px;
// // top: -2px;
// font-size: 1.1em;
// font-weight: bold;
// }
// }
} }
} }
} }
@ -999,6 +1065,29 @@ $button-radius: 50px;
} }
#challenge-header {
width: 100%;
padding: 1em;
display: flex;
justify-content: space-between;
#gameClock {
font-size: 1.3em;
}
#challengeControls {
button {
border: 0px;
border-radius: 5px;
padding: 0.3em;
font-size: 1.2em;
color: #555;
&:hover {
color: maroon;
}
}
}
}
#challengeWord { #challengeWord {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -1276,30 +1365,37 @@ $button-radius: 50px;
// font-family: 'Verdana'; // font-family: 'Verdana';
// font-size: 1.5em; // font-size: 1.5em;
// } // }
#morse-history {
#morseHistory-textbox { // border: 1px solid blue;
// border: 1px solid cyan; display: flex;
background: #f8f8f8; flex-direction: column;
border-radius: 5px; justify-content: center;
min-height: 4em; align-items: flex-end;
width: 80%; width: 80%;
max-width: 500px; max-width: 500px;
padding: 0.5em; #morseHistory-textbox {
font-family: Courier; // border: 1px solid cyan;
font-size: 1.5rem; background: #f8f8f8;
display: flex; border-radius: 5px;
align-content: flex-start; min-height: 4em;
flex-wrap: wrap; width: 100%;
padding: 0.5em;
span { font-family: Courier;
margin: 5px; font-size: 1.5rem;
background: #fdfdfd; display: flex;
height: 1.5rem; align-content: flex-start;
padding: 4px; flex-wrap: wrap;
padding-top: 0px;
padding-bottom: 0px; span {
border-radius: $main-border-radius; margin: 5px;
box-shadow: $main-box-shadow-dark; background: #fdfdfd;
height: 1.5rem;
padding: 4px;
padding-top: 0px;
padding-bottom: 0px;
border-radius: $main-border-radius;
box-shadow: $main-box-shadow-dark;
}
} }
} }
@ -1424,4 +1520,326 @@ $button-radius: 50px;
margin-right: 4px; margin-right: 4px;
} }
} }
}
// @media screen and (max-width: 415px) {
@media only screen and (max-width: 415px) {
html, body, #root, #main-interface {
width: 100vw;
overflow: hidden;
}
#header {
font-size: 2.1em;
line-height: 1.2em;
height: auto;
}
#playerAndLegend {
// border: 1px solid blue;
padding: 0 !important;
overflow-x: hidden;
width: 100vw;
#legend {
// margin-left: 2em;
width: 100vw;
}
}
#legend {
margin-top: 0px;
// width: 100%;
// border: 1px solid orange;
background: $main-bg-color-light;
display: flex;
flex-direction: column;
justify-content: space-evenly;
#legend-title {
// border: 1px solid purple;
margin-left: 0em;
font-size: 1.5em;
font-weight: bold;
margin-bottom: 0.3em;
}
#legend-items {
// border: 1px solid blue;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
width: fit-content;
height: fit-content;
margin-bottom: 10px;
.item, span {
cursor: pointer;
}
// &#letters .item {
// width: 17%;
// }
// &#numbers .item {
// width: 18%;
// }
// &#special .item {
// width: 20%;
// }
.item {
font-family: $ditDah-font;
font-size: 0.7em;
// height: 2em;
// height: 2em;
display: flex;
align-items: center;
// justify-content: space-between;
width: 20%;
margin: 5px;
padding: 0.3em;
border: 1px solid #ccc;
border-radius: 3px;
transition: all 50ms ease-in-out;
background: #ddd;
border: 0px;
background: $main-bg-color-light;
box-shadow: $main-box-shadow-light;
span {
transition: all 50ms ease-in-out;
}
&:active {
transform: scale(0.95);
border-color: rgba(112, 128, 144,0.6);
background: #ddd;
span:first-child {
background: rgba(112, 128, 144,0.6);
}
}
&:hover {
border-color: rgba(112, 128, 144,0.6);
background: #ddd;
span:first-child {
background: rgba(112, 128, 144,0.6);
}
}
// button {
// width: 20px;
// height: 20px;
// margin: 4px;
// border: 0px;
// border-radius: 2px;
// box-shadow: $main-box-shadow-light;
// &:active {
// transform: translateY(3px);
// box-shadow: 0px 0px 2px rgba(0,0,0,0.3);
// }
// }
span:first-child {
display: inline-block;
padding: 1px;
width: 1.5em;
background: #d6d6d6;
border-radius: 2px;
font-size: 1.5em;
transition: all 75ms ease-in-out;
}
span:last-child {
// background: #08c;
// font-family: $ditDah-font;
font-weight: bold;
font-size: 1em;
display: inline-block;
padding-left: 5px;
width: 100%;
}
}
}
}
#main-content {
top: 2.5em;
width: 100vw;
.sidebar#left {
min-width: 100vw;
// z-index: -5;
transition: all 500ms ease-in-out;
&.hide {
left: calc(-100vw + 40px);
top: 50px;
overflow-y: hidden;
background: transparent;
box-shadow: 0px 0px 0px transparent;
#sidebar-container {
#sidebar-content #info {
opacity: 0%;
overflow-y: hidden;
}
#info-icon {
// top: calc(100vh - 7em);
background: white;
&::after {
content: ">";
}
}
}
}
#sidebar-container {
width: 100%;
padding: 0em;
.navbar {
width: 100%;
// z-index: 11000;
.nav-item {
width: 25%;
// z-index: 11000;
&#nav-play {
display: flex;
justify-content: center;
}
}
}
#info-icon {
display: none;
}
#sidebar-content {
#info {
width: 100%;
padding: 1em;
}
}
}
}
#main-interface {
width: 100vw;
left: 0;
#morseBufferDisplay {
// background: white;
margin-bottom: 0px;
height: fit-content;
#overlay {
// background: blue;
box-shadow: inset 20px 0px 20px -5px $main-bg-color-light;
}
#alphanumeric-container {
// border: 1px solid red;
text-align: center;
max-width: 75%;
display: inline-block;
overflow: hidden;
padding-top: 0px;
#alphanumeric {
// border: 1px solid blue;
height: 4rem;
padding-top: 0.45rem;
font-size: 3rem;
margin-bottom: 0px;
border-radius: $main-border-radius;
// box-shadow: $main-box-shadow-light;
float: right;
}
}
}
* {
z-index: 1000;
}
&.expandLeft {
left: 0;
width: 100vw;
}
#morse-history {
// border: 1px solid blue;
width: 95%;
display: flex;
justify-content: flex-end;
#morseHistory-textbox {
// border: 1px solid blue;
width: 100%;
overflow-y: scroll;
padding: 5px;
margin: 0px;
min-height: 2.3em;
}
#clear-history {
border: 0px;
}
}
#morseButton {
margin-top: 5px;
}
#mainOptions {
// border: 1px solid red;
flex-direction: column;
height: 10em;
width: 100vw;
#options-left, #options-right {
.mode-picker {
#title {
// border: 1px solid red;
justify-content: flex-end;
width: 5em;
font-weight: bold;
font-size: 1em;
span#range {
display: none;
}
}
#buttons {
button {
margin: 5px;
}
}
#input {
font-size: 0.8em;
input {
height: 1.1rem;
font-size: 0.8rem;
}
select {
height: 1.4rem;
}
button {
width: 1.2em;
height: 1.2em;
border-radius: 3px;
font-size: 1em;
i {
left: -7px;
top: -3px;
font-size: 1rem;
}
}
}
button {
font-size: 0.8em;
color: $main-font-color-light;
}
}
}
}
}
}
} }