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:
@@ -61,6 +61,26 @@ const comparisonEngine = new CharacterComparisonEngine();
|
|||||||
|
|
||||||
let layoutResult = $state<ReturnType<typeof comparisonEngine.layout>>({ lines: [], totalHeight: 0 });
|
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, {
|
const sliderSpring = new Spring(50, {
|
||||||
stiffness: 0.2,
|
stiffness: 0.2,
|
||||||
damping: 0.7,
|
damping: 0.7,
|
||||||
@@ -124,25 +144,25 @@ $effect(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Layout effect — depends on content, settings AND containerWidth
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
const _text = comparisonStore.text;
|
const _text = comparisonStore.text;
|
||||||
const _weight = typography.weight;
|
const _weight = typography.weight;
|
||||||
const _size = typography.renderedSize;
|
const _size = typography.renderedSize;
|
||||||
const _height = typography.height;
|
const _height = typography.height;
|
||||||
const _spacing = typography.spacing;
|
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"
|
// PRETEXT API strings: "weight sizepx family"
|
||||||
const fontAStr = getPretextFontString(_weight, _size, fontA.name);
|
const fontAStr = getPretextFontString(_weight, _size, fontA.name);
|
||||||
const fontBStr = getPretextFontString(_weight, _size, fontB.name);
|
const fontBStr = getPretextFontString(_weight, _size, fontB.name);
|
||||||
|
|
||||||
// Use offsetWidth to avoid transform scaling issues
|
const padding = _isMobile ? 48 : 96;
|
||||||
const width = container.offsetWidth;
|
const availableWidth = Math.max(0, _width - padding);
|
||||||
const padding = isMobile ? 48 : 96;
|
|
||||||
const availableWidth = width - padding;
|
|
||||||
const lineHeight = _size * _height;
|
const lineHeight = _size * _height;
|
||||||
|
|
||||||
containerWidth = width;
|
|
||||||
layoutResult = comparisonEngine.layout(
|
layoutResult = comparisonEngine.layout(
|
||||||
_text,
|
_text,
|
||||||
fontAStr,
|
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.
|
// Dynamic backgroundSize based on isMobile — can't express this in Tailwind.
|
||||||
// Color is set to currentColor so it respects dark mode via text color.
|
// Color is set to currentColor so it respects dark mode via text color.
|
||||||
const gridStyle = $derived(
|
const gridStyle = $derived(
|
||||||
@@ -273,8 +269,8 @@ const scaleClass = $derived(
|
|||||||
class={cn(
|
class={cn(
|
||||||
'absolute z-10',
|
'absolute z-10',
|
||||||
responsive.isMobileOrTablet
|
responsive.isMobileOrTablet
|
||||||
? 'bottom-4 right-4 -translate-1/2'
|
? 'bottom-0 right-0 -translate-1/2'
|
||||||
: 'bottom-5 left-1/2 right-[unset] -translate-x-1/2',
|
: 'bottom-2.5 left-1/2 -translate-x-1/2',
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user