Skip to content

Commit 2368c5f

Browse files
committed
style: tooltips
1 parent 076579b commit 2368c5f

9 files changed

Lines changed: 43 additions & 40 deletions

File tree

packages/web/src/common/constants/web.constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ export enum ZIndex {
4848
export const Z_INDEX_FLOATING_FORM = ZIndex.MAX + ZIndex.LAYER_1;
4949
export const Z_INDEX_FLOATING_MENU = Z_INDEX_FLOATING_FORM + 1;
5050
export const Z_INDEX_MODAL = Z_INDEX_FLOATING_MENU + ZIndex.LAYER_1;
51+
// Tooltips are transient and anchored to their trigger, so they should float
52+
// above every persistent layer (floating form/menu/modal).
53+
export const Z_INDEX_TOOLTIP = Z_INDEX_MODAL + ZIndex.LAYER_1;
5154

5255
export const ACCEPTED_TIMES = [
5356
"12:00 AM",
Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import classNames from "classnames";
2-
import { type HTMLProps, type ReactNode } from "react";
2+
import { type ReactNode } from "react";
33

44
export function ShortcutHint({
55
children,
@@ -26,22 +26,3 @@ export function ShortcutHint({
2626
</span>
2727
);
2828
}
29-
30-
interface LegacyProps extends HTMLProps<HTMLDivElement> {
31-
children?: ReactNode;
32-
}
33-
34-
export const LegacyShortcutHint = ({
35-
children,
36-
className = "",
37-
...props
38-
}: LegacyProps) => {
39-
return (
40-
<div
41-
className={`flex rounded border border-bg-primary bg-fg-primary px-2.5 py-[5px] ${className}`}
42-
{...props}
43-
>
44-
{children}
45-
</div>
46-
);
47-
};

packages/web/src/components/Tooltip/Description/TooltipDescription.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,5 @@ interface Props {
66
}
77

88
export const TooltipDescription: FC<Props> = ({ description }) => {
9-
return (
10-
<Text size="m" style={{ paddingRight: 10 }}>
11-
{description}
12-
</Text>
13-
);
9+
return <Text style={{ paddingRight: 10 }}>{description}</Text>;
1410
};

packages/web/src/components/Tooltip/Tooltip.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { FloatingPortal, useMergeRefs } from "@floating-ui/react";
2+
import classNames from "classnames";
23
import {
34
cloneElement,
45
forwardRef,
@@ -7,7 +8,7 @@ import {
78
type ReactNode,
89
type Ref,
910
} from "react";
10-
import { ZIndex } from "@web/common/constants/web.constants";
11+
import { Z_INDEX_TOOLTIP, ZIndex } from "@web/common/constants/web.constants";
1112
import { useGridMaxZIndex } from "@web/common/hooks/useGridMaxZIndex";
1213
import { type TooltipOptions } from "./tooltip.types";
1314
import { TooltipContext, useTooltip, useTooltipContext } from "./useTooltip";
@@ -65,22 +66,24 @@ export const TooltipTrigger = forwardRef<
6566
export const TooltipContent = forwardRef<
6667
HTMLDivElement,
6768
HTMLProps<HTMLDivElement>
68-
>(function TooltipContent({ children, style, ...props }, propRef) {
69+
>(function TooltipContent({ children, className, style, ...props }, propRef) {
6970
const context = useTooltipContext();
7071
const maxZIndex = useGridMaxZIndex();
7172
const ref = useMergeRefs([context.refs.setFloating, propRef]);
7273

7374
return (
7475
<FloatingPortal>
75-
{context.open && (
76+
{context.isMounted && (
7677
<div
7778
ref={ref}
79+
className={classNames("c-tooltip", className)}
7880
style={{
7981
left: context.x ?? 0,
8082
position: context.strategy,
8183
top: context.y ?? 0,
8284
visibility: context.x == null ? "hidden" : "visible",
83-
zIndex: maxZIndex + ZIndex.LAYER_3,
85+
zIndex: Math.max(maxZIndex + ZIndex.LAYER_3, Z_INDEX_TOOLTIP),
86+
...context.transitionStyles,
8487
...style,
8588
}}
8689
{...context.getFloatingProps(props)}

packages/web/src/components/Tooltip/TooltipWrapper.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
TooltipTrigger,
99
} from "@web/components/Tooltip";
1010
import { type TooltipOptions } from "@web/components/Tooltip/tooltip.types";
11-
import { LegacyShortcutHint } from "../Shortcuts/ShortcutHint";
11+
import { ShortcutHint } from "../Shortcuts/ShortcutHint";
1212
import { TooltipDescription } from "./Description/TooltipDescription";
1313

1414
export interface Props {
@@ -37,19 +37,17 @@ export const TooltipWrapper: React.FC<Props> = ({
3737
{children}
3838
</TooltipTrigger>
3939

40-
<TooltipContent
41-
className={`${description ? "bg-fg-primary" : ""} rounded p-1`}
42-
>
40+
<TooltipContent>
4341
<Flex alignItems={AlignItems.CENTER}>
4442
{description && <TooltipDescription description={description} />}
4543
{shortcut && (
46-
<LegacyShortcutHint>
44+
<ShortcutHint variant="keycap">
4745
{typeof shortcut === "string" ? (
4846
<Text size="s">{shortcut}</Text>
4947
) : (
5048
shortcut
5149
)}
52-
</LegacyShortcutHint>
50+
</ShortcutHint>
5351
)}
5452
</Flex>
5553
</TooltipContent>

packages/web/src/components/Tooltip/useTooltip.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
useHover,
1010
useInteractions,
1111
useRole,
12+
useTransitionStyles,
1213
} from "@floating-ui/react";
1314
import { createContext, useContext, useMemo, useState } from "react";
1415
import { type TooltipOptions } from "./tooltip.types";
@@ -53,14 +54,30 @@ export function useTooltip({
5354

5455
const interactions = useInteractions([hover, focus, dismiss, role]);
5556

57+
// App-native fade + rise on appear, using the shared ease-out-expo curve.
58+
const transition = useTransitionStyles(context, {
59+
duration: { open: 160, close: 120 },
60+
initial: { opacity: 0, transform: "translateY(4px) scale(0.98)" },
61+
common: { transitionTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)" },
62+
});
63+
5664
return useMemo(
5765
() => ({
5866
open,
5967
setOpen,
68+
isMounted: transition.isMounted,
69+
transitionStyles: transition.styles,
6070
...interactions,
6171
...data,
6272
}),
63-
[open, setOpen, interactions, data],
73+
[
74+
open,
75+
setOpen,
76+
transition.isMounted,
77+
transition.styles,
78+
interactions,
79+
data,
80+
],
6481
);
6582
}
6683

packages/web/src/index.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,13 @@
417417
}
418418
}
419419

420+
@utility c-tooltip {
421+
@apply rounded bg-menu-tooltip-bg px-2 py-1 font-medium text-menu-tooltip-text leading-snug shadow-[0_4px_6px_var(--color-shadow-default)];
422+
font-size: var(--font-size-s);
423+
}
424+
420425
@utility c-context-tooltip {
421-
@apply pointer-events-none invisible absolute bottom-full z-10 mb-1.5 translate-y-[5px] whitespace-nowrap rounded bg-menu-tooltip-bg px-2 py-1 text-[13px] text-menu-tooltip-text opacity-0 transition-all duration-200 ease-in-out group-hover:visible group-hover:translate-y-0 group-hover:opacity-100;
426+
@apply c-tooltip pointer-events-none invisible absolute bottom-full z-10 mb-1.5 translate-y-1.25 whitespace-nowrap opacity-0 transition-all duration-200 ease-in-out group-hover:visible group-hover:translate-y-0 group-hover:opacity-100;
422427
}
423428

424429
@utility c-context-menu-item {

packages/web/src/views/Forms/ActionsMenu/MenuItem.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type React from "react";
22
import { type ReactNode, useEffect, useRef, useState } from "react";
3-
import { LegacyShortcutHint } from "@web/components/Shortcuts/ShortcutHint";
3+
import { ShortcutHint } from "@web/components/Shortcuts/ShortcutHint";
44
import {
55
Tooltip,
66
TooltipContent,
@@ -95,7 +95,7 @@ const MenuItem: React.FC<MenuItemProps> = ({
9595
</button>
9696
</TooltipTrigger>
9797
<TooltipContent>
98-
<LegacyShortcutHint>{tooltipContent}</LegacyShortcutHint>
98+
<ShortcutHint variant="keycap">{tooltipContent}</ShortcutHint>
9999
</TooltipContent>
100100
</Tooltip>
101101
);

packages/web/src/views/Life/LifeDotTooltip.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function LifeDotTooltip({ weekNumber, children }: LifeDotTooltipProps) {
4949
{children}
5050
{open ? (
5151
<span
52-
className="pointer-events-none absolute bottom-full left-1/2 z-50 mb-1 -translate-x-1/2 whitespace-nowrap rounded border border-border-primary bg-bg-secondary px-2 py-1 text-text-lighter text-xs shadow-lg"
52+
className="c-tooltip pointer-events-none absolute bottom-full left-1/2 z-50 mb-1 -translate-x-1/2 whitespace-nowrap"
5353
role="tooltip"
5454
>
5555
{label}

0 commit comments

Comments
 (0)