Commit
fix(fiche): panneau héro premier dans le DOM — plus de order:-1 mobile
Le panneau resto (nom, prix, adresse) était après le menu dans le DOM et
remonté sur mobile via .panel{order:-1} — contraire au standard Groupe Ka
« Ordre des sections — pages détail » (ordre DOM = ordre visuel).
- Resto.tsx : <aside .panel> déplacé en premier enfant de .detail-grid,
le bloc menu devient .detail-main
- styles.css : order:-1 supprimé ; sur desktop le panneau est placé en
colonne 2 via grid-column (aucun réordonnancement entre breakpoints)
- Validé Playwright 390px (panneau premier, scrollY=0) + 1440px (panneau
colonne droite)
modified
frontend/src/pages/Resto.tsx
+24 −20
@@ -148,26 +148,10 @@ export default function RestoPage() { | |||
| 148 | </nav> | 148 | </nav> |
| 149 | 149 | ||
| 150 | <div className="detail-grid"> | 150 | <div className="detail-grid"> |
| 151 | − <div> | 151 | + {/* Panneau resto (nom, prix, adresse) EN PREMIER dans le DOM : c'est le |
| 152 | − {menus.length > 1 && ( | 152 | + héro de la fiche — l'ordre du DOM est l'ordre visuel sur mobile |
| 153 | − <div className="view-toggle ctx-toggle" role="tablist" aria-label="Contexte de prix"> | 153 | + (standard Groupe Ka « Ordre des sections — pages détail »). |
| 154 | − {menus.map((m) => ( | 154 | + Sur desktop, le CSS le place explicitement en colonne 2. */} |
| 155 | − <button key={m.price_context} | ||
| 156 | − className={m.price_context === menu?.price_context ? "on" : ""} | ||
| 157 | − onClick={() => setCtx(m.price_context)}> | ||
| 158 | − {CONTEXT_SHORT[m.price_context] ?? m.price_context} | ||
| 159 | − </button> | ||
| 160 | − ))} | ||
| 161 | − </div> | ||
| 162 | − )} | ||
| 163 | − {menu ? <MenuBlock menu={menu} /> : ( | ||
| 164 | − <div className="notice"> | ||
| 165 | − <h2>Menu à venir</h2> | ||
| 166 | − <p>Ce resto est répertorié ; son menu sera capté à la prochaine synchronisation.</p> | ||
| 167 | − </div> | ||
| 168 | − )} | ||
| 169 | − </div> | ||
| 170 | − | ||
| 171 | <aside className="panel"> | 155 | <aside className="panel"> |
| 172 | <div className="panel-head"> | 156 | <div className="panel-head"> |
| 173 | {(resto.images ?? [])[0] && ( | 157 | {(resto.images ?? [])[0] && ( |
@@ -231,6 +215,26 @@ export default function RestoPage() { | |||
| 231 | resto et peuvent changer sans préavis. | 215 | resto et peuvent changer sans préavis. |
| 232 | </div> | 216 | </div> |
| 233 | </aside> | 217 | </aside> |
| 218 | + | ||
| 219 | + <div className="detail-main"> | ||
| 220 | + {menus.length > 1 && ( | ||
| 221 | + <div className="view-toggle ctx-toggle" role="tablist" aria-label="Contexte de prix"> | ||
| 222 | + {menus.map((m) => ( | ||
| 223 | + <button key={m.price_context} | ||
| 224 | + className={m.price_context === menu?.price_context ? "on" : ""} | ||
| 225 | + onClick={() => setCtx(m.price_context)}> | ||
| 226 | + {CONTEXT_SHORT[m.price_context] ?? m.price_context} | ||
| 227 | + </button> | ||
| 228 | + ))} | ||
| 229 | + </div> | ||
| 230 | + )} | ||
| 231 | + {menu ? <MenuBlock menu={menu} /> : ( | ||
| 232 | + <div className="notice"> | ||
| 233 | + <h2>Menu à venir</h2> | ||
| 234 | + <p>Ce resto est répertorié ; son menu sera capté à la prochaine synchronisation.</p> | ||
| 235 | + </div> | ||
| 236 | + )} | ||
| 237 | + </div> | ||
| 234 | </div> | 238 | </div> |
| 235 | </div> | 239 | </div> |
| 236 | ); | 240 | ); |
modified
frontend/src/styles.css
+9 −1
@@ -369,15 +369,23 @@ img { display: block; } | |||
| 369 | } | 369 | } |
| 370 | .crumbs a { border-bottom: 1.5px solid transparent; } | 370 | .crumbs a { border-bottom: 1.5px solid transparent; } |
| 371 | .crumbs a:hover { color: var(--green); border-color: var(--green); } | 371 | .crumbs a:hover { color: var(--green); border-color: var(--green); } |
| 372 | +/* Ordre DOM = ordre visuel (standard Groupe Ka « Ordre des sections — pages | ||
| 373 | + détail ») : le panneau héro (nom/prix/adresse) est 1er dans le DOM ; sur | ||
| 374 | + desktop il est placé en colonne 2 via grid-column — pas de `order` ni de | ||
| 375 | + `column-reverse` pour réordonner entre breakpoints. */ | ||
| 372 | .detail-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: 30px; align-items: start; } | 376 | .detail-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: 30px; align-items: start; } |
| 373 | @media (max-width: 900px) { .detail-grid { grid-template-columns: 1fr; } } | 377 | @media (max-width: 900px) { .detail-grid { grid-template-columns: 1fr; } } |
| 374 | .detail-grid > * { min-width: 0; } | 378 | .detail-grid > * { min-width: 0; } |
| 379 | +@media (min-width: 901px) { | ||
| 380 | + .detail-grid > .panel { grid-column: 2; grid-row: 1; } | ||
| 381 | + .detail-grid > .detail-main { grid-column: 1; grid-row: 1; } | ||
| 382 | +} | ||
| 375 | 383 | ||
| 376 | .panel { | 384 | .panel { |
| 377 | background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-card); | 385 | background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-card); |
| 378 | box-shadow: var(--shadow-off-soft); padding: 26px; position: sticky; top: 120px; | 386 | box-shadow: var(--shadow-off-soft); padding: 26px; position: sticky; top: 120px; |
| 379 | } | 387 | } |
| 380 | −@media (max-width: 900px) { .panel { position: static; order: -1; } } | 388 | +@media (max-width: 900px) { .panel { position: static; } } |
| 381 | .panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; } | 389 | .panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; } |
| 382 | .panel-logo { max-width: 110px; max-height: 54px; object-fit: contain; border-radius: var(--r-ctl); } | 390 | .panel-logo { max-width: 110px; max-height: 54px; object-fit: contain; border-radius: var(--r-ctl); } |
| 383 | .panel .price { | 391 | .panel .price { |
| 384 | 392 | ||