B: Fix tooltips for tabbed views

This commit is contained in:
Ivan 2025-11-17 15:11:50 +03:00
parent 73e74bdd2d
commit f63d9cf93e
4 changed files with 49 additions and 36 deletions

View File

@ -1,10 +1,11 @@
'use client';
import { useLayoutEffect } from 'react';
import { useLayoutEffect, useRef } from 'react';
import { useConceptNavigation } from '@/app/navigation/navigation-context';
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
import { useResetAttribute } from '@/hooks/use-reset-attribute';
import { useAppLayoutStore } from '@/stores/app-layout';
import { EditorOssCard } from './editor-oss-card';
@ -22,6 +23,9 @@ export function OssTabs({ activeTab }: OssTabsProps) {
const hideFooter = useAppLayoutStore(state => state.hideFooter);
const containerRef = useRef<HTMLDivElement>(null);
useResetAttribute(containerRef, 'data-tooltip-id');
useLayoutEffect(() => {
const oldTitle = document.title;
document.title = schema.title;
@ -68,7 +72,7 @@ export function OssTabs({ activeTab }: OssTabsProps) {
<TabLabel label='Граф' />
</TabList>
<div className='overflow-x-hidden'>
<div ref={containerRef} className='overflow-x-hidden'>
<TabPanel>
<EditorOssCard />
</TabPanel>

View File

@ -9,7 +9,7 @@ import { useWindowSize } from '@/hooks/use-window-size';
import { useFitHeight, useMainHeight } from '@/stores/app-layout';
import { useModificationStore } from '@/stores/modification';
import { usePreferencesStore } from '@/stores/preferences';
import { globalIDs, PARAMETER } from '@/utils/constants';
import { globalIDs } from '@/utils/constants';
import { useMutatingRSForm } from '../../../backend/use-mutating-rsform';
import { ViewConstituents } from '../../../components/view-constituents';
@ -43,7 +43,6 @@ export function EditorConstituenta() {
const { isModified } = useModificationStore();
const [toggleReset, setToggleReset] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const isProcessing = useMutatingRSForm();
const disabled = !activeCst || !isContentEditable || isProcessing;
@ -62,35 +61,6 @@ export function EditorConstituenta() {
}
}, [activeCst, selectedCst, setSelectedCst]);
useEffect(() => {
// Trigger tooltip re-initialization after component mounts and tab becomes visible
// This ensures tooltips work when loading the page directly with this tab active
// React-tabs hides inactive panels with CSS (display: none), so react-tooltip v5
// needs to re-scan the DOM when elements become visible
const timeoutId = setTimeout(() => {
if (!containerRef.current) {
return;
}
// Force react-tooltip to re-scan by temporarily removing and re-adding data-tooltip-id
// This triggers react-tooltip's internal MutationObserver to re-register the elements
const tooltipElements = containerRef.current.querySelectorAll('[data-tooltip-id]');
tooltipElements.forEach(element => {
if (element instanceof HTMLElement) {
const tooltipId = element.getAttribute('data-tooltip-id');
if (tooltipId) {
element.removeAttribute('data-tooltip-id');
requestAnimationFrame(() => {
element.setAttribute('data-tooltip-id', tooltipId);
});
}
}
});
}, PARAMETER.minimalTimeout);
return () => clearTimeout(timeoutId);
}, []);
function handleInput(event: React.KeyboardEvent<HTMLDivElement>) {
if (disabled) {
return;
@ -130,7 +100,6 @@ export function EditorConstituenta() {
return (
<div
ref={containerRef}
tabIndex={-1}
className={clsx(
'relative ',

View File

@ -1,10 +1,11 @@
'use client';
import { useLayoutEffect } from 'react';
import { useLayoutEffect, useRef } from 'react';
import { useConceptNavigation } from '@/app/navigation/navigation-context';
import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
import { useResetAttribute } from '@/hooks/use-reset-attribute';
import { useAppLayoutStore } from '@/stores/app-layout';
import { useModificationStore } from '@/stores/modification';
@ -88,6 +89,9 @@ export function RSTabs({ activeID, activeTab }: RSTabsProps) {
navigateRSForm({ tab: index as RSTabID, activeID: selectedCst.length > 0 ? selectedCst.at(-1) : undefined });
}
const containerRef = useRef<HTMLDivElement>(null);
useResetAttribute(containerRef, 'data-tooltip-id');
return (
<Tabs
selectedIndex={activeTab}
@ -104,7 +108,7 @@ export function RSTabs({ activeID, activeTab }: RSTabsProps) {
<TabLabel label='Граф' />
</TabList>
<div className='overflow-x-hidden'>
<div ref={containerRef} className='overflow-x-hidden'>
<TabPanel>
<EditorRSFormCard />
</TabPanel>

View File

@ -0,0 +1,36 @@
'use client';
import { useEffect } from 'react';
import { PARAMETER } from '@/utils/constants';
export function useResetAttribute(elementRef: React.RefObject<HTMLElement | null>, attribute: string) {
useEffect(() => {
// Trigger tooltip re-initialization after component mounts and tab becomes visible
// This ensures tooltips work when loading the page directly with this tab active
// React-tabs hides inactive panels with CSS (display: none), so react-tooltip v5
// needs to re-scan the DOM when elements become visible
const timeoutId = setTimeout(() => {
if (!elementRef.current) {
return;
}
// Force react-tooltip to re-scan by temporarily removing and re-adding data-tooltip-id
// This triggers react-tooltip's internal MutationObserver to re-register the elements
const tooltipElements = elementRef.current.querySelectorAll(`[${attribute}]`);
tooltipElements.forEach(element => {
if (element instanceof HTMLElement) {
const value = element.getAttribute(attribute);
if (value) {
element.removeAttribute(attribute);
requestAnimationFrame(() => {
element.setAttribute(attribute, value);
});
}
}
});
}, PARAMETER.minimalTimeout);
return () => clearTimeout(timeoutId);
}, [elementRef, attribute]);
}