fix(mobile): barre de thèmes masquée, modale @ hors écran, pastille d'avatar
CI / build-and-test (push) Successful in 14m14s
CI / build-and-test (push) Successful in 14m14s
Cinq correctifs signalés sur le mode mobile et le mode desktop. 1. La modale « @ » était confinée dans le header (desktop + mobile) <header> portait `backdrop-blur-sm`, et `backdrop-filter` fait de l'élément le containing block de ses descendants en position:fixed. Les overlays du provider-picker (et du menu Ctrl+K) se résolvaient donc contre le header : mesuré 1440x64 au lieu de 1440x900, dialogue réduit à 32px de haut pour 466px de contenu, haut de la fenêtre inatteignable. Le flou passe sur une couche enfant (`-z-10`) qui n'est pas un ancêtre des overlays : `fixed` redevient relatif au viewport. Desktop : dialogue 512x468 centré. Mobile : 358x686, entièrement visible. 2. La barre de thèmes disparaissait sous le header (desktop + mobile) `--header-offset` vaut 56/64px, mais le header mesure 57/65px (bordure) et 118px quand la feuille de recherche mobile est ouverte. La barre était donc déjà glissée dessous, et totalement invisible dans ce dernier cas (hauteur visible mesurée : 0px). HeaderComponent publie maintenant sa hauteur réelle dans `--header-measured` via ResizeObserver ; `--header-offset` l'utilise quand elle existe et garde la valeur statique en repli. Barre visible dans tous les cas, y compris feuille de recherche ouverte. 3. Barre de thèmes : icônes seules sur mobile Les libellés sont masqués sous md (`aria-label` conservé pour l'accessibilité). 7 pastilles visibles au lieu de 3, sans scroll. 4. Avatar en pastille `.avatar-circle` est renforcé : `rounded-full` dans le markup plus `border-radius: 9999px !important`, `aspect-ratio: 1/1`, min-width/min-height et `line-height: 1`, pour qu'aucun style de thème ne puisse le dégrader en rectangle. Vérifié : audit navigateur sur 17 routes x 320/390/768/1440 px — aucun débordement horizontal, barre de thèmes visible partout ; tests du dépôt verts ; build production OK.
This commit is contained in:
@@ -1,9 +1,17 @@
|
||||
|
||||
<header class="app-header bg-slate-800/50 backdrop-blur-sm fixed inset-x-0 top-0 z-50 shadow-lg border-b border-slate-700/60"
|
||||
<header class="app-header fixed inset-x-0 top-0 z-50 shadow-lg border-b border-slate-700/60"
|
||||
[style.paddingTop]="'var(--safe-top)'"
|
||||
[style.paddingLeft]="'var(--safe-left)'"
|
||||
[style.paddingRight]="'var(--safe-right)'">
|
||||
|
||||
<!-- Frosted layer lives on its own child, never on <header> itself.
|
||||
`backdrop-filter` makes an element the containing block for
|
||||
position:fixed descendants, so blurring the header trapped the
|
||||
provider-picker and Ctrl+K modals inside the 64px header box (their top
|
||||
was unreachable). The overlays below are siblings of this layer, so
|
||||
they resolve against the viewport again. -->
|
||||
<div aria-hidden="true" class="pointer-events-none absolute inset-0 -z-10 bg-slate-800/50 backdrop-blur-sm"></div>
|
||||
|
||||
<!-- Top row: burger + logo (always) / search (desktop) / actions -->
|
||||
<div class="flex items-center gap-1 h-14 md:h-16 px-2 md:px-4">
|
||||
|
||||
@@ -93,7 +101,7 @@
|
||||
<div class="relative" #userMenuContainer>
|
||||
<button type="button" (click)="toggleUserMenu()" class="app-avatar-btn focus-ring" aria-haspopup="true"
|
||||
[attr.aria-expanded]="userMenuOpen()" [attr.aria-label]="user()?.username || user()?.email || ('menu.account' | t)">
|
||||
<span class="avatar-circle" [ngClass]="avatarClasses()">{{ avatarLetter() }}</span>
|
||||
<span class="avatar-circle rounded-full" [ngClass]="avatarClasses()">{{ avatarLetter() }}</span>
|
||||
</button>
|
||||
@if (userMenuOpen()) {
|
||||
<div class="absolute right-0 mt-2 w-[min(20rem,calc(100vw-1rem))] overflow-hidden rounded-xl border border-slate-700 bg-slate-900 shadow-xl z-50" role="menu">
|
||||
@@ -120,7 +128,7 @@
|
||||
<!-- Mobile search sheet: the same <app-search-box> instance is rendered here
|
||||
through CSS only when the user asks for it. Kept out of the flow so the
|
||||
page never reflows while typing. -->
|
||||
<div id="mobile-search-sheet" class="md:hidden border-t border-slate-700/60 bg-slate-900/95 backdrop-blur-sm px-2 pb-2"
|
||||
<div id="mobile-search-sheet" class="md:hidden border-t border-slate-700/60 bg-slate-900/95 px-2 pb-2"
|
||||
[class.hidden]="!mobileSearchOpen()">
|
||||
<div class="relative">
|
||||
<app-search-box [placeholder]="('search.placeholder' | t)"
|
||||
@@ -183,7 +191,7 @@
|
||||
@if (user()) {
|
||||
<div class="border-t border-slate-800 px-4 py-3">
|
||||
<div class="mb-2 flex items-center gap-3">
|
||||
<span class="avatar-circle" [ngClass]="avatarClasses()">{{ avatarLetter() }}</span>
|
||||
<span class="avatar-circle rounded-full" [ngClass]="avatarClasses()">{{ avatarLetter() }}</span>
|
||||
<span class="min-w-0 flex-1">
|
||||
<span class="block truncate text-sm font-semibold text-slate-100">{{ user()?.username || user()?.email }}</span>
|
||||
<span class="block truncate text-xs text-slate-400">{{ user()?.email }}</span>
|
||||
|
||||
Reference in New Issue
Block a user