From d1acd1b5b52855a8d7cce9c5b24b56e638d9de19 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Fri, 2 Oct 2026 16:30:28 -0400 Subject: [PATCH] =?UTF-8?q?style(ui):=20harmonisation=20des=20couleurs=20p?= =?UTF-8?q?ar=20th=C3=A8me=20+=20contour=20fournisseur=201=20px?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Balayage de la couche d'overrides de index.css : les 75 jetons neutres slate/zinc/gray qui n'étaient pas couverts (36 fichiers) sont mappés sur les variables du thème — fonds, textes, bordures, anneaux, divide, placeholders, dégradés + variants hover/focus/focus-within/disabled/group-hover, alpha via color-mix. Barre de recherche, menus, panneaux, cartes et résultats de recherche suivent donc le thème appliqué (dark/light/blue/black) au lieu de la palette slate figée. Volontairement exclus : bg-white/text-black (boutons inversés), pastilles « inversées » conditionnelles au thème clair, chrome au-dessus des vidéos, rouges sémantiques. Panneau d'informations ⓘ des Shorts re-colorié dans son propre scope (fond/bordures/textes/pastilles d'action → panel/text/muted), les mêmes tokens restant blancs ailleurs (rail, méta). Marqueur border-l-4 des titres de page sur --accent. Cartes vidéo harmonisées : titre text-sm font-semibold leading-snug (résultats de recherche, chaîne, thèmes), méta text-xs, rayon rounded-lg sur les cadres, pastille de durée sans font-mono, titre « Abonnements » avec le marqueur d'accent. Contour fournisseur 1 px autour de chaque cadre vidéo, à la couleur du premier stop du dégradé de la pastille (table unique en CSS, ids longs + courts) : résultats de recherche, grille chaîne, pages thèmes, watch (lecteur + « à suivre »), shorts, historique, aimés/à regarder plus tard, détail de playlist. Tests verts (search, filters, kind, section, highlight, shorts-catalog, api 41/41) ; vérif UI Playwright desktop 1280x900 + mobile 390x844 sur 4 thèmes : 250 assertions + 13 couleurs de contour au vert. --- README.md | 1 + index.css | 285 ++++++++++++++++++ .../video-card/video-card.component.html | 4 +- .../account/history/history.component.html | 2 +- .../channel-video-grid.component.html | 2 +- src/components/home/home.component.html | 6 +- .../library/liked/liked.component.html | 2 +- .../playlists/playlist-detail.component.ts | 2 +- .../subscriptions.component.html | 2 +- .../shorts/watch-short.component.html | 1 + .../shorts/watch-short.component.ts | 5 +- .../themes/provider-theme-page.component.html | 14 +- .../themes/theme-page.component.html | 4 +- src/components/watch/watch.component.html | 4 +- 14 files changed, 311 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 306f106..fa280fe 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,7 @@ Ajoutez au besoin `log-driver`, `log-opts`, `default-address-pools`, etc. * ✅ Liste **« À regarder plus tard »** (watch later) — même stockage « tags » que les likes (aucune migration), bouton horloge à côté du cœur sur toutes les cartes, entrée « Vous » de la barre latérale, page `/#/library/watch-later` avec recherche serveur * ✅ PeerTube **multi-instances** (activer/désactiver, set active) * ✅ Thème (système / dark / light / blue / black) +* ✅ **Harmonisation visuelle** — tous les utilitaires neutres (`slate`/`zinc`/`gray`, fonds, textes, bordures, anneaux, placeholders, états `hover:`/`disabled:`) sont mappés sur les variables du thème (**75 jetons, 36 fichiers**) : barre de recherche, menus, panneaux et cartes suivent enfin le thème appliqué ; panneau **ⓘ des Shorts** re-colorié dans son périmètre (le chrome au-dessus de la vidéo reste blanc) ; marqueur `border-l-4` des titres de page sur l'accent du thème ; cartes vidéo harmonisées (`text-sm` / `font-semibold` / méta `text-xs` / rayon `rounded-lg`, pastille de durée sans `font-mono`) ; **contour fournisseur 1 px** à la couleur de la pastille autour de chaque cadre vidéo (grilles, recherche, channel, watch — lecteur et « à suivre » —, shorts, historique, aimés, playlist) * ✅ Préférences (langue, thème, région, qualité par défaut) * ✅ Auth légère (JWT), rate-limit API * ✅ **Recherche unifiée multi-providers** — panneau de filtres (sources / type / période / durée / tri, Ctrl/⌘+Maj+F), autocomplete `@` + opérateurs `live:`/`today:`, deep-links `?providers=…&type=…&period=…`, préférence `defaultProviders` persistée, filtres serveur, télémétrie minimale, a11y (focus trap, Esc, clavier complet sur le panneau de suggestions) diff --git a/index.css b/index.css index ce1502f..746efd6 100644 --- a/index.css +++ b/index.css @@ -459,6 +459,291 @@ body { color: #94a3b8; /* slate-400 */ } +/* --- Harmonisation : TOUS les utilitaires neutres suivent le thème -------- */ +/* Le bloc ci-dessus ne couvrait que 15 classes ; le reste de l'app parlait + « slate/zinc/gray » quand le thème parlait --panel/--text (36 fichiers, 75 + jetons). Ici : familles slate/zinc/gray -> variables du thème, alpha -> + color-mix, variants hover/focus/disabled/placeholders/ring/divide inclus. + Règle : !important gagne sur l'utilitaire Tailwind (injecté après ou avant + selon le CDN). VOLONTAIREMENT exclus — ils fonctionnent déjà dans tous les + thèmes et/ou sont conditionnels au thème clair : bg-white/text-black (boutons + inversés), bg-slate-50/100/200 + text-slate-700/800/900 (pastilles + « inversées » de la barre de filtres, bouton Google, avatar clair, barre de + thèmes en thème clair), bg-black/* + text-white au-dessus des vidéos. */ + +.bg-gray-900, +.bg-slate-950, +.bg-zinc-900, +.bg-zinc-950 { + background-color: var(--bg) !important; +} + +.bg-zinc-800 { + background-color: var(--panel) !important; +} + +.bg-slate-600 { + background-color: var(--panel-2) !important; +} + +.disabled\:bg-slate-800:disabled { + background-color: var(--panel) !important; +} + +.bg-slate-900\/40 { + background-color: color-mix(in srgb, var(--bg) 40%, transparent) !important; +} + +.bg-slate-900\/50, +.bg-zinc-900\/50 { + background-color: color-mix(in srgb, var(--bg) 50%, transparent) !important; +} + +.bg-slate-900\/60 { + background-color: color-mix(in srgb, var(--bg) 60%, transparent) !important; +} + +.bg-slate-900\/95, +.bg-slate-950\/95, +.bg-zinc-950\/95 { + background-color: color-mix(in srgb, var(--bg) 95%, transparent) !important; +} + +.bg-slate-800\/40 { + background-color: color-mix(in srgb, var(--panel) 40%, transparent) !important; +} + +.bg-slate-800\/60 { + background-color: color-mix(in srgb, var(--panel) 60%, transparent) !important; +} + +.bg-slate-800\/70 { + background-color: color-mix(in srgb, var(--panel) 70%, transparent) !important; +} + +.bg-slate-800\/80, +.bg-zinc-800\/80 { + background-color: color-mix(in srgb, var(--panel) 80%, transparent) !important; +} + +.bg-slate-800\/90 { + background-color: color-mix(in srgb, var(--panel) 90%, transparent) !important; +} + +.bg-slate-100\/10 { + background-color: color-mix(in srgb, var(--text) 10%, transparent) !important; +} + +.bg-slate-700\/50 { + background-color: color-mix(in srgb, var(--panel-2) 50%, transparent) !important; +} + +.bg-slate-700\/60 { + background-color: color-mix(in srgb, var(--panel-2) 60%, transparent) !important; +} + +.bg-slate-700\/70 { + background-color: color-mix(in srgb, var(--panel-2) 70%, transparent) !important; +} + +.bg-zinc-700\/80 { + background-color: color-mix(in srgb, var(--panel-2) 80%, transparent) !important; +} + +.bg-slate-700\/90 { + background-color: color-mix(in srgb, var(--panel-2) 90%, transparent) !important; +} + +.focus-within\:bg-slate-800\/60:focus-within { + background-color: color-mix(in srgb, var(--panel) 60%, transparent) !important; +} + +.hover\:bg-slate-800\/60:hover { + background-color: color-mix(in srgb, var(--panel) 60%, transparent) !important; +} + +.hover\:bg-slate-700\/40:hover { + background-color: color-mix(in srgb, var(--panel-2) 40%, transparent) !important; +} + +.hover\:bg-slate-700\/50:hover { + background-color: color-mix(in srgb, var(--panel-2) 50%, transparent) !important; +} + +.hover\:bg-slate-700\/60:hover { + background-color: color-mix(in srgb, var(--panel-2) 60%, transparent) !important; +} + +.hover\:bg-slate-700\/80:hover { + background-color: color-mix(in srgb, var(--panel-2) 80%, transparent) !important; +} + +.hover\:bg-slate-500:hover, +.hover\:bg-slate-600:hover, +.hover\:bg-slate-700:hover, +.hover\:bg-slate-800:hover, +.hover\:bg-zinc-600:hover { + background-color: color-mix(in srgb, var(--panel-2) 90%, var(--text)) !important; +} + +.text-gray-400, +.text-slate-500, +.text-slate-600, +.text-zinc-400, +.text-zinc-500, +.text-zinc-600 { + color: var(--muted) !important; +} + +.placeholder-slate-400::placeholder, +.placeholder-slate-500::placeholder, +.placeholder\:text-slate-500::placeholder, +.placeholder\:text-zinc-500::placeholder { + color: var(--muted) !important; +} + +.disabled\:text-slate-400:disabled { + color: var(--muted) !important; +} + +.group:hover .group-hover\:text-slate-200, +.text-zinc-100, +.text-zinc-200, +.text-zinc-300 { + color: var(--text) !important; +} + +.hover\:text-slate-100:hover, +.hover\:text-slate-200:hover, +.hover\:text-zinc-400:hover { + color: var(--text) !important; +} + +.border-slate-700\/60 { + border-color: color-mix(in srgb, var(--border) 60%, transparent) !important; +} + +.border-slate-500, +.border-slate-600, +.border-slate-800, +.border-zinc-700, +.border-zinc-800, +.border-zinc-950, +.divide-slate-700, +.divide-slate-800 { + border-color: var(--border) !important; +} + +.hover\:border-slate-400:hover, +.hover\:border-slate-500:hover, +.hover\:border-slate-600:hover, +.hover\:border-zinc-500:hover, +.hover\:border-zinc-600:hover { + border-color: var(--muted) !important; +} + +.ring-slate-500\/50, +.ring-slate-600\/50 { + --tw-ring-color: color-mix(in srgb, var(--border) 50%, transparent) !important; +} + +.focus-visible\:ring-slate-400\/60:focus-visible { + --tw-ring-color: var(--accent) !important; +} + +.from-slate-800 { + --tw-gradient-from: var(--panel) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; +} + +.from-slate-700 { + --tw-gradient-from: var(--panel-2) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; +} + +.to-slate-800\/50 { + --tw-gradient-to: color-mix(in srgb, var(--panel) 50%, transparent) !important; +} + +.to-slate-800 { + --tw-gradient-to: var(--panel) !important; +} + +@media (min-width: 768px) { +.md\:bg-slate-900\/70 { background-color: color-mix(in srgb, var(--bg) 70%, transparent) !important; } +} + +/* Marqueur des titres de page (barre `border-l-4`) : suit l'accent du thème + au lieu d'être figé en rouge (et rattrape les titres qui n'avaient pas de + couleur explicite, ex. Bibliothèque → Aimés). */ +.border-l-4 { border-left-color: var(--accent) !important; } + +/* --- Shorts : le panneau d'informations (ⓘ) suit le thème ----------------- */ +/* Ses couleurs sont du « verre blanc » (bg-white/*, text-white/*) : les mêmes + jetons servent AU-DESSUS de la vidéo (rail, méta) et doivent y rester + blancs — donc pas de reprise globale, uniquement un scope sur l'aside. */ +[data-theme] aside.shorts-info { + background-color: color-mix(in srgb, var(--panel) 94%, transparent) !important; + border-color: var(--border) !important; + color: var(--text) !important; +} +[data-theme] aside.shorts-info [class*="border-white/"] { border-color: var(--border) !important; } +[data-theme] aside.shorts-info [class*="bg-white/"] { + background-color: color-mix(in srgb, var(--panel-2) 75%, transparent) !important; +} +[data-theme] aside.shorts-info .hover\:bg-white\/20:hover, +[data-theme] aside.shorts-info .hover\:bg-white\/25:hover { + background-color: color-mix(in srgb, var(--panel-2) 90%, var(--text)) !important; +} +[data-theme] aside.shorts-info .bg-white { background-color: var(--text) !important; } +[data-theme] aside.shorts-info .text-black { color: var(--bg) !important; } +[data-theme] aside.shorts-info .hover\:bg-slate-200:hover { + background-color: color-mix(in srgb, var(--text) 85%, var(--bg)) !important; +} +[data-theme] aside.shorts-info [class*="ring-white/"] { --tw-ring-color: var(--border) !important; } +[data-theme] aside.shorts-info .text-white { color: var(--text) !important; } +[data-theme] aside.shorts-info .text-white\/40, +[data-theme] aside.shorts-info .text-white\/45, +[data-theme] aside.shorts-info .text-white\/50, +[data-theme] aside.shorts-info .text-white\/60 { color: var(--muted) !important; } +[data-theme] aside.shorts-info .text-white\/75, +[data-theme] aside.shorts-info .text-white\/80 { + color: color-mix(in srgb, var(--text) 85%, transparent) !important; +} +/* Pastilles d'action du panneau (définies en dur en rgba blanc plus haut). */ +[data-theme] aside.shorts-info .shorts-info-action { + color: var(--muted) !important; + background-color: color-mix(in srgb, var(--panel-2) 70%, transparent) !important; +} +[data-theme] aside.shorts-info .shorts-info-action:hover:not(:disabled) { + color: var(--text) !important; + background-color: color-mix(in srgb, var(--panel-2) 95%, var(--text)) !important; +} +[data-theme] aside.shorts-info .shorts-info-action--on { + color: var(--text) !important; + background-color: color-mix(in srgb, var(--panel-2) 90%, var(--text)) !important; +} + +/* --- Contour fournisseur autour de chaque cadre vidéo --------------------- */ +/* Contour fin (1 px) à la couleur de la pastille du fournisseur, sur toutes les + présentations de vidéo. La couleur = le PREMIER stop du dégradé de + app-provider-badge : c'est la seule table à tenir si une marque change. + `data-video-provider` accepte l'id long ET l'id court (les deux circulent : + VideoItem.provider est long, ChannelMeta.provider est court). + `outline` plutôt que `border` : zéro effet sur la boîte (les cadres sont + dimensionnés en aspect-ratio) et le rayon suit automatiquement. */ +[data-video-provider] { outline: 1px solid var(--prov, transparent); outline-offset: -1px; } +[data-video-provider="youtube"], +[data-video-provider="yt"] { --prov: #dc2626; } +[data-video-provider="dailymotion"], +[data-video-provider="dm"] { --prov: #0284c7; } +[data-video-provider="twitch"], +[data-video-provider="tw"] { --prov: #7c3aed; } +[data-video-provider="peertube"], +[data-video-provider="pt"] { --prov: #f59e0b; } +[data-video-provider="rumble"], +[data-video-provider="ru"] { --prov: #059669; } +[data-video-provider="odysee"], +[data-video-provider="od"] { --prov: #ec4899; } + /* Hide scrollbars on horizontal lists where we still want scrolling */ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; } diff --git a/src/app/shared/components/video-card/video-card.component.html b/src/app/shared/components/video-card/video-card.component.html index a61e21e..d6f46e8 100644 --- a/src/app/shared/components/video-card/video-card.component.html +++ b/src/app/shared/components/video-card/video-card.component.html @@ -3,7 +3,7 @@ -
+