From f9a6be5d2b3517aa877b1c7632799f8ae953fb74 Mon Sep 17 00:00:00 2001 From: literat Date: Tue, 23 Jul 2024 09:50:09 +0200 Subject: [PATCH] Feat(web-react): Introduce `positionStrategy` prop for Tooltip CSS positions * @see: https://floating-ui.com/docs/usefloating#strategy --- .../src/components/Tooltip/README.md | 34 ++++++++++--------- .../src/components/Tooltip/Tooltip.tsx | 2 ++ .../src/components/Tooltip/useFloating.ts | 4 +++ packages/web-react/src/types/tooltip.ts | 3 +- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/web-react/src/components/Tooltip/README.md b/packages/web-react/src/components/Tooltip/README.md index ef6851cab5..6de7da70bb 100644 --- a/packages/web-react/src/components/Tooltip/README.md +++ b/packages/web-react/src/components/Tooltip/README.md @@ -57,22 +57,23 @@ const [open, setOpen] = React.useState(false); ## API -| Attribute | Type | Default | Required | Description | -| ------------------------------- | -------------------------------------------- | ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `children` | `ReactNode` | — | ✓ | Tooltip children's nodes - `TooltipTrigger` and `TooltipPopover` | -| `enableFlipping` | `bool` | true | ✕ | Enables [flipping][floating-ui-flip] of the element’s placement when it starts to overflow its boundary area. For example `top` can be flipped to `bottom`. | -| `enableFlippingCrossAxis` | `bool` | true | ✕ | Enables flipping on the [cross axis][floating-ui-flip-cross-axis], the axis perpendicular to main axis. For example `top-end` can be flipped to the `top-start`. | -| `enableShifting` | `bool` | true | ✕ | Enables [shifting][floating-ui-shift] of the element to keep it inside the boundary area by adjusting its position. | -| `enableSizing` | `bool` | true | ✕ | Enables [sizing][floating-ui-size] of the element to keep it inside the boundary area by setting the max width. | -| `flipFallbackAxisSideDirection` | ["none" \| "start" \| "end"] | "none" | ✕ | Whether to allow [fallback to the opposite axis][floating-ui-flip-fallback-axis-side-direction] if no placements along the preferred placement axis fit, and if so, which side direction along that axis to choose. If necessary, it will fallback to the other direction. | -| `flipFallbackPlacements` | `string` | - | ✕ | This describes a list of [explicit placements][floating-ui-flip-fallback-placements] to try if the initial placement doesn’t fit on the axes in which overflow is checked. For example you can set `"top, right, bottom"` | -| `id` | `string` | - | ✓ | Tooltip id | -| `isDismissible` | `bool` | false | ✕ | Make tooltip dismissible | -| `isOpen` | `bool` | - | ✓ | Open state | -| `onToggle` | `() => void` | - | ✓ | Function for toggle open state of dropdown | -| `placement` | [Placement Dictionary][dictionary-placement] | "bottom" | ✕ | Placement of tooltip | -| `isFocusableOnHover` | `bool` | false | ✕ | Allows you to mouse over a tooltip without closing it. We suggest turning off the `click` trigger if you use this feature. | -| `trigger` | ["click" \| "hover" \| "manual"] | ["click", "hover" ] | ✕ | How tooltip is triggered: `click`, `hover`, `manual`. You may pass multiple triggers. If you pass `manual`, there will be no toggle functionality and you should provide your own toggle solution. | +| Attribute | Type | Default | Required | Description | +| ------------------------------- | ---------------------------------------------------------------- | ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `children` | `ReactNode` | — | ✓ | Tooltip children's nodes - `TooltipTrigger` and `TooltipPopover` | +| `enableFlipping` | `bool` | true | ✕ | Enables [flipping][floating-ui-flip] of the element’s placement when it starts to overflow its boundary area. For example `top` can be flipped to `bottom`. | +| `enableFlippingCrossAxis` | `bool` | true | ✕ | Enables flipping on the [cross axis][floating-ui-flip-cross-axis], the axis perpendicular to main axis. For example `top-end` can be flipped to the `top-start`. | +| `enableShifting` | `bool` | true | ✕ | Enables [shifting][floating-ui-shift] of the element to keep it inside the boundary area by adjusting its position. | +| `enableSizing` | `bool` | true | ✕ | Enables [sizing][floating-ui-size] of the element to keep it inside the boundary area by setting the max width. | +| `flipFallbackAxisSideDirection` | [`none` \| `start` \| `end`] | "none" | ✕ | Whether to allow [fallback to the opposite axis][floating-ui-flip-fallback-axis-side-direction] if no placements along the preferred placement axis fit, and if so, which side direction along that axis to choose. If necessary, it will fallback to the other direction. | +| `flipFallbackPlacements` | `string` | - | ✕ | This describes a list of [explicit placements][floating-ui-flip-fallback-placements] to try if the initial placement doesn’t fit on the axes in which overflow is checked. For example you can set `"top, right, bottom"` | +| `id` | `string` | - | ✓ | Tooltip id | +| `isDismissible` | `bool` | false | ✕ | Make tooltip dismissible | +| `isOpen` | `bool` | - | ✓ | Open state | +| `onToggle` | `() => void` | - | ✓ | Function for toggle open state of dropdown | +| `placement` | [Placement Dictionary][dictionary-placement] | "bottom" | ✕ | Placement of tooltip | +| `positionStrategy` | [`absolute` \| `fixed`] ([Strategy type][use-floating-strategy]) | "absolute" | ✕ | This is the type of CSS position property to use. | +| `isFocusableOnHover` | `bool` | false | ✕ | Allows you to mouse over a tooltip without closing it. We suggest turning off the `click` trigger if you use this feature. | +| `trigger` | [`click` \| `hover` \| `manual`] | ["click", "hover" ] | ✕ | How tooltip is triggered: `click`, `hover`, `manual`. You may pass multiple triggers. If you pass `manual`, there will be no toggle functionality and you should provide your own toggle solution. | On top of the API options, the components accept [additional attributes][readme-additional-attributes]. If you need more control over the styling of a component, you can use [style props][readme-style-props] @@ -88,3 +89,4 @@ and [escape hatches][readme-escape-hatches]. [readme-additional-attributes]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#additional-attributes [readme-escape-hatches]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#escape-hatches [readme-style-props]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#style-props +[use-floating-strategy]: https://floating-ui.com/docs/usefloating#strategy diff --git a/packages/web-react/src/components/Tooltip/Tooltip.tsx b/packages/web-react/src/components/Tooltip/Tooltip.tsx index 519a130c64..923db8c1e2 100644 --- a/packages/web-react/src/components/Tooltip/Tooltip.tsx +++ b/packages/web-react/src/components/Tooltip/Tooltip.tsx @@ -21,6 +21,7 @@ const Tooltip = (props: SpiritTooltipProps) => { isOpen = false, onToggle, placement: tooltipPlacement, + positionStrategy = 'absolute', trigger = ['click', 'hover'], ...restProps } = props; @@ -70,6 +71,7 @@ const Tooltip = (props: SpiritTooltipProps) => { onToggle, shiftProp, sizeProp, + positionStrategy, tooltipArrowWidth, tooltipMaxWidth, tooltipPlacement, diff --git a/packages/web-react/src/components/Tooltip/useFloating.ts b/packages/web-react/src/components/Tooltip/useFloating.ts index 0fae3d1767..faed2f1d42 100644 --- a/packages/web-react/src/components/Tooltip/useFloating.ts +++ b/packages/web-react/src/components/Tooltip/useFloating.ts @@ -1,5 +1,6 @@ import { Placement, + Strategy, arrow, autoUpdate, flip, @@ -33,6 +34,7 @@ type UseTooltipUIProps = { isFocusableOnHover?: boolean; shiftProp: boolean; sizeProp: boolean; + positionStrategy?: Strategy; tooltipArrowWidth?: number; tooltipMaxWidth?: number; tooltipPlacement?: Placement; @@ -58,6 +60,7 @@ export const useFloating = (props: UseTooltipUIProps) => { isFocusableOnHover, shiftProp, sizeProp, + positionStrategy = 'absolute', tooltipArrowWidth = 0, tooltipPlacement, trigger, @@ -133,6 +136,7 @@ export const useFloating = (props: UseTooltipUIProps) => { }), arrow({ element: arrowRef.current, padding: cornerOffset }), // should be the last middleware ], + strategy: positionStrategy, }); // Floating UI library interaction hooks diff --git a/packages/web-react/src/types/tooltip.ts b/packages/web-react/src/types/tooltip.ts index 7883d492e1..f961b7d2c1 100644 --- a/packages/web-react/src/types/tooltip.ts +++ b/packages/web-react/src/types/tooltip.ts @@ -1,4 +1,4 @@ -import { Placement } from '@floating-ui/react'; +import { Placement, Strategy } from '@floating-ui/react'; import { ChildrenProps, ClickEvent, StyleProps } from './shared'; export const TOOLTIP_TRIGGER = { @@ -40,5 +40,6 @@ export interface SpiritTooltipProps extends TooltipProps, ChildrenProps { flipFallbackAxisSideDirection?: 'none' | 'start' | 'end'; flipFallbackPlacements?: Placement | Placement[]; isFocusableOnHover?: boolean; + positionStrategy?: Strategy; trigger?: TooltipTriggerType[]; }