feat: Accessible Carousel Counter block#139
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new rt-carousel/carousel-counter child block to show the current slide position (current/total) and wires it into the existing Embla v8 + Interactivity API state on both frontend and editor.
Changes:
- Introduces the new Carousel Counter block (block.json, edit/save, and SCSS) and adds it to the default carousel navigation inner-block template.
- Extends the frontend interactivity store with count-related callbacks and adds
countLabelPatternto the carousel’s saveddata-wp-contextfor accessible labeling. - Updates PHP block registration/tests and JS unit tests to cover the new block and callbacks.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/php/Unit/PluginTest.php | Updates expected registered block list/count to include the new counter block. |
| inc/Plugin.php | Registers the new carousel/counter build block path in the plugin. |
| src/blocks/carousel/view.ts | Adds snap/count helpers and exposes counter callbacks via the interactivity store. |
| src/blocks/carousel/types.ts | Adds counter attribute type and countLabelPattern to the carousel context type. |
| src/blocks/carousel/save.tsx | Adds countLabelPattern into serialized data-wp-context for frontend labeling. |
| src/blocks/carousel/edit.tsx | Tracks scrollSnaps in editor state and inserts the counter into the default nav group. |
| src/blocks/carousel/editor-context.ts | Extends the editor context to include scrollSnaps. |
| src/blocks/carousel/editor.scss | Refactors editor-only carousel wrapper styles (moves/selectable-area styling). |
| src/blocks/carousel/counter/block.json | Declares the new counter block metadata and interactivity support. |
| src/blocks/carousel/counter/index.ts | Registers the counter block and loads its styles. |
| src/blocks/carousel/counter/edit.tsx | Renders the counter in the editor with an accessible label and compact text. |
| src/blocks/carousel/counter/save.tsx | Outputs frontend markup + interactivity bindings for current/total and aria-label. |
| src/blocks/carousel/counter/style.scss | Adds BEM counter styles and CSS variables. |
| src/blocks/carousel/tests/view.test.ts | Adds unit tests for the new count-related interactivity callbacks. |
| src/blocks/carousel/tests/edit.test.tsx | Tightens some component mock typings used by the editor tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ariaLabelPattern: __( 'Go to slide %d', 'rt-carousel' ), | ||
| /* translators: {{currentSlide}}: current slide number, {{totalSlides}}: total slide count. */ | ||
| countLabelPattern: __( | ||
| 'Slide {{currentSlide}} of {{totalSlides}}', | ||
| 'rt-carousel', | ||
| ), |
| setSelectedIndex( emblaApi.selectedScrollSnap() ); | ||
| setScrollSnaps( emblaApi.scrollSnapList() ); |
|
Hi Masud, while going through the query block example, the counter count breaks due to snap behaviour. The new counter/announcement logic mixes “snap count” and “slide count,” so it produces inconsistent output. The counter uses snap count and forces a minimum of 1, while the live-region announcement uses selectedIndex + 1 with total Screen.Recording.2026-05-11.at.5.12.55.PM.mov |
@imrraaj I tested the counter as per your video. It seems to be the default behavior of the carousel. Could you please remove the counter and test the same carousel again to confirm whether it behaves the same, or if the issue is related to the counter? |
imrraaj
left a comment
There was a problem hiding this comment.
LGTM. The counter issue described in the video is an interpretation mistake. Everything else looks good.
Summary
Adds an accessible Carousel Counter block that displays the current carousel position in a compact
current/totalformat, such as1/6. This gives users a clear slide position indicator alongside the existing controls and dots, powered by Embla Carousel v8 state.Type of change
Related issue(s)
Closes #138
What changed
rt-carousel/carousel-counterchild block with frontend/editor rendering.selectedScrollSnap()andscrollSnapList().role="group"and dynamicaria-label, while avoiding duplicate live announcements.Breaking changes
Does this introduce a breaking change? If yes, describe the impact and migration path below.
Testing
Describe how this was tested.
Test details:
npm run buildnpm run lint:cssnpm run lint:js -- src/blocks/carousel/__tests__/edit.test.tsxnpm run test:js -- --runInBand src/blocks/carousel/__tests__/view.test.tsnpm run test:js -- --runInBand src/blocks/carousel/__tests__/edit.test.tsxcomposer test -- --filter PluginTest1/6.Screenshots / recordings
Checklist