ergonomie
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1024" fill="none"><path fill="url(#a)" fill-rule="evenodd" d="M-217.58 475.75c91.82-72.02 225.52-29.38 341.2-44.74C240 415.56 372.33 315.14 466.77 384.9c102.9 76.02 44.74 246.76 90.31 366.31 29.83 78.24 90.48 136.14 129.48 210.23 57.92 109.99 169.67 208.23 155.9 331.77-13.52 121.26-103.42 264.33-224.23 281.37-141.96 20.03-232.72-220.96-374.06-196.99-151.7 25.73-172.68 330.24-325.85 315.72-128.6-12.2-110.9-230.73-128.15-358.76-12.16-90.14 65.87-176.25 44.1-264.57-26.42-107.2-167.12-163.46-176.72-273.45-10.15-116.29 33.01-248.75 124.87-320.79Z" clip-rule="evenodd" style="opacity:.154"/><path fill="url(#b)" fill-rule="evenodd" d="M1103.43 115.43c146.42-19.45 275.33-155.84 413.5-103.59 188.09 71.13 409 212.64 407.06 413.88-1.94 201.25-259.28 278.6-414.96 405.96-130 106.35-240.24 294.39-405.6 265.3-163.7-28.8-161.93-274.12-284.34-386.66-134.95-124.06-436-101.46-445.82-284.6-9.68-180.38 247.41-246.3 413.54-316.9 101.01-42.93 207.83 21.06 316.62 6.61Z" clip-rule="evenodd" style="opacity:.154"/><defs><linearGradient id="b" x1="373" x2="1995.44" y1="1100" y2="118.03" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient><linearGradient id="a" x1="107.37" x2="1130.66" y1="1993.35" y2="1026.31" gradientUnits="userSpaceOnUse"><stop stop-color="#3245FF"/><stop offset="1" stop-color="#BC52EE"/></linearGradient></defs></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,15 +1,24 @@
|
|||||||
---
|
---
|
||||||
import type { CollectionEntry } from "astro:content";
|
import type { CollectionEntry } from "astro:content";
|
||||||
import GoldButton from "./ui/GoldButton.astro";
|
|
||||||
import CodexCard from "./ui/CodexCard.astro";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
posts: CollectionEntry<"journal" | "logs" | "codex">[];
|
posts: CollectionEntry<"journal">[];
|
||||||
tags: string[];
|
tags: string[];
|
||||||
basePath: "journal" | "logs" | "codex";
|
basePath: "journal";
|
||||||
}
|
}
|
||||||
|
|
||||||
const { posts, tags, basePath } = Astro.props;
|
const { posts, tags, basePath } = Astro.props;
|
||||||
|
|
||||||
|
// Groupement simple
|
||||||
|
const groupedTags: Record<string, string[]> = { Général: [] };
|
||||||
|
tags.forEach((tag) => {
|
||||||
|
if (tag.includes(":")) {
|
||||||
|
const cat = tag.split(":")[0];
|
||||||
|
const catName = cat.charAt(0).toUpperCase() + cat.slice(1);
|
||||||
|
if (!groupedTags[catName]) groupedTags[catName] = [];
|
||||||
|
groupedTags[catName].push(tag);
|
||||||
|
} else {
|
||||||
|
groupedTags["Général"].push(tag);
|
||||||
|
}
|
||||||
|
});
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id="content-search-component">
|
<div id="content-search-component">
|
||||||
@@ -17,174 +26,190 @@ const { posts, tags, basePath } = Astro.props;
|
|||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
id="search-input"
|
id="search-input"
|
||||||
placeholder="Rechercher dans le grimoire..."
|
placeholder="Rechercher dans le journal..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tag-filters" class="tags-container">
|
<div class="filter-box">
|
||||||
<button class="tag-btn active" data-tag="all">Toutes</button>
|
<div class="category-nav">
|
||||||
|
<span class="nav-label">Filtres :</span>
|
||||||
|
<button class="cat-nav-btn active" data-target="all">Toutes</button>
|
||||||
{
|
{
|
||||||
tags.map((tag) => (
|
Object.keys(groupedTags).map(
|
||||||
<button class="tag-btn" data-tag={tag}>
|
(cat) =>
|
||||||
{tag}
|
cat !== "Général" && (
|
||||||
|
<button class="cat-nav-btn" data-target={cat}>
|
||||||
|
{cat}
|
||||||
</button>
|
</button>
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="tags-reveal-area">
|
||||||
|
{
|
||||||
|
Object.entries(groupedTags).map(([category, categoryTags]) => (
|
||||||
|
<div
|
||||||
|
class="tag-subgroup"
|
||||||
|
id={`group-${category}`}
|
||||||
|
style={category === "Général" ? "" : "display: none;"}
|
||||||
|
>
|
||||||
|
{categoryTags.map((tag) => (
|
||||||
|
<button class="js-tag-filter" data-tag={tag}>
|
||||||
|
{tag.includes(":") ? tag.split(":")[1] : tag}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="search-results" class="card-grid">
|
<div id="search-results" class="card-grid">
|
||||||
{
|
{
|
||||||
basePath === "codex"
|
posts.map((post) => (
|
||||||
? posts.map((post) => (
|
<a href={`/${basePath}/${post.id}/`} class="gold-button">
|
||||||
<CodexCard entry={post as CollectionEntry<"codex">} />
|
<div class="title">{post.data.title}</div>
|
||||||
))
|
<p class="body">
|
||||||
: posts.map((post) => (
|
Publié le{" "}
|
||||||
<GoldButton
|
{new Date(post.data.publishDate).toLocaleDateString(
|
||||||
href={`/${basePath}/${post.id}/`}
|
"fr-FR",
|
||||||
title={post.data.title}
|
)}
|
||||||
body={`Publié le ${new Date(post.data.publishDate).toLocaleDateString("fr-FR")}`}
|
</p>
|
||||||
/>
|
</a>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p id="no-results" class="no-results-message" style="display: none;">
|
|
||||||
Aucun parchemin ne correspond à votre recherche.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="search-data-bridge"
|
id="search-data-bridge"
|
||||||
data-posts={JSON.stringify(posts)}
|
data-posts={JSON.stringify(posts)}
|
||||||
data-basepath={basePath}
|
|
||||||
style="display: none;"
|
style="display: none;"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// On récupère les données via le DOM pour que l'éditeur reste coloré
|
function init() {
|
||||||
const bridge = document.getElementById("search-data-bridge");
|
const bridge = document.getElementById("search-data-bridge");
|
||||||
const posts = JSON.parse(bridge.dataset.posts);
|
const input = document.getElementById(
|
||||||
const basePath = bridge.dataset.basepath;
|
"search-input",
|
||||||
|
) as HTMLInputElement;
|
||||||
|
const container = document.getElementById("search-results");
|
||||||
|
if (!bridge || !input || !container) return;
|
||||||
|
|
||||||
const searchInput = document.body.querySelector("#search-input");
|
const posts = JSON.parse(bridge.getAttribute("data-posts") || "[]");
|
||||||
const resultsContainer = document.body.querySelector("#search-results");
|
|
||||||
const noResultsMessage = document.body.querySelector("#no-results");
|
|
||||||
const tagFiltersContainer = document.body.querySelector("#tag-filters");
|
|
||||||
|
|
||||||
let currentQuery = "";
|
|
||||||
let activeTag = "all";
|
let activeTag = "all";
|
||||||
|
|
||||||
function normalizeText(text) {
|
function update() {
|
||||||
if (!text) return "";
|
const query = input.value
|
||||||
return text
|
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.normalize("NFD")
|
.normalize("NFD")
|
||||||
.replace(/[\u0300-\u036f]/g, "");
|
.replace(/[\u0300-\u036f]/g, "");
|
||||||
|
const filtered = posts.filter((p) => {
|
||||||
|
const mQuery = p.data.title.toLowerCase().includes(query);
|
||||||
|
const mTag =
|
||||||
|
activeTag === "all" || p.data.tags?.includes(activeTag);
|
||||||
|
return mQuery && mTag;
|
||||||
|
});
|
||||||
|
|
||||||
|
container!.innerHTML = filtered
|
||||||
|
.map(
|
||||||
|
(p) => `
|
||||||
|
<a href="/journal/${p.id}/" class="gold-button">
|
||||||
|
<div class="title">${p.data.title}</div>
|
||||||
|
<p class="body">Publié le ${new Date(p.data.publishDate).toLocaleDateString("fr-FR")}</p>
|
||||||
|
</a>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCodexCardHTML(post) {
|
input.addEventListener("input", update);
|
||||||
const statusClass = (post.data.status || "draft")
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(" ", "-");
|
|
||||||
return `
|
|
||||||
<a href="/codex/${post.id}" class="codex-card">
|
|
||||||
<div class="card-header">
|
|
||||||
<div class="card-title">${post.data.title}</div>
|
|
||||||
<div class="card-subtitle">${post.data.subtitle || ""}</div>
|
|
||||||
<span class="status status-${statusClass}">${post.data.status || "Inconnu"}</span>
|
|
||||||
</div>
|
|
||||||
<div class="skill-section">
|
|
||||||
<div class="skill-header">Compétence</div>
|
|
||||||
<p class="skill-content">${post.data.mecanique || "En cours..."}</p>
|
|
||||||
<div class="skill-header">Application</div>
|
|
||||||
<p class="skill-content">${post.data.vision3D || "À venir..."}</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createGoldButtonHTML(post) {
|
document.querySelectorAll(".cat-nav-btn").forEach((btn) => {
|
||||||
const dateStr = new Date(post.data.publishDate).toLocaleDateString(
|
btn.addEventListener("click", () => {
|
||||||
"fr-FR",
|
document
|
||||||
);
|
.querySelectorAll(".cat-nav-btn")
|
||||||
return `
|
.forEach((b) => b.classList.remove("active"));
|
||||||
<a href="/${basePath}/${post.id}/" class="gold-button">
|
btn.classList.add("active");
|
||||||
<div class="title">${post.data.title}</div>
|
const target = btn.getAttribute("data-target");
|
||||||
<p class="body">Publié le ${dateStr}</p>
|
document.querySelectorAll(".tag-subgroup").forEach((g) => {
|
||||||
</a>
|
(g as HTMLElement).style.display =
|
||||||
`;
|
g.id === `group-${target}` ? "block" : "none";
|
||||||
|
});
|
||||||
|
if (target === "all") {
|
||||||
|
activeTag = "all";
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll(".js-tag-filter").forEach((t) => {
|
||||||
|
t.addEventListener("click", () => {
|
||||||
|
document
|
||||||
|
.querySelectorAll(".js-tag-filter")
|
||||||
|
.forEach((el) => el.classList.remove("active-tag"));
|
||||||
|
t.classList.add("active-tag");
|
||||||
|
activeTag = (t as HTMLElement).dataset.tag || "all";
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.addEventListener("astro:page-load", init);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Conteneur des tags : centrage et espacement */
|
|
||||||
.tags-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 0.6rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 3rem;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Le bouton de tag : on force les styles pour contrer Tailwind */
|
|
||||||
.tag-btn {
|
|
||||||
all: unset; /* On réinitialise les styles par défaut du navigateur */
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #f3ece0;
|
|
||||||
color: #4a4130;
|
|
||||||
padding: 0.4rem 1.2rem;
|
|
||||||
border-radius: 9999px; /* Forme pilule parfaite */
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
border: 1px solid #dcd0b9;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* État survolé */
|
|
||||||
.tag-btn:hover {
|
|
||||||
background-color: #fdf6e8;
|
|
||||||
border-color: #c89b3c;
|
|
||||||
color: #c89b3c;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* État actif (celui qui est doré sur ton image 2) */
|
|
||||||
.tag-btn.active {
|
|
||||||
background-color: #c89b3c !important;
|
|
||||||
color: #ffffff !important;
|
|
||||||
border-color: #b8860b !important;
|
|
||||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Centrage de la barre de recherche */
|
|
||||||
.search-wrapper {
|
.search-wrapper {
|
||||||
|
margin-bottom: 2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 2.5rem;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-input {
|
#search-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 450px;
|
max-width: 400px;
|
||||||
padding: 0.75rem 1.2rem;
|
padding: 0.7rem 1rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid var(--color-gold);
|
||||||
|
outline: none;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
.filter-box {
|
||||||
border: 1px solid #dcd0b9;
|
border: 1px solid #dcd0b9;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: rgba(253, 246, 232, 0.9);
|
background: #fffaf0;
|
||||||
font-family: "EB Garamond", serif;
|
margin-bottom: 2rem;
|
||||||
font-size: 1.1rem;
|
overflow: hidden;
|
||||||
color: #4a4130;
|
|
||||||
outline: none;
|
|
||||||
transition: border-color 0.2s;
|
|
||||||
}
|
}
|
||||||
|
.category-nav {
|
||||||
#search-input:focus {
|
background: #f3ece0;
|
||||||
border-color: #c89b3c;
|
padding: 0.5rem;
|
||||||
box-shadow: 0 0 0 2px rgba(200, 155, 60, 0.1);
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #dcd0b9;
|
||||||
|
}
|
||||||
|
.nav-label {
|
||||||
|
font-family: "Cinzel", serif;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--color-gold-dark);
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
.cat-nav-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-family: "Cinzel", serif;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--color-ink);
|
||||||
|
}
|
||||||
|
.cat-nav-btn.active {
|
||||||
|
color: var(--color-gold-dark);
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 2px solid var(--color-gold);
|
||||||
|
}
|
||||||
|
.tags-reveal-area {
|
||||||
|
padding: 0.8rem;
|
||||||
|
min-height: 40px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,7 +2,22 @@
|
|||||||
title: "L'Éveil du Cul Brillant"
|
title: "L'Éveil du Cul Brillant"
|
||||||
author: "G'Mas"
|
author: "G'Mas"
|
||||||
publishDate: 2026-01-10
|
publishDate: 2026-01-10
|
||||||
tags: ["Yeuze-sur-Chenarde", "Exploration", "Gurdil", "Bulle", "Social", "Mystère"]
|
tags: [
|
||||||
|
"lieu:Yeuze-sur-Chenarde",
|
||||||
|
"lieu:Grand-Chêne",
|
||||||
|
"lieu:Mine",
|
||||||
|
"aventurier:Gmas",
|
||||||
|
"aventurier:Nyrae",
|
||||||
|
"aventurier:Bulle",
|
||||||
|
"aventurier:Gurdil",
|
||||||
|
"aventurier:Jinn",
|
||||||
|
"perso:Kwel",
|
||||||
|
"perso:Mara",
|
||||||
|
"plot:Enfants-Disparus",
|
||||||
|
"plot:Cul-Brillant",
|
||||||
|
"plot:Mystère",
|
||||||
|
"lore:Légendes"
|
||||||
|
]
|
||||||
---
|
---
|
||||||
|
|
||||||
### Chroniques de Yeuze-sur-Chenarde
|
### Chroniques de Yeuze-sur-Chenarde
|
||||||
|
|||||||
@@ -2,7 +2,21 @@
|
|||||||
title: "Le Murmure des Rouages"
|
title: "Le Murmure des Rouages"
|
||||||
author: "G'Mas"
|
author: "G'Mas"
|
||||||
publishDate: 2026-01-18
|
publishDate: 2026-01-18
|
||||||
tags: ["Mine", "Combat", "Kruthik", "Nyrae", "Jinn", "Vase Grise"]
|
tags: [
|
||||||
|
"lieu:Yeuze-sur-Chenarde",
|
||||||
|
"lieu:Mine",
|
||||||
|
"aventurier:Gmas",
|
||||||
|
"aventurier:Nyrae",
|
||||||
|
"aventurier:Bulle",
|
||||||
|
"aventurier:Gurdil",
|
||||||
|
"aventurier:Jinn",
|
||||||
|
"perso:Maielan",
|
||||||
|
"mobs:Kruthik",
|
||||||
|
"mobs:Vase-Grise",
|
||||||
|
"plot:Enfants-Disparus",
|
||||||
|
"plot:Cul-Brillant",
|
||||||
|
"event:Combat"
|
||||||
|
]
|
||||||
---
|
---
|
||||||
|
|
||||||
### Les Griffes de l'Obscurité
|
### Les Griffes de l'Obscurité
|
||||||
|
|||||||
@@ -2,7 +2,25 @@
|
|||||||
title: "Le printemps sanglant"
|
title: "Le printemps sanglant"
|
||||||
author: "G'Mas"
|
author: "G'Mas"
|
||||||
publishDate: 2026-02-08
|
publishDate: 2026-02-08
|
||||||
tags: ["Vampire","Enfant perdu", "Maçonnerie"]
|
tags: [
|
||||||
|
"lieu:Yeuze-sur-Chenarde",
|
||||||
|
"lieu:Mine",
|
||||||
|
"lieu:Grand-Chêne",
|
||||||
|
"aventurier:Gmas",
|
||||||
|
"aventurier:Nyrae",
|
||||||
|
"aventurier:Bulle",
|
||||||
|
"aventurier:Gurdil",
|
||||||
|
"aventurier:Jinn",
|
||||||
|
"perso:Kwel",
|
||||||
|
"perso:Maielan",
|
||||||
|
"antagoniste:Constancia-Denney",
|
||||||
|
"plot:Enfants-Disparus",
|
||||||
|
"plot:Cul-Brillant",
|
||||||
|
"plot:Couronne-d-Argent",
|
||||||
|
"lore:Eladrin",
|
||||||
|
"event:Combat",
|
||||||
|
"event:Level-Up"
|
||||||
|
]
|
||||||
---
|
---
|
||||||
|
|
||||||
## L'Ombre de Constancia
|
## L'Ombre de Constancia
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
---
|
---
|
||||||
import { ClientRouter } from "astro:transitions";
|
import { ClientRouter } from "astro:transitions";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title } = Astro.props;
|
const { title } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -12,14 +10,8 @@ const { title } = Astro.props;
|
|||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
name="description"
|
<title>{title} | Hebel</title>
|
||||||
content="Clone de AFK Journey avec Astro et Three.js"
|
|
||||||
/>
|
|
||||||
<meta name="viewport" content="width=device-width" initial-scale="1" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
||||||
<meta name="generator" content={Astro.generator} />
|
|
||||||
<title>{title}</title>
|
|
||||||
<ClientRouter />
|
<ClientRouter />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -30,283 +22,163 @@ const { title } = Astro.props;
|
|||||||
</html>
|
</html>
|
||||||
|
|
||||||
<style is:global>
|
<style is:global>
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Cinzel:wght@700&family=EB+Garamond&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=Cinzel:wght@700&display=swap");
|
||||||
|
|
||||||
html {
|
:root {
|
||||||
background-color: #fdf6e8; /* Ton crème/parchemin */
|
--color-parchment: #fdf6e8;
|
||||||
|
--color-ink: #4a4130;
|
||||||
|
--color-gold: #c89b3c;
|
||||||
|
--color-gold-dark: #b8860b;
|
||||||
|
--obsidian-border: #dcd0b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
/* La couleur de fond est maintenant sur l'élément HTML */
|
background-color: var(--color-parchment);
|
||||||
background-color: transparent;
|
color: var(--color-ink);
|
||||||
color: #4a4a4a;
|
/* Calibri en priorité */
|
||||||
font-family: "EB Garamond", serif;
|
font-family: "Calibri", "Candara", "Segoe UI", sans-serif;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
/* Ajout d'un padding en bas pour ne pas que la nav masque le contenu */
|
line-height: 1.6;
|
||||||
padding: 2rem 2rem 100px 2rem;
|
overflow-x: hidden;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Applique une texture de grain de papier en arrière-plan */
|
main {
|
||||||
body::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
max-width: 1000px;
|
||||||
/* Assurez-vous d'avoir une image de texture dans public/textures/ */
|
margin: 0 auto;
|
||||||
background-image: url("/textures/paper-grain.png");
|
padding: 1rem;
|
||||||
opacity: 0.5; /* J'augmente l'opacité pour qu'elle soit bien visible */
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Styles des Titres --- */
|
/* --- TABLEAUX OBSIDIAN --- */
|
||||||
h1,
|
table {
|
||||||
h2 {
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
text-align: center;
|
|
||||||
color: #3a352a; /* Une couleur de texte sombre pour un bon contraste */
|
|
||||||
margin-bottom: 2rem; /* Espace après l'ornement */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ajoute un ornement doré sous les titres */
|
|
||||||
h1::after,
|
|
||||||
h2::after {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
width: 100px; /* Largeur de l'ornement */
|
|
||||||
height: 2px;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
transparent,
|
|
||||||
#c89b3c,
|
|
||||||
transparent
|
|
||||||
); /* Dégradé doré */
|
|
||||||
margin: 0.75rem auto 0; /* Espace entre le texte et l'ornement */
|
|
||||||
opacity: 0.8;
|
|
||||||
/* Animation pour "dessiner" la ligne */
|
|
||||||
transform: scaleX(0);
|
|
||||||
animation: drawLine 1s cubic-bezier(0.22, 1, 0.36, 1) 0.3s forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* On peut différencier légèrement le h2 */
|
|
||||||
h2 {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
color: #4a4130;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Styles pour le contenu Markdown (.prose) --- */
|
|
||||||
.prose h3 {
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
text-align: left;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
border-bottom: 1px solid #dcd0b9;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
margin-top: 2.5rem;
|
|
||||||
}
|
|
||||||
/* On retire l'ornement pour les h3 */
|
|
||||||
.prose h3::after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose p {
|
|
||||||
line-height: 1.7;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parchment-card a {
|
|
||||||
color: #c89b3c; /* Or vif */
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: bold;
|
|
||||||
transition: color 0.2s;
|
|
||||||
}
|
|
||||||
.parchment-card a:hover {
|
|
||||||
filter: brightness(1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose ul {
|
|
||||||
list-style: none;
|
|
||||||
padding-left: 1rem;
|
|
||||||
}
|
|
||||||
.prose ul li::before {
|
|
||||||
content: "•";
|
|
||||||
color: #c89b3c;
|
|
||||||
font-weight: bold;
|
|
||||||
display: inline-block;
|
|
||||||
width: 1em;
|
|
||||||
margin-left: -1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose hr {
|
|
||||||
border: 0;
|
|
||||||
height: 2px;
|
|
||||||
background: linear-gradient(90deg, transparent, #c89b3c, transparent);
|
|
||||||
margin: 3rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose table {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin: 2rem 0;
|
margin: 1.5rem 0;
|
||||||
|
border: 1px solid var(--obsidian-border);
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
.prose th,
|
th,
|
||||||
.prose td {
|
td {
|
||||||
padding: 0.75rem;
|
border: 1px solid var(--obsidian-border);
|
||||||
|
padding: 0.8rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid #dcd0b9; /* Ligne de séparation parchemin */
|
|
||||||
}
|
}
|
||||||
.prose th {
|
th {
|
||||||
|
background: rgba(220, 208, 185, 0.3);
|
||||||
font-family: "Cinzel", serif;
|
font-family: "Cinzel", serif;
|
||||||
background-color: rgba(
|
|
||||||
253,
|
|
||||||
246,
|
|
||||||
232,
|
|
||||||
0.5
|
|
||||||
); /* Fond de cellule plus clair */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Styles pour GoldButton --- */
|
/* --- LISTES MOBILE --- */
|
||||||
.gold-button {
|
ul,
|
||||||
background: linear-gradient(
|
ol {
|
||||||
145deg,
|
padding-left: 1.5rem;
|
||||||
#fefbf3,
|
margin: 1rem 0;
|
||||||
#f8f1e4
|
|
||||||
); /* Dégradé parchemin clair */
|
|
||||||
border: 2px solid #c89b3c;
|
|
||||||
border-radius: 15px;
|
|
||||||
color: #4a4130; /* Texte sombre pour le contraste */
|
|
||||||
padding: 1.5rem;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
display: block;
|
|
||||||
box-shadow:
|
|
||||||
0 4px 15px rgba(0, 0, 0, 0.1),
|
|
||||||
inset 0 0 5px rgba(200, 155, 60, 0.1);
|
|
||||||
}
|
}
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
ul ul,
|
||||||
|
ol ol {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
padding: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- CITATIONS (BLOCKQUOTES) --- */
|
||||||
|
blockquote {
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-left: 4px solid var(--color-gold);
|
||||||
|
background: rgba(200, 155, 60, 0.05);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- STYLE DES TAGS --- */
|
||||||
|
/* On utilise une classe explicite pour éviter l'erreur de build */
|
||||||
|
.tag-link {
|
||||||
|
display: inline-block !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
background: white !important;
|
||||||
|
border: 1px solid var(--color-gold) !important;
|
||||||
|
padding: 0.2rem 0.7rem !important;
|
||||||
|
border-radius: 15px !important;
|
||||||
|
font-family: "Cinzel", serif !important;
|
||||||
|
font-size: 0.7rem !important;
|
||||||
|
color: var(--color-ink) !important;
|
||||||
|
margin: 0.2rem !important;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
.tag-link:hover {
|
||||||
|
background: var(--color-gold) !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STYLE DES CARTES (Gold Button) */
|
||||||
|
.gold-button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: #fffaf0; /* Fond parchemin clair */
|
||||||
|
border: 2px solid var(--color-gold);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 1.5rem;
|
||||||
|
text-decoration: none !important;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
min-height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
.gold-button:hover {
|
.gold-button:hover {
|
||||||
transform: translateY(-5px);
|
transform: translateY(-5px);
|
||||||
filter: brightness(1.05);
|
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
|
||||||
box-shadow:
|
border-color: var(--color-gold-dark);
|
||||||
0 8px 25px rgba(0, 0, 0, 0.15),
|
background: white;
|
||||||
inset 0 0 10px rgba(200, 155, 60, 0.2);
|
|
||||||
border-color: #f0e6d2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.gold-button .title {
|
.gold-button .title {
|
||||||
/* Ciblage plus spécifique */
|
|
||||||
font-family: "Cinzel", serif;
|
font-family: "Cinzel", serif;
|
||||||
font-size: 1.5rem;
|
font-size: 1.2rem;
|
||||||
color: #b8860b; /* Titre en couleur or */
|
color: var(--color-gold-dark);
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gold-button .body {
|
.gold-button .body {
|
||||||
/* Ciblage plus spécifique */
|
font-family: "Calibri", sans-serif; /* Ta police demandée */
|
||||||
font-family: "EB Garamond", serif;
|
font-size: 0.9rem;
|
||||||
font-size: 1rem;
|
color: var(--color-ink);
|
||||||
color: #4a4130; /* Texte sombre pour le contraste */
|
opacity: 0.8;
|
||||||
}
|
|
||||||
.card-grid {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 2rem;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Styles pour les Tags --- */
|
/* GRILLE FLEXBOX */
|
||||||
.tags-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
.tag {
|
|
||||||
background-color: rgba(200, 155, 60, 0.2);
|
|
||||||
color: #b8860b;
|
|
||||||
padding: 0.25rem 0.75rem;
|
|
||||||
border-radius: 15px;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
border: 1px solid rgba(200, 155, 60, 0.3);
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
.tag:hover {
|
|
||||||
background-color: #c89b3c;
|
|
||||||
color: #2c2a24;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Keyframes pour l'animation de l'ornement */
|
|
||||||
@keyframes drawLine {
|
|
||||||
from {
|
|
||||||
transform: scaleX(0);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scaleX(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation pour la nouvelle page (le "pop-up") */
|
|
||||||
@keyframes slide-in {
|
|
||||||
from {
|
|
||||||
transform: translateY(15%) scale(0.95);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateY(0) scale(1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation pour l'ancienne page qui disparaît */
|
|
||||||
@keyframes fade-out {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* On applique nos animations aux pseudo-éléments de View Transitions */
|
|
||||||
::view-transition-new(root) {
|
|
||||||
animation: 0.4s cubic-bezier(0.22, 1, 0.36, 1) 0s 1 normal both running
|
|
||||||
slide-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
::view-transition-old(root) {
|
|
||||||
animation: 0.2s ease-out 0s 1 normal both running fade-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Ajustements pour les écrans mobiles --- */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
body {
|
|
||||||
padding: 1.5rem 1rem 100px 1rem; /* Réduction du padding latéral */
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 2rem; /* Réduction de la taille des titres principaux */
|
|
||||||
}
|
|
||||||
|
|
||||||
.parchment-card {
|
|
||||||
padding: 1.5rem; /* Moins de padding dans les cartes */
|
|
||||||
}
|
|
||||||
|
|
||||||
.gold-button {
|
|
||||||
padding: 1rem; /* Boutons moins hauts */
|
|
||||||
}
|
|
||||||
|
|
||||||
.gold-button .title {
|
|
||||||
font-size: 1.2rem; /* Titres des boutons plus petits */
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-grid {
|
.card-grid {
|
||||||
gap: 1rem; /* Moins d'espace entre les cartes */
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 2rem;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-grid > * {
|
||||||
|
flex: 1 1 300px;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.card-grid > * {
|
||||||
|
flex: 1 1 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
25
src/pages/index.astro
Normal file
25
src/pages/index.astro
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
import GameLayout from "../layouts/GameLayout.astro";
|
||||||
|
import ContentSearch from "../components/ContentSearch.astro";
|
||||||
|
|
||||||
|
// 1. Récupère TOUS les articles et les trie.
|
||||||
|
const allPosts = await getCollection("journal");
|
||||||
|
const sortedPosts = allPosts.sort(
|
||||||
|
(a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. Extrait toutes les balises uniques
|
||||||
|
const allTags = [...new Set(allPosts.flatMap((post) => post.data.tags || []))];
|
||||||
|
---
|
||||||
|
|
||||||
|
<GameLayout title="Journal d'Aventure">
|
||||||
|
<h1>📖 Journal d'Aventure</h1>
|
||||||
|
<p style="text-align: center; margin-bottom: 3rem;">
|
||||||
|
Les chroniques de nos voyages. Utilisez la barre de recherche pour
|
||||||
|
trouver un récit.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 2. On passe tous les articles au composant client -->
|
||||||
|
<ContentSearch posts={sortedPosts} tags={allTags} basePath="journal" />
|
||||||
|
</GameLayout>
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
// 1. Ajoute "render" dans ton import
|
|
||||||
import { getCollection, render } from "astro:content";
|
import { getCollection, render } from "astro:content";
|
||||||
import GameLayout from "../../layouts/GameLayout.astro";
|
import GameLayout from "../../layouts/GameLayout.astro";
|
||||||
|
|
||||||
@@ -12,136 +11,114 @@ export async function getStaticPaths() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { entry } = Astro.props;
|
const { entry } = Astro.props;
|
||||||
|
if (!entry) return Astro.redirect("/404");
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
return Astro.redirect("/404");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Utilise la fonction render(entry) au lieu de entry.render()
|
|
||||||
const { Content } = await render(entry);
|
const { Content } = await render(entry);
|
||||||
---
|
---
|
||||||
|
|
||||||
<GameLayout title={entry.data.title}>
|
<GameLayout title={entry.data.title}>
|
||||||
<main class="codex-entry-container">
|
<article class="journal-post">
|
||||||
<article class="parchment-card">
|
<header class="post-header">
|
||||||
<div class="header">
|
<a href="/" class="back-nav">← Retour au Journal</a>
|
||||||
<h1>{entry.data.title}</h1>
|
<h1>{entry.data.title}</h1>
|
||||||
<p class="publish-date">
|
<p class="date">
|
||||||
Savoir acquis le : {
|
Chroniqué le {
|
||||||
entry.data.publishDate.toLocaleDateString("fr-FR", {
|
entry.data.publishDate.toLocaleDateString("fr-FR", {
|
||||||
year: "numeric",
|
|
||||||
month: "long",
|
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
{
|
||||||
entry.data.tags && (
|
entry.data.tags && (
|
||||||
<div class="tags-container">
|
<div class="tags-row">
|
||||||
{entry.data.tags.map((tag) => (
|
{entry.data.tags.map((tag) => (
|
||||||
<a
|
<a
|
||||||
href={`/journal/tags/${tag.toLowerCase()}`}
|
href={`/journal/tags/${tag.toLowerCase()}`}
|
||||||
class="tag"
|
class="tag-link"
|
||||||
>
|
>
|
||||||
{tag}
|
{tag.includes(":") ? tag.split(":")[1] : tag}
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="prose">
|
<hr class="separator" />
|
||||||
|
|
||||||
|
<div class="prose-content">
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="/journal" class="back-link">
|
|
||||||
← Retourner au Journal
|
|
||||||
</a>
|
|
||||||
</article>
|
</article>
|
||||||
</main>
|
|
||||||
</GameLayout>
|
</GameLayout>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.codex-entry-container {
|
.journal-post {
|
||||||
max-width: 900px;
|
background: white;
|
||||||
margin: 0 auto;
|
border: 1px solid #dcd0b9;
|
||||||
padding: 2rem 1rem;
|
border-radius: 8px;
|
||||||
|
padding: 2.5rem;
|
||||||
|
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
.parchment-card {
|
.back-nav {
|
||||||
background: linear-gradient(145deg, #fefbf3, #f8f1e4);
|
font-family: "Cinzel", serif;
|
||||||
border: 2px solid #dcd0b9;
|
font-size: 0.8rem;
|
||||||
border-radius: 15px;
|
color: #b8860b;
|
||||||
padding: 2rem 3rem;
|
text-decoration: none;
|
||||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
display: block;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.post-header {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header h1 {
|
h1 {
|
||||||
margin-bottom: 0.5rem;
|
margin: 0.5rem 0;
|
||||||
}
|
font-family: "Cinzel", serif;
|
||||||
.header h2 {
|
font-size: 2.2rem;
|
||||||
font-family: "EB Garamond", serif;
|
color: #3a352a;
|
||||||
font-style: italic;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
color: #4a4130;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
/* On retire l'ornement pour le h2 de la carte */
|
|
||||||
.header h2::after {
|
|
||||||
content: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.publish-date {
|
.date {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
|
||||||
|
|
||||||
.transmutation-table {
|
|
||||||
margin: 2rem 0;
|
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
background-color: rgba(253, 246, 232, 0.5);
|
}
|
||||||
border: 1px solid #dcd0b9;
|
.tags-row {
|
||||||
border-radius: 8px;
|
margin-top: 1.2rem;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-row {
|
.separator {
|
||||||
display: grid;
|
border: 0;
|
||||||
grid-template-columns: 1fr 1.5fr 1.5fr;
|
height: 1px;
|
||||||
gap: 1rem;
|
background-image: linear-gradient(
|
||||||
padding: 0.75rem 1rem;
|
to right,
|
||||||
|
transparent,
|
||||||
|
#dcd0b9,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
margin: 2.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-row.header {
|
.prose-content {
|
||||||
background-color: rgba(220, 208, 185, 0.4);
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-row:not(.header) {
|
@media (max-width: 640px) {
|
||||||
border-top: 1px solid #dcd0b9;
|
.journal-post {
|
||||||
|
padding: 1.5rem 1rem;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
h1 {
|
||||||
.col-title {
|
font-size: 1.6rem;
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #4a4130;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-link {
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 3rem;
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
color: #b8860b;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
.back-link:hover {
|
|
||||||
transform: translateX(-5px);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
import { getCollection } from 'astro:content';
|
|
||||||
import GameLayout from '../../layouts/GameLayout.astro';
|
|
||||||
import ContentSearch from '../../components/ContentSearch.astro';
|
|
||||||
|
|
||||||
// 1. Récupère TOUS les articles et les trie.
|
|
||||||
const allPosts = await getCollection('journal');
|
|
||||||
const sortedPosts = allPosts.sort(
|
|
||||||
(a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf()
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. Extrait toutes les balises uniques
|
|
||||||
const allTags = [...new Set(allPosts.flatMap(post => post.data.tags || []))];
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<GameLayout title="Journal d'Aventure">
|
|
||||||
<h1>📖 Journal d'Aventure</h1>
|
|
||||||
<p style="text-align: center; margin-bottom: 3rem;">
|
|
||||||
Les chroniques de nos voyages. Utilisez la barre de recherche pour trouver un récit.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- 2. On passe tous les articles au composant client -->
|
|
||||||
<ContentSearch posts={sortedPosts} tags={allTags} basePath="journal" />
|
|
||||||
|
|
||||||
</GameLayout>
|
|
||||||
@@ -1,31 +1,38 @@
|
|||||||
---
|
---
|
||||||
|
// [tag].astro
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import GameLayout from "../../../layouts/GameLayout.astro";
|
import GameLayout from "../../../layouts/GameLayout.astro";
|
||||||
import GoldButton from "../../../components/ui/GoldButton.astro";
|
import GoldButton from "../../../components/ui/GoldButton.astro";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const allPosts = await getCollection("journal");
|
const allPosts = await getCollection("journal");
|
||||||
const allTags = [
|
const tags = [...new Set(allPosts.flatMap((p) => p.data.tags || []))];
|
||||||
...new Set(allPosts.flatMap((post) => post.data.tags || [])),
|
return tags.map((tag) => ({
|
||||||
];
|
params: { tag: tag.toLowerCase() },
|
||||||
|
props: {
|
||||||
return allTags.map((tag) => {
|
posts: allPosts.filter((p) => p.data.tags?.includes(tag)),
|
||||||
const filteredPosts = allPosts.filter((post) =>
|
originalTag: tag,
|
||||||
post.data.tags?.includes(tag),
|
},
|
||||||
);
|
}));
|
||||||
return {
|
|
||||||
params: { tag },
|
|
||||||
props: { posts: filteredPosts },
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
const { posts, originalTag } = Astro.props;
|
||||||
const { tag } = Astro.params;
|
|
||||||
const { posts } = Astro.props;
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<GameLayout title={`Récits: ${tag}`}>
|
<GameLayout title={`Archive : ${originalTag}`}>
|
||||||
<h1>Récits avec la balise : <span class="tag-title">{tag}</span></h1>
|
<div class="tag-page-container">
|
||||||
|
<a href="/" class="back-link">← Retour au Journal</a>
|
||||||
|
|
||||||
|
<div class="tag-header">
|
||||||
|
<h1>
|
||||||
|
Récits marqués : <span
|
||||||
|
>{
|
||||||
|
originalTag.includes(":")
|
||||||
|
? originalTag.split(":")[1]
|
||||||
|
: originalTag
|
||||||
|
}</span
|
||||||
|
>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card-grid">
|
<div class="card-grid">
|
||||||
{
|
{
|
||||||
@@ -33,15 +40,36 @@ const { posts } = Astro.props;
|
|||||||
<GoldButton
|
<GoldButton
|
||||||
href={`/journal/${post.id}/`}
|
href={`/journal/${post.id}/`}
|
||||||
title={post.data.title}
|
title={post.data.title}
|
||||||
body={`Publié le ${post.data.publishDate.toLocaleDateString("fr-FR")}`}
|
body={`Chronique du ${new Date(post.data.publishDate).toLocaleDateString("fr-FR")}`}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</GameLayout>
|
</GameLayout>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tag-title {
|
.tag-page-container {
|
||||||
color: #c89b3c;
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
}
|
||||||
|
.back-link {
|
||||||
|
color: var(--color-gold-dark);
|
||||||
|
text-decoration: none;
|
||||||
|
font-family: "Cinzel", serif;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.tag-header h1 {
|
||||||
|
font-size: 1.8rem; /* Titre réduit */
|
||||||
|
margin: 1.5rem 0 3rem;
|
||||||
|
}
|
||||||
|
.tag-header span {
|
||||||
|
color: var(--color-gold);
|
||||||
|
}
|
||||||
|
.card-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user