feat(ComparisonView): replace window resize listener with ResiseObserver on the container to catch the container size change on sidebar open/close

This commit is contained in:
Ilia Mashkov
2026-04-23 12:45:13 +03:00
parent cb7218cf3d
commit 1df03637a9
@@ -61,6 +61,26 @@ const comparisonEngine = new CharacterComparisonEngine();
let layoutResult = $state<ReturnType<typeof comparisonEngine.layout>>({ lines: [], totalHeight: 0 });
// Track container width changes (window resize, sidebar toggle, etc.)
$effect(() => {
if (!container) {
return;
}
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
// Use borderBoxSize if available, fallback to contentRect
const width = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
if (width > 0) {
containerWidth = width;
}
}
});
observer.observe(container);
return () => observer.disconnect();
});
const sliderSpring = new Spring(50, {
stiffness: 0.2,
damping: 0.7,
@@ -124,25 +144,25 @@ $effect(() => {
}
});
// Layout effect — depends on content, settings AND containerWidth
$effect(() => {
const _text = comparisonStore.text;
const _weight = typography.weight;
const _size = typography.renderedSize;
const _height = typography.height;
const _spacing = typography.spacing;
const _width = containerWidth;
const _isMobile = isMobile;
if (container && fontA && fontB) {
if (container && fontA && fontB && _width > 0) {
// PRETEXT API strings: "weight sizepx family"
const fontAStr = getPretextFontString(_weight, _size, fontA.name);
const fontBStr = getPretextFontString(_weight, _size, fontB.name);
// Use offsetWidth to avoid transform scaling issues
const width = container.offsetWidth;
const padding = isMobile ? 48 : 96;
const availableWidth = width - padding;
const padding = _isMobile ? 48 : 96;
const availableWidth = Math.max(0, _width - padding);
const lineHeight = _size * _height;
containerWidth = width;
layoutResult = comparisonEngine.layout(
_text,
fontAStr,
@@ -155,30 +175,6 @@ $effect(() => {
}
});
$effect(() => {
if (typeof window === 'undefined') {
return;
}
const handleResize = () => {
if (container && fontA && fontB) {
const width = container.offsetWidth;
const padding = isMobile ? 48 : 96;
containerWidth = width;
layoutResult = comparisonEngine.layout(
comparisonStore.text,
getPretextFontString(typography.weight, typography.renderedSize, fontA.name),
getPretextFontString(typography.weight, typography.renderedSize, fontB.name),
width - padding,
typography.renderedSize * typography.height,
typography.spacing,
typography.renderedSize,
);
}
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
});
// Dynamic backgroundSize based on isMobile — can't express this in Tailwind.
// Color is set to currentColor so it respects dark mode via text color.
const gridStyle = $derived(
@@ -273,8 +269,8 @@ const scaleClass = $derived(
class={cn(
'absolute z-10',
responsive.isMobileOrTablet
? 'bottom-4 right-4 -translate-1/2'
: 'bottom-5 left-1/2 right-[unset] -translate-x-1/2',
? 'bottom-0 right-0 -translate-1/2'
: 'bottom-2.5 left-1/2 -translate-x-1/2',
)}
/>
</div>