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="{
|
x-data="{
|
||||||
open: false,
|
open: false,
|
||||||
idx: 0,
|
idx: 0,
|
||||||
|
fill: false,
|
||||||
items: {{ $lbItems | jsonify }},
|
items: {{ $lbItems | jsonify }},
|
||||||
show(i) { this.idx = i; this.open = true },
|
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 },
|
prev() { this.idx = (this.idx - 1 + this.items.length) % this.items.length },
|
||||||
next() { this.idx = (this.idx + 1) % this.items.length }
|
next() { this.idx = (this.idx + 1) % this.items.length }
|
||||||
}"
|
}"
|
||||||
@keydown.escape.window="open && close()"
|
@keydown.escape.window="open && close()"
|
||||||
@keydown.arrow-left.window="open && prev()"
|
@keydown.arrow-left.window="open && prev()"
|
||||||
@keydown.arrow-right.window="open && next()"
|
@keydown.arrow-right.window="open && next()"
|
||||||
|
@keydown.f.window="open && (fill = !fill)"
|
||||||
>
|
>
|
||||||
|
|
||||||
<div class="flex items-center gap-5 mb-10">
|
<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"
|
<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>
|
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 -->
|
<!-- Close -->
|
||||||
<button
|
<button
|
||||||
@click="close()"
|
@click="close()"
|
||||||
@@ -190,14 +201,18 @@
|
|||||||
>{{ partial "icon.html" "arrow-left" }}</button>
|
>{{ partial "icon.html" "arrow-left" }}</button>
|
||||||
|
|
||||||
<!-- Media -->
|
<!-- 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 -->
|
||||||
<video
|
<video
|
||||||
x-show="items[idx] && items[idx].video"
|
x-show="items[idx] && items[idx].video"
|
||||||
:src="items[idx] && items[idx].video ? items[idx].video : ''"
|
:src="items[idx] && items[idx].video ? items[idx].video : ''"
|
||||||
:poster="items[idx] ? items[idx].img : ''"
|
:poster="items[idx] ? items[idx].img : ''"
|
||||||
x-effect="if (open && items[idx] && items[idx].video) { $el.load(); $el.play() }"
|
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
|
controls loop muted playsinline
|
||||||
></video>
|
></video>
|
||||||
<!-- Image -->
|
<!-- Image -->
|
||||||
@@ -205,7 +220,8 @@
|
|||||||
x-show="items[idx] && !items[idx].video"
|
x-show="items[idx] && !items[idx].video"
|
||||||
:src="items[idx] && !items[idx].video ? items[idx].img : ''"
|
:src="items[idx] && !items[idx].video ? items[idx].img : ''"
|
||||||
alt=""
|
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>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user