diff --git a/docs/docs/options.mdx b/docs/docs/options.mdx index f4b265606..2bd54d5b4 100644 --- a/docs/docs/options.mdx +++ b/docs/docs/options.mdx @@ -49,25 +49,26 @@ import 'react-tooltip/dist/react-tooltip.css' #### Available props -| name | type | required | default | values | description | -| -------------- | -------------------- | -------- | ------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| className | string | false | | | class name to customize tooltip element | -| classNameArrow | string | false | | | class name to customize tooltip arrow element | -| content | string | false | | | content to de displayed in tooltip (`content` prop is priorized over `html`) | -| html | string | false | | | html content to de displayed in tooltip | -| place | string | false | `top` | `top` `right` `bottom` `left` | place related to anchor element where the tooltip will be rendered if possible | -| offset | number | false | `10` | any `number` | space between the tooltip element and anchor element (arrow not included in calc) | -| id | string | false | React `useId` | any `string` | option to set a specific id into the tooltip element, the default value is handled by React `useId` introduced on React 18 | -| anchorId | string | false | `undefined` | any `string` | id reference from the element that the tooltip will be positioned around | -| variant | string | false | `dark` | `dark` `light` `success` `warning` `error` `info` | change the colors of tooltip with pre-defined values | -| wrapper | valid element | false | `div` | `ElementType` `div` `span` | element wrapper of tooltip container, can be `div`, `span` or any valid Element | -| children | valid React children | false | `undefined` | valid React children | content can be pass through props, data-attributes or as children, children will be priorized over other options | -| events | array | false | `hover` | `hover` `click` | pre-defined events to handle show or hide tooltip | -| delayShow | number | false | | any `number` | tooltip show will be delayed in miliseconds by the amount of value | -| delayHide | number | false | | any `number` | tooltip hide will be delayed in miliseconds by the amount of value | -| getContent | function | false | | (value: string) => string | a method available to parse, format or modify the given content of tooltip before show it | -| isOpen | boolen | false | handled by internal state | `true` `false` | the tooltip can be controlled or uncontrolled, this attribute can be used to handle show and hide tooltip outside tooltip (can be used **without** `setIsOpen`) | -| setIsOpen | function | false | | | the tooltip can be controlled or uncontrolled, this attribute can be used to handle show and hide tooltip outside tooltip | +| name | type | required | default | values | description | +| ---------------- | -------------------- | -------- | ------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| className | string | false | | | class name to customize tooltip element | +| classNameArrow | string | false | | | class name to customize tooltip arrow element | +| content | string | false | | | content to de displayed in tooltip (`content` prop is priorized over `html`) | +| html | string | false | | | html content to de displayed in tooltip | +| place | string | false | `top` | `top` `right` `bottom` `left` | place related to anchor element where the tooltip will be rendered if possible | +| offset | number | false | `10` | any `number` | space between the tooltip element and anchor element (arrow not included in calc) | +| id | string | false | React `useId` | any `string` | option to set a specific id into the tooltip element, the default value is handled by React `useId` introduced on React 18 | +| anchorId | string | false | `undefined` | any `string` | id reference from the element that the tooltip will be positioned around | +| variant | string | false | `dark` | `dark` `light` `success` `warning` `error` `info` | change the colors of tooltip with pre-defined values | +| wrapper | valid element | false | `div` | `ElementType` `div` `span` | element wrapper of tooltip container, can be `div`, `span` or any valid Element | +| children | valid React children | false | `undefined` | valid React children | content can be pass through props, data-attributes or as children, children will be priorized over other options | +| events | array | false | `hover` | `hover` `click` | pre-defined events to handle show or hide tooltip | +| positionStrategy | string | false | `absolute` | `absolute` `fixed` | the position strategy used for the tooltip. set to `fixed` if you run into issues with `overflow: hidden` on the tooltip parent container | +| delayShow | number | false | | any `number` | tooltip show will be delayed in miliseconds by the amount of value | +| delayHide | number | false | | any `number` | tooltip hide will be delayed in miliseconds by the amount of value | +| getContent | function | false | | (value: string) => string | a method available to parse, format or modify the given content of tooltip before show it | +| isOpen | boolen | false | handled by internal state | `true` `false` | the tooltip can be controlled or uncontrolled, this attribute can be used to handle show and hide tooltip outside tooltip (can be used **without** `setIsOpen`) | +| setIsOpen | function | false | | | the tooltip can be controlled or uncontrolled, this attribute can be used to handle show and hide tooltip outside tooltip | ### Data attributes @@ -87,17 +88,18 @@ import 'react-tooltip/dist/react-tooltip.css'; #### Available attributes -| name | type | required | default | values | description | -| -------------------- | ------ | -------- | ------- | ------------------------------------------------- | --------------------------------------------------------------------------------- | -| data-tooltip-content | string | false | | | content to de displayed in tooltip (`content` prop is priorized over `html`) | -| data-tooltip-html | string | false | | | html content to de displayed in tooltip | -| data-tooltip-place | string | false | `top` | `top` `right` `bottom` `left` | place related to anchor element where the tooltip will be rendered if possible | -| data-tooltip-offset | number | false | `10` | any `number` | space between the tooltip element and anchor element (arrow not included in calc) | -| data-tooltip-variant | string | false | `dark` | `dark` `light` `success` `warning` `error` `info` | change the colors of tooltip with pre-defined values | -| data-tooltip-wrapper | string | false | `div` | `div` `span` | element wrapper of tooltip container, can be `div`, `span` or any valid Element | -| data-tooltip-events | string | false | `hover` | `hover click` `hover` `click` | pre-defined events to handle show or hide tooltip | -| data-tooltip-show | number | false | | any `number` | tooltip show will be delayed in miliseconds by the amount of value | -| data-tooltip-hide | number | false | | any `number` | tooltip hide will be delayed in miliseconds by the amount of value | +| name | type | required | default | values | description | +| ------------------------------ | ------ | -------- | ---------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| data-tooltip-content | string | false | | | content to de displayed in tooltip (`content` prop is priorized over `html`) | +| data-tooltip-html | string | false | | | html content to de displayed in tooltip | +| data-tooltip-place | string | false | `top` | `top` `right` `bottom` `left` | place related to anchor element where the tooltip will be rendered if possible | +| data-tooltip-offset | number | false | `10` | any `number` | space between the tooltip element and anchor element (arrow not included in calc) | +| data-tooltip-variant | string | false | `dark` | `dark` `light` `success` `warning` `error` `info` | change the colors of tooltip with pre-defined values | +| data-tooltip-wrapper | string | false | `div` | `div` `span` | element wrapper of tooltip container, can be `div`, `span` or any valid Element | +| data-tooltip-events | string | false | `hover` | `hover click` `hover` `click` | pre-defined events to handle show or hide tooltip | +| data-tooltip-position-strategy | string | false | `absolute` | `absolute` `fixed` | the position strategy used for the tooltip. set to `fixed` if you run into issues with `overflow: hidden` on the tooltip parent container | +| data-tooltip-show | number | false | | any `number` | tooltip show will be delayed in miliseconds by the amount of value | +| data-tooltip-hide | number | false | | any `number` | tooltip hide will be delayed in miliseconds by the amount of value | #### Observations diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 67a6d3ee7..64ba07744 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -16,6 +16,7 @@ const Tooltip = ({ place = 'top', offset = 10, events = ['hover'], + positionStrategy = 'absolute', wrapper: WrapperElement = 'div', children = null, delayShow = 0, @@ -148,6 +149,7 @@ const Tooltip = ({ elementReference, tooltipReference: tooltipRef.current as HTMLElement, tooltipArrowReference: tooltipArrowRef.current as HTMLElement, + strategy: positionStrategy, }).then((computedStylesData) => { if (Object.keys(computedStylesData.tooltipStyles).length) { setInlineStyles(computedStylesData.tooltipStyles) @@ -170,6 +172,7 @@ const Tooltip = ({ role="tooltip" className={classNames(styles['tooltip'], styles[variant], className, { [styles['show']]: isOpen || show, + [styles['fixed']]: positionStrategy === 'fixed', })} style={inlineStyles} ref={tooltipRef as React.RefObject} diff --git a/src/components/Tooltip/TooltipTypes.d.ts b/src/components/Tooltip/TooltipTypes.d.ts index 1e9252cf2..73df7538d 100644 --- a/src/components/Tooltip/TooltipTypes.d.ts +++ b/src/components/Tooltip/TooltipTypes.d.ts @@ -10,6 +10,8 @@ export type ChildrenType = Element | ElementType | ReactNode export type EventsType = 'hover' | 'click' +export type PositionStrategy = 'absolute' | 'fixed' + export interface ITooltip { className?: string classNameArrow?: string @@ -24,6 +26,7 @@ export interface ITooltip { wrapper?: WrapperType children?: ChildrenType events?: EventsType[] + positionStrategy?: PositionStrategy delayShow?: number delayHide?: number isOpen?: boolean diff --git a/src/components/Tooltip/styles.module.css b/src/components/Tooltip/styles.module.css index f63b5dfc8..29833fa30 100644 --- a/src/components/Tooltip/styles.module.css +++ b/src/components/Tooltip/styles.module.css @@ -13,6 +13,10 @@ will-change: opacity, visibility; } +.fixed { + position: fixed; +} + .arrow { position: absolute; background: var(--rt-color-dark); diff --git a/src/components/TooltipController/TooltipController.tsx b/src/components/TooltipController/TooltipController.tsx index 79e322341..15ea6366b 100644 --- a/src/components/TooltipController/TooltipController.tsx +++ b/src/components/TooltipController/TooltipController.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react' import { Tooltip } from 'components/Tooltip' import type { EventsType, + PositionStrategy, PlacesType, VariantType, WrapperType, @@ -22,6 +23,7 @@ const TooltipController = ({ wrapper = 'div', children = null, events = ['hover'], + positionStrategy = 'absolute', delayShow = 0, delayHide = 0, getContent, @@ -36,6 +38,8 @@ const TooltipController = ({ const [tooltipDelayHide, setTooltipDelayHide] = useState(delayHide) const [tooltipWrapper, setTooltipWrapper] = useState(wrapper) const [tooltipEvents, setTooltipEvents] = useState(events) + const [tooltipPositionStrategy, setTooltipPositionStrategy] = + useState(positionStrategy) const [isHtmlContent, setIsHtmlContent] = useState(Boolean(html)) const getDataAttributesFromAnchorElement = (elementReference: HTMLElement) => { @@ -89,6 +93,9 @@ const TooltipController = ({ const parsedEvents = value.split(' ') setTooltipEvents(parsedEvents as EventsType[]) }, + positionStrategy: (value: PositionStrategy) => { + setTooltipPositionStrategy(value) + }, 'delay-show': (value: number) => { setTooltipDelayShow(Number(value)) }, @@ -181,6 +188,7 @@ const TooltipController = ({ offset: tooltipOffset, wrapper: tooltipWrapper, events: tooltipEvents, + positionStrategy: tooltipPositionStrategy, delayShow: tooltipDelayShow, delayHide: tooltipDelayHide, isOpen, diff --git a/src/components/TooltipController/TooltipControllerTypes.d.ts b/src/components/TooltipController/TooltipControllerTypes.d.ts index b077afd56..2537575e4 100644 --- a/src/components/TooltipController/TooltipControllerTypes.d.ts +++ b/src/components/TooltipController/TooltipControllerTypes.d.ts @@ -4,6 +4,7 @@ import type { WrapperType, ChildrenType, EventsType, + PositionStrategy, } from 'components/Tooltip/TooltipTypes' export interface ITooltipController { @@ -19,6 +20,7 @@ export interface ITooltipController { wrapper?: WrapperType children?: ChildrenType events?: EventsType[] + positionStrategy?: PositionStrategy delayShow?: number delayHide?: number getContent?: function diff --git a/src/utils/compute-positions-types.d.ts b/src/utils/compute-positions-types.d.ts index 49b1ef0dc..79cfc3d65 100644 --- a/src/utils/compute-positions-types.d.ts +++ b/src/utils/compute-positions-types.d.ts @@ -4,4 +4,5 @@ export interface IComputePositions { tooltipArrowReference?: Element | HTMLElement | null place?: 'top' | 'right' | 'bottom' | 'left' offset?: number + strategy?: 'absolute' | 'fixed' } diff --git a/src/utils/compute-positions.ts b/src/utils/compute-positions.ts index 43222b8ea..bedc64624 100644 --- a/src/utils/compute-positions.ts +++ b/src/utils/compute-positions.ts @@ -7,6 +7,7 @@ export const computeToolTipPosition = async ({ tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, + strategy = 'absolute', }: IComputePositions) => { if (!elementReference) { // elementReference can be null or undefined and we will not compute the position @@ -23,9 +24,9 @@ export const computeToolTipPosition = async ({ if (tooltipArrowReference) { middleware.push(arrow({ element: tooltipArrowReference as HTMLElement })) - return computePosition(elementReference as HTMLElement, tooltipReference as HTMLElement, { placement: place, + strategy, middleware, }).then(({ x, y, placement, middlewareData }) => { const styles = { left: `${x}px`, top: `${y}px` } @@ -55,6 +56,7 @@ export const computeToolTipPosition = async ({ return computePosition(elementReference as HTMLElement, tooltipReference as HTMLElement, { placement: 'bottom', + strategy, middleware, }).then(({ x, y }) => { const styles = { left: `${x}px`, top: `${y}px` }