fix(curriculum,a11y): improve accessibility of Drum Machine demo (#63050)

Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
This commit is contained in:
Om
2026-01-08 23:03:52 +05:30
committed by GitHub
parent 87a7e19c4b
commit 7f2a1bc6f5

View File

@@ -69,6 +69,15 @@ Inside your `#pad-bank` element you should have nine clickable drum pad elements
assert.lengthOf(document.querySelectorAll('#pad-bank .drum-pad'), 9);
```
Each `.drum-pad` should be a `button` element.
```js
const pads = document.querySelectorAll('.drum-pad');
pads.forEach(pad => {
assert.equal(pad.tagName, 'BUTTON');
});
```
Each `.drum-pad` should have one of the following letters as `innerText`, in order: `Q`, `W`, `E`, `A`, `S`, `D`, `Z`, `X`, `C`.
```js
@@ -178,24 +187,31 @@ assert.lengthOf(collection, 9);
<div class="controls-container">
<div class="control power-control">
<p>Power: <span id="power-status">On</span></p>
<div class="select">
<div class="inner"></div>
</div>
<label class="select">
<span>Power: <span id="power-status">On</span></span>
<span class="toggle-container">
<input type="checkbox" id="power-toggle" checked />
<span class="slider"></span>
</span>
</label>
</div>
<!-- Display for Drum Pad Name and Volume -->
<p id="display"></p>
<div class="volume-slider">
<input type="range" min="0" max="1" step="0.01" value="0.3" />
<label for="volume-control">Volume</label>
<input type="range" id="volume-control" min="0" max="1" step="0.01" value="0.3" />
</div>
<div class="control bank-control">
<p>Bank: <span id="current-bank">Heater Kit</span></p>
<div class="select">
<div class="inner"></div>
</div>
<label class="select">
<span>Bank: <span id="current-bank">Heater Kit</span></span>
<span class="toggle-container">
<input type="checkbox" id="bank-toggle" checked />
<span class="slider"></span>
</span>
</label>
</div>
</div>
</div>
@@ -247,14 +263,27 @@ body {
justify-content: center;
width: 70px;
height: 70px;
background: #444;
background: #666;
border: none;
border-radius: 5px;
font-size: 1.2em;
color: #fff;
cursor: pointer;
font-family: inherit;
}
.drum-pad:hover {
background: #777;
}
.drum-pad:focus-visible {
outline: 2px solid #0d6efd;
outline-offset: 2px;
}
.drum-pad.active {
background: #ffaa33;
color: #000;
}
.controls-container {
@@ -272,22 +301,77 @@ body {
}
.select {
width: 50px;
height: 20px;
background: #555;
border-radius: 10px;
cursor: pointer;
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
width: 100%;
}
.select .inner {
.toggle-container {
position: relative;
display: inline-flex;
align-items: center;
width: 50px;
height: 24px;
flex: 0 0 auto;
}
.toggle-container input[type="checkbox"] {
opacity: 0;
width: 0;
height: 0;
position: absolute;
}
.toggle-container .slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #6c757d; /* default gray for inactive state */
border-radius: 12px;
transition: background 0.25s ease, box-shadow 0.25s ease;
}
.toggle-container .slider::before {
position: absolute;
content: "";
width: 18px;
height: 18px;
background: #ffaa33;
left: 1px;
bottom: 3px;
background: #fff;
border-radius: 50%;
top: 1px;
left: calc(100% - 18px);
transition: transform 0.25s ease, background 0.25s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
/* move knob and set green background */
.toggle-container input:checked + .slider {
background: #28a745;
}
.toggle-container input:checked + .slider::before {
transform: translateX(26px);
}
/* add glow when active */
.toggle-container input#power-toggle:checked + .slider {
box-shadow: 0 0 0 4px rgba(40,167,69,0.12);
}
/* Bank toggle: always show green and glow in both states */
.toggle-container input#bank-toggle + .slider {
background: #28a745;
box-shadow: 0 0 0 4px rgba(40,167,69,0.12);
}
.toggle-container input:focus-visible + .slider {
outline: 2px solid #0d6efd;
outline-offset: 2px;
}
#display {
@@ -300,6 +384,16 @@ body {
width: 100%;
}
.volume-slider {
width: 100%;
}
.volume-slider label {
display: block;
margin-bottom: 5px;
font-size: 0.9em;
}
.volume-slider input[type='range'] {
width: 100%;
-webkit-appearance: none;
@@ -318,6 +412,11 @@ body {
border-radius: 50%;
cursor: pointer;
}
.volume-slider input[type='range']:focus-visible {
outline: 2px solid #0d6efd;
outline-offset: 2px;
}
```
```js
@@ -483,7 +582,7 @@ const renderPadBank = () => {
padBank.innerHTML = '';
state.currentPadBank.forEach(drum => {
const pad = document.createElement('div');
const pad = document.createElement('button');
pad.classList.add('drum-pad');
pad.id = drum.id;
pad.innerText = drum.keyTrigger;
@@ -513,9 +612,6 @@ const powerControl = () => {
: 'Off';
setDisplay('');
const powerSlider = document.querySelector('.power-control .select .inner');
powerSlider.style.left = state.power ? 'calc(100% - 18px)' : '0';
};
const selectBank = () => {
@@ -529,17 +625,16 @@ const selectBank = () => {
renderPadBank();
document.getElementById('current-bank').textContent =
state.currentPadBankId === 'Heater Kit' ? 'Heater Kit' : 'Smooth Piano Kit';
const bankControl = document.querySelector('.bank-control .select .inner');
bankControl.style.left =
state.currentPadBankId === 'Heater Kit' ? 'calc(100% - 18px)' : '0';
};
document
.querySelector('.power-control')
.addEventListener('click', powerControl);
document.querySelector('.bank-control').addEventListener('click', selectBank);
.getElementById('power-toggle')
.addEventListener('change', powerControl);
document
.querySelector('.volume-slider input')
.getElementById('bank-toggle')
.addEventListener('change', selectBank);
document
.getElementById('volume-control')
.addEventListener('input', adjustVolume);
renderPadBank();