feat(outils): Partir de soi en vue fiches, graphe des sept mots (B6-M2)
Le 3e sous-onglet de /outils remplace le rendu provisoire par VueFiches (état Mixte : liste des mots, graphe SVG statique, fiche d'un mot avec ses ressources). L'en-tête se compacte sur cet onglet, la vue prend la hauteur. Co-Authored-By: Claude Sonnet <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0136n5xMLHuaBDLcPJYCDjRW
This commit is contained in:
co-authored by
Claude Sonnet
parent
11f24c7925
commit
dfbac7dd12
+49
-138
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="outils-page">
|
||||
<div class="outils-page" :class="{ 'outils-page--vue': vueFiches }">
|
||||
|
||||
<!-- ══════════════════════ EN-TÊTE PAGE ══════════════════════ -->
|
||||
<header class="outils-header">
|
||||
@@ -9,9 +9,13 @@
|
||||
</div>
|
||||
<div class="outils-header__body">
|
||||
<h1 class="outils-header__title">Outils</h1>
|
||||
<EchelleTete echelle="S" :contribuer="false" />
|
||||
<p v-if="outils?.intro" class="outils-header__intro">{{ outils.intro }}</p>
|
||||
<!-- Partir de soi : la vue fiches prend la hauteur, l'en-tête se compacte (les sept mots sont dans le graphe) -->
|
||||
<EchelleTete v-if="!vueFiches" echelle="S" :contribuer="false" />
|
||||
<p v-if="outils?.intro && !vueFiches" class="outils-header__intro">{{ outils.intro }}</p>
|
||||
</div>
|
||||
<NuxtLink v-if="vueFiches && outils?.contribution" :to="outils.contribution.lien" class="outils-header__proposer">
|
||||
{{ outils.contribution.cta }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -44,6 +48,7 @@
|
||||
<main
|
||||
id="outils-panneau"
|
||||
class="outils-main"
|
||||
:class="{ 'outils-main--vue': vueFiches }"
|
||||
role="tabpanel"
|
||||
:aria-labelledby="`outils-tab-${tab}`"
|
||||
>
|
||||
@@ -159,57 +164,11 @@
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<!-- ══════════════ ONGLET 3 — Partir de soi (rendu provisoire, M2 le remplace par VueFiches) ══════════════ -->
|
||||
<template v-else>
|
||||
<p class="outils-intention">{{ outils.partir_de_soi.intention }}</p>
|
||||
<!-- ══════════════ ONGLET 3 — Partir de soi : la vue fiches (B6-M2) ══════════════ -->
|
||||
<OutilsPartirDeSoi v-else :data="outils.partir_de_soi" />
|
||||
|
||||
<section
|
||||
v-for="f in outils.partir_de_soi.fiches"
|
||||
:id="f.id"
|
||||
:key="f.id"
|
||||
class="outils-section fiche-s"
|
||||
:aria-labelledby="`titre-${f.id}`"
|
||||
>
|
||||
<h2 :id="`titre-${f.id}`" class="outils-section__title">{{ f.mot }}</h2>
|
||||
<p class="fiche-s__resume">{{ f.resume }}</p>
|
||||
<p v-if="f.vide" class="fiche-s__vide">{{ f.vide }}</p>
|
||||
<ul v-else class="ressources">
|
||||
<li v-for="r in ressourcesDe(f.id)" :key="r.id" class="ressource">
|
||||
<p class="ressource__titre">
|
||||
<a v-if="r.url" :href="r.url" target="_blank" rel="noopener noreferrer">{{ r.titre }}</a>
|
||||
<template v-else>{{ r.titre }}</template>
|
||||
</p>
|
||||
<p class="ressource__meta">{{ r.format }} · {{ r.acces }}</p>
|
||||
<p class="ressource__pourquoi">{{ r.pourquoi }}</p>
|
||||
<p v-if="r.urls?.length" class="ressource__liens">
|
||||
<template v-for="(u, i) in r.urls" :key="u">
|
||||
<span v-if="i > 0"> · </span>
|
||||
<a :href="u" target="_blank" rel="noopener noreferrer">{{ u.replace(/^https:\/\//, '') }}</a>
|
||||
</template>
|
||||
</p>
|
||||
<p v-if="r.note" class="ressource__note">{{ r.note }}</p>
|
||||
<ul v-if="r.episodes?.length" class="ofqa-list">
|
||||
<li v-for="ep in r.episodes" :key="ep.ep" class="ofqa-list__item">
|
||||
<component
|
||||
:is="ep.url ? 'a' : 'span'"
|
||||
v-bind="ep.url ? { href: ep.url, target: '_blank', rel: 'noopener noreferrer' } : {}"
|
||||
class="ofqa-list__link"
|
||||
:class="{ 'ofqa-list__link--disabled': !ep.url }"
|
||||
>
|
||||
<span class="ofqa-list__ep">EP/{{ ep.ep }}</span>
|
||||
<span class="ofqa-list__titre">{{ ep.titre }}</span>
|
||||
<span class="ofqa-list__personnes">— {{ ep.personnes }}</span>
|
||||
<span v-if="ep.note" class="ofqa-list__note">({{ ep.note }})</span>
|
||||
</component>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<!-- ══════════════ CONTRIBUTION (les 3 onglets) ══════════════ -->
|
||||
<footer v-if="outils?.contribution" class="outils-contribution">
|
||||
<!-- ══════════════ CONTRIBUTION (onglets 1 et 2 ; sur le 3e, le lien est dans l'en-tête) ══════════════ -->
|
||||
<footer v-if="outils?.contribution && !vueFiches" class="outils-contribution">
|
||||
<p class="outils-contribution__texte">{{ outils.contribution.texte }}</p>
|
||||
<NuxtLink :to="outils.contribution.lien" class="outils-contribution__cta">
|
||||
{{ outils.contribution.cta }}
|
||||
@@ -242,8 +201,8 @@ watch(() => route.query.tab, (q) => { tab.value = lireTab(q) })
|
||||
const { data: outils } = await useFetch<any>('/data/outils.json')
|
||||
const { data: fmhyData, pending: fmhyPending, error: fmhyError } = await useFetch<any>('/data/fmhy-curated.json')
|
||||
|
||||
const ressourcesDe = (ficheId: string) =>
|
||||
(outils.value?.partir_de_soi?.ressources ?? []).filter((r: any) => r.fiches?.includes(ficheId))
|
||||
// Partir de soi : la vue fiches remplit la hauteur sous la barre d'onglets (pas de défilement de page).
|
||||
const vueFiches = computed(() => tab.value === 'partir-de-soi' && !!outils.value)
|
||||
|
||||
// Flèches ← → (+ Début / Fin) : on se déplace et on active, comme un tablist à activation automatique.
|
||||
const tablistRef = ref<HTMLElement | null>(null)
|
||||
@@ -559,89 +518,6 @@ useSeoMeta({
|
||||
margin: 0.5rem 0 -0.5rem;
|
||||
}
|
||||
|
||||
/* ── Partir de soi (provisoire) ─────────────────────────────── */
|
||||
.fiche-s { gap: var(--space-sm); }
|
||||
|
||||
.fiche-s__resume {
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
max-width: 70ch;
|
||||
color: color-mix(in srgb, var(--text) 78%, transparent);
|
||||
}
|
||||
|
||||
.fiche-s__vide {
|
||||
font-size: 0.86rem;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 0.75rem 1rem;
|
||||
border: 1.5px dashed var(--border-strong);
|
||||
border-radius: var(--radius-md);
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
.ressources {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.ressource { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
||||
.ressource p { margin: 0; overflow-wrap: anywhere; }
|
||||
.ressource__titre { font-size: 0.92rem; font-weight: var(--fw-semibold); }
|
||||
.ressource__titre a, .ressource__liens a { color: var(--nav-primary-solid); }
|
||||
.ressource__meta { font-size: 0.78rem; color: color-mix(in srgb, var(--text) 78%, transparent); }
|
||||
.ressource__pourquoi { font-size: 0.84rem; line-height: 1.5; }
|
||||
.ressource__liens { font-size: 0.82rem; }
|
||||
.ressource__note { font-size: 0.78rem; font-style: italic; color: color-mix(in srgb, var(--text) 78%, transparent); }
|
||||
|
||||
/* ── Liste OFQA ─────────────────────────────────────────────── */
|
||||
.ofqa-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: var(--space-xs) 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.ofqa-list__link {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 0.4rem;
|
||||
flex-wrap: wrap;
|
||||
padding: 3px 6px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 0.84rem;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.ofqa-list__link:not(.ofqa-list__link--disabled):hover {
|
||||
background: var(--bg-alt);
|
||||
color: var(--nav-primary-solid);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ofqa-list__link--disabled { cursor: default; }
|
||||
|
||||
.ofqa-list__ep {
|
||||
font-family: var(--font-mono, 'JetBrains Mono', 'Courier New', monospace);
|
||||
font-size: 0.75rem;
|
||||
font-weight: var(--fw-semibold);
|
||||
flex-shrink: 0;
|
||||
min-width: 4.5rem;
|
||||
color: color-mix(in srgb, var(--text) 78%, transparent);
|
||||
}
|
||||
|
||||
.ofqa-list__titre { font-weight: var(--fw-medium); }
|
||||
.ofqa-list__personnes,
|
||||
.ofqa-list__note { font-size: 0.8rem; color: color-mix(in srgb, var(--text) 78%, transparent); }
|
||||
.ofqa-list__note { font-style: italic; }
|
||||
|
||||
/* ── Logiciels pro (placeholder) ────────────────────────────── */
|
||||
.outils-section--placeholder { opacity: 0.8; }
|
||||
|
||||
@@ -714,10 +590,45 @@ useSeoMeta({
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* ── Partir de soi : la vue fiches remplit la hauteur du conteneur de défilement (app.vue) ── */
|
||||
.outils-page--vue {
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.outils-page--vue .outils-header {
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
padding: var(--space-xs) var(--space-md) 0;
|
||||
}
|
||||
.outils-page--vue .outils-header__inner { align-items: center; }
|
||||
.outils-page--vue .outils-header__icon-wrap { width: 2rem; height: 2rem; padding: 0.4rem; }
|
||||
.outils-page--vue .outils-header__title { font-size: 1.25rem; margin: 0; }
|
||||
.outils-page--vue .outils-header__body { flex: 1 1 auto; }
|
||||
.outils-page--vue .outils-tabs { flex-shrink: 0; margin: 0; padding: 0 var(--space-md); }
|
||||
.outils-main--vue { flex: 1 1 0; min-height: 0; gap: 0; }
|
||||
|
||||
.outils-header__proposer {
|
||||
flex-shrink: 0;
|
||||
font-size: 0.85rem;
|
||||
font-weight: var(--fw-semibold);
|
||||
color: var(--nav-primary-solid);
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
.outils-header__proposer:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-sm); }
|
||||
|
||||
/* ── Mobile ─────────────────────────────────────────────────── */
|
||||
@media (max-width: 640px) {
|
||||
.outils-page { padding: var(--space-lg) var(--space-md) 4rem; }
|
||||
.outils-header__inner { flex-direction: column; gap: var(--space-sm); }
|
||||
.outils-page--vue { padding: 0; }
|
||||
.outils-page--vue .outils-header__inner { flex-direction: row; gap: var(--space-sm); }
|
||||
.outils-page--vue .outils-header__icon-wrap { display: none; }
|
||||
.outils-header__title { font-size: 1.4rem; }
|
||||
.outil-cards-grid { grid-template-columns: 1fr; }
|
||||
.outils-section--fmhy { padding: 1.25rem 1rem; }
|
||||
|
||||
Reference in New Issue
Block a user