Files
dydx-v4-web/src/components/WithTooltip.tsx
T
Bill 8d3cc76d14 Configurable URLs (#107)
* Configurable URLs

* add learnmore to tooltip

* Learnmore -> LearnMore
2023-10-31 11:02:45 -07:00

162 lines
3.8 KiB
TypeScript

import type { ReactNode } from 'react';
import styled, { AnyStyledComponent } from 'styled-components';
import { Content, Portal, Provider, Root, Trigger, Arrow } from '@radix-ui/react-tooltip';
import { STRING_KEYS } from '@/constants/localization';
import { tooltipStrings } from '@/constants/tooltips';
import { useStringGetter, useURLConfigs } from '@/hooks';
import { Icon, IconName } from '@/components/Icon';
import { Link } from '@/components/Link';
import { layoutMixins } from '@/styles/layoutMixins';
import { popoverMixins } from '@/styles/popoverMixins';
type ElementProps = {
tooltip?: keyof typeof tooltipStrings;
tooltipString?: string;
stringParams?: Record<string, string>;
withIcon?: boolean;
children?: ReactNode;
slotTooltip?: ReactNode;
};
type StyleProps = {
align?: 'start' | 'center' | 'end';
side?: 'top' | 'right' | 'bottom' | 'left';
className?: string;
};
export const WithTooltip = ({
tooltip,
tooltipString,
stringParams,
withIcon,
children,
align,
side,
className,
slotTooltip,
}: ElementProps & StyleProps) => {
const stringGetter = useStringGetter();
const urlConfigs = useURLConfigs();
const getTooltipStrings = tooltip && tooltipStrings[tooltip];
if (!getTooltipStrings && !tooltipString && !slotTooltip) return <>{children}</>;
let tooltipTitle;
let tooltipBody;
let tooltipLearnMore;
if (getTooltipStrings) {
const { title, body, learnMoreLink } = getTooltipStrings({
stringGetter,
stringParams,
urlConfigs,
});
tooltipTitle = title;
tooltipBody = body;
tooltipLearnMore = learnMoreLink;
} else {
tooltipBody = tooltipString;
}
return (
<Provider>
<Root delayDuration={300}>
<Trigger asChild>
<Styled.Abbr>
{children}
{withIcon && <Styled.Icon iconName={IconName.HelpCircle} />}
</Styled.Abbr>
</Trigger>
<Portal>
<Styled.Content sideOffset={8} side={side} align={align} className={className} asChild>
{slotTooltip ?? (
<dl>
{tooltipTitle && <dt>{tooltipTitle}</dt>}
{tooltipBody && <dd>{tooltipBody}</dd>}
{tooltipLearnMore && (
<dd>
<Styled.LearnMore href={tooltipLearnMore}>
{stringGetter({ key: STRING_KEYS.LEARN_MORE })}
</Styled.LearnMore>
</dd>
)}
<Styled.Arrow />
</dl>
)}
</Styled.Content>
</Portal>
</Root>
</Provider>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Abbr = styled.abbr`
${layoutMixins.inlineRow}
text-decoration: underline dashed 0px;
text-underline-position: under;
text-decoration-color: var(--color-text-0);
text-decoration-skip-ink: all;
cursor: help;
`;
Styled.Content = styled(Content)`
--tooltip-backgroundColor: var(--color-layer-4);
--tooltip-backgroundColor: hsl(
var(--layer-base-hue),
var(--layer-base-saturation),
calc(var(--layer-base-lightness) + 4%),
0.66
);
${popoverMixins.popover}
--popover-backgroundColor: var(--tooltip-backgroundColor);
--popover-textColor: var(--color-text-1);
${popoverMixins.popoverAnimation}
--popover-closed-height: auto;
max-width: 30ch;
display: grid;
align-items: end;
gap: 0.25rem;
padding: 0.75em;
font-size: 0.8125em;
border-radius: 0.33em;
dt {
font: var(--font-small-book);
}
dd {
font: var(--font-mini-book);
}
`;
Styled.Arrow = styled(Arrow)`
width: 0.75rem;
height: 0.375rem;
polygon {
fill: var(--tooltip-backgroundColor);
}
`;
Styled.Icon = styled(Icon)`
color: var(--color-text-0);
`;
Styled.LearnMore = styled(Link)`
--link-color: var(--color-accent);
`;