Skip to content
Brok UI

Loading…

No results

Scroll Split Card

Open source

A card whose two halves split apart as it scrolls through the viewport, revealing inner content between them. Driven purely by CSS scroll-timeline (view()).

Version
v1.1.6
Stability
stable
License
MIT
Related
Sticky Cards
Tilt Card
Mockup

Preview

Scroll inside this box

Scroll

Built for the scroll.

The halves drift apart as this card moves through the viewport, framing the message in the middle.

to reveal

previews.components.scroll-split-card.default.blade.php Blade
{{-- The split rides a view() timeline, so the card needs to travel through a
     scrollport: this stage scrolls on its own. --}}
<div class="relative mx-auto h-96 w-full max-w-md overflow-y-auto rounded-lg border border-border bg-background p-4 [scrollbar-width:thin]">
    <p class="mb-4 text-center text-xs text-muted-foreground">{{ __('Scroll inside this box') }}</p>
    <div class="h-72" aria-hidden="true"></div>
    <x-ui.scroll-split-card>
        <x-slot:top>
            <p class="text-sm font-medium uppercase tracking-wide text-muted-foreground">Scroll</p>
        </x-slot:top>

        <div class="space-y-1">
            <p class="text-lg font-semibold text-foreground">Built for the scroll.</p>
            <p class="text-sm text-muted-foreground">The halves drift apart as this card moves through the viewport, framing the message in the middle.</p>
        </div>

        <x-slot:bottom>
            <p class="text-sm font-medium uppercase tracking-wide text-muted-foreground">to reveal</p>
        </x-slot:bottom>
    </x-ui.scroll-split-card>
    <div class="h-80" aria-hidden="true"></div>
</div>

Installation

terminal
php artisan ui:add scroll-split-card

Registry contract

php artisan ui:add scroll-split-card writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.

  • blade resources/views/components/ui/scroll-split-card.blade.php
Registry dependencies
None — installs on its own.
Packages
composer: jml/brok:^0.2

Use with AI

A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.

scroll-split-card.md
# Brok UI: Scroll Split Card (`scroll-split-card`)

A card whose two halves split apart as it scrolls through the viewport, revealing inner content between them. Driven purely by CSS scroll-timeline (view()).

Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.

## Install

```bash
php artisan ui:add scroll-split-card
```

## Usage

```blade
{{-- The split rides a view() timeline, so the card needs to travel through a
     scrollport: this stage scrolls on its own. --}}
<div class="relative mx-auto h-96 w-full max-w-md overflow-y-auto rounded-lg border border-border bg-background p-4 [scrollbar-width:thin]">
    <p class="mb-4 text-center text-xs text-muted-foreground">{{ __('Scroll inside this box') }}</p>
    <div class="h-72" aria-hidden="true"></div>
    <x-ui.scroll-split-card>
        <x-slot:top>
            <p class="text-sm font-medium uppercase tracking-wide text-muted-foreground">Scroll</p>
        </x-slot:top>

        <div class="space-y-1">
            <p class="text-lg font-semibold text-foreground">Built for the scroll.</p>
            <p class="text-sm text-muted-foreground">The halves drift apart as this card moves through the viewport, framing the message in the middle.</p>
        </div>

        <x-slot:bottom>
            <p class="text-sm font-medium uppercase tracking-wide text-muted-foreground">to reveal</p>
        </x-slot:bottom>
    </x-ui.scroll-split-card>
    <div class="h-80" aria-hidden="true"></div>
</div>
```

## Props

- `split` (string, default `40%`) — CSS length or percentage each half slides away from the seam.
- `as` (string, default `div`) — Tag rendered for the root: div, article, or section.
- `top` (mixed|null, default `null`) — Content rendered in the top panel.
- `bottom` (mixed|null, default `null`) — Content rendered in the bottom panel.

## Use when

- Use only when visual expression supports storytelling, brand differentiation, or a clear showcase moment.
- Revealing content between two card halves that slide apart as the element scrolls through the viewport, using pure CSS scroll-driven animation.

## Avoid when

- Do not place heavy effects in task-dense workflows where clarity, speed, and readability matter more.
- Browser support for CSS scroll-driven animation is required everywhere; confirm the static-split fallback is acceptable before relying on the reveal.
- Needing the reveal to be user-controlled rather than scroll-driven; use sticky-cards or tilt-card instead.

## Anti-patterns

- Heavy effects in forms or task-dense workflows
- Motion that interferes with reading or focus

## Rules

- Use the `<brok:scroll-split-card>` tag (or `<x-ui.scroll-split-card>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.

## Links

- Docs: https://brokui.dev/docs/components/scroll-split-card
- Registry JSON (files, props, contract): https://brokui.dev/r/open/scroll-split-card.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

API

manifest knowledge + registry-derived coverage

Props

Props accepted by this component: name, type, default value and description.
Prop Type Default Description
split string 40% CSS length or percentage each half slides away from the seam.
as string div Tag rendered for the root: div, article, or section.
top mixed | null null Content rendered in the top panel.
bottom mixed | null null Content rendered in the bottom panel.

Slots

  • default —

Renders as div, article, section.

Data slots

Stable hooks for CSS overrides and browser tests.

scroll-split-card scroll-split-card-bottom scroll-split-card-reveal scroll-split-card-top

Behavior

  • The top and bottom panels ride an animation-timeline: view() animation tied to the element's scroll progress, sliding apart by --split with no JS or scroll listeners.
  • Reduced motion and lack of @supports for scroll-driven animation are gated in ui.css, keeping the panels in their resting split position.
  • Declares registry capability flags: a11y, responsive, rtl, darkMode, localized, reducedMotion.

Guidance

Expressive and showcase effect

Support brand expression or a showcase moment.

Use when

  • Use only when visual expression supports storytelling, brand differentiation, or a clear showcase moment.
  • Revealing content between two card halves that slide apart as the element scrolls through the viewport, using pure CSS scroll-driven animation.

Avoid when

  • Do not place heavy effects in task-dense workflows where clarity, speed, and readability matter more.
  • Browser support for CSS scroll-driven animation is required everywhere; confirm the static-split fallback is acceptable before relying on the reveal.
  • Needing the reveal to be user-controlled rather than scroll-driven; use sticky-cards or tilt-card instead.

Use instead

  • Static content-first presentation

Anti-patterns

  • Heavy effects in forms or task-dense workflows
  • Motion that interferes with reading or focus
Anatomy
root scroll-split-card-top scroll-split-card-reveal scroll-split-card-bottom
Theming hooks
scroll-split-card scroll-split-card-bottom scroll-split-card-reveal scroll-split-card-top

Accessibility

WCAG 2.2 AA Keyboard focus-visible RTL-ready Localized labels Dark mode
Keyboard
No component-owned keyboard interaction; native element behavior applies.
Focus
none
  • as renders the root as a div, article, or section so the wrapper can carry the semantic role that fits its content.
  • Semantic HTML and a stable data-slot attribute for styling and scripting hooks.
  • Focus-visible rings use the ring token, so keyboard focus is always visible.
  • Disabled and invalid states are conveyed to assistive tech, not by color alone.
  • Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
  • Labels go through __() and layout uses logical properties (ms-*, text-start), so it mirrors under dir="rtl" — flip the preview to RTL to confirm.
  • Dark mode uses the same semantic tokens under the dark class; high contrast follows forced-color system tokens.

Livewire

Safe

Livewire can update this component through forwarded wire:* attributes.

Source

The exact, editable file ui:add writes into your app. Previews render this same code; there are no preview-only components.

resources/views/components/ui/scroll-split-card.blade.php Blade
@props([
    'split' => '40%',
    'as' => 'div',
    'top' => null,
    'bottom' => null,
])

@php
    // Pure CSS scroll-driven split. The two panels (top + bottom) ride an
    // `animation-timeline: view()` so their travel is tied to the element's
    // progress through the viewport — no JS, no scroll listeners.
    //
    // Keyframes (`ui-split-top`/`ui-split-bottom`) and the @supports +
    // prefers-reduced-motion gating live in ui.css, keyed on this data-slot.
    // `--split` is how far each half slides away from the seam.
    //
    // Regions: `top` + `bottom` props are the two panels (token bg-card);
    // the default slot is the revealed centre content that sits between them.
    $allowedTags = ['div', 'article', 'section'];
    $tag = in_array($as, $allowedTags, true) ? $as : 'div';
@endphp

<{{ $tag }}
    data-slot="scroll-split-card"
    style="--split: {{ $split }};"
    {{ $attributes->merge(['class' => 'relative isolate flex flex-col items-stretch rounded-lg']) }}
>
    <div data-slot="scroll-split-card-top" class="z-10 rounded-t-lg border border-b-0 border-border bg-card px-6 py-6 text-center text-card-foreground shadow-sm">
        {{ $top }}
    </div>

    <div data-slot="scroll-split-card-reveal" class="-my-px flex items-center justify-center px-6 py-4 text-center">
        {{ $slot }}
    </div>

    <div data-slot="scroll-split-card-bottom" class="z-10 rounded-b-lg border border-t-0 border-border bg-card px-6 py-6 text-center text-card-foreground shadow-sm">
        {{ $bottom }}
    </div>
</{{ $tag }}>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.1.6
Status
Stable
License
open
Accessibility reviewed
No review date recorded
Last breaking change
No date recorded
Deprecation
Not deprecated
Contract
v6
Foundation
≥ 1.0.0