Skip to content

feat: Accessible Carousel Counter block#139

Merged
theMasudRana merged 5 commits into
developfrom
feature/slide-count
May 29, 2026
Merged

feat: Accessible Carousel Counter block#139
theMasudRana merged 5 commits into
developfrom
feature/slide-count

Conversation

@theMasudRana
Copy link
Copy Markdown
Collaborator

Summary

Adds an accessible Carousel Counter block that displays the current carousel position in a compact current/total format, such as 1/6. This gives users a clear slide position indicator alongside the existing controls and dots, powered by Embla Carousel v8 state.

Type of change

  • Bug fix
  • New feature
  • Enhancement/refactor
  • Documentation update
  • Test update
  • Build/CI/tooling

Related issue(s)

Closes #138

What changed

  • Added new rt-carousel/carousel-counter child block with frontend/editor rendering.
  • Wired counter state to Embla v8 APIs using selectedScrollSnap() and scrollSnapList().
  • Added the counter to the default carousel navigation group.
  • Added accessible counter labeling with role="group" and dynamic aria-label, while avoiding duplicate live announcements.
  • Added BEM-based counter styles and CSS variables for customization.
  • Registered the new block in PHP and updated focused JS/PHP tests.
  • Cleaned up related lint issues in carousel test/editor styles.

Breaking changes

Does this introduce a breaking change? If yes, describe the impact and migration path below.

  • Yes — migration path:
  • No

Testing

Describe how this was tested.

  • Unit tests
  • Manual testing
  • Cross-browser testing (if UI changes)

Test details:

  • npm run build
  • npm run lint:css
  • npm run lint:js -- src/blocks/carousel/__tests__/edit.test.tsx
  • npm run test:js -- --runInBand src/blocks/carousel/__tests__/view.test.ts
  • npm run test:js -- --runInBand src/blocks/carousel/__tests__/edit.test.tsx
  • composer test -- --filter PluginTest
  • Manually verified the counter loads after adding a fresh carousel block and displays as 1/6.

Screenshots / recordings

image

Checklist

  • I have self-reviewed this PR
  • I have added/updated tests where needed
  • I have updated docs where needed
  • I have checked for breaking changes

Copilot AI review requested due to automatic review settings May 11, 2026 05:28
@theMasudRana theMasudRana self-assigned this May 11, 2026
@theMasudRana theMasudRana requested a review from imrraaj May 11, 2026 05:29
@theMasudRana theMasudRana changed the title Feature/slide count feat: Accessible Carousel Counter block May 11, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 countLabelPattern to the carousel’s saved data-wp-context for 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.

Comment on lines 54 to +59
ariaLabelPattern: __( 'Go to slide %d', 'rt-carousel' ),
/* translators: {{currentSlide}}: current slide number, {{totalSlides}}: total slide count. */
countLabelPattern: __(
'Slide {{currentSlide}} of {{totalSlides}}',
'rt-carousel',
),
Comment thread src/blocks/carousel/edit.tsx
@imrraaj
Copy link
Copy Markdown
Collaborator

imrraaj commented May 11, 2026

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 slideCount.

Screen.Recording.2026-05-11.at.5.12.55.PM.mov

@theMasudRana
Copy link
Copy Markdown
Collaborator Author

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 slideCount.

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
imrraaj previously approved these changes May 14, 2026
Copy link
Copy Markdown
Collaborator

@imrraaj imrraaj left a comment

Choose a reason for hiding this comment

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

LGTM. The counter issue described in the video is an interpretation mistake. Everything else looks good.

@milindmore22
Copy link
Copy Markdown

@theMasudRana Can you please resolve merge conflicts

@theMasudRana
Copy link
Copy Markdown
Collaborator Author

@theMasudRana Can you please resolve merge conflicts

@milindmore22 I have resolved the conflicts. Could you please review/approve the PR now?
Thanks

Copy link
Copy Markdown

@milindmore22 milindmore22 left a comment

Choose a reason for hiding this comment

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

Can you please, re-run lint, tests and coverage and make sure it passes all

Comment thread src/blocks/carousel/view.ts Outdated
Comment thread src/blocks/carousel/__tests__/edit.test.tsx
Comment thread src/blocks/carousel/counter/save.tsx
Comment thread src/blocks/carousel/__tests__/edit.test.tsx Outdated
Comment thread src/blocks/carousel/counter/block.json Outdated
Copilot AI review requested due to automatic review settings May 29, 2026 11:52
@theMasudRana theMasudRana requested a review from milindmore22 May 29, 2026 11:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Comment on lines +55 to +59
/* translators: {{currentSlide}}: current slide number, {{totalSlides}}: total slide count. */
countLabelPattern: __(
'Slide {{currentSlide}} of {{totalSlides}}',
'rt-carousel',
),
Comment on lines +230 to +239
getCountLabel: () => {
const context = getContext<CarouselContext>();
const current = getCurrentSnap( context ).toString();
const total = getSnapCount( context ).toString();
return interpolateSlidePattern(
context.countLabelPattern || 'Slide {{currentSlide}} of {{totalSlides}}',
current,
total,
);
},
Copy link
Copy Markdown

@milindmore22 milindmore22 left a comment

Choose a reason for hiding this comment

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

LGTM

@theMasudRana theMasudRana merged commit 49fd86b into develop May 29, 2026
4 checks passed
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.

[Feature]: Add accessible Carousel Counter block

4 participants