From c1d3f25d50b9a2adf4f05bdf462ffcd43a92e383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Mon, 27 Apr 2026 16:45:49 +0100 Subject: [PATCH] WIP Add basic photo gallery --- app/components/place-photos-carousel.gjs | 28 ++++++++- app/styles/app.css | 78 ++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/app/components/place-photos-carousel.gjs b/app/components/place-photos-carousel.gjs index 4c115bc..3a31ae7 100644 --- a/app/components/place-photos-carousel.gjs +++ b/app/components/place-photos-carousel.gjs @@ -1,8 +1,10 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; +import { fn } from '@ember/helper'; import Blurhash from './blurhash'; import Icon from './icon'; +import PhotoGallery from './photo-gallery'; import fadeInImage from '../modifiers/fade-in-image'; import { on } from '@ember/modifier'; import { modifier } from 'ember-modifier'; @@ -10,6 +12,8 @@ import { modifier } from 'ember-modifier'; export default class PlacePhotosCarousel extends Component { @tracked canScrollLeft = false; @tracked canScrollRight = false; + @tracked isGalleryOpen = false; + @tracked selectedPhoto = 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; + } + } diff --git a/app/styles/app.css b/app/styles/app.css index 0be48a5..1df9504 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -909,6 +909,7 @@ abbr[title] { } .carousel-slide { + cursor: pointer; position: relative; flex: 0 0 100%; scroll-snap-align: start; @@ -1866,3 +1867,80 @@ button.create-place { .btn-link:hover { 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; +}