Scroller

v0.0.10

v0.0.10StableHeadlessStatelessAccessibleJSApache-2.0
Installation mix mishka.ui.gen.headless scroller
Source View Source

Overview of the Phoenix and LiveView Headless Scroller Component

The Mishka Chelekom Headless Scroller puts previous and next buttons around a horizontal row of items. In Phoenix LiveView it renders a root div, a viewport that holds your items, and two native buttons. A small Scroller hook scrolls the viewport by about 80% of its width, or by scroll_by pixels, when a button is pressed.

At each end of the row the matching button gets data-disabled and the native disabled attribute, and a ResizeObserver keeps that right when the viewport changes size. Buttons are styled with control_class, the viewport with viewport_class and the root with class.

Base UI Scroller example - cards with previous and next buttons (Phoenix headless)

Base UI Scroller example - cards with previous and next buttons (Phoenix headless)

1
2
3
4
5
6
7
8
9
10
heex
<.scroller
  id="baseui-scroller"
  class="flex w-full max-w-80 items-center gap-2"
  control_class="grid size-8 shrink-0 place-items-center rounded-full border border-neutral-300 bg-white text-lg text-neutral-800 data-[disabled]:opacity-30 dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-200"
  viewport_class="flex gap-3 overflow-x-auto scroll-smooth pb-1"
>
  <div
    :for={n <- 1..10}
    class="grid size-16 shrink-0 place-items-center rounded-lg bg-neutral-100 text-sm font-medium text-neutral-800 dark:bg-neutral-800 dark:text-neutral-200"
  >
    {n}
  </div>
</.scroller>

Attributes and parts

id is required, because the hook is attached to the root. scroll_by is the distance in pixels for one press; without it the viewport scrolls by 80% of its width. prev_label and next_label are the aria-label values of the two buttons and default to "Scroll left" and "Scroll right".

The parts are the root (data-part="root"), prev, viewport and next. control_class is applied to both buttons. Their arrows are the characters ‹ and › inside an aria-hidden span, and the component has no slot to replace them. Style the data-disabled state with a variant such as data-[disabled]:opacity-30.

Accessibility

There is no formal WAI-ARIA pattern for a scroller. The two controls are native buttons, so Tab reaches them and Enter and Space press them, and a disabled end button leaves the tab order. The buttons are named by prev_label and next_label, so translate them for your users. Items inside the viewport that can take focus scroll into view as focus reaches them.