change expand and collapse icon and fix tooltip bug

This commit is contained in:
EthanHealy01 2025-10-10 15:04:53 +01:00
parent a5c3f96664
commit 3ad837891d
3 changed files with 34 additions and 30 deletions

View File

@ -29,6 +29,10 @@ export interface TooltipProps {
pinOnClick?: boolean;
/** If true, clicking outside also closes when not pinned (default true) */
closeOnOutside?: boolean;
/** If true, tooltip interaction is disabled entirely */
disabled?: boolean;
/** If false, tooltip will not open on focus (hover only) */
openOnFocus?: boolean;
}
export const Tooltip: React.FC<TooltipProps> = ({
@ -49,6 +53,8 @@ export const Tooltip: React.FC<TooltipProps> = ({
containerStyle = {},
pinOnClick = false,
closeOnOutside = true,
disabled = false,
openOnFocus = true,
}) => {
const [internalOpen, setInternalOpen] = useState(false);
const [isPinned, setIsPinned] = useState(false);
@ -69,7 +75,7 @@ export const Tooltip: React.FC<TooltipProps> = ({
const sidebarContext = sidebarTooltip ? useSidebarContext() : null;
const isControlled = controlledOpen !== undefined;
const open = isControlled ? !!controlledOpen : internalOpen;
const open = (isControlled ? !!controlledOpen : internalOpen) && !disabled;
const setOpen = useCallback(
(newOpen: boolean) => {
@ -149,15 +155,16 @@ export const Tooltip: React.FC<TooltipProps> = ({
// === Trigger handlers ===
const openWithDelay = useCallback(() => {
clearTimers();
if (disabled) return;
openTimeoutRef.current = setTimeout(() => setOpen(true), Math.max(0, delay || 0));
}, [clearTimers, setOpen, delay]);
}, [clearTimers, setOpen, delay, disabled]);
const handlePointerEnter = useCallback(
(e: React.PointerEvent) => {
if (!isPinned) openWithDelay();
if (!isPinned && !disabled) openWithDelay();
(children.props as any)?.onPointerEnter?.(e);
},
[isPinned, openWithDelay, children.props]
[isPinned, openWithDelay, children.props, disabled]
);
const handlePointerLeave = useCallback(
@ -220,10 +227,10 @@ export const Tooltip: React.FC<TooltipProps> = ({
// Keyboard / focus accessibility
const handleFocus = useCallback(
(e: React.FocusEvent) => {
if (!isPinned) openWithDelay();
if (!isPinned && !disabled && openOnFocus) openWithDelay();
(children.props as any)?.onFocus?.(e);
},
[isPinned, openWithDelay, children.props]
[isPinned, openWithDelay, children.props, disabled, openOnFocus]
);
const handleBlur = useCallback(
@ -346,9 +353,13 @@ export const Tooltip: React.FC<TooltipProps> = ({
return (
<>
{childWithHandlers}
{portalTarget && document.body.contains(portalTarget)
? tooltipElement && createPortal(tooltipElement, portalTarget)
: tooltipElement}
{(() => {
const defaultTarget = typeof document !== 'undefined' ? document.body : null;
const target = portalTarget ?? defaultTarget;
return tooltipElement && target
? createPortal(tooltipElement, target)
: tooltipElement;
})()}
</>
);
};

View File

@ -1,6 +1,6 @@
import { useState, useRef } from 'react';
import { ActionIcon, ScrollArea, Switch, Tooltip, useMantineColorScheme } from '@mantine/core';
import ViewSidebarRoundedIcon from '@mui/icons-material/ViewSidebarRounded';
import { ActionIcon, ScrollArea, Switch, useMantineColorScheme } from '@mantine/core';
import DoubleArrowIcon from '@mui/icons-material/DoubleArrow';
import { useTranslation } from 'react-i18next';
import ToolSearch from './toolPicker/ToolSearch';
import FullscreenToolList from './FullscreenToolList';
@ -8,8 +8,10 @@ import { ToolRegistryEntry } from '../../data/toolsTaxonomy';
import { ToolId } from '../../types/toolId';
import { useFocusTrap } from '../../hooks/useFocusTrap';
import { BASE_PATH } from '../../constants/app';
import { Tooltip } from '../shared/Tooltip';
import './ToolPanel.css';
import { ToolPanelGeometry } from '../../hooks/tools/useToolPanelGeometry';
import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex';
interface FullscreenToolSurfaceProps {
searchQuery: string;
@ -103,7 +105,7 @@ const FullscreenToolSurface = ({
<img src={brandTextSrc} alt={brandAltText} className="tool-panel__fullscreen-brand-text" />
</div>
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
<Tooltip label={toggleLabel} position="bottom" withArrow>
<Tooltip content={toggleLabel} position="bottom" arrow={true} openOnFocus={false} containerStyle={{ zIndex: Z_INDEX_OVER_FULLSCREEN_SURFACE }}>
<ActionIcon
variant="subtle"
radius="xl"
@ -112,7 +114,7 @@ const FullscreenToolSurface = ({
aria-label={toggleLabel}
style={{ color: 'var(--right-rail-icon)' }}
>
<ViewSidebarRoundedIcon fontSize="small" />
<DoubleArrowIcon fontSize="small" style={{ transform: 'rotate(180deg)' }} />
</ActionIcon>
</Tooltip>
</div>

View File

@ -7,18 +7,17 @@ import ToolRenderer from './ToolRenderer';
import ToolSearch from './toolPicker/ToolSearch';
import { useSidebarContext } from "../../contexts/SidebarContext";
import rainbowStyles from '../../styles/rainbow.module.css';
import { ActionIcon, ScrollArea, Tooltip } from '@mantine/core';
import { ActionIcon, ScrollArea } from '@mantine/core';
import { ToolId } from '../../types/toolId';
import { useMediaQuery } from '@mantine/hooks';
import ViewSidebarRoundedIcon from '@mui/icons-material/ViewSidebarRounded';
import DashboardCustomizeRoundedIcon from '@mui/icons-material/DashboardCustomizeRounded';
import DoubleArrowIcon from '@mui/icons-material/DoubleArrow';
import { useTranslation } from 'react-i18next';
import FullscreenToolSurface from './FullscreenToolSurface';
import { useToolPanelGeometry } from '../../hooks/tools/useToolPanelGeometry';
import { useLocalStorageState } from '../../hooks/tools/useJsonLocalStorageState';
import { useRightRail } from '../../contexts/RightRailContext';
import { Tooltip } from '../shared/Tooltip';
import './ToolPanel.css';
import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex';
// No props needed - component uses context
@ -138,14 +137,10 @@ export default function ToolPanel() {
/>
{!isMobile && leftPanelView === 'toolPicker' && (
<Tooltip
label={toggleLabel}
position="bottom"
withArrow
styles={{
tooltip: {
zIndex: Z_INDEX_OVER_FULLSCREEN_SURFACE,
}
}}
content={toggleLabel}
position="bottom"
arrow={true}
openOnFocus={false}
>
<ActionIcon
variant="subtle"
@ -155,11 +150,7 @@ export default function ToolPanel() {
aria-label={toggleLabel}
className="tool-panel__mode-toggle"
>
{isFullscreenMode ? (
<ViewSidebarRoundedIcon fontSize="small" />
) : (
<DashboardCustomizeRoundedIcon fontSize="small" />
)}
<DoubleArrowIcon fontSize="small" />
</ActionIcon>
</Tooltip>
)}