Skip to content

Ci/pr category check#1

Merged
Ashutoshx7 merged 223 commits intomasterfrom
ci/pr-category-check
Mar 4, 2026
Merged

Ci/pr category check#1
Ashutoshx7 merged 223 commits intomasterfrom
ci/pr-category-check

Conversation

@Ashutoshx7
Copy link
Owner

@Ashutoshx7 Ashutoshx7 commented Mar 4, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Progressive Web App (PWA) installation support
    • Added record mode selection (canvas-only or with toolbars)
    • Added keyboard navigation for toolbar controls and dropdowns
    • Added language preference persistence via browser storage
  • Bug Fixes

    • Fixed focus outline visibility improvements for keyboard navigation
    • Fixed canvas height calculations on mobile devices
    • Fixed Lilypond export pitch transformations
    • Improved clipboard copy reliability with fallback support
    • Enhanced dark mode styling for table elements
  • Documentation

    • Updated contribution guidelines with deployment instructions
    • Added production build optimization strategy documentation
  • Tests

    • Added end-to-end (Cypress) test automation

varruunnn and others added 30 commits February 7, 2026 22:45
…onsole-log

Remove debug console.log from toolbar play handler
chore: remove debug console statements from js/palette.js
… Context Menu (sugarlabs#5599)

* Manage click listeners to prevent duplicates

* Forgot to Close trashViewClickHandler function
* fix(graphics): add SVG output support for Bezier curves

* fix(svg): start bezier path at turtle position to preserve initial tangent

* fix: svg output tally with shown output

* formatting code
…ics (sugarlabs#5606)

* fix: replace loose equality operators with strict equality in SaveInterface.js and block.js

* fix: use strict equality where behavior is unchanged
…abs#5642)

* fix: resolve initialization crashes and loading screen issues

- Restore missing createArtwork method in turtles.js that was causing
  TypeError during turtle initialization
- Add guard clause in doSearch to prevent crash when searchWidget is
  undefined
- Add robust null checks in showContents to prevent crashes on missing
  DOM elements and ensure loading screen is properly hidden
- Add RequireJS shim for constraints.js to depend on interface.js,
  fixing 'JSInterface is not defined' ReferenceError
- Add safe fallback for DEFAULTVOLUME in turtle-singer.js to handle
  module loading order issues

These fixes address race conditions and missing methods that were
preventing the application from fully loading and causing the
'Combining math and music...' loading screen to persist.

* style: format files with prettier

* fix(playback): resolve turtle cache infinite loop and missing bpm constant

* style: fix formatting in js files
…garlabs#5575)

* Remove tuner test helper functions

Remove the testTuner and testSpecificFrequency methods from the Synth() class. The helper functions of these tests create an audio context, oscillator, and gain node to play the test frequencies for verification of the manual tuner. This is more for ad-hoc tests rather than runtime.

* Add tuner AudioContext tests; remove debug logs
This PR fixes a UI state inconsistency where the Stop button failed to update its visual state (turning red) when music playback was initiated using the Space key.
…overage

test: add unit tests for p5-adapter factory and window bindings
…y-debug-console-log

fix: remove debug console.log from KeySignatureEnv initialization
…asic-coverage

test: add tuner and sample preload edge case coverage for synthutils
…-message-scope

test: Enhance error scope validation in AST2BlockList tests
omsuneri and others added 26 commits February 26, 2026 02:25
…tests

test: add unit tests for Reflection widget
…Manager-tests

Add IndexedDB integration tests for Planet CacheManager.js
The crescendo end listener pops crescendoDelta and
crescendoInitialVolume but never pops inCrescendo, causing
it to grow unboundedly and trigger spurious volume resets
on subsequent notes.

Signed-off-by: Ady0333 <adityashinde1525@gmail.com>
…arlabs#5929)

* fix: reduce canvas and bitmap memory by lazy-caching grids and shrinking scroll buffer

- Remove eager bitmap.cache() from _createGrid() — 8 grids were each
  allocating a 1200x900x4 (~4.3 MB) backing canvas at startup even
  though at most 1 grid is visible at a time (~35 MB wasted)
- Add cache(0,0,1200,900) in _show*() methods so grids are only cached
  when made visible, and uncache() in _hide*() to free the backing
  canvas immediately when hidden
- Skip trashed blocks in clearCache() to avoid re-creating backing
  canvases for invisible blocks on every theme/resize event
- Uncache trashed block containers in sendStackToTrash() and delete
  their blockArt/blockCollapseArt SVG strings to free memory
- Cap trashStacks undo history at 100 entries to prevent unbounded
  growth during long editing sessions
- Reduce scroll canvas from 3x to 2x viewport dimensions in
  doScrollXY(), saving ~40 MB at 1920x1080 (75 MB -> 33 MB)
- Update scroll boundary clamps to match the new 2x canvas size

Estimated RAM savings: ~70-120 MB depending on viewport size and
number of trashed blocks.

* fix: stop calling updateCache() on uncached accidental bitmaps — fixes grid display

* fix: guard updateCache() for uncached blocks and re-cache on restore from trash
…oad-coverage

Test: Improve boundary.js coverage – image onload callback
- Add PR Category section to PR template with 5 categories (Bug Fix, Feature, Performance, Tests, Documentation)

- Add GitHub Actions workflow that validates PR category selection

- Auto-apply matching repo labels (Issue-Bug, Issue-Enhancement, Issue-Performance, Issue-Testing, Issue-Documentation)

- Auto-remove labels when categories are unchecked

- Uses pull_request_target for fork PR compatibility
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Sorry, we are unable to review this pull request

The GitHub API does not allow us to fetch diffs exceeding 20000 lines

@Ashutoshx7 Ashutoshx7 merged commit 283a7b7 into master Mar 4, 2026
6 of 8 checks passed
@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c5fcc4bc-e649-4c30-9725-2a1d60e08dcd

📥 Commits

Reviewing files that changed from the base of the PR and between 81cefcb and 5980640.

⛔ Files ignored due to path filters (10)
  • dist/css/style.css is excluded by !**/dist/**
  • images/loading-animation-ja.svg is excluded by !**/*.svg
  • loading-animation-ja.png is excluded by !**/*.png
  • msie_flashFallback/as3/.DS_Store is excluded by !**/.DS_Store
  • msie_flashFallback/as3/meSpeakFallback/.DS_Store is excluded by !**/.DS_Store
  • msie_flashFallback/as3/meSpeakFallback/src/.DS_Store is excluded by !**/.DS_Store
  • msie_flashFallback/as3/meSpeakFallback/src/org/.DS_Store is excluded by !**/.DS_Store
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/.DS_Store is excluded by !**/.DS_Store
  • msie_flashFallback/meSpeakFallback.swf is excluded by !**/*.swf
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (142)
  • .github/PULL_REQUEST_TEMPLATE/generic.md
  • .github/workflows/pr-category-check.yml
  • .github/workflows/pr-cypress-e2e.yml
  • CONTRIBUTING.md
  • Docs/PRODUCTION_BUILD_STRATEGY.md
  • css/activities.css
  • css/darkmode.css
  • css/style.css
  • cypress/e2e/main.cy.js
  • env.js
  • examples/test-suite.html
  • index.html
  • index.js
  • js/LogoDependencies.js
  • js/SaveInterface.js
  • js/__tests__/IntervalsBlocks.test.js
  • js/__tests__/SaveInterface.test.js
  • js/__tests__/activity_context_regression.test.js
  • js/__tests__/boundary.test.js
  • js/__tests__/jseditor_console.test.js
  • js/__tests__/loader.test.js
  • js/__tests__/logo-dependencies.test.js
  • js/__tests__/logo.test.js
  • js/__tests__/logoconstants.test.js
  • js/__tests__/macros.test.js
  • js/__tests__/p5-adapter.test.js
  • js/__tests__/p5-sound-adapter.test.js
  • js/__tests__/palette.test.js
  • js/__tests__/toolbar.test.js
  • js/__tests__/trash.test.js
  • js/__tests__/turtle-painter.test.js
  • js/__tests__/turtle-singer.test.js
  • js/__tests__/turtle.test.js
  • js/__tests__/turtledefs.test.js
  • js/__tests__/turtles.test.js
  • js/activity-context.js
  • js/activity.js
  • js/block.js
  • js/blocks.js
  • js/blocks/EnsembleBlocks.js
  • js/blocks/IntervalsBlocks.js
  • js/blocks/MediaBlocks.js
  • js/blocks/MeterBlocks.js
  • js/blocks/ProgramBlocks.js
  • js/blocks/WidgetBlocks.js
  • js/blocks/__tests__/ProgramBlocks.test.js
  • js/blocks/__tests__/WidgetBlocks.test.js
  • js/js-export/__tests__/ast2blocklist.test.js
  • js/js-export/__tests__/export.test.js
  • js/js-export/__tests__/generate.test.js
  • js/js-export/__tests__/interface.test.js
  • js/js-export/interface.js
  • js/loader.js
  • js/logo.js
  • js/logoconstants.js
  • js/macros.js
  • js/p5-sound-adapter.js
  • js/palette.js
  • js/piemenus.js
  • js/toolbar.js
  • js/turtle-painter.js
  • js/turtle-singer.js
  • js/turtleactions/DictActions.js
  • js/turtleactions/MeterActions.js
  • js/turtleactions/OrnamentActions.js
  • js/turtleactions/PitchActions.js
  • js/turtleactions/VolumeActions.js
  • js/turtleactions/__tests__/OrnamentActions.test.js
  • js/turtleactions/__tests__/PitchActions.test.js
  • js/turtledefs.js
  • js/turtles.js
  • js/utils/__tests__/mathutils.test.js
  • js/utils/__tests__/musicutils.test.js
  • js/utils/__tests__/synthutils.test.js
  • js/utils/__tests__/tonemock.js
  • js/utils/__tests__/utils.test.js
  • js/utils/musicutils.js
  • js/utils/synthutils.js
  • js/utils/utils.js
  • js/widgets/PhraseMakerAudio.js
  • js/widgets/PhraseMakerGrid.js
  • js/widgets/PhraseMakerUI.js
  • js/widgets/PhraseMakerUtils.js
  • js/widgets/__tests__/PhraseMakerGrid.test.js
  • js/widgets/__tests__/PhraseMakerUI.test.js
  • js/widgets/__tests__/PhraseMakerUtils.test.js
  • js/widgets/__tests__/aidebugger.test.js
  • js/widgets/__tests__/arpeggio.test.js
  • js/widgets/__tests__/help.test.js
  • js/widgets/__tests__/jseditor.test.js
  • js/widgets/__tests__/oscilloscope.test.js
  • js/widgets/__tests__/phrasemaker.test.js
  • js/widgets/__tests__/pitchdrummatrix.test.js
  • js/widgets/__tests__/pitchstaircase.test.js
  • js/widgets/__tests__/reflection.test.js
  • js/widgets/__tests__/temperament.test.js
  • js/widgets/__tests__/tempo.test.js
  • js/widgets/__tests__/timbre.test.js
  • js/widgets/__tests__/widgetWindows.test.js
  • js/widgets/aiwidget.js
  • js/widgets/arpeggio.js
  • js/widgets/help.js
  • js/widgets/jseditor.js
  • js/widgets/legobricks.js
  • js/widgets/musickeyboard.js
  • js/widgets/oscilloscope.js
  • js/widgets/phrasemaker.js
  • js/widgets/pitchdrummatrix.js
  • js/widgets/pitchstaircase.js
  • js/widgets/reflection.js
  • js/widgets/statistics.js
  • js/widgets/statistics.test.js
  • js/widgets/temperament.js
  • js/widgets/timbre.js
  • js/widgets/widgetWindows.js
  • lib/mespeak.js
  • lib/mespeak_config.json
  • lib/sw.js
  • lib/voices/en/en.json
  • lib/webL10n.js
  • lib/webL10n.sugarizer.js
  • localization.ini
  • msie_flashFallback/as3/meSpeakFallback/src/meSpeakFallback.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/WavSound.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/WavSoundChannel.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/WavSoundPlayer.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/core/AudioSamples.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/core/AudioSetting.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/format/riff/Chunk.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/format/riff/LIST.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/format/riff/RIFF.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/format/wav/Wav.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/format/wav/chunk/WavdataChunk.as
  • msie_flashFallback/as3/meSpeakFallback/src/org/as3wavsound/sazameki/format/wav/chunk/WavfmtChunk.as
  • msie_flashFallback/flashFallback.js
  • msie_flashFallback/index.html
  • package.json
  • planet/index.html
  • planet/js/ServerInterface.js
  • planet/js/__tests__/CacheManager.test.js
  • scripts/analyze-production-assets.js
  • sw.js

📝 Walkthrough

Walkthrough

This pull request introduces substantial enhancements across multiple systems: GitHub Actions workflows for PR validation and E2E testing, PWA support with install prompts, ActivityContext singleton for centralized activity management, comprehensive test coverage expansion, async/fetch-based HTTP handling, keyboard navigation in the toolbar, audio voice tracking improvements, block system refactoring with metadata caching, SVG/Bezier rendering enhancements, and responsive pie menu sizing. Documentation updates include contributing guidelines and production build strategy. CSS improvements address accessibility (focus-visible) and dark mode styling.

Changes

Cohort / File(s) Summary
GitHub Workflows & CI
.github/workflows/pr-category-check.yml, .github/workflows/pr-cypress-e2e.yml, .github/PULL_REQUEST_TEMPLATE/generic.md
New PR category validation workflow that parses PR body and auto-syncs labels; E2E test workflow using Cypress with Chrome and artifact uploads; PR template updated with category checklist section.
Documentation
CONTRIBUTING.md, Docs/PRODUCTION_BUILD_STRATEGY.md
Contributing guide reworded with AI guidelines, explicit prettier instructions, and new "After PR merge" section; new production build strategy doc outlining asset optimization, minification, and versioning approaches.
CSS & Styling
css/activities.css, css/darkmode.css, css/style.css
Accessibility improvements: focus-visible outline styling (2px solid #0066FF), dynamic viewport-height calculations for mobile, scrollable help wrapper; dark mode support for windowFrame tables and bold text; trailing dash cleanup.
HTML & PWA Support
index.html, env.js
PWA install button with beforeinstallprompt handling; canvas elements refactored to use CSS sizing (100% width/height); language preference persistence via localStorage; viewport-height CSS variable for mobile; record dropdown options; new env.js with MB_ENV and MB_IS_DEV globals.
Activity Context & Singleton Pattern
js/activity-context.js, js/activity.js
New ActivityContext module providing frozen singleton with getActivity/setActivity; Activity constructor now registers via ActivityContext; deprecation guard for window.activity with console warnings on access/set.
Block System & Metadata
js/blocks.js, js/block.js, js/blocks/IntervalsBlocks.js, js/blocks/WidgetBlocks.js, js/blocks/ProgramBlocks.js, js/blocks/MediaBlocks.js, js/blocks/MeterBlocks.js, js/blocks/EnsembleBlocks.js
New actionMetadata(blk) method centralizing block return/arg checks; batch caching updates in requestAnimationFrame; undo history capped at 100 entries; container uncaching on trash; for-of loop iterations replacing index access; CommonJS exports for IntervalsBlocks/WidgetBlocks; async fetch for heap loading; BPM clamping [30, 1000]; input validation guards for canvas dimensions.
Server & Environment
index.js, js/loader.js
New /env.js endpoint serving browser environment config with cache-control headers; loader.js updated with activity-context dependencies, i18next initialization phases, reduced preload strategy, optional highlight.js loading.
Activity & Recording
js/activity.js
Major refactoring: ActivityContext integration, deprecation guard installation, DOM lookup caching, idle/resize/visibility guards, SVG-based block value injection using DOM parsing, bitmap caching strategy revision (_show/_hide paths), canvas-based recording mode via localStorage (musicBlocksRecordMode), currentStream/audioDestination lifecycle management, robust cleanup/error handling.
Audio System & Voice Tracking
js/turtle-singer.js, js/utils/synthutils.js, js/turtleactions/PitchActions.js, js/turtleactions/VolumeActions.js, js/turtleactions/MeterActions.js, js/turtleactions/OrnamentActions.js
Singer: activeVoices tracking, killAllVoices() cleanup, safe defaults for masterBPM/defaultBPMFactor/masterVolume when undefined, MIN_HIGHLIGHT_DURATION_MS highlighting; Synth: interval caching in temperamentChanged, consolidated chainNodes routing, _trackVoice() for garbage collection, volume clamping [0-100], ramp timing optimization, getSafeActivity proxy for tuner, DOM-node-based cents slider restoration; PitchActions: transformed frequency computation for Lilypond export using noteOctaves/noteCents; OrnamentActions: per-block listener names including blk parameter; MeterActions: _clearDefaultStrongBeats helper; VolumeActions: additional inCrescendo pop cleanup.
Toolbar & Keyboard Navigation
js/toolbar.js
New setupKeyboardNavigation() method enabling keyboard-driven toolbar/dropdown/modal navigation with spatial proximity heuristics; focus state management via CSS classes (toolbar-btn-focused, dropdown-item-focused); mode-aware Record button and dropdown (recordDropdownArrow) visibility; localStorage persistence for record mode; new-project modal keyboard support (Arrow/Enter/Escape).
SVG & Path Rendering
js/turtle-painter.js
New _svgBezier() and _estimateBezierSteps() helpers for cubic Bezier sampling; _svgArc() signature expanded to handle anticlockwise and drawOnCanvas parameters; updated coordinate transformations and arc wrapping logic; parity between SVG export and canvas drawing.
Palette & Pie Menus
js/palette.js, js/piemenus.js
Palette: cached deltaY DOM lookups, removed debug logging in selector/maker/status paths, early-exit returns when protoBlock null; Pie menus: setWheelSize() responsive sizing, getPieMenuSize() block-bounds calculation, debouncedSetWheelSize() throttling, configureExitWheel() clearing selection state across all piemenu functions, enableWheelScroll debouncing with temporary navigation disable.
Dependencies & Exports
js/LogoDependencies.js, js/SaveInterface.js, js/macros.js, js/logo.js, js/logoconstants.js, js/utils/utils.js, js/utils/musicutils.js
LogoDependencies: constructor expanded with instruments, instrumentsFilters, instrumentsEffects, widgetWindows, Singer, Tone, utils, classes (removed meSpeak); SaveInterface: STR_MY_PROJECT/STR_SHOW/STR_HIDE constants, strict equality conversions, navigator.clipboard with textarea fallback; macros: export shape changed to { blockIsMacro, getMacroExpansion }; Logo: added LogoDependencies and NOTATION_* constants to exports; logoconstants: MIN_HIGHLIGHT_DURATION_MS added, single exportsObj pattern; utils: fetch-based httpGet/httpPost replacing XMLHttpRequest, CameraManager module, rationalSum non-mutating version, safeSVG /g flag expansion, additional public exports (rationalSum, format, etc.); musicutils: removed debug logs for missing drum/noise/voice names.
Turtles & Graphics
js/turtles.js
getTurtleCount() caching in loops; new createArtwork(turtle, i, useTurtleArtwork) for turtle visual setup; new makeBackground(setCollapsed) for canvas background, buttons, boundaries, collapse/expand behavior, debounced resize handling; removed AMD define wrapper.
Test Coverage Expansion
js/__tests__/*, js/blocks/__tests__/*, js/js-export/__tests__/*, js/turtleactions/__tests__/*, js/utils/__tests__/*
Comprehensive test additions: IntervalsBlocks (819 lines), SaveInterface clipboard scenarios (68 lines), activity_context_regression (199 lines), boundary edge cases (261 lines), jseditor_console (32 lines), logo-dependencies (21 lines), logo comprehensive coverage (882 lines), logoconstants validation (112 lines), macros expansion (28 lines), p5-adapter factory/shims (101 lines), p5-sound-adapter audio restoration (118 lines), palette extensive mocking (1816 lines), toolbar mock DOM utilities (48 lines), trash edge cases (242 lines), turtle-painter rendering tests (484 lines), turtle-singer state/lifecycle (752 lines), turtle initialization (252 lines), turtledefs Music Blocks mode (89 lines), turtles coordinate conversion/scaling (406 lines), ProgramBlocks async fetch (38 lines), WidgetBlocks setup (352 lines), ast2blocklist error context (4 lines), export.test MusicBlocks.run (87 lines), generate.test tree building (265 lines), interface.test constraint validation (332 lines), loader timing (1 line), p5-sound-adapter tonemock volume ramping (24 lines), mathutils edge cases (31 lines), musicutils exports (110 lines), synthutils tuner tests (420 lines), utils comprehensive utilities (622 lines), PitchActions microtonal tests (67 lines), OrnamentActions listener naming (8 lines).
Example Updates
examples/test-suite.html
Copy to Clipboard button for Project Code block; copyCode() function with user feedback alerts; CSS button styling enhancements.
Version & Utilities
js/turtledefs.js, js/p5-sound-adapter.js, js/turtleactions/DictActions.js
Version bump to 3.7.1; var→const for p5-sound-adapter AudioNode.prototype.connect patch; var→const in DictActions getValue error messages.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client/Browser
    participant GitHub as GitHub Actions
    participant PR as Pull Request
    participant Workflow as Category Check Workflow
    participant API as GitHub REST API

    Client->>GitHub: Push/Open PR with body containing checkboxes
    GitHub->>Workflow: Trigger pr_category_check on pull_request_target
    Workflow->>PR: Parse PR body via regex
    Note over Workflow: Extract checked categories<br/>(Issue-Bug, Issue-Enhancement, etc.)
    alt No categories matched
        Workflow->>API: FAIL workflow with error table
        API-->>Client: PR Check Failed
    else Categories matched
        Workflow->>API: GET current PR labels
        Workflow->>Workflow: Compute labelsToAdd & labelsToRemove
        Workflow->>API: Add missing labels
        Workflow->>API: Remove unchecked labels
        Note over API: Per-label error handling<br/>(warn if label not in repo)
        API-->>Client: PR Check Passed + Labels Synced
        Workflow->>Workflow: Log selected categories & synced labels
    end
Loading
sequenceDiagram
    participant User as User/Browser
    participant Activity as Activity Module
    participant Context as ActivityContext Singleton
    participant Window as window (deprecated)

    User->>Activity: Initialize Activity
    Activity->>Context: setActivity(this)
    Context->>Context: Store activity reference
    Note over Context: Freeze public API<br/>(prevent overrides)
    
    User->>Context: Call getActivity()
    Context-->>User: Return stored activity
    
    User->>Window: Access deprecated window.activity
    Window->>Window: Deprecation guard IIFE
    Note over Window: console.warn:<br/>Use ActivityContext.getActivity()
    Window-->>User: undefined (not persisted)
    
    User->>Window: Assign window.activity = newVal
    Window->>Window: Deprecation guard IIFE
    Note over Window: console.error:<br/>Use ActivityContext.setActivity()
    Window-->>User: Assignment blocked
Loading
sequenceDiagram
    participant User as User
    participant Toolbar as Toolbar UI
    participant Handler as Keyboard Handler
    participant DOM as DOM/Elements
    participant Modal as Modal/Dropdown

    User->>Toolbar: Press ArrowRight/ArrowDown
    Toolbar->>Handler: setupKeyboardNavigation()
    Handler->>DOM: Discover focusable buttons
    Handler->>DOM: Find spatial neighbors
    Note over Handler: Proximity heuristics for<br/>vertical/horizontal navigation
    Handler->>DOM: Apply toolbar-btn-focused class
    Handler->>DOM: Update tabindex & focus
    DOM-->>User: Visual focus indicator
    
    User->>Toolbar: Press Enter on button
    Handler->>Modal: Check if dropdown/regular
    alt Regular Button
        Handler->>Modal: Invoke button action
        Handler->>Toolbar: Auto-refocus after action
    else Dropdown
        Handler->>Modal: Open dropdown menu
        Modal->>DOM: Show items
        Handler->>DOM: Apply dropdown-item-focused
        User->>Modal: Navigate items with Arrow keys
        User->>Modal: Press Enter to select
        Handler->>Modal: Close dropdown
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 With categories checked and workflows aligned,
E2E tests running and keyboards now fine,
ActivityContext holds the activity tight,
Audio voices tracked through the musical night,
Canvas and SVG in harmony sing,
What a marvelous update this PR does bring! 🎵

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ci/pr-category-check

@github-actions
Copy link

github-actions bot commented Mar 4, 2026

✅ All Jest tests passed! This PR is ready to merge.

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.