Bug/v2/fix rtl (#4958)

This commit is contained in:
Reece Browne
2025-11-24 16:57:36 +00:00
committed by GitHub
parent 5d18184e46
commit 861e4394df
20 changed files with 225 additions and 54 deletions
@@ -42,11 +42,26 @@ export function useToolPanelGeometry({
const computeAndSetGeometry = () => {
const rect = panelEl.getBoundingClientRect();
const rail = rightRailEl();
const rightOffset = rail ? Math.max(0, window.innerWidth - rail.getBoundingClientRect().left) : 0;
const width = Math.max(360, window.innerWidth - rect.left - rightOffset);
const isRTL = typeof document !== 'undefined' && document.documentElement.dir === 'rtl';
const railRect = rail?.getBoundingClientRect();
const railIsOnRight = railRect ? railRect.right > window.innerWidth / 2 : false;
const rightOffset = railRect && railIsOnRight ? Math.max(0, window.innerWidth - railRect.right) : 0;
let width: number;
let left: number;
if (isRTL) {
// In RTL, QuickAccessBar is on the right, so start after it (using rect.right as the right edge)
const quickAccessRect = quickAccessRef.current?.getBoundingClientRect();
const quickAccessWidth = quickAccessRect ? quickAccessRect.width : 0;
width = Math.max(360, window.innerWidth - quickAccessWidth - rightOffset);
left = quickAccessWidth;
} else {
width = Math.max(360, window.innerWidth - rect.left - rightOffset);
left = rect.left;
}
const height = Math.max(rect.height, window.innerHeight - rect.top);
setGeometry({
left: rect.left,
left,
top: rect.top,
width,
height,
@@ -0,0 +1,33 @@
import { useEffect, useState } from 'react';
import { SidebarRefs } from '@app/types/sidebar';
export function useRightRailTooltipSide(
sidebarRefs?: SidebarRefs,
defaultOffset: number = 16
): { position: 'left' | 'right'; offset: number } {
const [position, setPosition] = useState<'left' | 'right'>('left');
useEffect(() => {
const computePosition = () => {
const rail = sidebarRefs?.rightRailRef?.current;
const isRTL = typeof document !== 'undefined' && document.documentElement.dir === 'rtl';
// Fallback to left if we can't measure
if (!rail || typeof window === 'undefined') {
setPosition(isRTL ? 'left' : 'left');
return;
}
const rect = rail.getBoundingClientRect();
const center = rect.left + rect.width / 2;
const preferred = center > window.innerWidth / 2 ? 'left' : 'right';
setPosition(isRTL ? 'left' : preferred);
};
computePosition();
window.addEventListener('resize', computePosition);
return () => window.removeEventListener('resize', computePosition);
}, [sidebarRefs]);
return { position, offset: defaultOffset };
}
+15 -5
View File
@@ -74,6 +74,7 @@ export function useTooltipPosition({
// Fallback sidebar position (only used as last resort)
const sidebarLeft = 240;
const isRTL = typeof document !== 'undefined' && document.documentElement.dir === 'rtl';
const updatePosition = () => {
if (!triggerRef.current || !open) return;
@@ -93,7 +94,11 @@ export function useTooltipPosition({
}
const sidebarInfo = getSidebarInfo(sidebarRefs, sidebarState);
const currentSidebarRight = sidebarInfo.rect ? sidebarInfo.rect.right : sidebarLeft;
const rect = sidebarInfo.rect;
if (!rect) {
setPositionReady(false);
return;
}
// Only show tooltip if we have the tool panel active
if (!sidebarInfo.isToolPanelActive) {
@@ -102,13 +107,18 @@ export function useTooltipPosition({
return;
}
// Position to the right of active sidebar with 20px gap
left = currentSidebarRight + 20;
const tooltipRect = tooltipRef.current?.getBoundingClientRect() || null;
// Position adjacent to sidebar; mirror for RTL
if (isRTL) {
left = rect.left - (tooltipRect?.width || 0) - 20;
} else {
left = rect.right + 20;
}
top = triggerRect.top; // Align top of tooltip with trigger element
// Only clamp if we have tooltip dimensions
if (tooltipRef.current) {
const tooltipRect = tooltipRef.current.getBoundingClientRect();
if (tooltipRect) {
const maxTop = window.innerHeight - tooltipRect.height - 4;
const originalTop = top;
top = clamp(top, 4, maxTop);