Layout primitives
Split Panels code
Copy the implementation or inspect every file that belongs to this component unit.
resources/views/components/ui/split-panels.blade.php
@props([
'orientation' => 'horizontal',
'initial' => 50,
'min' => 20,
'max' => 80,
'height' => 'h-96',
])
@php
/*
| Resizable split panels with a draggable divider (no dependencies). Drag the
| handle to resize the two panes; `initial`, `min` and `max` are percentages.
|
| orientation: horizontal (side-by-side) | vertical (stacked)
|
| Usage:
| <x-ui.split-panels :initial="40" class="rounded-2xl border border-gray-200 dark:border-gray-800">
| <x-slot:start>...</x-slot:start>
| <x-slot:end>...</x-slot:end>
| </x-ui.split-panels>
*/
$vertical = $orientation === 'vertical';
@endphp
<div
x-data="{
pos: {{ (int) $initial }},
min: {{ (int) $min }},
max: {{ (int) $max }},
vertical: @js($vertical),
dragging: false,
start() {
this.dragging = true;
document.body.style.userSelect = 'none';
document.body.style.cursor = this.vertical ? 'row-resize' : 'col-resize';
},
move(event) {
if (! this.dragging) { return; }
const rect = this.$el.getBoundingClientRect();
const raw = this.vertical
? ((event.clientY - rect.top) / rect.height) * 100
: ((event.clientX - rect.left) / rect.width) * 100;
this.pos = Math.min(this.max, Math.max(this.min, raw));
},
stop() {
this.dragging = false;
document.body.style.userSelect = '';
document.body.style.cursor = '';
},
}"
@pointermove.window="move($event)"
@pointerup.window="stop()"
{{ $attributes->merge(['class' => 'relative flex w-full overflow-hidden '.($vertical ? 'flex-col' : 'flex-row').' '.$height]) }}
>
<div
class="min-h-0 min-w-0 overflow-auto"
:style="vertical ? `height: ${pos}%` : `width: ${pos}%`"
>
{{ $start ?? '' }}
</div>
<div
role="separator"
:aria-orientation="vertical ? 'horizontal' : 'vertical'"
@pointerdown.prevent="start()"
class="group relative flex shrink-0 items-center justify-center bg-gray-200 transition hover:bg-brand-400 dark:bg-gray-800 dark:hover:bg-brand-500"
:class="[
vertical ? 'h-1.5 w-full cursor-row-resize' : 'w-1.5 cursor-col-resize',
dragging ? (vertical ? 'bg-brand-500' : 'bg-brand-500') : '',
]"
>
<span
class="rounded-full bg-white/70 dark:bg-gray-500/70"
:class="vertical ? 'h-1 w-8' : 'h-8 w-1'"
></span>
</div>
<div class="min-h-0 min-w-0 flex-1 overflow-auto">
{{ $end ?? '' }}
</div>
</div>