Stop the kitten measuring the size it shrank itself to
The mascot shrinks a step when it yields to a card, and the overlap test read getBoundingClientRect, which reports the scaled box. So a card resting at the mascot's edge drove a loop: overlap, shrink, no overlap, grow, overlap again, every poll tick. Measure the layout box instead — centre plus offsetWidth/offsetHeight, which the yield transform doesn't move. Hysteresis would have hidden the pulsing; this removes the path that caused it. Claude-Session: https://claude.ai/code/session_01GJHNvirh7Hzhc9RL3HAvz7
This commit is contained in:
@@ -24,6 +24,21 @@ export interface CardOverlap {
|
|||||||
modal: boolean
|
modal: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The mascot shrinks a step when it yields (.petal-companion-faded), and
|
||||||
|
// getBoundingClientRect reports the *scaled* box. Measuring that lets the
|
||||||
|
// mascot shrink out of its own overlap test: it yields, stops overlapping,
|
||||||
|
// wakes back up, overlaps again — pulsing forever against a card that sits just
|
||||||
|
// at its edge. The layout box doesn't move when it yields, so measure that. The
|
||||||
|
// transform origin is the centre, so it's the visual centre ± the layout size.
|
||||||
|
function layoutRect(el: HTMLElement) {
|
||||||
|
const r = el.getBoundingClientRect()
|
||||||
|
const halfW = el.offsetWidth / 2
|
||||||
|
const halfH = el.offsetHeight / 2
|
||||||
|
const cx = (r.left + r.right) / 2
|
||||||
|
const cy = (r.top + r.bottom) / 2
|
||||||
|
return { left: cx - halfW, right: cx + halfW, top: cy - halfH, bottom: cy + halfH }
|
||||||
|
}
|
||||||
|
|
||||||
// Reports what, if anything, the mascot should yield to at the given element.
|
// Reports what, if anything, the mascot should yield to at the given element.
|
||||||
// Used to fade the corner mascot out of the way when a card or panel reaches
|
// Used to fade the corner mascot out of the way when a card or panel reaches
|
||||||
// into its corner, so nothing is ever hidden (or made unclickable) by the
|
// into its corner, so nothing is ever hidden (or made unclickable) by the
|
||||||
@@ -37,7 +52,7 @@ export function useCardOverlap(ref: RefObject<HTMLElement | null>): CardOverlap
|
|||||||
const check = () => {
|
const check = () => {
|
||||||
const el = ref.current
|
const el = ref.current
|
||||||
if (!el) return
|
if (!el) return
|
||||||
const r = el.getBoundingClientRect()
|
const r = layoutRect(el)
|
||||||
const hits = (selector: string) => {
|
const hits = (selector: string) => {
|
||||||
for (const other of document.querySelectorAll(selector)) {
|
for (const other of document.querySelectorAll(selector)) {
|
||||||
const b = other.getBoundingClientRect()
|
const b = other.getBoundingClientRect()
|
||||||
|
|||||||
Reference in New Issue
Block a user