commit 6d0548512000970d2cc2a91324d7dc40de088d57
parent ac571718ef71218b477cc68775093dcb8793f16e
Author: hrryt <harry@mayesfield.uk>
Date: Thu, 30 Jul 2026 14:19:22 +0100
Use 98.css, begin implementing question parameter inputs
Diffstat:
14 files changed, 89 insertions(+), 69 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -2,3 +2,5 @@ node_modules
package-lock.json
www/js
www/css
+www/*.woff
+www/*.woff2
diff --git a/esbuild.json b/esbuild.json
@@ -4,5 +4,9 @@
{ "out": "css/index", "in": "src/styles/index.css" }
],
"bundle": true,
- "outdir": "www"
+ "outdir": "www",
+ "loader": {
+ ".woff": "file",
+ ".woff2": "file"
+ }
}
diff --git a/package.json b/package.json
@@ -1,5 +1,6 @@
{
"dependencies": {
+ "98.css": "^0.1.21",
"kern-typ": "^0.2.0",
"react": "^19.2.8",
"react-dom": "^19.2.8"
diff --git a/src/components/App.jsx b/src/components/App.jsx
@@ -0,0 +1,6 @@
+import * as React from 'react';
+import TestQuestionPanel from './TestQuestionPanel.jsx';
+
+export default function App() {
+ return <TestQuestionPanel />;
+}
diff --git a/src/components/Equation.jsx b/src/components/Equation.jsx
@@ -2,11 +2,11 @@ import * as React from 'react';
import { render } from 'kern-typ';
export default function Equation({ equation, displayMode = false }) {
- const elementRef = React.useRef();
+ const ref = React.useRef(null);
React.useEffect(() => {
- render(equation, elementRef.current, { displayMode: displayMode });
+ render(equation, ref.current, { displayMode: displayMode });
}, [equation]);
- return <div className="Equation" ref={elementRef} />;
+ return <div ref={ref} />;
}
diff --git a/src/components/MultipleSelection.jsx b/src/components/MultipleSelection.jsx
@@ -0,0 +1,15 @@
+import * as React from 'react';
+
+export default function MultipleSelection({ legend, values, labels = values, defaults = values.map(() => true) }) {
+ return (
+ <fieldset ref={ref}>
+ <legend>{legend}</legend>
+ {values.map((value, i) => (
+ <div className="field-row">
+ <input type="checkbox" name={value} defaultChecked={defaults[i]}></input>
+ <label for={value}>{labels[i]}</label>
+ </div>
+ ))}
+ </fieldset>
+ );
+}
diff --git a/src/components/Question.jsx b/src/components/Question.jsx
@@ -3,7 +3,7 @@ import Equation from './Equation.jsx';
export default function Question({ question, answer, showAnswer }) {
return (
- <li className={"Question" + (showAnswer ? " Answer" : "")}>
+ <li>
<Equation equation={showAnswer ? answer : question} />
</li>
);
diff --git a/src/components/QuestionList.jsx b/src/components/QuestionList.jsx
@@ -1,5 +1,5 @@
import * as React from 'react';
export default function QuestionList({ children }) {
- return <ol className="QuestionList">{children}</ol>;
+ return <ol>{children}</ol>;
}
diff --git a/src/components/QuestionPanel.jsx b/src/components/QuestionPanel.jsx
@@ -34,7 +34,7 @@ function shuffleArray(arr, n, seed) {
return Array.from({ length: n }).map(() => arr[getRandomInt(0, max, ++seed)]);
}
-export default function QuestionPanel({ questionLists }) {
+export default function QuestionPanel({ data }) {
const [showAnswers, setShowAnswers] = React.useState(false);
const [seed , setSeed ] = React.useState(Math.random());
@@ -42,7 +42,7 @@ export default function QuestionPanel({ questionLists }) {
function triggerRefresh() { setSeed(getRandomNumber(seed)); }
let current_seed = seed;
- const questions = questionLists.map(questionList => {
+ const questions = data.questionLists.map(questionList => {
const { id: id, n: n, questions: unique_questions } = questionList;
const questions = shuffleArray(unique_questions, n, current_seed);
const randomQuestionList = getQuestionList(id, questions, showAnswers, current_seed);
@@ -50,18 +50,36 @@ export default function QuestionPanel({ questionLists }) {
return randomQuestionList;
});
+ const formRef = React.useRef();
+ function submitForm() { formRef.current.submit(); }
+ function handleSubmit(e) { e.preventDefault(); }
+
return (
- <div className="QuestionPanel">
- <div className="ButtonPanel">
- <button className="RevealButton" onClick={revealAnswers}>
- {showAnswers ? "Hide" : "Show"} Answers
- </button>
- <button className="RefreshButton" onClick={triggerRefresh}>
- Refresh Questions
- </button>
+ <div className="window">
+ <div className="title-bar">
+ <div className="title-bar-text">Questions</div>
+ <div className="title-bar-controls">
+ <button aria-label="Minimize" />
+ <button aria-label="Maximize" />
+ <button aria-label="Close" />
+ </div>
</div>
- <div className="QuestionSet">
- {questions}
+ <div className="window-body">
+ <form ref={formRef} onChange={submitForm} onSubmit={handleSubmit}>
+ <fieldset>
+ <legend>Options</legend>
+ <button onClick={revealAnswers}>
+ {showAnswers ? "Hide" : "Show"} Answers
+ </button>
+ <button onClick={triggerRefresh}>
+ Refresh Questions
+ </button>
+ </fieldset>
+ </form>
+ <br />
+ <div className="field-border">
+ {questions}
+ </div>
</div>
</div>
);
diff --git a/src/components/TestQuestionPanel.jsx b/src/components/TestQuestionPanel.jsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import QuestionPanel from './QuestionPanel.jsx';
-import { questionLists } from '../data/test-question-panel.js';
+import { questionPanel } from '../data/test-question-panel.js';
export default function TestQuestionPanel() {
- return <QuestionPanel questionLists={questionLists} />;
+ return <QuestionPanel data={questionPanel} />;
}
diff --git a/src/data/test-question-panel.js b/src/data/test-question-panel.js
@@ -1,17 +1,19 @@
-export const questionLists = [{
- id: 0,
- n: 10,
- questions: [{
- type: 'quadratic-equation',
- parameters: { factorise: false }
- }, {
- type: 'quadratic-equation',
- parameters: { a: 1, factorise: true }
+export const questionPanel = {
+ inputs: [{
+ id: 'a',
+ legend: 'Quadratic Equations: a',
+ type: 'multiple-selection',
+ values: [1, 2, 3],
+ }],
+ questionLists: [{
+ id: 0,
+ n: 10,
+ questions: [{
+ type: 'quadratic-equation',
+ controlledParameters: { a: 'a' },
+ lockedParameters: { factorise: false },
+ }, {
+ type: 'adding-fractions',
+ }]
}]
-}, {
- id: 1,
- n: 5,
- questions: [{
- type: 'adding-fractions',
- }]
-}]
+}
diff --git a/src/scripts/react-roots.js b/src/scripts/react-roots.js
@@ -1,7 +1,7 @@
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
-import TestQuestionPanel from '../components/TestQuestionPanel.jsx';
+import App from '../components/App.jsx';
function renderComponent(id, component) {
node = document.getElementById(id);
@@ -9,4 +9,4 @@ function renderComponent(id, component) {
root.render(createElement(component));
}
-renderComponent('test-question-panel', TestQuestionPanel);
+renderComponent('app', App);
diff --git a/src/styles/index.css b/src/styles/index.css
@@ -1,21 +1,6 @@
@import 'kern-typ/kern.css';
+@import '98.css';
-html {
- display: table;
- margin: 0 auto;
- background-color: #008080;
-}
-
-body {
- display: table-cell;
- vertical-align: middle;
- width: 100vw;
+.window {
max-width: 800px;
- background-color: #202020;
- color: #c5c5c5;
- padding: 0 1em;
-}
-
-.QuestionSet {
- display: flex;
}
diff --git a/www/index.html b/www/index.html
@@ -5,20 +5,7 @@
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
- <h1>Hello world!</h1>
- <section>
- <h2>Introduction</h2>
- <p>$ x^2 + 5x + 6 $ is an expression.</p>
- $$ x^2 + 5x + 6 = 0 $$
- $$ x = -3 "or" x = -2 $$
- </section>
- <section>
- <h2>Random questions</h2>
- <div id="test-question-panel"></div>
- </section>
- <footer>
- <p>Fin</p>
- </footer>
+ <div id="app"></div>
<script src="js/index.js"></script>
</body>
</html>