Compare commits
3 commits
6115268587
...
cd1ca94b11
| Author | SHA1 | Date | |
|---|---|---|---|
| cd1ca94b11 | |||
| c80e2bd386 | |||
| 98778965d2 |
7 changed files with 229 additions and 94 deletions
|
|
@ -7,62 +7,3 @@
|
||||||
.prose img {
|
.prose img {
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sun {
|
|
||||||
transform: translate3d(0, 0px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#moon {
|
|
||||||
transform: translate3d(0, 0px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#darkToggle:hover #sun {
|
|
||||||
transform: translate3d(0, 10px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#darkToggle:hover #moon {
|
|
||||||
transform: translate3d(0, 10px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark #darkToggle:hover .horizon {
|
|
||||||
border-color: #718096 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizon .setting {
|
|
||||||
animation: 1s ease 0s 1 setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizon .rising {
|
|
||||||
animation: 1s ease 0s 1 rising;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes setting {
|
|
||||||
0% {
|
|
||||||
transform: translate3d(0, 10px, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
transform: translate3d(0, -2px, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
transform: translate3d(0, 30px, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rising {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translate3d(0, 30px, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translate3d(0, -2px, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translate3d(0, 10, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -31,12 +31,13 @@ const currentMenus = menus[currentLang] || menus.fr;
|
||||||
class="flex items-center justify-between h-full max-w-5xl pl-6 pr-4 mx-auto border-b border-l-0 border-r-0 border-transparent select-none lg:border-r lg:border-l lg:rounded-b-xl"
|
class="flex items-center justify-between h-full max-w-5xl pl-6 pr-4 mx-auto border-b border-l-0 border-r-0 border-transparent select-none lg:border-r lg:border-l lg:rounded-b-xl"
|
||||||
>
|
>
|
||||||
<Logo />
|
<Logo />
|
||||||
<div
|
<button
|
||||||
id="mobileMenuBackground"
|
id="mobileMenuBackground"
|
||||||
onclick="closeMobileMenu()"
|
type="button"
|
||||||
class="fixed inset-0 z-20 hidden w-screen h-screen duration-300 ease-out bg-white/90 dark:bg-neutral-950/90"
|
aria-label="Fermer le menu"
|
||||||
|
class="fixed inset-0 z-20 hidden w-screen h-screen duration-300 ease-out bg-white/90 dark:bg-neutral-950/90 appearance-none border-0 p-0 cursor-default"
|
||||||
>
|
>
|
||||||
</div>
|
</button>
|
||||||
<nav
|
<nav
|
||||||
class="relative z-30 flex flex-row-reverse justify-start w-full text-sm sm:justify-end text-neutral-500 dark:text-neutral-400 sm:flex-row"
|
class="relative z-30 flex flex-row-reverse justify-start w-full text-sm sm:justify-end text-neutral-500 dark:text-neutral-400 sm:flex-row"
|
||||||
>
|
>
|
||||||
|
|
@ -94,3 +95,9 @@ const currentMenus = menus[currentLang] || menus.fr;
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
document.getElementById('mobileMenuBackground').addEventListener('click', function () {
|
||||||
|
window.closeMobileMenu();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import { Picture } from 'astro:assets';
|
import { Picture } from 'astro:assets';
|
||||||
import ScrollIndicator from './ScrollIndicator.astro';
|
import HeroViewport from './HeroViewport.astro';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -15,25 +15,26 @@ const { title, description, date, tags, coverImage, scrollTarget = '.info-sectio
|
||||||
---
|
---
|
||||||
|
|
||||||
{coverImage && (
|
{coverImage && (
|
||||||
<div class="hero-image">
|
<HeroViewport targetSelector={scrollTarget}>
|
||||||
<Picture src={coverImage} alt={title} widths={[800, 1200, 1920]} formats={['webp']} />
|
<div class="hero-image">
|
||||||
<div class="hero-overlay">
|
<Picture src={coverImage} alt={title} widths={[800, 1200, 1920]} formats={['webp']} />
|
||||||
<div class="hero-content">
|
<div class="hero-overlay">
|
||||||
<h1 class="album-title">{title}</h1>
|
<div class="hero-content">
|
||||||
{description && <p class="album-description">{description}</p>}
|
<h1 class="album-title">{title}</h1>
|
||||||
{date && (
|
{description && <p class="album-description">{description}</p>}
|
||||||
<time class="album-date">
|
{date && (
|
||||||
{date.toLocaleDateString('fr-FR', {
|
<time class="album-date">
|
||||||
year: 'numeric',
|
{date.toLocaleDateString('fr-FR', {
|
||||||
month: 'long',
|
year: 'numeric',
|
||||||
day: 'numeric'
|
month: 'long',
|
||||||
})}
|
day: 'numeric'
|
||||||
</time>
|
})}
|
||||||
)}
|
</time>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ScrollIndicator targetSelector={scrollTarget} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</HeroViewport>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tags && tags.length > 0 && (
|
{tags && tags.length > 0 && (
|
||||||
|
|
@ -47,10 +48,13 @@ const { title, description, date, tags, coverImage, scrollTarget = '.info-sectio
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
:global(.hero-viewport) {
|
||||||
|
--hero-height: calc(100vh - var(--header-height, 53px) - var(--footer-height, 54px));
|
||||||
|
}
|
||||||
|
|
||||||
.hero-image {
|
.hero-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - var(--header-height, 53px) - var(--footer-height, 54px));
|
height: 100%;
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import CategoryNav from './CategoryNav.astro';
|
import CategoryNav from './CategoryNav.astro';
|
||||||
import ScrollIndicator from './ScrollIndicator.astro';
|
import HeroViewport from './HeroViewport.astro';
|
||||||
import Lightbox from './Lightbox.astro';
|
import Lightbox from './Lightbox.astro';
|
||||||
import { Picture } from 'astro:assets';
|
import { Picture } from 'astro:assets';
|
||||||
import { getEntry } from 'astro:content';
|
import { getEntry } from 'astro:content';
|
||||||
|
|
@ -49,7 +49,7 @@ const lightboxImages = images.map(img => ({
|
||||||
<CategoryNav currentCategory={category} opaque={true} />
|
<CategoryNav currentCategory={category} opaque={true} />
|
||||||
|
|
||||||
<!-- Image hero avec titre en overlay -->
|
<!-- Image hero avec titre en overlay -->
|
||||||
<header class="hero-cover">
|
<HeroViewport targetSelector="#thumbnails">
|
||||||
<div class="hero-image">
|
<div class="hero-image">
|
||||||
{images[0] && <Picture src={images[0].src} alt={images[0].alt} widths={[800, 1200, 1920]} formats={['webp']} class="hero-bg" />}
|
{images[0] && <Picture src={images[0].src} alt={images[0].alt} widths={[800, 1200, 1920]} formats={['webp']} class="hero-bg" />}
|
||||||
<div class="hero-overlay">
|
<div class="hero-overlay">
|
||||||
|
|
@ -61,10 +61,9 @@ const lightboxImages = images.map(img => ({
|
||||||
<p class="hero-subtitle">{categoryData.data.subtitle}</p>
|
<p class="hero-subtitle">{categoryData.data.subtitle}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ScrollIndicator targetSelector="#thumbnails" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</HeroViewport>
|
||||||
|
|
||||||
<!-- Grille de thumbnails -->
|
<!-- Grille de thumbnails -->
|
||||||
<div id="thumbnails" class="thumbnails-grid">
|
<div id="thumbnails" class="thumbnails-grid">
|
||||||
|
|
@ -144,11 +143,8 @@ document.addEventListener('scroll', onScroll);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-cover {
|
.category-container :global(.hero-viewport) {
|
||||||
position: relative;
|
--hero-height: calc(100vh - var(--header-height) - var(--footer-height));
|
||||||
width: 100%;
|
|
||||||
height: calc(100vh - var(--header-height) - var(--footer-height));
|
|
||||||
overflow: hidden;
|
|
||||||
margin-top: var(--header-height);
|
margin-top: var(--header-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
150
src/components/photo/ExploreSection.astro
Normal file
150
src/components/photo/ExploreSection.astro
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
---
|
||||||
|
import { getCollection } from 'astro:content';
|
||||||
|
|
||||||
|
const photoCategories = await getCollection('photoCategories');
|
||||||
|
const sortedCategories = photoCategories.sort((a, b) => (a.data.order || 99) - (b.data.order || 99));
|
||||||
|
---
|
||||||
|
|
||||||
|
<section id="explore-section" class="explore-section">
|
||||||
|
<div class="explore-content">
|
||||||
|
<div class="explore-card">
|
||||||
|
<h2 class="explore-card-title">Catégories</h2>
|
||||||
|
<p class="explore-card-desc">Parcourir les photos par thème</p>
|
||||||
|
<ul class="category-list">
|
||||||
|
{sortedCategories.map(cat => (
|
||||||
|
<li>
|
||||||
|
<a href={`/photo/albums/${cat.id}`} class="category-link">
|
||||||
|
{cat.data.title}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="explore-card">
|
||||||
|
<h2 class="explore-card-title">Fil Photo</h2>
|
||||||
|
<p class="explore-card-desc">Parcourir les séries chronologiques, reportages et histoires en images</p>
|
||||||
|
<a href="/photo/blog" class="explore-cta">
|
||||||
|
Voir le fil
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="5" y1="12" x2="19" y2="12"/>
|
||||||
|
<polyline points="12 5 19 12 12 19"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.explore-section {
|
||||||
|
position: relative;
|
||||||
|
background: #000;
|
||||||
|
z-index: 20;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
padding-top: 8rem;
|
||||||
|
min-height: 60vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-section::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -30vh;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 30vh;
|
||||||
|
background: linear-gradient(to bottom, transparent, #000);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-content {
|
||||||
|
display: flex;
|
||||||
|
gap: 3rem;
|
||||||
|
max-width: 900px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-card {
|
||||||
|
flex: 1;
|
||||||
|
padding: 2rem;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-card-title {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-card-desc {
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-link {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.4rem 0.9rem;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
|
border-radius: 20px;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: background 0.2s ease, color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-link:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-cta {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.6rem 1.2rem;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-cta:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.explore-section {
|
||||||
|
padding: 3rem 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-content {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explore-card {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
33
src/components/photo/HeroViewport.astro
Normal file
33
src/components/photo/HeroViewport.astro
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
import ScrollIndicator from './ScrollIndicator.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
targetSelector?: string;
|
||||||
|
transparent?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { targetSelector = '#content', transparent = false } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class:list={['hero-viewport', { transparent }]}>
|
||||||
|
<slot />
|
||||||
|
<ScrollIndicator targetSelector={targetSelector} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero-viewport {
|
||||||
|
position: relative;
|
||||||
|
height: var(--hero-height, 100vh);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-viewport.transparent {
|
||||||
|
z-index: 25;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-viewport.transparent :global(.scroll-indicator) {
|
||||||
|
pointer-events: auto;
|
||||||
|
bottom: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
---
|
---
|
||||||
import PhotoLayout from '../layouts/PhotoLayout.astro';
|
import PhotoLayout from '../layouts/PhotoLayout.astro';
|
||||||
import PhotoGallery from '../components/photo/PhotoGallery.astro';
|
import PhotoGallery from '../components/photo/PhotoGallery.astro';
|
||||||
|
import HeroViewport from '../components/photo/HeroViewport.astro';
|
||||||
|
import ExploreSection from '../components/photo/ExploreSection.astro';
|
||||||
|
|
||||||
const title = "Galerie Photo - Jalil Arfaoui";
|
const title = "Galerie Photo - Jalil Arfaoui";
|
||||||
---
|
---
|
||||||
|
|
||||||
<PhotoLayout title={title}>
|
<PhotoLayout title={title} enableScroll={true}>
|
||||||
<PhotoGallery category="all" />
|
<PhotoGallery category="all" />
|
||||||
|
<HeroViewport targetSelector="#explore-section" transparent />
|
||||||
|
<ExploreSection />
|
||||||
</PhotoLayout>
|
</PhotoLayout>
|
||||||
Loading…
Add table
Reference in a new issue