WIP Add basic photo gallery

This commit is contained in:
2026-04-27 16:45:49 +01:00
parent 2087cfc4f7
commit c1d3f25d50
2 changed files with 105 additions and 1 deletions

View File

@@ -1,8 +1,10 @@
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking'; import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object'; import { action } from '@ember/object';
import { fn } from '@ember/helper';
import Blurhash from './blurhash'; import Blurhash from './blurhash';
import Icon from './icon'; import Icon from './icon';
import PhotoGallery from './photo-gallery';
import fadeInImage from '../modifiers/fade-in-image'; import fadeInImage from '../modifiers/fade-in-image';
import { on } from '@ember/modifier'; import { on } from '@ember/modifier';
import { modifier } from 'ember-modifier'; import { modifier } from 'ember-modifier';
@@ -10,6 +12,8 @@ import { modifier } from 'ember-modifier';
export default class PlacePhotosCarousel extends Component { export default class PlacePhotosCarousel extends Component {
@tracked canScrollLeft = false; @tracked canScrollLeft = false;
@tracked canScrollRight = false; @tracked canScrollRight = false;
@tracked isGalleryOpen = false;
@tracked selectedPhoto = null;
carouselElement = null; carouselElement = null;
@@ -103,6 +107,18 @@ export default class PlacePhotosCarousel extends Component {
}); });
} }
@action
openGallery(photo) {
this.selectedPhoto = photo;
this.isGalleryOpen = true;
}
@action
closeGallery() {
this.isGalleryOpen = false;
this.selectedPhoto = null;
}
<template> <template>
{{#if this.photos.length}} {{#if this.photos.length}}
<div class="place-photos-carousel-wrapper"> <div class="place-photos-carousel-wrapper">
@@ -114,12 +130,13 @@ export default class PlacePhotosCarousel extends Component {
{{on "scroll" this.updateScrollState}} {{on "scroll" this.updateScrollState}}
> >
{{#each this.photos as |photo|}} {{#each this.photos as |photo|}}
{{! template-lint-disable no-inline-styles }} {{! template-lint-disable no-inline-styles no-invalid-interactive }}
<div <div
class="carousel-slide class="carousel-slide
{{if photo.isLandscape 'landscape' 'portrait'}}" {{if photo.isLandscape 'landscape' 'portrait'}}"
style={{photo.style}} style={{photo.style}}
data-event-id={{photo.eventId}} data-event-id={{photo.eventId}}
{{on "click" (fn this.openGallery photo)}}
> >
{{#if photo.blurhash}} {{#if photo.blurhash}}
<Blurhash <Blurhash
@@ -185,5 +202,14 @@ export default class PlacePhotosCarousel extends Component {
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
{{#if this.isGalleryOpen}}
<PhotoGallery
@photos={{this.photos}}
@selectedPhoto={{this.selectedPhoto}}
@placeName={{@name}}
@onClose={{this.closeGallery}}
/>
{{/if}}
</template> </template>
} }

View File

@@ -909,6 +909,7 @@ abbr[title] {
} }
.carousel-slide { .carousel-slide {
cursor: pointer;
position: relative; position: relative;
flex: 0 0 100%; flex: 0 0 100%;
scroll-snap-align: start; scroll-snap-align: start;
@@ -1866,3 +1867,80 @@ button.create-place {
.btn-link:hover { .btn-link:hover {
text-decoration: underline; text-decoration: underline;
} }
/* Photo Gallery */
.photo-gallery-overlay {
position: fixed;
inset: 0;
background: rgb(0 0 0 / 80%);
z-index: 9999;
display: flex;
flex-direction: column;
}
.photo-gallery-overlay .photo-gallery-content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
}
.photo-gallery-overlay .close-btn {
position: absolute;
top: 0.5rem;
right: 1rem;
width: 48px;
height: 48px;
z-index: 10;
color: white;
background: transparent;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.2s ease;
}
@media (width <= 768px) {
.photo-gallery-overlay .close-btn {
right: 0.5rem;
}
}
.photo-gallery-overlay .main-photo-container {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
overflow: hidden;
}
.photo-gallery-overlay .main-photo-container img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.photo-gallery-overlay .thumbnail-strip {
height: 100px;
display: flex;
gap: 0.5rem;
padding: 1rem;
overflow-x: auto;
background: rgb(0 0 0 / 50%);
}
.photo-gallery-overlay .thumbnail-strip .thumbnail {
height: 100%;
flex-shrink: 0;
cursor: pointer;
}
.photo-gallery-overlay .thumbnail-strip img {
height: 100%;
width: auto;
object-fit: cover;
border-radius: 4px;
}