Skip to content

Commit 55df6c9

Browse files
committed
1 parent 49563f3 commit 55df6c9

File tree

5 files changed

+179
-0
lines changed

5 files changed

+179
-0
lines changed

app/components/Tooltip/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./tooltip";
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { tooltipAnatomy } from "@ark-ui/anatomy";
2+
import { defineSlotRecipe } from "@pandacss/dev";
3+
4+
export const tooltip = defineSlotRecipe({
5+
className: "tooltip",
6+
slots: tooltipAnatomy.keys(),
7+
base: {
8+
content: {
9+
background: "gray.a12",
10+
borderRadius: "l2",
11+
boxShadow: "sm",
12+
color: "bg.default",
13+
fontWeight: "semibold",
14+
px: "3",
15+
py: "2",
16+
textStyle: "xs",
17+
maxWidth: "2xs",
18+
zIndex: "tooltip",
19+
_open: {
20+
animation: "fadeIn 0.25s ease-out",
21+
},
22+
_closed: {
23+
animation: "fadeOut 0.2s ease-out",
24+
},
25+
},
26+
},
27+
});
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use client";
2+
import type { Assign } from "@ark-ui/react";
3+
import { Tooltip } from "@ark-ui/react/tooltip";
4+
import { type TooltipVariantProps, tooltip } from "styled-system/recipes";
5+
import type { ComponentProps, HTMLStyledProps } from "styled-system/types";
6+
import { createStyleContext } from "./utils/create-style-context";
7+
8+
const { withRootProvider, withContext } = createStyleContext(tooltip);
9+
10+
export type RootProviderProps = ComponentProps<typeof RootProvider>;
11+
export const RootProvider = withRootProvider<
12+
Assign<Tooltip.RootProviderProps, TooltipVariantProps>
13+
>(Tooltip.RootProvider);
14+
15+
export type RootProps = ComponentProps<typeof Root>;
16+
export const Root = withRootProvider<
17+
Assign<Tooltip.RootProps, TooltipVariantProps>
18+
>(Tooltip.Root);
19+
20+
export const Arrow = withContext<
21+
HTMLDivElement,
22+
Assign<HTMLStyledProps<"div">, Tooltip.ArrowBaseProps>
23+
>(Tooltip.Arrow, "arrow");
24+
25+
export const ArrowTip = withContext<
26+
HTMLDivElement,
27+
Assign<HTMLStyledProps<"div">, Tooltip.ArrowTipBaseProps>
28+
>(Tooltip.ArrowTip, "arrowTip");
29+
30+
export const Content = withContext<
31+
HTMLDivElement,
32+
Assign<HTMLStyledProps<"div">, Tooltip.ContentBaseProps>
33+
>(Tooltip.Content, "content");
34+
35+
export const Positioner = withContext<
36+
HTMLDivElement,
37+
Assign<HTMLStyledProps<"div">, Tooltip.PositionerBaseProps>
38+
>(Tooltip.Positioner, "positioner");
39+
40+
export const Trigger = withContext<
41+
HTMLButtonElement,
42+
Assign<HTMLStyledProps<"button">, Tooltip.TriggerBaseProps>
43+
>(Tooltip.Trigger, "trigger");
44+
45+
export { TooltipContext as Context } from "@ark-ui/react/tooltip";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import {
2+
type ElementType,
3+
type ForwardRefExoticComponent,
4+
type PropsWithoutRef,
5+
type RefAttributes,
6+
createContext,
7+
forwardRef,
8+
useContext,
9+
} from "react";
10+
import { cx } from "styled-system/css";
11+
import { type StyledComponent, isCssProperty, styled } from "styled-system/jsx";
12+
13+
type Props = Record<string, unknown>;
14+
type Recipe = {
15+
(props?: Props): Props;
16+
splitVariantProps: (props: Props) => [Props, Props];
17+
};
18+
type Slot<R extends Recipe> = keyof ReturnType<R>;
19+
type Options = { forwardProps?: string[] };
20+
21+
const shouldForwardProp = (
22+
prop: string,
23+
variantKeys: string[],
24+
options: Options = {},
25+
) =>
26+
options.forwardProps?.includes(prop) ||
27+
(!variantKeys.includes(prop) && !isCssProperty(prop));
28+
29+
export const createStyleContext = <R extends Recipe>(recipe: R) => {
30+
const StyleContext = createContext<Record<Slot<R>, string> | null>(null);
31+
32+
const withRootProvider = <P extends {}>(Component: ElementType) => {
33+
const StyledComponent = (props: P) => {
34+
const [variantProps, otherProps] = recipe.splitVariantProps(props);
35+
const slotStyles = recipe(variantProps) as Record<Slot<R>, string>;
36+
37+
return (
38+
<StyleContext.Provider value={slotStyles}>
39+
<Component {...otherProps} />
40+
</StyleContext.Provider>
41+
);
42+
};
43+
return StyledComponent;
44+
};
45+
46+
const withProvider = <T, P extends { className?: string | undefined }>(
47+
Component: ElementType,
48+
slot: Slot<R>,
49+
options?: Options,
50+
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> => {
51+
const StyledComponent = styled(
52+
Component,
53+
{},
54+
{
55+
shouldForwardProp: (prop, variantKeys) =>
56+
shouldForwardProp(prop, variantKeys, options),
57+
},
58+
) as StyledComponent<ElementType>;
59+
const StyledSlotProvider = forwardRef<T, P>((props, ref) => {
60+
const [variantProps, otherProps] = recipe.splitVariantProps(props);
61+
const slotStyles = recipe(variantProps) as Record<Slot<R>, string>;
62+
63+
return (
64+
<StyleContext.Provider value={slotStyles}>
65+
<StyledComponent
66+
{...otherProps}
67+
ref={ref}
68+
className={cx(slotStyles?.[slot], props.className)}
69+
/>
70+
</StyleContext.Provider>
71+
);
72+
});
73+
74+
StyledSlotProvider.displayName = Component.displayName || Component.name;
75+
76+
return StyledSlotProvider;
77+
};
78+
79+
const withContext = <T, P extends { className?: string | undefined }>(
80+
Component: ElementType,
81+
slot: Slot<R>,
82+
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> => {
83+
const StyledComponent = styled(Component);
84+
const StyledSlotComponent = forwardRef<T, P>((props, ref) => {
85+
const slotStyles = useContext(StyleContext);
86+
return (
87+
<StyledComponent
88+
{...props}
89+
ref={ref}
90+
className={cx(slotStyles?.[slot], props.className)}
91+
/>
92+
);
93+
});
94+
95+
StyledSlotComponent.displayName = Component.displayName || Component.name;
96+
97+
return StyledSlotComponent;
98+
};
99+
100+
return {
101+
withRootProvider,
102+
withProvider,
103+
withContext,
104+
};
105+
};

app/components/Tooltip/tooltip.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * as Tooltip from "./styled/tooltip";

0 commit comments

Comments
 (0)