diff --git a/packages/@mantine/core/src/components/Tooltip/Tooltip.story.tsx b/packages/@mantine/core/src/components/Tooltip/Tooltip.story.tsx index 3859ca1549..bfd717a072 100644 --- a/packages/@mantine/core/src/components/Tooltip/Tooltip.story.tsx +++ b/packages/@mantine/core/src/components/Tooltip/Tooltip.story.tsx @@ -194,15 +194,32 @@ export const WithArrowRadius = () => ( export function Inline() { return ( -
- Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vitae ipsam in quos aperiam magni - quas neque{' '} - - aliquid laboriosam dolorum - - , eum voluptate, perferendis placeat repudiandae nesciunt explicabo quibusdam deserunt, animi - dicta. -
+ <> +
+ Via inline prop: +
+ Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vitae ipsam in quos aperiam + magni quas neque{' '} + + aliquid laboriosam dolorum + + , eum voluptate, perferendis placeat repudiandae nesciunt explicabo quibusdam deserunt, + animi dicta. +
+
+
+ Via middlewares prop: +
+ Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vitae ipsam in quos aperiam + magni quas neque{' '} + + aliquid laboriosam dolorum + + , eum voluptate, perferendis placeat repudiandae nesciunt explicabo quibusdam deserunt, + animi dicta. +
+
+ ); } diff --git a/packages/@mantine/core/src/components/Tooltip/Tooltip.tsx b/packages/@mantine/core/src/components/Tooltip/Tooltip.tsx index 2f572a9ecb..db6ac07ad5 100644 --- a/packages/@mantine/core/src/components/Tooltip/Tooltip.tsx +++ b/packages/@mantine/core/src/components/Tooltip/Tooltip.tsx @@ -110,6 +110,7 @@ const defaultProps: Partial = { events: { hover: true, focus: false, touch: false }, zIndex: getDefaultZIndex('popover'), positionDependencies: [], + middlewares: { flip: true, shift: true, inline: false }, }; const varsResolver = createVarsResolver((theme, { radius, color }) => ({ @@ -162,6 +163,7 @@ export const Tooltip = factory((_props, ref) => { portalProps, mod, floatingStrategy, + middlewares, ...others } = useProps('Tooltip', defaultProps, props); @@ -181,6 +183,7 @@ export const Tooltip = factory((_props, ref) => { positionDependencies: [...positionDependencies!, children], inline, strategy: floatingStrategy, + middlewares, }); const getStyles = useStyles({ diff --git a/packages/@mantine/core/src/components/Tooltip/Tooltip.types.ts b/packages/@mantine/core/src/components/Tooltip/Tooltip.types.ts index 0c1d05d249..c91229f211 100644 --- a/packages/@mantine/core/src/components/Tooltip/Tooltip.types.ts +++ b/packages/@mantine/core/src/components/Tooltip/Tooltip.types.ts @@ -1,3 +1,4 @@ +import type { FlipOptions, InlineOptions, ShiftOptions, SizeOptions } from '@floating-ui/react'; import { BoxProps, ElementProps, MantineColor, MantineRadius, StylesApiProps } from '../../core'; import { FloatingPosition } from '../Floating'; import { PortalProps } from '../Portal'; @@ -8,6 +9,13 @@ export type TooltipCssVariables = { tooltip: '--tooltip-radius' | '--tooltip-bg' | '--tooltip-color'; }; +export interface TooltipMiddlewares { + shift?: boolean | ShiftOptions; + flip?: boolean | FlipOptions; + inline?: boolean | InlineOptions; + size?: boolean | SizeOptions; +} + export interface TooltipBaseProps extends BoxProps, StylesApiProps, @@ -44,4 +52,7 @@ export interface TooltipBaseProps /** Props to pass down to the portal when withinPortal is true */ portalProps?: Omit; + + /** Floating ui middlewares to configure position handling, `{ flip: true, shift: true, inline: false }` by default */ + middlewares?: TooltipMiddlewares; } diff --git a/packages/@mantine/core/src/components/Tooltip/use-tooltip.ts b/packages/@mantine/core/src/components/Tooltip/use-tooltip.ts index 299436ad88..67cebc24e5 100644 --- a/packages/@mantine/core/src/components/Tooltip/use-tooltip.ts +++ b/packages/@mantine/core/src/components/Tooltip/use-tooltip.ts @@ -13,6 +13,7 @@ import { useHover, useInteractions, useRole, + type Middleware, } from '@floating-ui/react'; import { useDidUpdate, useId } from '@mantine/hooks'; import { @@ -21,6 +22,7 @@ import { FloatingStrategy, useFloatingAutoUpdate, } from '../Floating'; +import { type TooltipMiddlewares } from './Tooltip.types'; import { useTooltipGroupContext } from './TooltipGroup/TooltipGroup.context'; interface UseTooltip { @@ -37,6 +39,57 @@ interface UseTooltip { positionDependencies: any[]; inline?: boolean; strategy?: FloatingStrategy; + middlewares?: TooltipMiddlewares; +} + +function getDefaultMiddlewares(middlewares: TooltipMiddlewares | undefined): TooltipMiddlewares { + if (middlewares === undefined) { + return { shift: true, flip: true }; + } + + const result = { ...middlewares }; + if (middlewares.shift === undefined) { + result.shift = true; + } + + if (middlewares.flip === undefined) { + result.flip = true; + } + + return result; +} + +function getTooltipMiddlewares(settings: UseTooltip) { + const middlewaresOptions = getDefaultMiddlewares(settings.middlewares); + const middlewares: Middleware[] = [offset(settings.offset)]; + + if (middlewaresOptions.shift) { + middlewares.push( + shift( + typeof middlewaresOptions.shift === 'boolean' + ? { padding: 8 } + : { padding: 8, ...middlewaresOptions.shift } + ) + ); + } + + if (middlewaresOptions.flip) { + middlewares.push( + typeof middlewaresOptions.flip === 'boolean' ? flip() : flip(middlewaresOptions.flip) + ); + } + + middlewares.push(arrow({ element: settings.arrowRef!, padding: settings.arrowOffset })); + + if (middlewaresOptions.inline) { + middlewares.push( + typeof middlewaresOptions.inline === 'boolean' ? inline() : inline(middlewaresOptions.inline) + ); + } else if (settings.inline) { + middlewares.push(inline()); + } + + return middlewares; } export function useTooltip(settings: UseTooltip) { @@ -72,13 +125,7 @@ export function useTooltip(settings: UseTooltip) { placement: settings.position, open: opened, onOpenChange: onChange, - middleware: [ - offset(settings.offset), - shift({ padding: 8 }), - flip(), - arrow({ element: settings.arrowRef!, padding: settings.arrowOffset }), - ...(settings.inline ? [inline()] : []), - ], + middleware: getTooltipMiddlewares(settings), }); useDelayGroup(context, { id: uid });