Tooltip
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
afc072da2c
commit
6acc84fd9e
2 changed files with 98 additions and 76 deletions
|
@ -1,76 +0,0 @@
|
||||||
import React, { forwardRef, useRef } from "react";
|
|
||||||
import { useTooltipTriggerState } from "@react-stately/tooltip";
|
|
||||||
import { FocusableProvider } from "@react-aria/focus";
|
|
||||||
import { useTooltipTrigger, useTooltip } from "@react-aria/tooltip";
|
|
||||||
import { mergeProps, useObjectRef } from "@react-aria/utils";
|
|
||||||
import styles from "./Tooltip.module.css";
|
|
||||||
import classNames from "classnames";
|
|
||||||
import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays";
|
|
||||||
|
|
||||||
export const Tooltip = forwardRef(
|
|
||||||
({ position, state, className, ...props }, ref) => {
|
|
||||||
let { tooltipProps } = useTooltip(props, state);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(styles.tooltip, className)}
|
|
||||||
{...mergeProps(props, tooltipProps)}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const TooltipTrigger = forwardRef(({ children, ...rest }, ref) => {
|
|
||||||
const tooltipState = useTooltipTriggerState(rest);
|
|
||||||
const triggerRef = useObjectRef(ref);
|
|
||||||
const overlayRef = useRef();
|
|
||||||
const { triggerProps, tooltipProps } = useTooltipTrigger(
|
|
||||||
rest,
|
|
||||||
tooltipState,
|
|
||||||
triggerRef
|
|
||||||
);
|
|
||||||
|
|
||||||
const { overlayProps } = useOverlayPosition({
|
|
||||||
placement: rest.placement || "top",
|
|
||||||
targetRef: triggerRef,
|
|
||||||
overlayRef,
|
|
||||||
isOpen: tooltipState.isOpen,
|
|
||||||
offset: 5,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (
|
|
||||||
!Array.isArray(children) ||
|
|
||||||
children.length > 2 ||
|
|
||||||
typeof children[1] !== "function"
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
"TooltipTrigger must have two props. The first being a button and the second being a render prop."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [tooltipTrigger, tooltip] = children;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FocusableProvider ref={triggerRef} {...triggerProps}>
|
|
||||||
{<tooltipTrigger.type {...mergeProps(tooltipTrigger.props, rest)} />}
|
|
||||||
{tooltipState.isOpen && (
|
|
||||||
<OverlayContainer>
|
|
||||||
<Tooltip
|
|
||||||
state={tooltipState}
|
|
||||||
{...mergeProps(tooltipProps, overlayProps)}
|
|
||||||
ref={overlayRef}
|
|
||||||
>
|
|
||||||
{tooltip()}
|
|
||||||
</Tooltip>
|
|
||||||
</OverlayContainer>
|
|
||||||
)}
|
|
||||||
</FocusableProvider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
TooltipTrigger.defaultProps = {
|
|
||||||
delay: 250,
|
|
||||||
};
|
|
98
src/Tooltip.tsx
Normal file
98
src/Tooltip.tsx
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import React, {
|
||||||
|
ForwardedRef,
|
||||||
|
forwardRef,
|
||||||
|
ReactElement,
|
||||||
|
ReactNode,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
|
import {
|
||||||
|
TooltipTriggerState,
|
||||||
|
useTooltipTriggerState,
|
||||||
|
} from "@react-stately/tooltip";
|
||||||
|
import { FocusableProvider } from "@react-aria/focus";
|
||||||
|
import { useTooltipTrigger, useTooltip } from "@react-aria/tooltip";
|
||||||
|
import { mergeProps, useObjectRef } from "@react-aria/utils";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays";
|
||||||
|
import { Placement } from "@react-types/overlays";
|
||||||
|
|
||||||
|
import styles from "./Tooltip.module.css";
|
||||||
|
|
||||||
|
interface TooltipProps {
|
||||||
|
className?: string;
|
||||||
|
state: TooltipTriggerState;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
||||||
|
(
|
||||||
|
{ state, className, children, ...rest }: TooltipProps,
|
||||||
|
ref: ForwardedRef<HTMLDivElement>
|
||||||
|
) => {
|
||||||
|
const { tooltipProps } = useTooltip(rest, state);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(styles.tooltip, className)}
|
||||||
|
{...mergeProps(rest, tooltipProps)}
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
interface TooltipTriggerProps {
|
||||||
|
children: ReactElement;
|
||||||
|
placement?: Placement;
|
||||||
|
delay?: number;
|
||||||
|
tooltip: () => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TooltipTrigger = forwardRef<HTMLElement, TooltipTriggerProps>(
|
||||||
|
(
|
||||||
|
{ children, placement, tooltip, ...rest }: TooltipTriggerProps,
|
||||||
|
ref: ForwardedRef<HTMLElement>
|
||||||
|
) => {
|
||||||
|
const tooltipTriggerProps = { delay: 250, ...rest };
|
||||||
|
const tooltipState = useTooltipTriggerState(tooltipTriggerProps);
|
||||||
|
const triggerRef = useObjectRef<HTMLElement>(ref);
|
||||||
|
const overlayRef = useRef();
|
||||||
|
const { triggerProps, tooltipProps } = useTooltipTrigger(
|
||||||
|
tooltipTriggerProps,
|
||||||
|
tooltipState,
|
||||||
|
triggerRef
|
||||||
|
);
|
||||||
|
|
||||||
|
const { overlayProps } = useOverlayPosition({
|
||||||
|
placement: placement || "top",
|
||||||
|
targetRef: triggerRef,
|
||||||
|
overlayRef,
|
||||||
|
isOpen: tooltipState.isOpen,
|
||||||
|
offset: 5,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FocusableProvider ref={triggerRef} {...triggerProps}>
|
||||||
|
<children.type
|
||||||
|
{...mergeProps<typeof children.props | typeof rest>(
|
||||||
|
children.props,
|
||||||
|
rest
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{tooltipState.isOpen && (
|
||||||
|
<OverlayContainer>
|
||||||
|
<Tooltip
|
||||||
|
state={tooltipState}
|
||||||
|
ref={overlayRef}
|
||||||
|
{...mergeProps(tooltipProps, overlayProps)}
|
||||||
|
>
|
||||||
|
{tooltip()}
|
||||||
|
</Tooltip>
|
||||||
|
</OverlayContainer>
|
||||||
|
)}
|
||||||
|
</FocusableProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
Loading…
Add table
Reference in a new issue