# Scroll Buttons `scrollbuttons` is a **horizontal scroller with prev/next buttons**. The block body is a wide row of content that scrolls sideways, and chevron controls fade in at each edge so a reader can page through it a screenful at a time. The controls only show when there is more content to reach in that direction, and the row can also be dragged with the pointer. It is the right tool for a strip of cards, a row of images, or any rail too wide for the page. This is a different widget from `scroller`, which is a plain native-overflow box with the browser's own scrollbars — `scrollbuttons` adds the paging chevron controls. Use it as `{% scrollbuttons %}` in Markdown, or call it from Python logic (loops, snippets) via `component('aardvark', 'scrollbuttons', …)`. ## Demonstrations The block body is the scrolling row; give the children enough width to overflow so the controls have something to page to. `scrollAmount` sets how many pixels each chevron click moves: First card Second card Third card Fourth card Fifth card Sixth card
Source: Markdown ```aardvark {% scrollbuttons scrollAmount=240 %} {% group wrap='nowrap' gap='md' %} {% paper withBorder=true radius='md' p='lg' w='200' %}First card{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}Second card{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}Third card{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}Fourth card{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}Fifth card{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}Sixth card{% endPaper %} {% endGroup %} {% endScrollbuttons %} ``` Source: Python ```python cards = ''.join( component('aardvark', 'paper', withBorder=True, radius='md', p='lg', w='200', children=label) for label in ('First card', 'Second card', 'Third card', 'Fourth card', 'Fifth card', 'Sixth card') ) row = component('aardvark', 'group', wrap='nowrap', gap='md', children=cards) component('aardvark', 'scrollbuttons', scrollAmount=240, children=row) ``` Pin both controls on with `showStartControl` / `showEndControl` (so they show even at the ends), and `controlSize` resizes the chevron buttons: React Mantine Markdown Static Islands Themes Search Analytics
Source: Markdown ```aardvark {% scrollbuttons showStartControl=true showEndControl=true controlSize='48' %} {% group wrap='nowrap' gap='sm' %} {% badge size='xl' color='blue' %}React{% endBadge %} {% badge size='xl' color='grape' %}Mantine{% endBadge %} {% badge size='xl' color='green' %}Markdown{% endBadge %} {% badge size='xl' color='orange' %}Static{% endBadge %} {% badge size='xl' color='red' %}Islands{% endBadge %} {% badge size='xl' color='teal' %}Themes{% endBadge %} {% badge size='xl' color='indigo' %}Search{% endBadge %} {% badge size='xl' color='pink' %}Analytics{% endBadge %} {% endGroup %} {% endScrollbuttons %} ``` Source: Python ```python badges = ''.join( component('aardvark', 'badge', size='xl', color=c, children=label) for c, label in (('blue', 'React'), ('grape', 'Mantine'), ('green', 'Markdown'), ('orange', 'Static'), ('red', 'Islands'), ('teal', 'Themes'), ('indigo', 'Search'), ('pink', 'Analytics')) ) row = component('aardvark', 'group', wrap='nowrap', gap='sm', children=badges) component('aardvark', 'scrollbuttons', showStartControl=True, showEndControl=True, controlSize='48', children=row) ``` ## Attributes Omit any attribute to take its default. | Attribute | Valid values | Description | | --- | --- | --- | | `scrollAmount` | An integer, pixels (default `200`) | How far each chevron click scrolls the row. | | `controlSize` | A number or CSS length (default `60px`) | Size of the chevron control buttons. | | `edgeGradientColor` | Any CSS color (default the page background) | Color of the fade behind the controls. | | `draggable` | bare flag or `true` / `false` (default `true`) | Allow dragging the row with the pointer. Set `false` to disable. | | `showStartControl` | `true` / `false` (default `false`) | Keep the start (left) control visible even at that end. | | `showEndControl` | `true` / `false` (default `false`) | Keep the end (right) control visible even at that end. | `attr={...}` forwards raw HTML attributes onto the rendered element. ## CSS Selectors Each `scrollbuttons` mounts as an island, so its outer wrapper carries `data-aardvark-island="Scroller"` — a stable hook independent of Mantine's hashed class names. Inside, the native Scroller exposes its Styles API parts as `mantine-Scroller-*` classes: `root` is the component, `container` the clipping frame, `content` the scrolling track that holds the children, `control` each chevron button, and `chevron` the icon within a control. ```css /* The island wrapper — the most stable selector. */ [data-aardvark-island="Scroller"] { margin-block: 1rem; } /* Mantine Styles API parts. */ .mantine-Scroller-root {} .mantine-Scroller-container {} .mantine-Scroller-content {} /* the scrolling track of children */ .mantine-Scroller-control { /* the prev / next chevron buttons */ background: var(--mantine-color-body); } .mantine-Scroller-chevron {} /* the icon inside a control */ ``` ## Injecting Attributes `attr={...}` passes raw HTML attributes straight onto the rendered element — handy for ids, data hooks, ARIA, or inline handlers the macro doesn't expose as named options. Pass a dictionary literal; every key/value lands verbatim on the element. Below, an injected `onclick` reports the element's text content when the row is clicked: Click anywhere on this row to see its text content via the injected handler then keep scrolling
Source: Markdown ```aardvark {% scrollbuttons attr={'onclick': ''' const value = this.innerText; console.log('attr demo value:', value); alert(value); '''} %} {% group wrap='nowrap' gap='md' %} {% paper withBorder=true radius='md' p='lg' w='200' %}Click anywhere on this row{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}to see its text content{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}via the injected handler{% endPaper %} {% paper withBorder=true radius='md' p='lg' w='200' %}then keep scrolling{% endPaper %} {% endGroup %} {% endScrollbuttons %} ``` Source: Python ```python cards = ''.join( component('aardvark', 'paper', withBorder=True, radius='md', p='lg', w='200', children=label) for label in ('Click anywhere on this row', 'to see its text content', 'via the injected handler', 'then keep scrolling') ) row = component('aardvark', 'group', wrap='nowrap', gap='md', children=cards) print(component('aardvark', 'scrollbuttons', children=row, attr={'onclick': ''' const value = this.innerText; console.log('attr demo value:', value); alert(value); '''})) ```