Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ Entrées **antéchronologiques** (la plus récente en haut). La date au format `

---

## 2026-06-17 — Toolbar (shell) alignée sur la DA festive

- **Contexte** : la toolbar gardait l'esthétique « atelier » sobre (fond
`--cc-surface` plat, filet `--cc-border`, texte sombre) et détonnait avec le
reste du front déjà migré vers la DA festive (héros et cartes à dégradé).
- **Décision** : restyler le shell sans toucher au routing ni à `navLinks`.
Barre en `--cc-gradient-festive` + `--cc-shadow-2`, texte clair
(`--cc-on-primary`) ; icône de marque dans une pastille
(`brand__badge`, `--cc-radius-pill`, teinte `--cc-primary-tint`) ; liens de
nav en **pilules** (`--cc-radius-pill`) avec survol clair rebondi
(`--cc-transition-bounce`) ; **lien actif** = pilule pleine claire à texte
framboise (contraste fort, indice non chromatique via le fond), en plus de
`aria-current`. Seul changement de markup : un `<span class="brand__badge">`
autour de l'icône. `min-height` tactile tokenisé (`44px` → `var(--cc-space-7)`,
48px ≥ 44px).
- **Options écartées** : (1) garder le fond clair en ne colorant que les liens
(rejeté — l'écart « atelier » venait surtout du fond plat) ; (2) ajouter un
garde `prefers-reduced-motion` local (rejeté — le bloc global de `styles.scss`
neutralise déjà toutes les transitions avec `!important`, doublon inutile) ;
(3) souligner le lien actif comme avant (`inset box-shadow`) plutôt qu'une
pilule pleine (rejeté — moins lisible et moins festif sur le dégradé).
- **Pourquoi** : cohérence visuelle du shell avec les pages migrées, sans
refactor ni dépendance, accessibilité préservée (focus-visible, aria-current,
contraste AA texte clair sur dégradé, reduced-motion via le global).
- **Trace** : `npm run check` vert (lint + build).

## 2026-06-17 — Mixins SCSS partagés (`shared/styles/`) pour le CSS dupliqué

- **Contexte** : du SCSS strictement identique était recopié entre features —
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

<mat-toolbar class="app-toolbar" role="banner">
<a routerLink="/" class="brand" aria-label="CraftCode — accueil">
<mat-icon aria-hidden="true">handyman</mat-icon>
<span class="brand__badge" aria-hidden="true">
<mat-icon>handyman</mat-icon>
</span>
<span>CraftCode</span>
</a>

Expand All @@ -15,11 +17,10 @@
[routerLinkActiveOptions]="{ exact: !!item.exact }"
#rla="routerLinkActive"
[attr.aria-current]="rla.isActive ? 'page' : null"
>{{ item.label }}</a>
>{{ item.label }}</a
>
}
</nav>

<span class="tagline">Boîte à outils du développeur</span>
</mat-toolbar>

<main id="main-content" class="app-content" tabindex="-1">
Expand Down
73 changes: 36 additions & 37 deletions frontend/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
.app-toolbar {
// Barre « papier » sobre, ancrée par un filet cuivre. Hauteur fluide pour
// laisser la navigation se replier proprement sur petit écran (pas de
// hamburger). L'encapsulation du composant rend ces règles prioritaires sur
// la hauteur fixe de Material (.mat-toolbar-single-row).
// Barre festive en dégradé de marque (framboise → violet), cohérente avec
// les héros à dégradé. Hauteur fluide pour laisser la navigation se replier
// proprement sur petit écran (pas de hamburger). L'encapsulation du composant
// rend ces règles prioritaires sur la hauteur fixe de Material
// (.mat-toolbar-single-row).
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--cc-space-2) var(--cc-space-4);
height: auto;
min-height: var(--cc-toolbar-h);
white-space: normal;
padding: var(--cc-space-2) var(--cc-space-4);
background: var(--cc-surface);
color: var(--cc-ink);
border-bottom: 1px solid var(--cc-border);
box-shadow: var(--cc-shadow-1);
padding: var(--cc-space-2) var(--cc-space-5);
background: var(--cc-gradient-festive);
color: var(--cc-on-primary);
box-shadow: var(--cc-shadow-2);
position: sticky;
top: 0;
z-index: 10;
Expand All @@ -25,21 +25,28 @@
align-items: center;
gap: var(--cc-space-2);
flex-shrink: 0;
color: var(--cc-ink);
color: var(--cc-on-primary);
text-decoration: none;
font-weight: 700;
font-size: 1.25rem;
letter-spacing: -0.01em;
padding: var(--cc-space-1) var(--cc-space-2);
border-radius: var(--cc-radius-sm);
border-radius: var(--cc-radius-pill);

mat-icon {
// Pastille translucide claire autour de l'icône — petit signe festif.
&__badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--cc-space-1);
border-radius: var(--cc-radius-pill);
background: var(--cc-primary-tint);
color: var(--cc-primary);
transition: transform var(--cc-transition-bounce);
}

// L'outil « pétille » quand on survole la marque.
&:hover mat-icon {
&:hover &__badge {
transform: rotate(-12deg) scale(1.12);
}
}
Expand All @@ -54,10 +61,10 @@
.app-nav__link {
display: inline-flex;
align-items: center;
min-height: 44px; // cible tactile
padding: var(--cc-space-2) var(--cc-space-3);
border-radius: var(--cc-radius-sm);
color: var(--cc-ink-soft);
min-height: var(--cc-space-7); // cible tactile (48px ≥ 44px)
padding: var(--cc-space-2) var(--cc-space-4);
border-radius: var(--cc-radius-pill);
color: var(--cc-on-primary);
text-decoration: none;
font-size: var(--cc-fs-small);
font-weight: 600;
Expand All @@ -68,34 +75,26 @@
box-shadow var(--cc-transition),
transform var(--cc-transition-bounce);

// Survol : pastille claire translucide + léger lift rebondi.
&:hover {
background: var(--cc-surface-2);
color: var(--cc-ink);
transform: translateY(-1px);
background: var(--cc-primary-tint);
color: var(--cc-primary);
transform: translateY(-2px);
box-shadow: var(--cc-shadow-1);
}

// Page courante : texte + fond + soulignement (indices non basés sur la
// seule couleur), en plus de aria-current="page". Texte foncé (primary-hover)
// pour garder le contraste AA sur la teinte festive.
// Page courante : pilule pleine claire à texte framboise — distincte et
// lisible sur le dégradé (indice non basé sur la seule couleur via le
// contraste de fond), en plus de aria-current="page".
&--active {
color: var(--cc-primary-hover);
background: var(--cc-primary-tint);
box-shadow: inset 0 -2px 0 var(--cc-primary);
color: var(--cc-primary);
background: var(--cc-on-primary);
box-shadow: var(--cc-shadow-1);
}
}

.tagline {
margin-left: auto;
font-size: var(--cc-fs-small);
color: var(--cc-ink-soft);
}

// Petit écran : la tagline se masque et la navigation occupe sa propre ligne.
// Petit écran : la navigation occupe sa propre ligne.
@media (max-width: 480px) {
.tagline {
display: none;
}

.app-nav {
width: 100%;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<mat-card class="tool-card" [class.tool-card--disabled]="!tool.available" appearance="outlined">
<mat-card
class="tool-card"
[class.tool-card--disabled]="!tool.available"
appearance="outlined"
>
<mat-card-header>
<div mat-card-avatar class="tool-card__avatar">
<mat-icon>{{ tool.icon }}</mat-icon>
Expand All @@ -15,9 +19,14 @@

<mat-card-actions align="end">
@if (tool.available) {
<a mat-flat-button color="primary" [routerLink]="tool.route">
<a
mat-stroked-button
color="primary"
class="tool-card__cta"
[routerLink]="tool.route"
>
Ouvrir
<mat-icon>arrow_forward</mat-icon>
<mat-icon class="tool-card__cta-arrow">arrow_forward</mat-icon>
</a>
} @else {
<button mat-button disabled>Bientôt</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@
transform: translateY(-2px) scale(1);
}

// CTA « Ouvrir » : la flèche glisse vers la droite quand la carte est
// survolée/focalisée — micro-interaction festive, comportement inchangé.
.tool-card__cta-arrow {
transition: transform var(--cc-transition-bounce);
}

.tool-card:not(.tool-card--disabled):hover .tool-card__cta-arrow,
.tool-card:not(.tool-card--disabled):focus-within .tool-card__cta-arrow {
transform: translateX(var(--cc-space-1));
}

.tool-card--disabled {
opacity: 0.7;
}
Expand Down
Loading