feat: lightbox fill/fit toggle mode
Add fill state (default false) to the Alpine lightbox data: - FILL button (top-right, left of ✕): switches media to object-cover, filling the entire overlay edge-to-edge; button turns heat pink - FIT restores object-contain with padding; button returns to fog - Keyboard shortcut F toggles fill while lightbox is open - close() resets fill to false for the next open - transition-all duration-300 on container padding and media for a smooth morph between modes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -116,15 +116,17 @@
|
||||
x-data="{
|
||||
open: false,
|
||||
idx: 0,
|
||||
fill: false,
|
||||
items: {{ $lbItems | jsonify }},
|
||||
show(i) { this.idx = i; this.open = true },
|
||||
close() { this.open = false },
|
||||
close() { this.open = false; this.fill = false },
|
||||
prev() { this.idx = (this.idx - 1 + this.items.length) % this.items.length },
|
||||
next() { this.idx = (this.idx + 1) % this.items.length }
|
||||
}"
|
||||
@keydown.escape.window="open && close()"
|
||||
@keydown.arrow-left.window="open && prev()"
|
||||
@keydown.arrow-right.window="open && next()"
|
||||
@keydown.f.window="open && (fill = !fill)"
|
||||
>
|
||||
|
||||
<div class="flex items-center gap-5 mb-10">
|
||||
@@ -174,6 +176,15 @@
|
||||
<div class="absolute top-5 left-1/2 -translate-x-1/2 label text-fog tabular-nums"
|
||||
x-text="`${String(idx + 1).padStart(2,'0')} / ${String(items.length).padStart(2,'0')}`"></div>
|
||||
|
||||
<!-- Fill / Fit toggle -->
|
||||
<button
|
||||
@click="fill = !fill"
|
||||
class="absolute top-3 right-16 w-10 h-10 flex items-center justify-center label transition-colors"
|
||||
:class="fill ? 'text-heat hover:text-chalk' : 'text-fog hover:text-heat'"
|
||||
:aria-label="fill ? 'Switch to fit mode' : 'Switch to fill mode'"
|
||||
x-text="fill ? 'FIT' : 'FILL'"
|
||||
></button>
|
||||
|
||||
<!-- Close -->
|
||||
<button
|
||||
@click="close()"
|
||||
@@ -190,14 +201,18 @@
|
||||
>{{ partial "icon.html" "arrow-left" }}</button>
|
||||
|
||||
<!-- Media -->
|
||||
<div class="w-full h-full flex items-center justify-center px-14 md:px-20 py-14">
|
||||
<div
|
||||
class="w-full h-full flex items-center justify-center transition-all duration-300"
|
||||
:class="fill ? 'p-0' : 'px-14 md:px-20 py-14'"
|
||||
>
|
||||
<!-- Video -->
|
||||
<video
|
||||
x-show="items[idx] && items[idx].video"
|
||||
:src="items[idx] && items[idx].video ? items[idx].video : ''"
|
||||
:poster="items[idx] ? items[idx].img : ''"
|
||||
x-effect="if (open && items[idx] && items[idx].video) { $el.load(); $el.play() }"
|
||||
class="max-w-full max-h-full object-contain"
|
||||
:class="fill ? 'w-full h-full object-cover' : 'max-w-full max-h-full object-contain'"
|
||||
class="transition-all duration-300"
|
||||
controls loop muted playsinline
|
||||
></video>
|
||||
<!-- Image -->
|
||||
@@ -205,7 +220,8 @@
|
||||
x-show="items[idx] && !items[idx].video"
|
||||
:src="items[idx] && !items[idx].video ? items[idx].img : ''"
|
||||
alt=""
|
||||
class="max-w-full max-h-full object-contain"
|
||||
:class="fill ? 'w-full h-full object-cover' : 'max-w-full max-h-full object-contain'"
|
||||
class="transition-all duration-300"
|
||||
>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user