@recursica/mantine-adapter 0.13.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/mantine-adapter.cjs +1 -1
- package/dist/mantine-adapter.cjs.map +1 -1
- package/dist/mantine-adapter.css +1 -1
- package/dist/mantine-adapter.js +1329 -1082
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/HoverCard/HoverCard.d.ts +55 -3
- package/dist/src/components/NumberInput/NumberInput.d.ts +10 -2
- package/dist/src/components/Panel/Panel.d.ts +65 -3
- package/dist/src/components/Tooltip/Tooltip.d.ts +42 -3
- package/package.json +1 -1
- package/src/components/Card/Card.module.css +1 -0
- package/src/components/Card/Card.stories.tsx +48 -58
- package/src/components/Dropdown/Dropdown.module.css +0 -3
- package/src/components/HoverCard/HOVERCARD_IMPLEMENTATION_NOTES.md +77 -0
- package/src/components/HoverCard/HoverCard.module.css +84 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +160 -5
- package/src/components/HoverCard/HoverCard.tsx +153 -4
- package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/NumberInput/NumberInput.module.css +250 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +84 -4
- package/src/components/NumberInput/NumberInput.tsx +144 -5
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +106 -0
- package/src/components/Panel/Panel.module.css +154 -0
- package/src/components/Panel/Panel.stories.tsx +216 -6
- package/src/components/Panel/Panel.tsx +153 -4
- package/src/components/TextArea/TextArea.module.css +0 -3
- package/src/components/TextField/TextField.module.css +0 -3
- package/src/components/Tooltip/TOOLTIP_IMPLEMENTATION_NOTES.md +85 -0
- package/src/components/Tooltip/Tooltip.module.css +81 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +154 -6
- package/src/components/Tooltip/Tooltip.tsx +114 -4
|
@@ -1,17 +1,165 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Tooltip } from "./Tooltip";
|
|
3
|
-
import {
|
|
2
|
+
import { Tooltip, type TooltipProps } from "./Tooltip";
|
|
3
|
+
import { Button } from "../Button";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Tooltip story axes:
|
|
7
|
+
* - position: tooltip alignment relative to target
|
|
8
|
+
* - withBeak: beak (arrow) indicator on the tooltip
|
|
9
|
+
* - openDelay / closeDelay: hover timing controls
|
|
10
|
+
* - multiline: text wrapping behavior
|
|
11
|
+
* - disabled: suppress the tooltip entirely
|
|
12
|
+
* - layer: tested via the global Layer decorator (withLayer/layer args)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
type TooltipStoryArgs = Record<string, any>;
|
|
17
|
+
|
|
18
|
+
const meta: Meta = {
|
|
19
|
+
title: "UI-Kit/Tooltip",
|
|
7
20
|
component: Tooltip,
|
|
8
21
|
tags: ["autodocs"],
|
|
22
|
+
argTypes: {
|
|
23
|
+
label: {
|
|
24
|
+
control: "text",
|
|
25
|
+
description: "Content displayed inside the tooltip.",
|
|
26
|
+
},
|
|
27
|
+
position: {
|
|
28
|
+
control: "select",
|
|
29
|
+
options: [
|
|
30
|
+
"bottom",
|
|
31
|
+
"bottom-start",
|
|
32
|
+
"bottom-end",
|
|
33
|
+
"top",
|
|
34
|
+
"top-start",
|
|
35
|
+
"top-end",
|
|
36
|
+
"left",
|
|
37
|
+
"left-start",
|
|
38
|
+
"left-end",
|
|
39
|
+
"right",
|
|
40
|
+
"right-start",
|
|
41
|
+
"right-end",
|
|
42
|
+
],
|
|
43
|
+
description: "The position of the tooltip relative to the target.",
|
|
44
|
+
},
|
|
45
|
+
withBeak: {
|
|
46
|
+
control: "boolean",
|
|
47
|
+
description:
|
|
48
|
+
"Whether to display a beak (arrow) pointing to the target. Recursica equivalent of Mantine's withArrow.",
|
|
49
|
+
},
|
|
50
|
+
offset: {
|
|
51
|
+
control: "number",
|
|
52
|
+
description: "Distance in px between the tooltip and the target element.",
|
|
53
|
+
},
|
|
54
|
+
openDelay: {
|
|
55
|
+
control: "number",
|
|
56
|
+
description: "Delay in ms before the tooltip opens on hover.",
|
|
57
|
+
},
|
|
58
|
+
closeDelay: {
|
|
59
|
+
control: "number",
|
|
60
|
+
description: "Delay in ms before the tooltip closes when hover ends.",
|
|
61
|
+
},
|
|
62
|
+
disabled: {
|
|
63
|
+
control: "boolean",
|
|
64
|
+
description: "If set, the tooltip will not be rendered.",
|
|
65
|
+
},
|
|
66
|
+
opened: {
|
|
67
|
+
control: "boolean",
|
|
68
|
+
description:
|
|
69
|
+
"Force the tooltip to stay open. Useful for inspecting styling.",
|
|
70
|
+
},
|
|
71
|
+
// Hide auto-detected HTML attributes that leak from ElementProps<'div'>
|
|
72
|
+
defaultChecked: { table: { disable: true } },
|
|
73
|
+
defaultValue: { table: { disable: true } },
|
|
74
|
+
suppressContentEditableWarning: { table: { disable: true } },
|
|
75
|
+
suppressHydrationWarning: { table: { disable: true } },
|
|
76
|
+
},
|
|
77
|
+
parameters: {
|
|
78
|
+
layout: "centered",
|
|
79
|
+
docs: {
|
|
80
|
+
description: {
|
|
81
|
+
component: `
|
|
82
|
+
The \`Tooltip\` component displays a floating label when the user hovers over or focuses a target element. It wraps Mantine's \`Tooltip\` while enforcing strict Recursica design token styling.
|
|
83
|
+
|
|
84
|
+
### API
|
|
85
|
+
|
|
86
|
+
Unlike \`HoverCard\`, Tooltip is a single component — content is passed via the \`label\` prop:
|
|
87
|
+
\`\`\`tsx
|
|
88
|
+
<Tooltip label="Helpful text" withBeak>
|
|
89
|
+
<Button>Hover me</Button>
|
|
90
|
+
</Tooltip>
|
|
91
|
+
\`\`\`
|
|
92
|
+
|
|
93
|
+
### Static Sub-Components
|
|
94
|
+
- \`Tooltip.Floating\` — A tooltip that follows the cursor position
|
|
95
|
+
- \`Tooltip.Group\` — Groups multiple tooltips to share hover delay
|
|
96
|
+
|
|
97
|
+
### Key Behaviors
|
|
98
|
+
- The beak (arrow) is shown by default (\`withBeak={true}\`)
|
|
99
|
+
- Supports \`openDelay\` and \`closeDelay\` for timing control
|
|
100
|
+
- Set \`multiline\` to allow text wrapping within max-width
|
|
101
|
+
`,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
9
105
|
};
|
|
10
106
|
|
|
11
107
|
export default meta;
|
|
12
108
|
|
|
13
|
-
type Story = StoryObj<
|
|
109
|
+
type Story = StoryObj<TooltipStoryArgs>;
|
|
14
110
|
|
|
15
111
|
export const Default: Story = {
|
|
16
|
-
|
|
112
|
+
args: {
|
|
113
|
+
label: "This is a helpful tooltip",
|
|
114
|
+
position: "top",
|
|
115
|
+
withBeak: true,
|
|
116
|
+
offset: 5,
|
|
117
|
+
openDelay: 0,
|
|
118
|
+
closeDelay: 0,
|
|
119
|
+
disabled: false,
|
|
120
|
+
},
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
122
|
+
render: ({ withLayer, layer, ...args }: TooltipStoryArgs) => {
|
|
123
|
+
return (
|
|
124
|
+
<Tooltip {...(args as TooltipProps)}>
|
|
125
|
+
<Button variant="solid">Hover me</Button>
|
|
126
|
+
</Tooltip>
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const WithoutBeak: Story = {
|
|
132
|
+
args: {
|
|
133
|
+
label: "Tooltip without a beak indicator",
|
|
134
|
+
position: "top",
|
|
135
|
+
withBeak: false,
|
|
136
|
+
offset: 5,
|
|
137
|
+
},
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
139
|
+
render: ({ withLayer, layer, ...args }: TooltipStoryArgs) => {
|
|
140
|
+
return (
|
|
141
|
+
<Tooltip {...(args as TooltipProps)}>
|
|
142
|
+
<Button variant="outline">Without Beak</Button>
|
|
143
|
+
</Tooltip>
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const LongContent: Story = {
|
|
149
|
+
args: {
|
|
150
|
+
label:
|
|
151
|
+
"This is a longer tooltip message that demonstrates how text wraps within the maximum width defined by the design system.",
|
|
152
|
+
position: "top",
|
|
153
|
+
withBeak: true,
|
|
154
|
+
opened: true,
|
|
155
|
+
offset: 5,
|
|
156
|
+
},
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
158
|
+
render: ({ withLayer, layer, ...args }: TooltipStoryArgs) => {
|
|
159
|
+
return (
|
|
160
|
+
<Tooltip {...(args as TooltipProps)}>
|
|
161
|
+
<Button variant="solid">Long Content</Button>
|
|
162
|
+
</Tooltip>
|
|
163
|
+
);
|
|
164
|
+
},
|
|
17
165
|
};
|
|
@@ -1,7 +1,117 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
Tooltip as MantineTooltip,
|
|
3
|
+
type TooltipProps as MantineTooltipProps,
|
|
4
|
+
} from "@mantine/core";
|
|
5
|
+
import {
|
|
6
|
+
filterStylingProps,
|
|
7
|
+
type RecursicaOverStyled,
|
|
8
|
+
} from "../../utils/filterStylingProps";
|
|
9
|
+
import styles from "./Tooltip.module.css";
|
|
2
10
|
|
|
3
|
-
|
|
11
|
+
// ============================================================
|
|
12
|
+
// TOOLTIP
|
|
13
|
+
// ============================================================
|
|
4
14
|
|
|
5
|
-
|
|
6
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Recursica-specific props for Tooltip.
|
|
17
|
+
*/
|
|
18
|
+
export interface RecursicaTooltipProps {
|
|
19
|
+
/**
|
|
20
|
+
* Whether to display a beak (arrow) pointing from the tooltip to the target.
|
|
21
|
+
* This is the Recursica equivalent of Mantine's `withArrow`.
|
|
22
|
+
* When both `withBeak` and `withArrow` are provided, `withBeak` takes precedence.
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
withBeak?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Recursica Tooltip component wrapping Mantine's Tooltip.
|
|
30
|
+
*
|
|
31
|
+
* Displays a floating label when the user hovers over or focuses a target element.
|
|
32
|
+
* Unlike HoverCard, Tooltip is a single component (not composable) — content is
|
|
33
|
+
* passed via the `label` prop, and the trigger is passed as `children`.
|
|
34
|
+
*
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <Tooltip label="Helpful information" withBeak>
|
|
37
|
+
* <Button>Hover me</Button>
|
|
38
|
+
* </Tooltip>
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* Static sub-components available via dot-notation:
|
|
42
|
+
* - `Tooltip.Floating` — Tooltip that follows the cursor
|
|
43
|
+
* - `Tooltip.Group` — Shared hover delay group for multiple tooltips
|
|
44
|
+
*/
|
|
45
|
+
export type TooltipProps = RecursicaOverStyled<
|
|
46
|
+
MantineTooltipProps & RecursicaTooltipProps
|
|
47
|
+
>;
|
|
48
|
+
|
|
49
|
+
const TooltipBase = function Tooltip({
|
|
50
|
+
overStyled = false,
|
|
51
|
+
withBeak = true,
|
|
52
|
+
...rest
|
|
53
|
+
}: TooltipProps) {
|
|
54
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
55
|
+
|
|
56
|
+
// Bind CSS module classes to Mantine's internal classNames API
|
|
57
|
+
const mergedClassNames: Partial<Record<string, string>> = {
|
|
58
|
+
tooltip: styles.tooltip,
|
|
59
|
+
arrow: styles.arrow,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const classNamesProp = (sanitizedProps as Record<string, unknown>).classNames;
|
|
63
|
+
if (
|
|
64
|
+
classNamesProp &&
|
|
65
|
+
typeof classNamesProp === "object" &&
|
|
66
|
+
!Array.isArray(classNamesProp)
|
|
67
|
+
) {
|
|
68
|
+
const o = classNamesProp as Record<string, string>;
|
|
69
|
+
Object.keys(o).forEach((key) => {
|
|
70
|
+
if (mergedClassNames[key]) {
|
|
71
|
+
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
72
|
+
} else {
|
|
73
|
+
mergedClassNames[key] = o[key];
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// arrowSize must be a JS number prop — Mantine uses it for inline width/height
|
|
79
|
+
// and positioning offset (-arrowSize/2) calculations that cannot be CSS-driven.
|
|
80
|
+
// Default to 16 to match the Recursica beak-size token (16px).
|
|
81
|
+
const arrowSize =
|
|
82
|
+
((sanitizedProps as Record<string, unknown>).arrowSize as
|
|
83
|
+
| number
|
|
84
|
+
| undefined) ?? 16;
|
|
85
|
+
|
|
86
|
+
// Resolve withBeak (Recursica) vs withArrow (Mantine).
|
|
87
|
+
// withBeak takes precedence when both are provided.
|
|
88
|
+
const withArrow = (sanitizedProps as Record<string, unknown>).withArrow as
|
|
89
|
+
| boolean
|
|
90
|
+
| undefined;
|
|
91
|
+
const resolvedWithArrow = withBeak ?? withArrow;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<MantineTooltip
|
|
95
|
+
position="top" /* Recursica default; Mantine defaults to "bottom" */
|
|
96
|
+
multiline /* Always allow text wrapping within max-width */
|
|
97
|
+
arrowSize={arrowSize}
|
|
98
|
+
withArrow={resolvedWithArrow}
|
|
99
|
+
classNames={mergedClassNames}
|
|
100
|
+
{...(sanitizedProps as unknown as MantineTooltipProps)}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
7
103
|
};
|
|
104
|
+
TooltipBase.displayName = "Tooltip";
|
|
105
|
+
|
|
106
|
+
// ============================================================
|
|
107
|
+
// DOT NOTATION EXPORT
|
|
108
|
+
// ============================================================
|
|
109
|
+
|
|
110
|
+
type TooltipComponent = typeof TooltipBase & {
|
|
111
|
+
Floating: typeof MantineTooltip.Floating;
|
|
112
|
+
Group: typeof MantineTooltip.Group;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const Tooltip = TooltipBase as TooltipComponent;
|
|
116
|
+
Tooltip.Floating = MantineTooltip.Floating;
|
|
117
|
+
Tooltip.Group = MantineTooltip.Group;
|