Merge branch 'upg100/p6-card-row-dev' into upg100/land-pair
# Conflicts: # public/dx-maps/country-posters/countries-map/index.html # public/dx-maps/country-posters/country-poster-wall/index.html # public/dx-maps/country-posters/country-posters-mfe/index.html # public/dx-maps/country-posters/country-posters.js # public/dx-maps/doxa-maps-spa/manifest.json # public/dx-maps/manifest.json # public/dx-maps/my-upg-100-list/my-upg-100-list.js # public/dx-maps/my-upg-100-list/poster-wall/index.html # public/dx-maps/my-upg-100-list/upg-100-list/index.html # public/dx-maps/my-upg-100-list/upg-100-mfe/index.html # public/dx-maps/regions-dashboard/region-dashboards/index.html # public/dx-maps/regions-dashboard/regions-dashboard.js # public/dx-maps/regions-dashboard/regions-list/index.html # public/dx-maps/regions-dashboard/regions-mfe/index.html
This commit is contained in:
commit
fa2a7fc0e7
2 changed files with 55 additions and 3 deletions
|
|
@ -208,6 +208,7 @@ async function measure(width, lang) {
|
|||
let previewsPainted = 0, previewsBroken = 0, noPreview = 0, unnamedPreview = 0
|
||||
let notTaped = 0, worstTape = 0, selectsInRow = 0
|
||||
let headNotTaped = 0, worstHead = 0, mapCovered = 0, worstCover = 0
|
||||
let uncontained = 0, worstBelow = 0
|
||||
for (const { c, b } of boxes) {
|
||||
const row = c.querySelector('.pfs')
|
||||
if (!row) continue
|
||||
|
|
@ -216,6 +217,14 @@ async function measure(width, lang) {
|
|||
overflowing++
|
||||
worst = Math.max(worst, Math.round(Math.max(rb.right - b.right, b.left - rb.left)))
|
||||
}
|
||||
// ★ AND THE CARD CONTAINS ITS ROW (2026-09-30, from a phone at two posters per row). The row
|
||||
// wrapped to three lines and hung about 45px below the card's white box, into the row gap:
|
||||
// horizontally inside, so the check above stayed green. PosterWall now fits each card to its
|
||||
// own row (--pfs-room); this is the assertion that keeps that true in every locale x width.
|
||||
if (rb.bottom > b.bottom + 0.5) {
|
||||
uncontained++
|
||||
worstBelow = Math.max(worstBelow, Math.round(rb.bottom - b.bottom))
|
||||
}
|
||||
// ⚠ THE VERTICAL AXIS TOO — this measured only left/right, which is exactly how it passed a
|
||||
// visible regression. Fixing the horizontal overflow with flex-wrap grew the row
|
||||
// 35px -> 78px, and because it sits at bottom:-14px the extra height pushed its TOP from
|
||||
|
|
@ -364,7 +373,8 @@ async function measure(width, lang) {
|
|||
overflowing, worst, intrusions, coveringPreview, worstY,
|
||||
previewsPainted, previewsBroken, noPreview, unnamedPreview, clipped: clipped.length,
|
||||
controls: ctrls.length, tiny: tiny.length, perRow, cardW,
|
||||
notTaped, worstTape, selectsInRow, headNotTaped, worstHead, mapCovered, worstCover }
|
||||
notTaped, worstTape, selectsInRow, headNotTaped, worstHead, mapCovered, worstCover,
|
||||
uncontained, worstBelow }
|
||||
})()`)
|
||||
await page.close()
|
||||
return { width, lang, hover, reach, ...out }
|
||||
|
|
@ -382,6 +392,7 @@ console.log(` leaf : ${LEAF}`)
|
|||
for (const r of results) {
|
||||
console.log(` ${(r.lang || 'en').padEnd(2)} ${String(r.width).padStart(4)}px cards ${String(r.cards).padStart(2)}`
|
||||
+ ` · overflow ${r.overflowing}${r.worst ? ` (${r.worst}px)` : ''}`
|
||||
+ ` · below-card ${r.uncontained}${r.worstBelow ? ` (${r.worstBelow}px)` : ''}`
|
||||
+ ` · neighbour ${r.intrusions}`
|
||||
+ ` · over-preview ${r.coveringPreview}${r.worstY ? ` (${r.worstY}px)` : ''}`
|
||||
+ ` · off-frame ${r.notTaped}${r.worstTape ? ` (${r.worstTape > 0 ? '+' : ''}${r.worstTape}px)` : ''}`
|
||||
|
|
@ -408,6 +419,7 @@ for (const r of results) {
|
|||
if (!r.rows) { fails.push(`${at}: ${r.cards} card(s) but none carry a .pfs print-options row`); continue }
|
||||
if (r.intrusions) fails.push(`${at}: ${r.intrusions} print row(s) overlap a NEIGHBOURING card`)
|
||||
if (r.overflowing) fails.push(`${at}: ${r.overflowing} print row(s) extend past their own card (worst ${r.worst}px)`)
|
||||
if (r.uncontained) fails.push(`${at}: ${r.uncontained} print row(s) hang below their own card's box (worst ${r.worstBelow}px): the card must contain its row`)
|
||||
// ⚠ "Nothing overflows" is trivially satisfied by a row whose buttons collapsed to nothing.
|
||||
if (r.tiny) {
|
||||
fails.push(`${at}: ${r.tiny} print control(s) shrank below a usable size — fitting the row by `
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
* CROSS-PANE COMMS — this wall NEVER imports a map. It dispatches a window
|
||||
* CustomEvent scoped by instanceId, so several embeds on one page never cross-talk.
|
||||
*/
|
||||
import { computed, ref, watch, onBeforeUnmount, onMounted } from 'vue'
|
||||
import { computed, ref, watch, onBeforeUnmount, onMounted, onUpdated } from 'vue'
|
||||
import { tStatic } from '../../i18n/index.js'
|
||||
|
||||
// This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside
|
||||
|
|
@ -365,6 +365,44 @@ onMounted(() => {
|
|||
})
|
||||
onBeforeUnmount(() => { for (const mo of paneMOs) mo.disconnect(); paneMOs = [] })
|
||||
|
||||
// ★ THE CARD CONTAINS ITS PRINT ROW (2026-09-30, from a phone at two posters per row). The row is a sticker
|
||||
// pinned --tape-overlap over the banner's bottom edge that grows DOWNWARD as its labels wrap. One line
|
||||
// fits inside the card's 26px bottom padding; on a ~162px two-up card it wraps to three lines and hung
|
||||
// about 45px below the card's white box. No fixed padding fits every locale x width (the reason the row
|
||||
// is pinned by its overlap and not its centre), so each card is fitted to its own row: a ResizeObserver
|
||||
// on every .pfs writes --pfs-room on the card: for a row that hangs past the white box (the 26px padding
|
||||
// and the 1px border), the part below the banner plus ROW_DAYLIGHT_PX that the 26px does not cover. A row
|
||||
// that fits writes 0 (a one-line row ends ~5px inside the box), so every card that fit is unchanged.
|
||||
// The revealed packet/size rows stay overlays on purpose (.has-tape-open lifts the card above its
|
||||
// neighbours); only the print row itself is contained.
|
||||
const CARD_PAD_BOTTOM_PX = 26
|
||||
const CARD_BORDER_PX = 1
|
||||
const ROW_DAYLIGHT_PX = 8
|
||||
let rowRO = null
|
||||
function fitCardToRow(pfs) {
|
||||
const card = pfs.closest('.card')
|
||||
const banner = pfs.parentElement
|
||||
if (!card || !banner) return
|
||||
// Rect DIFFERENCES inside one card: the hover lift (a translateY on the card) moves both edges alike.
|
||||
const below = pfs.getBoundingClientRect().bottom - banner.getBoundingClientRect().bottom
|
||||
const hangs = below > CARD_PAD_BOTTOM_PX + CARD_BORDER_PX
|
||||
const room = `${hangs ? Math.ceil(below + ROW_DAYLIGHT_PX - CARD_PAD_BOTTOM_PX) : 0}px`
|
||||
if (card.style.getPropertyValue('--pfs-room') !== room) card.style.setProperty('--pfs-room', room)
|
||||
}
|
||||
// observe() is idempotent, so re-scanning after every render only adds the rows that are new (items,
|
||||
// sections opened, the per-row choice); a hidden wall reports 0 and writes 0 until it is shown.
|
||||
function observeRows() {
|
||||
if (!rowRO || !wallEl.value) return
|
||||
for (const pfs of wallEl.value.querySelectorAll('.pfs')) rowRO.observe(pfs)
|
||||
}
|
||||
onMounted(() => {
|
||||
if (typeof ResizeObserver === 'undefined') return
|
||||
rowRO = new ResizeObserver((entries) => { for (const e of entries) fitCardToRow(e.target) })
|
||||
observeRows()
|
||||
})
|
||||
onUpdated(observeRows)
|
||||
onBeforeUnmount(() => { if (rowRO) rowRO.disconnect(); rowRO = null })
|
||||
|
||||
function showOnMap(item) {
|
||||
// TOGGLE, not a one-way set: a control the user can turn on but not off reads as
|
||||
// broken even when the selection is correct.
|
||||
|
|
@ -758,7 +796,9 @@ useShadowStyles(
|
|||
// hand-typed 24px would.
|
||||
'.card{--card-pad-top:24px;--tape-overlap:16px;position:relative;background:#fff;border:1px solid #e3e6ea;' +
|
||||
'border-radius:3px;' +
|
||||
'padding:var(--card-pad-top) 12px 26px;' +
|
||||
// --pfs-room: the extra bottom padding a card needs to CONTAIN its print row once that row wraps
|
||||
// (fitCardToRow in the script). 0 wherever the row fits the 26px, so those cards are unchanged.
|
||||
'padding:var(--card-pad-top) 12px calc(26px + var(--pfs-room,0px));' +
|
||||
'box-shadow:0 1px 3px rgba(0,0,0,.10),0 6px 18px rgba(0,0,0,.07);' +
|
||||
'transition:transform .16s ease,box-shadow .16s ease}' +
|
||||
// ★ THE BLUE OUTLINE IS A HOVER STATE, NOT A MISSING STATIC BORDER. Several reports have asked
|
||||
|
|
|
|||
Loading…
Reference in a new issue