Custom Gutenberg Slider
Locomotive Gutenberg Slider Assignment
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/davidjos03/locomotive-gutenberg-slider/archive/refs/heads/main.zipA WordPress plugin that adds a Marketing Slider block to the block editor. Editors build slides visually with core Gutenberg blocks, and the plugin always appends an email signup form as the final slide.
assessment/slider— parent block, dynamically rendered in PHPassessment/slide— child block, only valid inside the slider
The public frontend is a dependency-free, accessible carousel.
Requirements
| Requirement | Version |
|---|---|
| WordPress | 6.4 or newer |
| PHP | 7.4 or newer |
| Node.js | 18 or newer |
No third-party carousel library, CSS framework, or plugin dependency is required.
Installation
-
Place the plugin in your site:
wp-content/plugins/custom-gutenberg-slider -
Install dependencies:
npm install -
Build the assets:
npm run build -
Activate the plugin:
WordPress Admin → Plugins → Custom Gutenberg Slider → Activate
-
Open a page:
Pages → Add New / Edit Page
-
Insert the block:
Click the inserter and choose Marketing Slider
The build/ directory must exist before activation, since blocks are registered from built block metadata.
Development
Watch and rebuild on save:
npm run start
Production Build
npm run build
Other scripts:
| Script | Purpose |
|---|---|
npm run format |
Format source files |
npm run lint:js |
Lint JavaScript and TypeScript |
npm run test:unit |
Run the Jest unit tests |
npm run check-engines |
Verify the Node version |
Tests
npm run test:unit
Unit tests run on the Jest setup bundled with @wordpress/scripts and live in src/slider/test/.
signup-form.test.ts covers the signup flow against a mocked REST endpoint: a valid email submits successfully, whitespace is trimmed, malformed and empty addresses never reach the network, a 400 shows the server's validation message, server errors and dropped connections fall back to the failure message, and the form locks while a request is in flight so it cannot be submitted twice. Each case also asserts the accessibility state, including aria-invalid, aria-busy, and the status text.
slider-controller.test.ts covers the carousel: progress-bar construction, navigation, disabled arrows at both ends, inert and aria-hidden on inactive slides, live-region announcements, touch swipe, arrow keys, arrow keys being ignored inside form fields, and two sliders on one page keeping independent state.
Usage
Adding slides
Insert Marketing Slider. It starts with one slide. Use the block appender (+) inside the slider to add more. Only assessment/slide can be inserted there.
Editing slides
Each slide is a locked template of core blocks, edited directly on the canvas:
- Image —
core/image, with the normal media library and alt text controls - Headline —
core/heading - Supporting text —
core/paragraph - CTA label and URL —
core/button, using the standard link toolbar
Because these are core blocks, the usual block toolbars, Inspector settings, and undo/redo all work as expected.
Reordering slides
Use the block movers, drag and drop, or the List View. This is native Gutenberg behavior, not a custom implementation.
Deleting slides
Select a slide and delete it like any other block, or remove it from the List View.
Final signup slide
The signup slide is rendered by the parent block in PHP, so it is not an editable child block. In the editor it appears as a labelled preview after the slides. It cannot be reordered, deleted, or moved out of last position, and it needs no configuration.
Frontend behavior
- Previous and Next, disabled at the first and last slide
- A segmented progress bar showing the current position, with each segment clickable
- Left and right arrow keys, ignored while typing in a field
- Touch swipe on mobile
- Multiple sliders per page, each with independent state
- Server-rendered content, so slides remain readable if JavaScript fails
Email signup
The final slide posts to a public REST route:
POST /wp-json/assessment-slider/v1/signup
The email is validated in the browser and again on the server with sanitize_email() and is_email(). A valid submission returns a JSON success response. There is no CRM integration and no database storage, as permitted by the brief.