Compare commits
No commits in common. "d42217fd209a1f664ea05784578fd862e2fad0e7" and "600ce937a3c7b78ca3151f0b3afcfebf97c2f584" have entirely different histories.
d42217fd20
...
600ce937a3
8 changed files with 110 additions and 151 deletions
|
|
@ -1,14 +1,113 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'debug' => true,
|
// Debug mode (désactiver en production)
|
||||||
'languages' => true,
|
'debug' => true,
|
||||||
|
|
||||||
|
// Panel configuration
|
||||||
'panel' => [
|
'panel' => [
|
||||||
'css' => 'assets/css/custom-panel.css',
|
'css' => 'assets/css/custom-panel.css',
|
||||||
'theme' => 'dark',
|
'theme' => 'dark',
|
||||||
'menu' => require __DIR__ . '/menu.php',
|
// Menu personnalisé du panel
|
||||||
|
'menu' => [
|
||||||
|
'site' => [
|
||||||
|
'label' => 'Données partagées',
|
||||||
|
'icon' => 'cog',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, '/site');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'-', // Séparateur
|
||||||
|
'home' => [
|
||||||
|
'label' => 'Accueil',
|
||||||
|
'icon' => 'home',
|
||||||
|
'link' => 'pages/home',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, 'pages/home');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'expertise' => [
|
||||||
|
'label' => 'Expertise',
|
||||||
|
'icon' => 'wand',
|
||||||
|
'link' => 'pages/expertise',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, 'pages/expertise');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'portfolio' => [
|
||||||
|
'label' => 'Portfolio',
|
||||||
|
'icon' => 'images',
|
||||||
|
'link' => 'pages/portfolio',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, 'pages/portfolio');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'jouer' => [
|
||||||
|
'label' => 'Jouer',
|
||||||
|
'icon' => 'play',
|
||||||
|
'link' => 'pages/jouer',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, 'pages/jouer');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'a-propos' => [
|
||||||
|
'label' => 'À propos',
|
||||||
|
'icon' => 'users',
|
||||||
|
'link' => 'pages/a-propos',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, 'pages/a-propos');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'blog' => [
|
||||||
|
'label' => 'Blog',
|
||||||
|
'icon' => 'text',
|
||||||
|
'link' => 'pages/blog',
|
||||||
|
'current' => function (string $current): bool {
|
||||||
|
$path = Kirby\Cms\App::instance()->path();
|
||||||
|
return Str::contains($path, 'pages/blog');
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'-', // Séparateur
|
||||||
|
'users',
|
||||||
|
'system'
|
||||||
|
]
|
||||||
],
|
],
|
||||||
|
|
||||||
'thumbs' => require __DIR__ . '/thumbs.php',
|
// Langues
|
||||||
];
|
'languages' => true,
|
||||||
|
|
||||||
|
// Thumbs
|
||||||
|
'thumbs' => [
|
||||||
|
'quality' => 80,
|
||||||
|
'srcsets' => [
|
||||||
|
'default' => [
|
||||||
|
'300w' => ['width' => 300],
|
||||||
|
'600w' => ['width' => 600],
|
||||||
|
'900w' => ['width' => 900],
|
||||||
|
'1200w' => ['width' => 1200],
|
||||||
|
],
|
||||||
|
// Galerie portfolio — desktop ~15vw, mobile ~33vw (3 colonnes)
|
||||||
|
// Widths couvrent 1x et 2x retina pour les deux breakpoints
|
||||||
|
'gallery' => [
|
||||||
|
'200w' => ['width' => 200],
|
||||||
|
'300w' => ['width' => 300],
|
||||||
|
'400w' => ['width' => 400],
|
||||||
|
'600w' => ['width' => 600],
|
||||||
|
'800w' => ['width' => 800],
|
||||||
|
],
|
||||||
|
'gallery-webp' => [
|
||||||
|
'200w' => ['width' => 200, 'format' => 'webp'],
|
||||||
|
'300w' => ['width' => 300, 'format' => 'webp'],
|
||||||
|
'400w' => ['width' => 400, 'format' => 'webp'],
|
||||||
|
'600w' => ['width' => 600, 'format' => 'webp'],
|
||||||
|
'800w' => ['width' => 800, 'format' => 'webp'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper : génère un item de menu avec détection automatique du lien actif.
|
|
||||||
*/
|
|
||||||
function menuItem(string $id, string $label, string $icon, string $link): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'label' => $label,
|
|
||||||
'icon' => $icon,
|
|
||||||
'link' => $link,
|
|
||||||
'current' => function () use ($link): bool {
|
|
||||||
return Str::contains(Kirby\Cms\App::instance()->path(), $link);
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'site' => [
|
|
||||||
'label' => 'Données partagées',
|
|
||||||
'icon' => 'cog',
|
|
||||||
'current' => function (): bool {
|
|
||||||
return Str::contains(Kirby\Cms\App::instance()->path(), '/site');
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'-',
|
|
||||||
'home' => menuItem('home', 'Accueil', 'home', 'pages/home'),
|
|
||||||
'expertise' => menuItem('expertise', 'Expertise','wand', 'pages/expertise'),
|
|
||||||
'portfolio' => menuItem('portfolio', 'Portfolio','images', 'pages/portfolio'),
|
|
||||||
'jouer' => menuItem('jouer', 'Jouer', 'play', 'pages/jouer'),
|
|
||||||
'a-propos' => menuItem('a-propos', 'À propos', 'users', 'pages/a-propos'),
|
|
||||||
'blog' => menuItem('blog', 'Blog', 'text', 'pages/blog'),
|
|
||||||
'-',
|
|
||||||
'users',
|
|
||||||
'system',
|
|
||||||
];
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Génère un preset srcset Kirby à partir d'un tableau [label => largeur_px].
|
|
||||||
* Applique le multiplicateur et optionnellement un format (ex: 'webp').
|
|
||||||
*/
|
|
||||||
function srcsetPreset(array $widths, float $mult, ?string $format = null): array
|
|
||||||
{
|
|
||||||
$preset = [];
|
|
||||||
foreach ($widths as $label => $px) {
|
|
||||||
$entry = ['width' => (int) round($px * $mult)];
|
|
||||||
if ($format !== null) {
|
|
||||||
$entry['format'] = $format;
|
|
||||||
}
|
|
||||||
$preset[$label] = $entry;
|
|
||||||
}
|
|
||||||
return $preset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Génère une paire de presets (original + webp) depuis un tableau de widths.
|
|
||||||
* Retourne ['name' => [...], 'name-webp' => [...]].
|
|
||||||
*/
|
|
||||||
function srcsetPair(string $name, array $widths, float $mult): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
$name => srcsetPreset($widths, $mult),
|
|
||||||
$name . '-webp' => srcsetPreset($widths, $mult, 'webp'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiplicateur global (ex: 1.5 pour avoir de la marge sur les écrans Retina)
|
|
||||||
$m = 1.5;
|
|
||||||
|
|
||||||
// Définition des widths par usage (une seule fois)
|
|
||||||
$widths = [
|
|
||||||
'default' => ['300w' => 300, '600w' => 600, '900w' => 900, '1200w' => 1200],
|
|
||||||
// Galerie portfolio — desktop ~15vw, mobile ~33vw (3 colonnes)
|
|
||||||
'gallery' => ['200w' => 200, '300w' => 300, '400w' => 400, '600w' => 600, '800w' => 800],
|
|
||||||
// Mockup portfolio — desktop ~25vw, mobile ~90vw
|
|
||||||
'mockup' => ['350w' => 350, '480w' => 480, '700w' => 700, '960w' => 960],
|
|
||||||
// Vignettes jeux — active: clamp(170px, 18.41vw, 355px)
|
|
||||||
'thumbnail' => ['170w' => 170, '255w' => 255, '355w' => 355, '510w' => 510, '710w' => 710],
|
|
||||||
];
|
|
||||||
|
|
||||||
return [
|
|
||||||
'quality' => 80,
|
|
||||||
'srcsets' => array_merge(
|
|
||||||
['default' => srcsetPreset($widths['default'], $m)],
|
|
||||||
srcsetPair('gallery', $widths['gallery'], $m),
|
|
||||||
srcsetPair('mockup', $widths['mockup'], $m),
|
|
||||||
srcsetPair('thumbnail', $widths['thumbnail'], $m),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
@ -8,8 +8,6 @@ $specificData = [
|
||||||
'lettering' => $game->lettering()->toFile()?->url(),
|
'lettering' => $game->lettering()->toFile()?->url(),
|
||||||
'description' => $game->description()->value(),
|
'description' => $game->description()->value(),
|
||||||
'thumbnail' => $game->thumbnail()->toFile()?->url(),
|
'thumbnail' => $game->thumbnail()->toFile()?->url(),
|
||||||
'thumbnailSrcset' => $game->thumbnail()->toFile()?->srcset('thumbnail'),
|
|
||||||
'thumbnailWebp' => $game->thumbnail()->toFile()?->srcset('thumbnail-webp'),
|
|
||||||
'backgroundColor' => $game->backgroundColor()->value() ?: null,
|
'backgroundColor' => $game->backgroundColor()->value() ?: null,
|
||||||
'preview' => $game->preview()->toFile()?->url(),
|
'preview' => $game->preview()->toFile()?->url(),
|
||||||
'playLink' => $game->playLink()->value() ?: null,
|
'playLink' => $game->playLink()->value() ?: null,
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ $specificData = [
|
||||||
'webp' => $f->srcset('gallery-webp'),
|
'webp' => $f->srcset('gallery-webp'),
|
||||||
])->values(),
|
])->values(),
|
||||||
'mockup' => $project->mockup()->toFile()?->url(),
|
'mockup' => $project->mockup()->toFile()?->url(),
|
||||||
'mockupSrcset' => $project->mockup()->toFile()?->srcset('mockup'),
|
|
||||||
'mockupWebp' => $project->mockup()->toFile()?->srcset('mockup-webp'),
|
|
||||||
'galleryBackgroundColor' => $project->galleryBackgroundColor()->value(),
|
'galleryBackgroundColor' => $project->galleryBackgroundColor()->value(),
|
||||||
'keywords' => $project->keywords()->toStructure()->map(fn($i) => [
|
'keywords' => $project->keywords()->toStructure()->map(fn($i) => [
|
||||||
'label' => $i->label()->value(),
|
'label' => $i->label()->value(),
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<script>
|
|
||||||
/**
|
|
||||||
* Image responsive avec support WebP via <picture>.
|
|
||||||
*
|
|
||||||
* @prop {string} src — URL fallback (format original)
|
|
||||||
* @prop {string} srcset — srcset format original (ex: "200w ..., 400w ...")
|
|
||||||
* @prop {string} webp — srcset format WebP
|
|
||||||
* @prop {string} sizes — valeur de l'attribut sizes
|
|
||||||
* @prop {string} [alt] — texte alternatif
|
|
||||||
* @prop {string} [cls] — classe CSS à appliquer sur <img>
|
|
||||||
*/
|
|
||||||
let { src, srcset, webp, sizes, alt = '', cls = '' } = $props()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
{#if webp}
|
|
||||||
<source type="image/webp" srcset={webp} {sizes} />
|
|
||||||
{/if}
|
|
||||||
<img
|
|
||||||
{src}
|
|
||||||
{srcset}
|
|
||||||
{sizes}
|
|
||||||
{alt}
|
|
||||||
class={cls}
|
|
||||||
loading="lazy"
|
|
||||||
decoding="async"
|
|
||||||
/>
|
|
||||||
</picture>
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import { slides } from '@state/slides.svelte'
|
import { slides } from '@state/slides.svelte'
|
||||||
import ResponsivePicture from '@components/ui/ResponsivePicture.svelte'
|
|
||||||
|
|
||||||
let { data } = $props()
|
let { data } = $props()
|
||||||
|
|
||||||
|
|
@ -197,13 +196,7 @@
|
||||||
onclick={() => selectGame(i)}
|
onclick={() => selectGame(i)}
|
||||||
>
|
>
|
||||||
{#if game.thumbnail}
|
{#if game.thumbnail}
|
||||||
<ResponsivePicture
|
<img src={game.thumbnail} alt="" />
|
||||||
src={game.thumbnail}
|
|
||||||
srcset={game.thumbnailSrcset}
|
|
||||||
webp={game.thumbnailWebp}
|
|
||||||
sizes="clamp(170px, 18.41vw, 355px)"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
<span class="play-carousel-title">{game.title}</span>
|
<span class="play-carousel-title">{game.title}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -367,8 +360,7 @@
|
||||||
width: clamp(170px, 18.41vw, 355px);
|
width: clamp(170px, 18.41vw, 355px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.play-carousel-item button img,
|
.play-carousel-item button img {
|
||||||
.play-carousel-item button :global(picture img) {
|
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
transition: border-color 0.4s var(--ease-standard);
|
transition: border-color 0.4s var(--ease-standard);
|
||||||
}
|
}
|
||||||
|
|
@ -379,8 +371,7 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.play-carousel-item.active button img,
|
.play-carousel-item.active button img {
|
||||||
.play-carousel-item.active button :global(picture img) {
|
|
||||||
border: 4px solid var(--color-primary);
|
border: 4px solid var(--color-primary);
|
||||||
border-radius: 25%;
|
border-radius: 25%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
import { slides } from '@state/slides.svelte'
|
import { slides } from '@state/slides.svelte'
|
||||||
import { createScrollNav } from '@composables/useScrollNav.svelte.js'
|
import { createScrollNav } from '@composables/useScrollNav.svelte.js'
|
||||||
import GalleryAnimation from '@components/ui/GalleryAnimation.svelte'
|
import GalleryAnimation from '@components/ui/GalleryAnimation.svelte'
|
||||||
import ResponsivePicture from '@components/ui/ResponsivePicture.svelte'
|
|
||||||
|
|
||||||
let { data } = $props()
|
let { data } = $props()
|
||||||
|
|
||||||
|
|
@ -102,14 +101,7 @@
|
||||||
|
|
||||||
<!-- Mockup device (centre) -->
|
<!-- Mockup device (centre) -->
|
||||||
<div class="portfolio-mockup">
|
<div class="portfolio-mockup">
|
||||||
<ResponsivePicture
|
<img src={currentProject.mockup} alt={currentProject.title} />
|
||||||
src={currentProject.mockup}
|
|
||||||
srcset={currentProject.mockupSrcset}
|
|
||||||
webp={currentProject.mockupWebp}
|
|
||||||
sizes="(max-width: 700px) 90vw, 25vw"
|
|
||||||
alt={currentProject.title}
|
|
||||||
cls="portfolio-mockup-img"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Infos projet (droite) -->
|
<!-- Infos projet (droite) -->
|
||||||
|
|
@ -183,8 +175,7 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.portfolio-mockup :global(picture),
|
.portfolio-mockup img {
|
||||||
.portfolio-mockup :global(.portfolio-mockup-img) {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue