From 7f2a1bc6f558d941bb581e4ac2cbb44489a2b355 Mon Sep 17 00:00:00 2001
From: Om <130749526+Om7035@users.noreply.github.com>
Date: Thu, 8 Jan 2026 23:03:52 +0530
Subject: [PATCH] fix(curriculum,a11y): improve accessibility of Drum Machine
demo (#63050)
Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
---
.../6762ec275cef87635acc4fe3.md | 159 ++++++++++++++----
1 file changed, 127 insertions(+), 32 deletions(-)
diff --git a/curriculum/challenges/english/blocks/lab-drum-machine/6762ec275cef87635acc4fe3.md b/curriculum/challenges/english/blocks/lab-drum-machine/6762ec275cef87635acc4fe3.md
index be4acc883ad..052738e7482 100644
--- a/curriculum/challenges/english/blocks/lab-drum-machine/6762ec275cef87635acc4fe3.md
+++ b/curriculum/challenges/english/blocks/lab-drum-machine/6762ec275cef87635acc4fe3.md
@@ -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);
@@ -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();