Skip to content

Commit 96c7f24

Browse files
committed
Align MIDI Studio V2 piano keys to the right and improve keyboard realism - PR_26146_044-midi-studio-v2-piano-key-right-alignment
1 parent f702767 commit 96c7f24

3 files changed

Lines changed: 109 additions & 10 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# PR_26146_044 MIDI Studio V2 Piano Key Right Alignment Validation
2+
3+
Status: PASS
4+
5+
## Scope
6+
7+
- Right-aligned MIDI Studio V2 black piano keys within the frozen keyboard column.
8+
- Preserved full-width white/natural keys.
9+
- Filled the unused left area behind black keys with the same white-key background.
10+
- Preserved readable left-aligned note text inside the right-aligned black key surface.
11+
- Preserved frozen keyboard axis behavior, row alignment, square cells, zoom controls, active note highlights without printed note text, multi-note/chord editing, section/loop behavior, and Play/Stop.
12+
13+
## Files Changed
14+
15+
- `tools/midi-studio-v2/styles/midiStudioV2.css`
16+
- `tests/playwright/tools/MidiStudioV2.spec.mjs`
17+
- `docs/dev/reports/PR_26146_044-midi-studio-v2-piano-key-right-alignment_validation.md`
18+
- `docs/dev/reports/coverage_changed_js_guardrail.txt`
19+
- `docs/dev/codex_commands.md`
20+
- `docs/dev/commit_comment.txt`
21+
22+
Review artifacts are generated separately:
23+
24+
- `docs/dev/reports/codex_review.diff`
25+
- `docs/dev/reports/codex_changed_files.txt`
26+
- `docs/dev/reports/playwright_v8_coverage_report.txt`
27+
28+
## Validation Commands
29+
30+
PASS:
31+
32+
```powershell
33+
node --check tests/playwright/tools/MidiStudioV2.spec.mjs
34+
node --check tools/midi-studio-v2/js/controls/InstrumentGridControl.js
35+
node -e "const fs=require('fs'); const p='tools/midi-studio-v2/index.html'; const html=fs.readFileSync(p,'utf8'); if(/<script(?![^>]*\ssrc=)[^>]*>/i.test(html)) throw new Error('Inline script block found'); if(/<style\b/i.test(html)) throw new Error('Inline style block found'); if(/\son[a-z]+\s*=/i.test(html)) throw new Error('Inline event handler found'); console.log('HTML external-only guard passed:', p);"
36+
node -e "const fs=require('fs'); for (const file of ['tools/midi-studio-v2/styles/midiStudioV2.css']) { const text=fs.readFileSync(file,'utf8'); let depth=0; for (const ch of text) { if (ch==='{') depth++; if (ch==='}') depth--; if (depth<0) throw new Error(file+': unexpected }'); } if (depth!==0) throw new Error(file+': unbalanced braces'); console.log(file+': CSS brace check OK'); }"
37+
npx.cmd playwright test tests/playwright/tools/MidiStudioV2.spec.mjs -g "octave timeline freezes compact headers and note labels while active cells stay textless|fast octave note editing supports drag painting keyboard shortcuts selection and timeline scroll sync|renders timing ruler, section navigation, and loop region visualization" --config=codex_playwright_system_chrome.config.cjs --reporter=list --workers=1 --timeout=60000
38+
git diff --check
39+
```
40+
41+
Playwright result:
42+
43+
```text
44+
Running 3 tests using 1 worker
45+
46+
ok 1 MIDI Studio V2 - fast octave note editing supports drag painting keyboard shortcuts selection and timeline scroll sync
47+
ok 2 MIDI Studio V2 - octave timeline freezes compact headers and note labels while active cells stay textless
48+
ok 3 MIDI Studio V2 - renders timing ruler, section navigation, and loop region visualization
49+
50+
3 passed
51+
```
52+
53+
Notes:
54+
55+
- `git diff --check` exited 0. Git emitted line-ending warnings for touched files; no whitespace errors were reported.
56+
- Full samples smoke test was not run.
57+
58+
## Test Evidence
59+
60+
- Right-aligned keys: Playwright verifies white keys remain full-width and black keys have `right: 0`.
61+
- Black-key inset: Playwright verifies the black key is narrower than the white key and has unused left space.
62+
- White bed behind black keys: Playwright verifies the black-key row bed background matches the white-key background.
63+
- Text readability/alignment: Playwright verifies white and black note letters are visible, use readable colors, and black-key text sits inside the right-aligned black-key surface.
64+
- Frozen horizontal behavior: Playwright scrolls horizontally and verifies the keyboard axis remains visible while header/body columns stay aligned.
65+
- Row alignment: Playwright verifies keyboard label rows and timeline cells remain aligned within 1px.
66+
- Active note cells: Playwright toggles a note and verifies the cell text is empty while highlight metadata and the visual marker remain present.
67+
- Play and Stop: targeted Playwright verifies Play enables Stop and Stop re-enables Play.
68+
69+
## Coverage
70+
71+
- No browser runtime JavaScript files changed in this PR.
72+
- `docs/dev/reports/playwright_v8_coverage_report.txt` was still generated by the targeted MIDI Studio V2 Playwright run.
73+
- Coverage is advisory for this CSS/test-only PR.
74+
75+
## Samples
76+
77+
Full samples smoke test: SKIP.
78+
79+
Reason: PR scope is limited to MIDI Studio V2 piano-key styling and targeted Playwright coverage; sample JSON alignment and full samples smoke are explicitly out of scope.
80+
81+
## Manual UAT
82+
83+
1. Open MIDI Studio V2 and import the UAT manifest.
84+
2. Confirm the Studio tab Octave Timeline keyboard column has full-width white keys and right-aligned inset black keys.
85+
3. Confirm the area left of each black key looks like the white-key bed.
86+
4. Scroll horizontally and vertically, edit a few notes, then confirm Play and Stop still work.

tests/playwright/tools/MidiStudioV2.spec.mjs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,20 +1041,27 @@ test.describe("MIDI Studio V2", () => {
10411041
const blackLabelRect = blackLabel.getBoundingClientRect();
10421042
const whiteCellRect = whiteCell.getBoundingClientRect();
10431043
const blackCellRect = blackCell.getBoundingClientRect();
1044+
const labelWidth = firstLabel.getBoundingClientRect().width;
1045+
const blackKeyRight = Number.parseFloat(blackKeyStyle.right);
1046+
const blackKeyWidth = Number.parseFloat(blackKeyStyle.width);
10441047
return {
10451048
alternatingRowsDiffer: getComputedStyle(firstRow).backgroundColor !== getComputedStyle(secondRow).backgroundColor,
1049+
blackBedBackground: blackLabelStyle.backgroundImage || blackLabelStyle.backgroundColor,
10461050
blackBackground: blackKeyStyle.backgroundImage || blackKeyStyle.backgroundColor,
10471051
blackClass: blackLabel.className,
10481052
blackColor: blackLabelStyle.color,
10491053
blackJustifyItems: blackLabelStyle.justifyItems,
1050-
blackKeyLeft: Number.parseFloat(blackKeyStyle.left),
1054+
blackKeyInsetLeft: labelWidth - blackKeyWidth - blackKeyRight,
1055+
blackKeyRight,
10511056
blackKeyTop: Number.parseFloat(blackKeyStyle.top),
1052-
blackKeyWidth: Number.parseFloat(blackKeyStyle.width),
1057+
blackKeyWidth,
10531058
blackKind: blackLabel.dataset.keyKind,
10541059
blackLabelHeight: blackLabelRect.height,
1060+
blackLabelRight: blackLabelRect.right,
10551061
blackLabelText: blackLabel.textContent,
10561062
blackTextColor: blackTextStyle.color,
10571063
blackTextLeft: blackText.getBoundingClientRect().left,
1064+
blackTextRight: blackText.getBoundingClientRect().right,
10581065
blackTextVisible: blackText.getBoundingClientRect().width > 0,
10591066
blackTextAlign: blackLabelStyle.textAlign,
10601067
borderRightWidth: getComputedStyle(firstNote).borderRightWidth,
@@ -1091,7 +1098,7 @@ test.describe("MIDI Studio V2", () => {
10911098
whiteRowHeightDelta: Math.abs(whiteLabelRect.height - whiteCellRect.height),
10921099
blackRowDelta: Math.abs(blackLabelRect.top - blackCellRect.top),
10931100
blackRowHeightDelta: Math.abs(blackLabelRect.height - blackCellRect.height),
1094-
labelWidth: firstLabel.getBoundingClientRect().width,
1101+
labelWidth,
10951102
topScrollbarHeight: topScrollbar.getBoundingClientRect().height
10961103
};
10971104
});
@@ -1115,6 +1122,7 @@ test.describe("MIDI Studio V2", () => {
11151122
expect(gridLayout.whiteLabelText).toBe("C5");
11161123
expect(gridLayout.blackLabelText).toBe("C#5");
11171124
expect(gridLayout.whiteBackground).not.toBe(gridLayout.blackBackground);
1125+
expect(gridLayout.blackBedBackground).toBe(gridLayout.whiteBackground);
11181126
expect(gridLayout.whiteColor).not.toBe(gridLayout.blackColor);
11191127
expect(gridLayout.whiteTextVisible).toBe(true);
11201128
expect(gridLayout.blackTextVisible).toBe(true);
@@ -1133,11 +1141,13 @@ test.describe("MIDI Studio V2", () => {
11331141
expect(gridLayout.whiteKeyLeft).toBe(0);
11341142
expect(gridLayout.whiteKeyTop).toBe(0);
11351143
expect(Math.abs(gridLayout.whiteKeyWidth - gridLayout.labelWidth)).toBeLessThanOrEqual(1);
1136-
expect(gridLayout.blackKeyLeft).toBeGreaterThan(0);
1144+
expect(gridLayout.blackKeyRight).toBe(0);
1145+
expect(gridLayout.blackKeyInsetLeft).toBeGreaterThan(0);
11371146
expect(gridLayout.blackKeyTop).toBeLessThan(0);
11381147
expect(gridLayout.blackKeyWidth).toBeLessThan(gridLayout.whiteKeyWidth);
11391148
expect(gridLayout.whiteTextLeft).toBeGreaterThanOrEqual(gridLayout.whiteKeyLeft);
1140-
expect(gridLayout.blackTextLeft).toBeGreaterThan(gridLayout.blackKeyLeft);
1149+
expect(gridLayout.blackTextLeft).toBeGreaterThan(gridLayout.blackKeyInsetLeft);
1150+
expect(gridLayout.blackTextRight).toBeLessThanOrEqual(gridLayout.blackLabelRight);
11411151
expect(gridLayout.whiteRowDelta).toBeLessThanOrEqual(1);
11421152
expect(gridLayout.blackRowDelta).toBeLessThanOrEqual(1);
11431153
expect(gridLayout.whiteRowHeightDelta).toBeLessThanOrEqual(1);

tools/midi-studio-v2/styles/midiStudioV2.css

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -795,26 +795,29 @@ body[data-tool-id="midi-studio-v2"] #instrumentGridContent {
795795
}
796796

797797
.midi-studio-v2__octave-row-label--black-key {
798-
background: #f8fafc;
798+
background: linear-gradient(90deg, #ffffff 0%, #f8fafc 78%, #dbeafe 100%);
799799
border-right-color: #020617;
800800
color: #f8fafc;
801801
justify-items: start;
802802
z-index: 6;
803803
}
804804

805805
.midi-studio-v2__octave-row-label--black-key .midi-studio-v2__octave-row-label-text {
806-
padding-left: 0.95rem;
806+
box-sizing: border-box;
807+
justify-self: end;
808+
padding-left: 0.4rem;
807809
text-shadow: 0 1px 1px rgba(2, 6, 23, 0.9);
810+
width: 64%;
808811
}
809812

810813
.midi-studio-v2__octave-row-label--black-key::before {
811814
background: linear-gradient(90deg, #020617 0%, #020617 68%, #1e293b 100%);
812815
border: 1px solid #020617;
813-
border-left: 0;
814-
border-radius: 0 4px 4px 0;
816+
border-radius: 4px 0 0 4px;
815817
box-shadow: 0 2px 4px rgba(2, 6, 23, 0.38), inset -1.15rem 0 0 rgba(2, 6, 23, 0.96), inset 0 -1px 0 rgba(248, 250, 252, 0.18);
816818
bottom: -12%;
817-
left: 0.58rem;
819+
left: auto;
820+
right: 0;
818821
top: -12%;
819822
width: 64%;
820823
}

0 commit comments

Comments
 (0)