Skip to main content

Documentation

No results found.
Features

Accessible Interactive Components

WebProCMS ships its sliders/carousels and accordions (FAQ rows and anywhere else they appear) with WCAG 2.1 AA-friendly keyboard support and ARIA semantics built in. Site owners don't have to know what aria-expanded or tabindex means to get...

WebProCMS ships its sliders/carousels and accordions (FAQ rows and anywhere else they appear) with WCAG 2.1 AA-friendly keyboard support and ARIA semantics built in. Site owners don't have to know what aria-expanded or tabindex means to get screen-reader-friendly, keyboard-navigable widgets — every design library row built on these components inherits the behavior automatically.


Sliders & carousels

Every slider in the design library — image sliders, testimonial sliders, hero sliders, feature carousels, and the rest — handles keyboard focus correctly out of the box.

  • Inactive slides are not keyboard-reachable. When a slide isn't the active one it's fully hidden (display:none), which removes it and everything inside it from the tab order. A keyboard user tabbing through the page never lands on a link or button buried in a slide they can't see. Off-screen slides also start hidden in the raw HTML, so this holds even before JavaScript loads.
  • Arrow keys move between slides. Left/Right arrow keys advance and rewind the active slider.
  • Labelled controls. Previous/Next arrows and the dot navigation each carry descriptive aria-labels ("Previous slide", "Go to slide 3") so assistive tech announces what they do, and the active dot carries aria-current so the position is announced too.
  • Announced as a carousel. The slider root is a role="region" landmark with aria-roledescription="carousel", and each slide is a role="group" with aria-roledescription="slide" and an "N of M" label — screen readers identify the widget and the visitor's position in it (WAI-ARIA carousel pattern).
  • Slide changes are announced only when the visitor is driving. The slide container's aria-live is polite while the slider is stopped (manual navigation announces the new slide) and off while autoplay is running, so an auto-rotating slider never spams the screen reader.
  • Autoplay pauses on hover and only runs when there's more than one slide, so it never traps or distracts when there's nothing to rotate.
  • Native-scroll carousels stay fully reachable. The multi-card "scroller" style sliders (where several cards are visible and you swipe/scroll horizontally) keep every card visible and tabbable by design — nothing is hidden, so nothing is unreachable.

The shared slider component lives in resources/views/components/dl/slider.blade.php (with dl/slide.blade.php for slot-mode slides). Both the <x-dl.slider> + <x-dl.slide> pattern and the standalone custom-x-data slider rows hide inactive slides with x-show (→ display:none), so the no-tab-into-hidden-slides guarantee is structural, not per-row.

Accordions (FAQ rows and beyond)

Every accordion built on the shared <x-dl.accordion> / <x-dl.accordion-item> components — the FAQs Accordion and FAQs Search Accordion design library rows, plus the FAQ shortcode/blog accordion — follows the WAI-ARIA Authoring Practices accordion pattern.

Keyboard navigation

With focus on any accordion header:

Key Action
Enter / Space Expand or collapse the focused section (native button behavior)
Down Arrow Move focus to the next header (wraps from last to first)
Up Arrow Move focus to the previous header (wraps from first to last)
Home Move focus to the first header
End Move focus to the last header

The arrow/Home/End keys move focus only — they never expand a section, matching the APG spec — and they call preventDefault() so Up/Down don't also scroll the page out from under the user.

Screen-reader semantics

  • aria-expanded on each header button flips between true and false as the section opens and closes, so assistive tech announces "expanded" / "collapsed".
  • aria-controls links each header to the panel it toggles, and the panel carries role="region" + aria-labelledby pointing back at its header — so a screen reader can jump from a header to its answer and back, and announces the answer region with the question as its label.
  • type="button" on every header so an accordion placed inside a form never accidentally submits it.
  • Decorative chevrons are aria-hidden="true", so screen readers don't read a meaningless "image" between every question.

The header/panel IDs are generated automatically and are unique per accordion instance on the page, so two accordions on one page never collide.

What this means for your users

  • Keyboard-only visitors can operate every slider and accordion without a mouse.
  • Screen-reader users hear meaningful labels and state ("Frequently asked questions, button, collapsed") instead of bare, unlabelled controls.
  • You can't accidentally ship an inaccessible FAQ or carousel — the behavior is baked into the shared components, so it can't be "forgotten" on a per-row basis.

For developers

The accessibility behavior is implemented in the shared components, not copied into each row template, so it propagates to every existing page automatically (page blades reference <x-dl.accordion-item> / <x-dl.slider>, which resolve to the shared components at render time):

  • resources/views/components/dl/accordion.blade.php — adds data-accordion-root to the wrapper.
  • resources/views/components/dl/accordion-item.blade.php — renders the header button (type, id, aria-controls, reactive aria-expanded, the four x-on:keydown handlers, data-accordion-header) and the panel (id, role="region", aria-labelledby).
  • resources/views/components/faq-accordion.blade.php — the same treatment for the FAQ shortcode/blog accordion.
  • resources/js/public.js — defines window.dlAccordionNav(headerEl, dir), the focus-mover called by the keydown handlers. It scopes to the nearest [data-accordion-root] and moves focus among [data-accordion-header] buttons. It's loaded on the public site; in the editor preview iframe (which doesn't load public.js) the keydown handlers no-op gracefully and expand/collapse still works.

Any new slider or accordion design library row built on the standard <x-dl.slider> / <x-dl.slide> / <x-dl.accordion> / <x-dl.accordion-item> components inherits all of this for free — there is nothing extra to wire up per row. New accordion rows must use <x-dl.accordion-item> for each item (not a hand-rolled <button> + panel) to get the keyboard nav and ARIA. New slider rows must hide inactive slides with x-show (or use the native-scroll pattern) rather than translating still-displayed slides off-screen, so hidden slides stay out of the tab order.

For the design library these rows come from, see design-library.md. For accessible header/menu navigation, see accessible-navigation.md; for the automated audit tool, see accessibility-scanner.md.