Skip to content

feat(editor): View ▸ Canvas appearance — customizable grid & canvas, DAW-style - #300

Merged
byrongamatos merged 1 commit into
mainfrom
feat/canvas-appearance
Jul 16, 2026
Merged

feat(editor): View ▸ Canvas appearance — customizable grid & canvas, DAW-style#300
byrongamatos merged 1 commit into
mainfrom
feat/canvas-appearance

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What

Community fix + feature in one (from #song-editor-feedback):

"can you make the grid lines a little brighter i cane see the 2 3 4 beat grid line" — an EOF charter
"taking it from an Ableton workflow, you can customize the grid like brightness and other stuff" — +1'd

The fix: default beat lines were #16162c at 0.5 px on a #0c0c1c background — invisible on many panels. Defaults are now #20203e at 1 px (beats) / #32325c (measures): visible out of the box.

The feature: View ▸ Canvas appearance… — modeled on Ableton Live 12's Theme ▸ Customization tab (the org's DAW design reference), four live sliders:

  • Grid lines (25–400%) — strength of beat/measure lines and lane separators; the "I can't see the grid" lever
  • Brightness — canvas background lift
  • Color intensity — saturation (0 = grayscale)
  • Hue — palette rotation

Deliberate boundary: only the canvas's structural palette restyles. String/lane colors, drum piece colors, note, selection, and playhead colors carry meaning and never change. The dialog says so.

How

New src/canvas-appearance.js: a named structural palette (CP(name)) + a pure hex→HSL→hex adjustment pipeline (@pure block). Adjusted colors cache per settings generation — steady-state draw cost is one map lookup (no per-frame color math). Settings are a global editor preference (editorCanvasAppearance in localStorage, like editorTheme — the chrome theme deliberately leaves the canvas alone; this is its canvas counterpart), junk-tolerant and clamped. Module is window-guarded so it imports cleanly under node.

Adopters in this PR: draw.js (lanes, piano rows, beat/measure grid, label gutters), drum.js (lane grid), parts-view.js (lanes, headers, downbeat ticks). Remaining surfaces (ruler, tempo lane, annotation lanes, waveform bg) can adopt CP incrementally.

Docs: USER-GUIDE gets a "Canvas appearance" section under The Workspace.

Tests

tests/canvas_appearance.test.mjs12 new: hex↔HSL round-trip, sanitization/clamping (junk → per-field default), adjustment semantics (brightness scaling, grid strength reaching only grid-bucket entries, desaturation, hue rotation ±4°, never-clips-to-white guard), CP cache invalidation on change, and a pin that the default beat line is genuinely brighter than the old #16162c with the measure > beat visual hierarchy intact.

Gates: JS suite green (song_fit's failure reproduces on pristine main — environmental), lint 0 errors / 3 baseline warnings, routes.py untouched.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q

Summary by CodeRabbit

  • New Features
    • Added View ▸ Canvas appearance… with a modal to adjust grid strength, brightness, color intensity, and hue (live updates), plus Reset to defaults.
    • The styling affects canvas structure colors (grid, lanes, separators) while preserving string/note/selection/playhead colors.
  • Bug Fixes
    • Improved default grid visibility by making beat and measure lines brighter and clearer.
  • Documentation
    • Updated the user guide and changelog to explain the new controls.
  • Tests
    • Added regression tests for Canvas appearance behavior and drum beat/measure grid rendering.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 97726dbc-8be2-4fdc-be82-7caedf49498a

📥 Commits

Reviewing files that changed from the base of the PR and between b28f4cd and f7c7899.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • docs/USER-GUIDE.md
  • screen.html
  • src/canvas-appearance.js
  • src/draw.js
  • src/drum.js
  • src/menu-bar.js
  • src/parts-view.js
  • tests/canvas_appearance.test.mjs
  • tests/drum_grid_appearance.test.mjs

📝 Walkthrough

Walkthrough

Changes

The editor now provides persisted canvas appearance controls for grid strength, brightness, color intensity, and hue. A View menu entry and modal expose live updates and reset behavior, while structural canvas rendering uses the adjusted palette across editor, drum, piano-roll, and parts views.

Canvas appearance customization

Layer / File(s) Summary
Appearance settings and palette engine
src/canvas-appearance.js, tests/canvas_appearance.test.mjs
Adds sanitized settings, color conversion and adjustment helpers, persistence, cached palette lookup, and tests for transformations, defaults, caching, and grid brightness.
Appearance dialog and menu wiring
screen.html, src/canvas-appearance.js, src/menu-bar.js, docs/USER-GUIDE.md, CHANGELOG.md
Adds the Canvas Appearance modal, live and reset handlers, View menu entry, and documentation for the controls and structural-only styling behavior.
Structural palette rendering integration
src/draw.js, src/drum.js, src/parts-view.js, tests/drum_grid_appearance.test.mjs
Routes lane, grid, piano-roll, gutter, drum, and parts-view structural colors through CP(...), with drum grid regression coverage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EditorMenu
  participant AppearanceModal
  participant CanvasAppearance
  participant CanvasRenderer
  EditorMenu->>AppearanceModal: open Canvas Appearance
  AppearanceModal->>CanvasAppearance: update slider setting
  CanvasAppearance->>CanvasRenderer: provide adjusted CP palette
  CanvasRenderer->>CanvasRenderer: redraw structural canvas colors
  AppearanceModal->>CanvasAppearance: reset settings
  CanvasAppearance->>CanvasRenderer: redraw defaults
Loading

Possibly related PRs

Suggested reviewers: byrongamatos

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: a new Canvas appearance editor for customizable grid and canvas styling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/canvas-appearance

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 16-22: Update the CHANGELOG entry’s semantic-color exclusion list
to remove “lane,” while retaining the exclusions for string, drum piece, note,
selection, and playhead colors. Keep the structural palette description and
implementation references unchanged.

In `@screen.html`:
- Around line 723-764: The editor-canvas-appearance-modal needs dialog
accessibility and focus management. Add role="dialog", aria-modal="true", and an
accessible name; associate each visible label with its corresponding slider, and
give the close button an aria-label. Update editorShowCanvasAppearance and
editorHideCanvasAppearance to move focus into the modal when opened and restore
it to the triggering control when closed, preserving the existing visibility
behavior.

In `@src/canvas-appearance.js`:
- Around line 36-42: Update _appearanceFieldPure to reject null and blank-string
values before calling Number(value), returning the field’s default for those
inputs. Preserve the existing finite-number validation and range clamping for
valid numeric values.

In `@src/drum.js`:
- Around line 308-311: Update the drum beat rendering loop near the lane
separator to replace hard-coded RGBA colors with CP-based palette lookups, using
CP('gridMeasure') for measure lines and CP('gridBeat') for regular beat lines.
Preserve the existing line classification and ensure grid strength, brightness,
intensity, and hue settings affect both drum grid types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e1bb0bf1-2442-457a-92e3-a05e481850e8

📥 Commits

Reviewing files that changed from the base of the PR and between 35b7632 and 9fc08b4.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • docs/USER-GUIDE.md
  • screen.html
  • src/canvas-appearance.js
  • src/draw.js
  • src/drum.js
  • src/menu-bar.js
  • src/parts-view.js
  • tests/canvas_appearance.test.mjs

Comment thread CHANGELOG.md
Comment thread screen.html Outdated
Comment on lines +723 to +764
<div id="editor-canvas-appearance-modal" class="hidden absolute inset-0 z-50 flex items-center justify-center" style="background:rgba(0,0,0,0.7)">
<div class="bg-dark-700 rounded-xl border border-gray-700 w-full max-w-sm flex flex-col">
<div class="flex items-center justify-between px-4 py-3 border-b border-gray-700">
<span class="text-sm font-medium">Canvas Appearance</span>
<button onclick="editorHideCanvasAppearance()" class="text-gray-500 hover:text-white">&times;</button>
</div>
<div class="p-4 space-y-4">
<div>
<div class="flex justify-between items-baseline mb-1">
<label class="text-xs font-medium text-gray-400">Grid lines</label>
<span id="editor-canvas-app-grid-val" class="text-xs text-gray-500">100%</span>
</div>
<input type="range" id="editor-canvas-app-grid" min="25" max="400" step="5" value="100"
class="w-full" oninput="editorCanvasAppearanceInput('grid', this.value)"
title="Strength of grid lines and lane separators — raise it if beat lines are hard to see">
</div>
<div>
<div class="flex justify-between items-baseline mb-1">
<label class="text-xs font-medium text-gray-400">Brightness</label>
<span id="editor-canvas-app-brightness-val" class="text-xs text-gray-500">100%</span>
</div>
<input type="range" id="editor-canvas-app-brightness" min="50" max="250" step="5" value="100"
class="w-full" oninput="editorCanvasAppearanceInput('brightness', this.value)"
title="Overall canvas background brightness">
</div>
<div>
<div class="flex justify-between items-baseline mb-1">
<label class="text-xs font-medium text-gray-400">Color intensity</label>
<span id="editor-canvas-app-intensity-val" class="text-xs text-gray-500">100%</span>
</div>
<input type="range" id="editor-canvas-app-intensity" min="0" max="200" step="5" value="100"
class="w-full" oninput="editorCanvasAppearanceInput('intensity', this.value)"
title="Color saturation of the canvas palette (0 = grayscale)">
</div>
<div>
<div class="flex justify-between items-baseline mb-1">
<label class="text-xs font-medium text-gray-400">Hue</label>
<span id="editor-canvas-app-hue-val" class="text-xs text-gray-500">0°</span>
</div>
<input type="range" id="editor-canvas-app-hue" min="-180" max="180" step="5" value="0"
class="w-full" oninput="editorCanvasAppearanceInput('hue', this.value)"
title="Hue rotation of the canvas palette (structural colors only — string, note and drum-piece colors keep their meaning)">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and find the modal handlers.
git ls-files | rg '(^|/)screen\.html$|(^|/)(.*\.(js|ts|html))$' >/tmp/files.txt
printf '\n-- screen.html locations --\n'
rg -n "editor-canvas-appearance-modal|editorHideCanvasAppearance|editorCanvasAppearanceInput|Canvas Appearance" screen.html || true

printf '\n-- nearby lines in screen.html --\n'
sed -n '700,790p' screen.html

printf '\n-- search for related JS handlers in repo --\n'
rg -n "function editorHideCanvasAppearance|editorHideCanvasAppearance\s*\(|editorShowCanvasAppearance|editorCanvasAppearanceInput\s*\(" . || true

Repository: got-feedBack/feedBack-plugin-editor

Length of output: 7813


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n-- canvas appearance handlers --\n'
sed -n '180,280p' src/canvas-appearance.js

printf '\n-- search for focus handling and ARIA in modal-related code --\n'
rg -n "aria-|role=|focus\(|activeElement|restore|inert|trap|dialog" src screen.html || true

printf '\n-- inspect any label associations in screen.html --\n'
rg -n "editor-canvas-app-(grid|brightness|intensity|hue)|for=\"editor-canvas-app" screen.html || true

Repository: got-feedBack/feedBack-plugin-editor

Length of output: 41151


Make the Canvas Appearance modal a proper dialog. It still lacks role="dialog"/aria-modal="true", an accessible name, and focus handling on open/close. Associate the four visible labels with their sliders, give the × button an aria-label, and move focus into the dialog on open and back to the trigger on close.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@screen.html` around lines 723 - 764, The editor-canvas-appearance-modal needs
dialog accessibility and focus management. Add role="dialog", aria-modal="true",
and an accessible name; associate each visible label with its corresponding
slider, and give the close button an aria-label. Update
editorShowCanvasAppearance and editorHideCanvasAppearance to move focus into the
modal when opened and restore it to the triggering control when closed,
preserving the existing visibility behavior.

Comment thread src/canvas-appearance.js
Comment thread src/drum.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/drum_grid_appearance.test.mjs (1)

51-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover measure-grid scaling in the slider test.

The test changes the appearance setting but asserts only gridBeat. A regression that leaves measure lines unchanged would still pass, despite both beat and measure grids being part of this feature.

Proposed assertion
     const beatDefault = CP('gridBeat');
+    const measureDefault = CP('gridMeasure');
     setCanvasAppearance('grid', 400);
     const beatBright = CP('gridBeat');
+    const measureBright = CP('gridMeasure');
     assert.notStrictEqual(beatBright, beatDefault); // sanity: slider changed the color
+    assert.notStrictEqual(measureBright, measureDefault);
     const strokes = drive();
     assert.ok(strokes.includes(beatBright),
         `raising Grid lines must brighten the drum beat grid to ${beatBright}, got ${JSON.stringify(strokes)}`);
+    assert.ok(strokes.includes(measureBright),
+        `raising Grid lines must brighten the measure grid to ${measureBright}, got ${JSON.stringify(strokes)}`);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/drum_grid_appearance.test.mjs` around lines 51 - 59, Extend the test
“the Grid-lines slider reaches the drum beat grid” to also capture the default
and updated measure-grid color via CP('gridMeasure'), then assert the driven
strokes include the updated measure color. Keep the existing gridBeat assertions
and slider behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/drum_grid_appearance.test.mjs`:
- Around line 51-59: Extend the test “the Grid-lines slider reaches the drum
beat grid” to also capture the default and updated measure-grid color via
CP('gridMeasure'), then assert the driven strokes include the updated measure
color. Keep the existing gridBeat assertions and slider behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ae654f26-f162-4a58-a685-13dd3898ef66

📥 Commits

Reviewing files that changed from the base of the PR and between 9fc08b4 and e5b03e1.

📒 Files selected for processing (2)
  • src/drum.js
  • tests/drum_grid_appearance.test.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/drum.js

@byrongamatos

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@byrongamatos

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@byrongamatos
byrongamatos force-pushed the feat/canvas-appearance branch from b28f4cd to f7c7899 Compare July 16, 2026 18:48
@byrongamatos
byrongamatos merged commit d154a02 into main Jul 16, 2026
3 of 4 checks passed
@byrongamatos
byrongamatos deleted the feat/canvas-appearance branch July 16, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants