Slider Block

A carousel/slider that cycles through slides. Slides are stored as an object_list — each slide has a title, description, image, and optional button.

New Release
Product Launch 2025

Discover our latest innovations.

Learn More
Featured
Award-Winning Design

Recognized for excellence in UX.

See Details

Developer Reference

Schema

Pass this object inside the blocks option when calling initBridge() to register this block type with the admin UI. See Custom Blocks for the full setup guide.

{
  "fieldsets": [
    {
      "id": "default",
      "title": "Default",
      "fields": [
        "slides",
        "variation",
        "autoplayEnabled",
        "autoplayDelay",
        "autoplayJump",
        "headline",
        "headlineTag"
      ]
    }
  ],
  "properties": {
    "headline": {
      "title": "Headline",
      "type": "string"
    },
    "headlineTag": {
      "title": "Headline tag",
      "widget": "select",
      "choices": [
        [
          "h1",
          "h1"
        ],
        [
          "h2",
          "h2"
        ],
        [
          "h3",
          "h3"
        ],
        [
          "h4",
          "h4"
        ],
        [
          "h5",
          "h5"
        ],
        [
          "h6",
          "h6"
        ]
      ]
    },
    "slides": {
      "title": "Slides",
      "widget": "object_list",
      "itemTypeField": "variation",
      "allowedBlocks": [
        "slide",
        "image",
        "listing",
        "teaser"
      ],
      "typeField": "@type",
      "defaultBlockType": "slide"
    },
    "variation": {
      "title": "Item Type",
      "widget": "blockTypeSelect"
    },
    "autoplayEnabled": {
      "title": "Autoplay Enabled",
      "type": "boolean",
      "default": false
    },
    "autoplayDelay": {
      "title": "Autoplay Delay",
      "type": "integer",
      "default": 4000
    },
    "autoplayJump": {
      "title": "Autoplay Jump",
      "type": "boolean",
      "default": false
    }
  },
  "required": []
}

JSON Block Data

Example JSON as stored in the Plone content API. This is the data structure your component will receive in the block prop.

{
  "@type": "slider",
  "autoplayEnabled": false,
  "autoplayDelay": 5000,
  "slides": [
    {
      "@id": "slide-1",
      "@type": "slide",
      "head_title": "New Release",
      "title": "Product Launch 2025",
      "description": "Discover our latest innovations.",
      "preview_image": [
        {
          "@id": "data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27800%27 height=%27400%27%3E%3Crect width=%27100%25%27 height=%27100%25%27 fill=%27%235577aa%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 fill=%27white%27 text-anchor=%27middle%27 font-size=%2724%27%3ESlide 1%3C/text%3E%3C/svg%3E"
        }
      ],
      "buttonText": "Learn More"
    },
    {
      "@id": "slide-2",
      "@type": "slide",
      "head_title": "Featured",
      "title": "Award-Winning Design",
      "description": "Recognized for excellence in UX.",
      "preview_image": [
        {
          "@id": "data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27800%27 height=%27400%27%3E%3Crect width=%27100%25%27 height=%27100%25%27 fill=%27%23aa5577%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 fill=%27white%27 text-anchor=%27middle%27 font-size=%2724%27%3ESlide 2%3C/text%3E%3C/svg%3E"
        }
      ],
      "buttonText": "See Details",
      "hideButton": true
    }
  ]
}

Rendering

How this block renders in your frontend. Add its handling to your renderer, or — for list-style blocks — register a fetcher and reuse your list rendering.

import { getImageUrl } from './utils.js';

function SliderBlock({ block }) {
  const [current, setCurrent] = useState(0);
  const slides = expandTemplatesSync(block.slides || [], { idField: '@id' });

  return (
    <div data-block-uid={block['@uid']} className="slider-block">
      {slides.map((slide, i) => (
        <div
          key={slide['@id']}
          data-block-uid={slide['@id']}
          className="slide"
          style={{ display: i === current ? 'block' : 'none' }}
        >
          {slide.preview_image && (
            <img
              data-edit-media="preview_image"
              src={getImageUrl(slide.preview_image)}
              alt=""
            />
          )}
          <span data-edit-text="head_title">{slide.head_title}</span>
          <h2 data-edit-text="title">{slide.title}</h2>
          <p data-edit-text="description">{slide.description}</p>
          <button data-edit-text="buttonText">{slide.buttonText}</button>
        </div>
      ))}
      <div className="slider-dots">
        {slides.map((_, i) => (
          <button key={i} onClick={() => setCurrent(i)} className={i === current ? 'active' : ''} />
        ))}
      </div>
    </div>
  );
}