Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -443,16 +443,15 @@ function App({ userId, getToken, isAdmin, onOpenSettings, onRequestList, localMo
{mode === "type" && <h2 className="question-title">Type the word you hear.</h2>}

{mode === "choice" ? (
<div className="choice-wrap">
<div className={`choice-wrap${feedback ? ' is-answered' : ''}`}>
{feedback && <div className={`feedback ${feedback}`} role="status" aria-live="polite"><div className="feedback-copy"><span>{feedback === 'correct' ? <Check size={18}/> : <X size={18}/>}</span><div><strong>{feedback === 'correct' ? 'Correct' : 'Incorrect'}</strong><p>Correct spelling: <b className="correct-spelling">{currentWord}</b></p><p>Your choice: <em>{answer}</em></p></div></div></div>}
<div className="choices">
{choices.map((choice, choiceIndex) => {
const isCorrectChoice = feedback && choice.toLowerCase() === currentWord.toLowerCase();
const isWrongChoice = feedback === "incorrect" && answer === choice;
return <button key={`${choice}-${choiceIndex}`} className={`${answer === choice ? "picked " : ""}${isCorrectChoice ? "right " : ""}${isWrongChoice ? "wrong" : ""}`} disabled={Boolean(feedback)} onClick={() => setAnswer(choice)}><b>{String.fromCharCode(65 + choiceIndex)}</b>{choice}</button>;
return <button key={`${choice}-${choiceIndex}`} className={`${answer === choice ? "picked " : ""}${isCorrectChoice ? "right " : ""}${isWrongChoice ? "wrong" : ""}`} disabled={Boolean(feedback)} onClick={() => checkAnswer(choice)}><b>{String.fromCharCode(65 + choiceIndex)}</b>{choice}</button>;
})}
</div>
{!feedback && <button className="primary check-button" disabled={!answer} onClick={() => checkAnswer()}>Check answer</button>}
</div>
) : (
<div className="type-row"><input autoFocus value={answer} onChange={(event) => setAnswer(event.target.value)} onKeyDown={(event) => event.key === "Enter" && checkAnswer()} placeholder="Type your spelling here" disabled={Boolean(feedback)} /><button className="primary" onClick={() => checkAnswer()}>Check answer</button></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,17 @@ button:disabled { cursor: not-allowed; opacity: .55; }
.question-title, .prompt-sentence { margin: 30px 0 24px; font: 400 43px/1.12 "Libre Caslon Display", Georgia, serif; letter-spacing: -1.5px; }
.prompt-sentence { font-size: 36px; line-height: 1.25; }
.choices { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
.choice-wrap > .feedback { margin: 0 0 18px; }
.choice-wrap { position: relative; isolation: isolate; }
.choice-wrap > .feedback { position: absolute; top: 50%; left: 50%; z-index: 3; width: min(400px, calc(100% - 20px)); margin: 0; transform: translate(-50%, -50%); border: 1px solid #94bba0; box-shadow: 0 18px 45px #17333a40, 0 3px 9px #17333a26; }
.choice-wrap > .feedback.incorrect { border-color: #dcae9e; }
.choice-wrap.is-answered .choices { opacity: .24; filter: blur(1px); }
.feedback-copy .correct-spelling { display: block; margin-top: 4px; color: var(--ink); font-size: 22px; }
.choice-next { margin-top: 22px; }
.choices button { display: flex; align-items: center; gap: 13px; min-height: 64px; padding: 12px 16px; border: 1px solid var(--line); border-radius: 10px; background: white; color: var(--ink); font-weight: 600; text-align: left; }
.choices button:hover, .choices button.picked { border: 2px solid var(--ink); background: #f8f2df; }
.choices button.right { border: 2px solid #5e9c6d; background: #e7f4e9; }
.choices button.wrong { border: 2px solid var(--coral); background: #fff0eb; }
.choices b { display: grid; place-items: center; width: 25px; height: 25px; border: 1px solid #bac6c0; border-radius: 50%; color: #67777a; font-size: 10px; }
.check-button { margin-top: 16px; }
.type-row { display: flex; gap: 10px; }
.type-row input { flex: 1; min-width: 0; padding: 16px 18px; border: 1px solid #bdc9c3; border-radius: 9px; background: white; color: var(--ink); outline-color: var(--ink); }
.hint-controls { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 31px; }
Expand Down
5 changes: 5 additions & 0 deletions local/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# BeeBright releases

## 2.6 bugfix

- Clicking a multiple-choice word checks it immediately. The extra Check answer button is removed from this mode.
- Correct or Incorrect appears on a raised panel in front of the dimmed choices, with the correct spelling above the selected spelling. Next word remains below the panel.

## 2.6

- Origin hints show language paths without historical spellings, roots or cognates. Uncertain histories and compounds remain qualified instead of inventing a borrowing sequence.
Expand Down
2 changes: 1 addition & 1 deletion local/release.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"name":"BeeBright","version":"2.6"}
{"name":"BeeBright","version":"2.6 bugfix"}
3 changes: 2 additions & 1 deletion tools/test_local_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ def test(w):
if mode=='Multiple Choice':
chosen=w.evaluate_js("document.querySelector('.choices button').innerText.substring(1).trim()")
w.evaluate_js("document.querySelector('.choices button').click()")
w.evaluate_js("document.querySelector('.check-button').click()")
wait(w,"document.querySelector('.feedback') !== null")
assert w.evaluate_js("document.querySelector('.check-button')===null && Array.from(document.querySelectorAll('.choices button')).every(b=>b.disabled)")
assert w.evaluate_js("document.querySelector('.choice-wrap > .feedback')!==null && document.querySelector('.feedback').compareDocumentPosition(document.querySelector('.choices')) & Node.DOCUMENT_POSITION_FOLLOWING")
assert w.evaluate_js("(()=>{const panel=document.querySelector('.choice-wrap > .feedback'),choices=document.querySelector('.choices'),p=panel.getBoundingClientRect(),c=choices.getBoundingClientRect();return getComputedStyle(panel).position==='absolute' && Number(getComputedStyle(panel).zIndex)>0 && getComputedStyle(choices).opacity<1 && p.top<c.bottom && p.bottom>c.top && p.left<c.right && p.right>c.left;})()")
assert w.evaluate_js("['Correct','Incorrect'].includes(document.querySelector('.feedback strong').innerText) && document.querySelector('.correct-spelling').innerText.length>0")
assert w.evaluate_js("document.querySelectorAll('.feedback p')[0].innerText.startsWith('Correct spelling:') && document.querySelectorAll('.feedback p')[1].innerText.startsWith('Your choice:')")
assert w.evaluate_js("document.querySelector('.feedback em').innerText")==chosen
Expand Down
Loading