@kiwicom/orbit-components
Version:
Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.
93 lines (90 loc) • 3.42 kB
JavaScript
import React, { useState, useRef, useMemo, useCallback } from "react";
import styled, { css } from "styled-components";
import { getBreakpointWidth } from "../utils/mediaQuery";
import { SIZE_OPTIONS } from "./consts";
import { StyledText } from "../Text";
import Portal from "../Portal";
import RandomID from "../utils/randomID";
import { QUERIES } from "../utils/mediaQuery/consts";
import useTheme from "../hooks/useTheme";
import TooltipContent from "./components/TooltipContent";
import useStateWithTimeout from "../hooks/useStateWithTimeout";
const StyledTooltipChildren = styled.span.withConfig({
displayName: "Tooltip__StyledTooltipChildren",
componentId: "sc-1l15bi-0"
})(["display:inline-flex;&:focus:active{outline:none;}", ";"], ({
enabled,
removeUnderlinedText
}) => enabled && !removeUnderlinedText && css(["", "{display:inline-block;text-decoration:underline;text-decoration:underline currentColor dotted;}"], StyledText));
const Tooltip = ({
children,
enabled = true,
tabIndex = "0",
dataTest,
size = SIZE_OPTIONS.SMALL,
content,
preferredPosition,
stopPropagation = false,
removeUnderlinedText
}) => {
const theme = useTheme();
const [shown, setShown] = useState(false);
const [render, setRender, setRenderWithTimeout, clearRenderTimeout] = useStateWithTimeout(false, 200);
const [shownMobile, setShownMobile, setShownMobileWithTimeout] = useStateWithTimeout(false, 200);
const tooltipId = useMemo(() => RandomID("tooltip"), []);
const container = useRef(null);
const handleIn = useCallback(() => {
if (window.innerWidth > +getBreakpointWidth(QUERIES.LARGEMOBILE, theme, true)) {
setRender(true);
setShown(true);
clearRenderTimeout();
}
}, [clearRenderTimeout, setRender, theme]);
const handleOut = useCallback(() => {
if (window.innerWidth > +getBreakpointWidth(QUERIES.LARGEMOBILE, theme, true)) {
setShown(false);
setRenderWithTimeout(false);
}
}, [setRenderWithTimeout, theme]);
const handleInMobile = useCallback(ev => {
if (stopPropagation) {
ev.stopPropagation();
}
if (window.innerWidth <= +getBreakpointWidth(QUERIES.LARGEMOBILE, theme, true)) {
ev.preventDefault();
setRender(true);
setShownMobileWithTimeout(true);
clearRenderTimeout();
}
}, [clearRenderTimeout, setRender, setShownMobileWithTimeout, stopPropagation, theme]);
const handleOutMobile = useCallback(() => {
setShownMobile(false);
setRenderWithTimeout(false);
}, [setRenderWithTimeout, setShownMobile]);
return React.createElement(React.Fragment, null, React.createElement(StyledTooltipChildren, {
onMouseEnter: handleIn,
onMouseLeave: handleOut,
onClick: handleInMobile,
onFocus: handleIn,
onBlur: handleOut,
ref: container,
"aria-describedby": enabled ? tooltipId : undefined,
tabIndex: enabled ? tabIndex : undefined,
enabled: enabled,
removeUnderlinedText: removeUnderlinedText
}, children), enabled && render && React.createElement(Portal, {
renderInto: "tooltips"
}, React.createElement(TooltipContent, {
dataTest: dataTest,
shownMobile: shownMobile,
shown: shown,
size: size,
tooltipId: tooltipId,
onClose: handleOut,
onCloseMobile: handleOutMobile,
onEnter: handleIn,
preferredPosition: preferredPosition,
containerRef: container
}, content)));
};
export default Tooltip;