app/components/Gallery/fancybox.latte
{*
Fancybox — wrapper pro lightbox link s hover overlay.
Single image:
{include fancybox.latte, src => '/img/large.jpg', thumb => '/img/thumb.jpg', alt => 'Foto'}
Group (galerie — všechny linky se stejným $group jsou navigovatelné):
{include fancybox.latte, src => $url, thumb => $thumbUrl, group => 'gallery-1', alt => $alt}
Parametry:
- $src (string) URL plnohodnotného obrázku (povinné)
- $thumb (string|null) URL náhledu (default = $src)
- $alt (string) alt text (default '')
- $group (string|null) group ID pro galerii (Fancybox data-fancybox)
- $caption (string|null) popisek v lightboxu
- $class (string|null) extra třída
- $showOverlay (bool) hover overlay s ikonou (default true)
*}
{var $src = $src ?? null}
{var $thumb = $thumb ?? $src}
{var $alt = $alt ?? ''}
{var $group = $group ?? 'fancybox'}
{var $caption = $caption ?? null}
{var $class = $class ?? null}
{var $showOverlay = $showOverlay ?? true}
<a href="{$src}"
class="fancybox-trigger{if $class} {$class}{/if}"
data-fancybox="{$group}"
{if $caption}data-caption="{$caption}"{/if}>
<img src="{$thumb}" alt="{$alt}" loading="lazy">
{if $showOverlay}
<span class="fancybox-trigger__overlay" aria-hidden="true">
<svg class="fancybox-trigger__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="7"/>
<line x1="16.5" y1="16.5" x2="21" y2="21"/>
<line x1="11" y1="8" x2="11" y2="14"/>
<line x1="8" y1="11" x2="14" y2="11"/>
</svg>
</span>
{/if}
</a>
resources/sass/components/_fancybox.scss
// ─── Configurable variables (override before @import) ──────────────────
$cgui-fancybox-trigger-cursor: zoom-in !default;
$cgui-fancybox-trigger-overlay-bg: rgba(0, 0, 0, 0.4) !default;
$cgui-fancybox-trigger-overlay-color: #fff !default;
$cgui-fancybox-trigger-icon-size: 38px !default;
$cgui-fancybox-trigger-radius: $cgui-radius !default;
$cgui-fancybox-trigger-transition: opacity 0.2s !default;
// ───────────────────────────────────────────────────────────────────────
// Wrapper kolem trigger linku — přidává hover overlay s ikonou lupy.
.fancybox-trigger {
position: relative;
display: block;
overflow: hidden;
border-radius: $cgui-fancybox-trigger-radius;
cursor: $cgui-fancybox-trigger-cursor;
img {
display: block;
width: 100%;
height: auto;
transition: transform 0.3s;
}
&__overlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: $cgui-fancybox-trigger-overlay-bg;
color: $cgui-fancybox-trigger-overlay-color;
opacity: 0;
transition: $cgui-fancybox-trigger-transition;
pointer-events: none;
}
&__icon {
width: $cgui-fancybox-trigger-icon-size;
height: $cgui-fancybox-trigger-icon-size;
}
&:hover,
&:focus {
.fancybox-trigger__overlay {
opacity: 1;
}
img {
transform: scale(1.03);
}
}
}
resources/js/components/fancybox.js
// Fancybox — auto-bind pro [data-fancybox]. Wraps Fancybox.
// Vyžaduje: npm install @fancyapps/ui
import { Fancybox } from '@fancyapps/ui';
const DEFAULT_OPTIONS = {
hideScrollbar: true,
Toolbar: {
display: {
left: ['infobar'],
middle: [],
right: ['slideshow', 'thumbs', 'close'],
},
},
Thumbs: {
type: 'classic',
},
};
let bound = false;
export function bind(selector = '[data-fancybox]', options = {}) {
Fancybox.bind(selector, { ...DEFAULT_OPTIONS, ...options });
bound = true;
}
export function unbind(selector = '[data-fancybox]') {
Fancybox.unbind(selector);
}
export function open(items, options = {}) {
return Fancybox.show(items, { ...DEFAULT_OPTIONS, ...options });
}
// Auto-bind on first import
if (typeof document !== 'undefined' && !bound) {
if (document.readyState !== 'loading') {
bind();
} else {
document.addEventListener('DOMContentLoaded', () => bind());
}
}
export { Fancybox };