Skip to content

feat: add arrow position options (below/overlay/outside) to Controls block - #187

Open
sanketio wants to merge 5 commits into
developfrom
feat/controls-arrow-position
Open

feat: add arrow position options (below/overlay/outside) to Controls block#187
sanketio wants to merge 5 commits into
developfrom
feat/controls-arrow-position

Conversation

@sanketio

@sanketio sanketio commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a Position option to the Carousel Controls block so the prev/next arrows can sit Below the slides (current default, unchanged), Overlay on the slide edges, or Outside flanking the slides. This is the common "arrows left/right of / over the cards" slider layout requested in #143.

The setting lives on the Controls block as a new position attribute, exposed via a SelectControl in the block inspector. A shared pure helper derives the wrapper class so edit and save can't drift, and CSS positions the arrows against the ancestor .rt-carousel (already position: relative), using :has() for the Outside gutter — the same :has() pattern already used for tabs mode.

Type of change

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

Related issue(s)

Closes #143

What changed

  • New position attribute (below default / overlay / outside) on rt-carousel/carousel-controls with a labelled Position SelectControl in the inspector (plus a hint to place Controls as a direct child of the carousel for overlay/outside).
  • Shared getPositionClassName helper used by both edit.tsx and save.tsxbelow emits only rt-carousel-controls; overlay/outside add is-position-overlay / is-position-outside.
  • CSS (controls/style.scss): overlay floats arrows over the slide edges (absolute, vertically centered); outside adds side gutters via :has() so arrows flank the slides. Horizontal-only (:not([data-axis="y"])); RTL handled by existing logical-property + icon-flip rules. Tunable via --rt-carousel-control-inset / --rt-carousel-control-gutter / --rt-carousel-control-gutter-mobile.
  • Tests: unit tests for the helper (4) and the editor control/class + back-compat + help-text (7).

Breaking changes

  • Yes — migration path:
  • No

Default is below, which is not serialized and emits byte-identical markup to the current output (class="rt-carousel-controls", no modifier). Existing saved Controls blocks re-parse as valid — no block-validation errors, no deprecation entry, no forced re-save. New CSS activates only on the opt-in classes, so sites that just update the plugin look pixel-for-pixel the same.

Testing

Describe how this was tested.

  • Unit tests
  • Manual testing (live editor + front end)
  • Cross-browser testing (relies on :has() for the Outside gutter — already used by tabs mode; overlay does not use :has())

Test details — run from the plugin root after checking out this branch:

npm ci
npm run build
npm run test:js          # 199 passing (10 suites)
npm run lint:js:types    # exit 0
npm run lint:css         # exit 0

Manual (in a WordPress editor): insert a Carousel → select the Controls block → set Position to Overlay then Outside, and verify on the front end:

  • Overlay — arrows float over the left/right slide edges, vertically centered; slides remain clickable/draggable between them.
  • Outside — arrows sit in side gutters, flanking the slides (not covering content).
  • Below (default) — unchanged; an existing Controls block loads with no "unexpected content" warning.

Full step-by-step How-to-test lives on the issue: #143.

Note on overlay centering

Overlay/outside arrows center on the slide track (.rt-carousel / viewport). If slide media carries a trailing margin — e.g. WordPress core/theme's :where(figure){margin:0 0 1em} on image slides — the track is taller than the visible media, so the arrows read as ~8px low. This is theme/content styling (the author controls it), not the feature's CSS, which adds no vertical margin/padding. Slides that fill their height (Cover blocks, vertically-centered content) don't show it.

Screenshots / recordings

Verified on a local site with three carousels (below / overlay / outside); the compiled overlay/outside rules are served and applied on the front end. (Local dev env — no public URL to link.)

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 balanced review requested due to automatic review settings August 7, 2026 08:33
@sanketio sanketio self-assigned this Aug 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds a new Controls-block “Position” option to let carousel arrows render below (default), overlaying the slide edges, or outside in side gutters, while keeping the default output byte-identical for existing content.

Changes:

  • Introduces a new position attribute for rt-carousel/carousel-controls plus editor UI (SelectControl) to configure it.
  • Adds a shared getPositionClassName helper used by both edit and save to avoid class drift.
  • Adds CSS for overlay/outside positioning (including :has()-based gutters) and updates/extends unit tests.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/blocks/carousel/types.ts Adds the position attribute typing for Controls.
src/blocks/carousel/controls/block.json Declares the new position attribute with default below.
src/blocks/carousel/controls/get-position-class.ts New helper to compute wrapper classes consistently.
src/blocks/carousel/controls/edit.tsx Adds Inspector control + uses helper-driven class name.
src/blocks/carousel/controls/save.tsx Uses helper-driven class name in saved markup.
src/blocks/carousel/controls/style.scss Implements overlay/outside arrow positioning and gutters.
src/blocks/carousel/controls/tests/get-position-class.test.ts Unit tests for the helper.
src/blocks/carousel/controls/tests/edit.test.tsx Updates editor tests for new UI + class behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +36 to +37
export type CarouselControlsPosition = 'below' | 'overlay' | 'outside';
export type CarouselControlsAttributes = { position: CarouselControlsPosition };
Comment on lines +78 to +82
onChange={ ( value ) =>
setAttributes( {
position: value as CarouselControlsPosition,
} )
}
Comment on lines +63 to +71
.rt-carousel:not([data-axis="y"]) .rt-carousel-controls.is-position-overlay,
.rt-carousel:not([data-axis="y"]) .rt-carousel-controls.is-position-outside {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: space-between;
pointer-events: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement]: Left Right controls left and right of cards?

2 participants