Skip to content

Commit

Permalink
[Tooltip] Modernize implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
atomiks committed Sep 13, 2024
1 parent f8906ef commit 47eacd8
Show file tree
Hide file tree
Showing 26 changed files with 412 additions and 515 deletions.
12 changes: 6 additions & 6 deletions docs/data/api/tooltip-root.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
"props": {
"animated": { "type": { "name": "bool" }, "default": "true" },
"closeDelay": { "type": { "name": "number" }, "default": "0" },
"defaultOpen": { "type": { "name": "bool" } },
"defaultOpen": { "type": { "name": "bool" }, "default": "false" },
"delay": { "type": { "name": "number" }, "default": "600" },
"delayType": {
"type": { "name": "enum", "description": "'hover'<br>&#124;&nbsp;'rest'" },
"default": "'rest'"
},
"followCursorAxis": {
"hoverable": { "type": { "name": "bool" }, "default": "true" },
"onOpenChange": { "type": { "name": "func" } },
"open": { "type": { "name": "bool" }, "default": "false" },
"trackCursorAxis": {
"type": {
"name": "enum",
"description": "'both'<br>&#124;&nbsp;'none'<br>&#124;&nbsp;'x'<br>&#124;&nbsp;'y'"
},
"default": "'none'"
},
"hoverable": { "type": { "name": "bool" }, "default": "true" },
"onOpenChange": { "type": { "name": "func" } },
"open": { "type": { "name": "bool" } }
}
},
"name": "TooltipRoot",
"imports": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
"collisionPadding": {
"description": "The padding between the tooltip popup element and the edges of the collision boundary to add whitespace between them to prevent them from touching."
},
"container": {
"description": "The container element to which the tooltip positioner is appended to."
},
"container": { "description": "The container element the tooltip positioner is appended to." },
"hideWhenDetached": {
"description": "Whether the tooltip popup element is hidden if it appears detached from its anchor element due to the anchor element being clipped (or hidden) from view."
},
Expand Down
12 changes: 5 additions & 7 deletions docs/data/translations/api-docs/tooltip-root/tooltip-root.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,21 @@
},
"closeDelay": { "description": "The delay in milliseconds until the tooltip popup is closed." },
"defaultOpen": {
"description": "Specifies whether the tooltip is open initially when uncontrolled."
"description": "Whether the tooltip popup is open by default. Use when uncontrolled."
},
"delay": { "description": "The delay in milliseconds until the tooltip popup is opened." },
"delayType": {
"description": "The delay type to use. <code>rest</code> means the <code>delay</code> represents how long the user&#39;s cursor must rest on the trigger before the tooltip popup is opened. <code>hover</code> means the <code>delay</code> represents how long to wait as soon as the user&#39;s cursor has entered the trigger."
},
"followCursorAxis": {
"description": "Determines which axis the tooltip should follow the cursor on."
},
"hoverable": {
"description": "Whether the user can move their cursor from the trigger to the tooltip popup without it closing."
"description": "Whether the can move their cursor from the trigger element toward the tooltip popup element without it closing using a &quot;safe polygon&quot; technique."
},
"onOpenChange": {
"description": "Callback fired when the tooltip popup is requested to be opened or closed. Use when controlled."
},
"open": {
"description": "If <code>true</code>, the tooltip popup is open. Use when controlled."
"open": { "description": "Whether the tooltip popup is open. Use when controlled." },
"trackCursorAxis": {
"description": "Determines which axis the tooltip should track the cursor on."
}
},
"classDescriptions": {}
Expand Down
39 changes: 29 additions & 10 deletions packages/mui-base/src/Tooltip/Arrow/TooltipArrow.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
'use client';
import * as React from 'react';
import PropTypes from 'prop-types';
import type { TooltipArrowOwnerState, TooltipArrowProps } from './TooltipArrow.types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useForkRef } from '../../utils/useForkRef';
import { useTooltipPositionerContext } from '../Positioner/TooltipPositionerContext';
import { useTooltipArrow } from './useTooltipArrow';
import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps';
import type { BaseUIComponentProps } from '../../utils/types';
import type { Side, Alignment } from '../../utils/useAnchorPositioning';

const customStyleHookMapping: CustomStyleHookMapping<TooltipArrow.OwnerState> = {
open(value) {
return {
'data-state': value ? 'open' : 'closed',
};
},
};

/**
* Renders an arrow that points to the center of the anchor element.
Expand All @@ -19,7 +29,7 @@ import { useTooltipArrow } from './useTooltipArrow';
* - [TooltipArrow API](https://base-ui.netlify.app/components/react-tooltip/#api-reference-TooltipArrow)
*/
const TooltipArrow = React.forwardRef(function TooltipArrow(
props: TooltipArrowProps,
props: TooltipArrow.Props,
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const { className, render, hideWhenUncentered = false, ...otherProps } = props;
Expand All @@ -32,7 +42,7 @@ const TooltipArrow = React.forwardRef(function TooltipArrow(
hidden: hideWhenUncentered && arrowUncentered,
});

const ownerState: TooltipArrowOwnerState = React.useMemo(
const ownerState: TooltipArrow.OwnerState = React.useMemo(
() => ({
open,
side,
Expand All @@ -50,18 +60,27 @@ const TooltipArrow = React.forwardRef(function TooltipArrow(
className,
ref: mergedRef,
extraProps: otherProps,
customStyleHookMapping: {
open(value) {
return {
'data-state': value ? 'open' : 'closed',
};
},
},
customStyleHookMapping,
});

return renderElement();
});

namespace TooltipArrow {
export interface OwnerState {
open: boolean;
side: Side;
alignment: Alignment;
}
export interface Props extends BaseUIComponentProps<'div', OwnerState> {
/**
* If `true`, the arrow will be hidden when it can't point to the center of the anchor element.
* @default false
*/
hideWhenUncentered?: boolean;
}
}

TooltipArrow.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
Expand Down
16 changes: 0 additions & 16 deletions packages/mui-base/src/Tooltip/Arrow/TooltipArrow.types.ts

This file was deleted.

27 changes: 18 additions & 9 deletions packages/mui-base/src/Tooltip/Arrow/useTooltipArrow.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
'use client';
import * as React from 'react';
import { mergeReactProps } from '../../utils/mergeReactProps';
import type {
UseTooltipArrowParameters,
UseTooltipArrowReturnValue,
} from './useTooltipArrow.types';
import type { GenericHTMLProps } from '../../utils/types';

export function useTooltipArrow(params: UseTooltipArrowParameters): UseTooltipArrowReturnValue {
const { arrowStyles } = params;
export function useTooltipArrow(params: useTooltipArrow.Parameters): useTooltipArrow.ReturnValue {
const { arrowStyles, hidden } = params;

const getArrowProps = React.useCallback(
(externalProps = {}) => {
return mergeReactProps<'div'>(externalProps, {
style: arrowStyles,
style: {
...arrowStyles,
...(hidden && { visibility: 'hidden' }),
},
});
},
[arrowStyles],
[arrowStyles, hidden],
);

return React.useMemo(
Expand All @@ -25,3 +24,13 @@ export function useTooltipArrow(params: UseTooltipArrowParameters): UseTooltipAr
[getArrowProps],
);
}

namespace useTooltipArrow {
export interface Parameters {
arrowStyles: React.CSSProperties;
hidden?: boolean;
}
export interface ReturnValue {
getArrowProps: (props?: GenericHTMLProps) => GenericHTMLProps;
}
}
11 changes: 0 additions & 11 deletions packages/mui-base/src/Tooltip/Arrow/useTooltipArrow.types.ts

This file was deleted.

26 changes: 17 additions & 9 deletions packages/mui-base/src/Tooltip/Popup/TooltipPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client';
import * as React from 'react';
import PropTypes from 'prop-types';
import type { TooltipPopupOwnerState, TooltipPopupProps } from './TooltipPopup.types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useTooltipRootContext } from '../Root/TooltipRootContext';
import { useTooltipPositionerContext } from '../Positioner/TooltipPositionerContext';
import { useTooltipPopup } from './useTooltipPopup';
import { useForkRef } from '../../utils/useForkRef';
import type { BaseUIComponentProps } from '../../utils/types';
import type { Alignment, Side } from '../../utils/useAnchorPositioning';

/**
* The tooltip popup element.
Expand All @@ -20,7 +20,7 @@ import { useForkRef } from '../../utils/useForkRef';
* - [TooltipPopup API](https://base-ui.netlify.app/components/react-tooltip/#api-reference-TooltipPopup)
*/
const TooltipPopup = React.forwardRef(function TooltipPopup(
props: TooltipPopupProps,
props: TooltipPopup.Props,
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const { className, render, ...otherProps } = props;
Expand All @@ -29,11 +29,7 @@ const TooltipPopup = React.forwardRef(function TooltipPopup(
useTooltipRootContext();
const { side, alignment } = useTooltipPositionerContext();

const { getPopupProps } = useTooltipPopup({
getProps: getRootPopupProps,
});

const ownerState: TooltipPopupOwnerState = React.useMemo(
const ownerState: TooltipPopup.OwnerState = React.useMemo(
() => ({
open,
side,
Expand All @@ -50,7 +46,7 @@ const TooltipPopup = React.forwardRef(function TooltipPopup(
// The content element needs to be a child of a wrapper floating element in order to avoid
// conflicts with CSS transitions and the positioning transform.
const { renderElement } = useComponentRenderer({
propGetter: getPopupProps,
propGetter: getRootPopupProps,
render: render ?? 'div',
className,
ownerState,
Expand All @@ -74,6 +70,18 @@ const TooltipPopup = React.forwardRef(function TooltipPopup(
return renderElement();
});

namespace TooltipPopup {
export interface OwnerState {
open: boolean;
side: Side;
alignment: Alignment;
instant: 'delay' | 'focus' | 'dismiss' | undefined;
entering: boolean;
exiting: boolean;
}
export interface Props extends BaseUIComponentProps<'div', OwnerState> {}
}

TooltipPopup.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
Expand Down
13 changes: 0 additions & 13 deletions packages/mui-base/src/Tooltip/Popup/TooltipPopup.types.ts

This file was deleted.

30 changes: 0 additions & 30 deletions packages/mui-base/src/Tooltip/Popup/useTooltipPopup.ts

This file was deleted.

9 changes: 0 additions & 9 deletions packages/mui-base/src/Tooltip/Popup/useTooltipPopup.types.ts

This file was deleted.

Loading

0 comments on commit 47eacd8

Please sign in to comment.