<div id="app"></div>
* {
box-sizing: border-box;
}
.container {
width: 50%;
min-width: 300px;
margin: 0 auto;
margin-top: 64px;
display: flex;
flex-direction: column;
align-items: center;
}
.dice-form {
display: flex;
flex-direction: column;
width: 200px;
margin-bottom: 32px;
}
.dice-form label {
margin-bottom: 16px;
display: flex;
flex-direction: column;
}
.dice-form label input {
margin-top: 8px;
}
.dice-container {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.die {
width: 64px;
height: 64px;
border: 1px solid black;
border-radius: 5px;
margin: 16px;
padding: 8px;
display: flex;
}
.dot-container {
position: relative;
width: 100%;
height: 100%;
}
.dot {
position: absolute;
width: 12px;
height: 12px;
background-color: #000;
border-radius: 50%;
}
.dot.center {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.dot.top-right {
top: 0;
right: 0;
}
.dot.bottom-left {
bottom: 0;
left: 0;
}
.dot.bottom-right {
bottom: 0;
right: 0;
}
.dot.center-left {
top: 50%;
transform: translateY(-50%);
left: 0;
}
.dot.center-right {
top: 50%;
transform: translateY(-50%);
right: 0;
}
const { useEffect, useState } = React;
const DIE_FACES = [
['center'],
['top-right', 'bottom-left'],
['top-right', 'center', 'bottom-left'],
['top-left', 'top-right', 'bottom-left', 'bottom-right'],
['top-left', 'top-right', 'center', 'bottom-left', 'bottom-right'],
['top-left', 'top-right', 'center-left', 'center-right', 'bottom-left', 'bottom-right'],
];
const generateDice = (quantity) => {
const NUM_SIDES = 6;
let emptyDiceArray = new Array(quantity);
return emptyDiceArray.fill().map(_ => Math.ceil(Math.random() * NUM_SIDES));
}
const DiceForm = ({ onSubmit }) => {
const [numDice, setNumDice] = useState(undefined);
const handleSubmit = (e) => {
e.preventDefault();
if (!numDice) {
return;
}
onSubmit(numDice);
}
return (
<form className="dice-form" onSubmit={handleSubmit}>
<label>
Number of dice
<input type="number" min="1" max="99" onChange={(e) => setNumDice(Number(e.target.value))}/>
</label>
<button type="submit" disabled={!numDice}>Roll</button>
</form>
);
}
const Die = ({ value }) => {
const dots = DIE_FACES[value - 1];
return (
<div className={`die face-${value}`}>
<div className="dot-container">
{dots.map(dotPosition => <div className={`dot ${dotPosition}`} />)}
</div>
</div>
);
}
const Dice = ({ values }) => {
return (
<div className="dice-container">
{values.map(value => <Die value={value} />)}
</div>
);
}
const App = () => {
const [diceValues, setDiceValues] = useState(new Array(3).fill(6));
const handleDiceFormSubmit = (numDice) => {
setDiceValues(generateDice(numDice));
}
return (
<div className="container">
<DiceForm onSubmit={handleDiceFormSubmit} />
<Dice values={diceValues} />
</div>
);
}
ReactDOM.render(
<App/>,
document.querySelector('#app')
);
View Compiled
This Pen doesn't use any external CSS resources.