From 82d0a8fb3b5a1bfe4a5da35a3d4f57911f046d37 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Thu, 1 Oct 2026 08:26:41 -0400 Subject: [PATCH] fix(menu-fab): navigation du menu correcte sur /shorts + FAB plus compact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - app-player-menu : stopPropagation wheel/touchstart/touchend sur le host — les handlers window:wheel et window:touch* de /shorts ne volaient plus les gestes sur le panneau (impossible de scroller jusqu'en bas du menu, tap = play/pause, swipe = changement de short) - /shorts : ArrowUp/Down ignore quand le menu est ouvert - /shorts : le FAB passe en haut a DROITE du cadre (la fleche retour mobile z-20 passait par-dessus le FAB piege dans la scene z-10) - Look/taille : FAB 40->36px, panneau 288->240px, items compacts, max-height 70vh/480 -> 65vh/430 (plus de rognage par overflow:hidden), pastille en degrade + relief, panneau rounded-xl + highlight interne --- index.css | 85 ++++++++++++------- .../player-menu/player-menu.component.ts | 9 ++ .../shorts/watch-short.component.ts | 3 +- 3 files changed, 63 insertions(+), 34 deletions(-) diff --git a/index.css b/index.css index 4277b0a..b208ecb 100644 --- a/index.css +++ b/index.css @@ -577,42 +577,54 @@ body { avec en-tête, entrée/sortie animées. Harmonisé avec les commandes overlay des players YouTube/Dailymotion (fond sombre translucide, blur, ring fin). */ -/* Pastille FAB (haut-gauche du lecteur). */ +/* Pastille FAB (coin du lecteur) : disque compact en dégradé sombre, léger + relief (ombre + highlight interne) et agrandissement au survol. */ .pm-fab { display: inline-flex; align-items: center; justify-content: center; - width: 2.5rem; /* 40px */ - height: 2.5rem; + width: 2.25rem; /* 36px */ + height: 2.25rem; border-radius: 9999px; color: #fff; - background: rgba(0, 0, 0, .55); - border: 1px solid rgba(255, 255, 255, .14); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); + background: linear-gradient(180deg, rgba(30, 41, 59, .88), rgba(2, 6, 23, .9)); + border: 1px solid rgba(255, 255, 255, .18); + box-shadow: 0 4px 14px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 255, 255, .12); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); cursor: pointer; - transition: background-color .15s ease, border-color .15s ease, transform .15s ease; + transition: background .15s ease, border-color .15s ease, transform .15s ease, box-shadow .15s ease; } -.pm-fab svg { width: 1.125rem; height: 1.125rem; } -.pm-fab:hover { background: rgba(0, 0, 0, .72); border-color: rgba(255, 255, 255, .24); } -.pm-fab:active { transform: scale(.93); } -.pm-fab-open { background: rgba(0, 0, 0, .72); border-color: rgba(255, 255, 255, .24); } -.pm-fab:focus-visible { outline: 2px solid rgba(255, 255, 255, .55); outline-offset: 2px; } +.pm-fab svg { width: 1rem; height: 1rem; opacity: .92; } +.pm-fab:hover { + background: linear-gradient(180deg, rgba(51, 65, 85, .95), rgba(15, 23, 42, .95)); + border-color: rgba(255, 255, 255, .32); + transform: scale(1.06); +} +.pm-fab:active { transform: scale(.94); } +.pm-fab-open { + background: linear-gradient(180deg, rgba(51, 65, 85, .95), rgba(2, 6, 23, .95)); + border-color: rgba(255, 255, 255, .32); +} +.pm-fab:focus-visible { outline: 2px solid rgba(255, 255, 255, .6); outline-offset: 2px; } /* Panneau déroulant (toujours monté, animé via open/close). */ .pm-panel { position: absolute; top: calc(100% + 0.5rem); left: 0; - width: 18rem; /* 288px */ - max-height: min(70vh, 480px); + width: 15rem; /* 240px */ + /* Borné à 65vh : le cadre /shorts a `overflow:hidden` — au-delà, le bas du + menu serait rogné sur les petits écrans (le corps scrolle donc). */ + max-height: min(65vh, 430px); display: flex; flex-direction: column; overflow: hidden; - border-radius: 1rem; - background: rgba(15, 23, 42, .92); /* slate-900/92 */ - border: 1px solid rgba(255, 255, 255, .1); - box-shadow: 0 18px 50px rgba(0, 0, 0, .55), 0 2px 10px rgba(0, 0, 0, .35); + border-radius: 0.75rem; + background: rgba(15, 23, 42, .94); /* slate-900/94 */ + border: 1px solid rgba(255, 255, 255, .12); + box-shadow: 0 20px 50px rgba(0, 0, 0, .6), 0 2px 10px rgba(0, 0, 0, .4), + inset 0 1px 0 rgba(255, 255, 255, .07); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px); opacity: 0; @@ -635,13 +647,13 @@ body { display: flex; align-items: center; justify-content: space-between; - gap: 0.75rem; - padding: 0.625rem 0.625rem 0.625rem 0.875rem; + gap: 0.5rem; + padding: 0.4375rem 0.4375rem 0.4375rem 0.75rem; border-bottom: 1px solid rgba(255, 255, 255, .08); flex-shrink: 0; } .pm-panel-title { - font-size: 0.8125rem; + font-size: 0.75rem; /* 12px */ font-weight: 600; letter-spacing: .02em; color: rgba(255, 255, 255, .92); @@ -653,20 +665,20 @@ body { display: inline-flex; align-items: center; justify-content: center; - width: 1.75rem; - height: 1.75rem; + width: 1.5rem; + height: 1.5rem; border-radius: 9999px; color: rgba(255, 255, 255, .7); flex-shrink: 0; transition: background-color .15s ease, color .15s ease; } -.pm-panel-close svg { width: 1rem; height: 1rem; } +.pm-panel-close svg { width: 0.875rem; height: 0.875rem; } .pm-panel-close:hover { background: rgba(255, 255, 255, .1); color: #fff; } .pm-panel-close:focus-visible { outline: 2px solid rgba(255, 255, 255, .5); outline-offset: 1px; } /* Corps scrollable du panneau. */ .pm-panel-body { - padding: 0.5rem; + padding: 0.375rem; overflow-y: auto; overscroll-behavior: contain; flex: 1; @@ -677,7 +689,7 @@ body { /* Libellé de section. */ .pm-section-label { - padding: 0.625rem 0.75rem 0.375rem; + padding: 0.5rem 0.625rem 0.25rem; font-size: 0.6875rem; /* 11px */ font-weight: 600; letter-spacing: 0.06em; @@ -689,11 +701,11 @@ body { .pm-item { display: flex; align-items: center; - gap: 0.75rem; + gap: 0.625rem; width: 100%; - padding: 0.5625rem 0.75rem; - border-radius: 0.625rem; - font-size: 0.84375rem; /* 13.5px */ + padding: 0.5rem 0.625rem; + border-radius: 0.5rem; + font-size: 0.8125rem; /* 13px */ color: var(--text); text-align: left; line-height: 1.3; @@ -706,10 +718,17 @@ body { .pm-item:disabled { opacity: .4; cursor: not-allowed; } .pm-item svg { flex-shrink: 0; color: rgba(255, 255, 255, .75); } .pm-item .pm-item-label { flex: 1; min-width: 0; } -.pm-item .pm-item-hint { font-size: 0.71875rem; color: var(--muted); } +.pm-item .pm-item-hint { font-size: 0.6875rem; color: var(--muted); } /* Séparateur. */ -.pm-sep { height: 1px; margin: 0.375rem 0.625rem; background: rgba(255, 255, 255, .08); } +.pm-sep { height: 1px; margin: 0.25rem 0.5rem; background: rgba(255, 255, 255, .08); } + +/* /shorts : la flèche « retour accueil » occupe le coin haut-gauche (mobile) + et passait PAR-DESSUS le FAB (elle est à z-20 au niveau de la scène, le FAB + étant enfermé dans le contexte z-10). Le FAB passe donc en haut à droite du + cadre, panneau ancré sur le même côté. */ +.shorts-frame app-player-menu { left: auto; right: 0.5rem; } +.shorts-frame app-player-menu .pm-panel { left: auto; right: 0; transform-origin: top right; } /* --- Drawer / overlay plumbing -------------------------------------------- */ /* Applied to while a full-screen drawer or modal owns the viewport. diff --git a/src/app/shared/components/player-menu/player-menu.component.ts b/src/app/shared/components/player-menu/player-menu.component.ts index 5928709..10ef1f1 100644 --- a/src/app/shared/components/player-menu/player-menu.component.ts +++ b/src/app/shared/components/player-menu/player-menu.component.ts @@ -18,6 +18,15 @@ import { CommonModule } from '@angular/common'; standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], + // Les pages /shorts hijackent `window:wheel` / `window:touchstart|end` pour + // naviguer d'un short à l'autre : sans ces stopPropagation, tout geste SUR le + // panneau ouvert scrolle la vidéo au lieu du menu (impossible d'atteindre le + // bas du menu). Arrêté ici = corrigé une fois pour /watch ET /shorts. + host: { + '(wheel)': '$event.stopPropagation()', + '(touchstart)': '$event.stopPropagation()', + '(touchend)': '$event.stopPropagation()', + }, template: `