@recursica/mui-adapter 0.4.0 → 0.6.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.
Files changed (177) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/mui-adapter.cjs +74 -1
  3. package/dist/mui-adapter.cjs.map +1 -1
  4. package/dist/mui-adapter.css +1 -1
  5. package/dist/mui-adapter.js +6651 -201
  6. package/dist/mui-adapter.js.map +1 -1
  7. package/dist/src/components/Accordion/Accordion.d.ts +63 -2
  8. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +9 -2
  9. package/dist/src/components/Autocomplete/Autocomplete.d.ts +17 -0
  10. package/dist/src/components/Autocomplete/index.d.ts +1 -0
  11. package/dist/src/components/Avatar/Avatar.d.ts +14 -2
  12. package/dist/src/components/Badge/Badge.d.ts +13 -3
  13. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +10 -3
  14. package/dist/src/components/Button/Button.d.ts +1 -1
  15. package/dist/src/components/Card/Card.d.ts +40 -3
  16. package/dist/src/components/Checkbox/Checkbox.d.ts +15 -2
  17. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +16 -0
  18. package/dist/src/components/Checkbox/index.d.ts +5 -1
  19. package/dist/src/components/Chip/Chip.d.ts +18 -2
  20. package/dist/src/components/Dropdown/Dropdown.d.ts +23 -3
  21. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +10 -2
  22. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +24 -2
  23. package/dist/src/components/HoverCard/HoverCard.d.ts +55 -3
  24. package/dist/src/components/Label/Label.d.ts +13 -2
  25. package/dist/src/components/Link/Link.d.ts +1 -1
  26. package/dist/src/components/Menu/Menu.d.ts +99 -3
  27. package/dist/src/components/Modal/Modal.d.ts +36 -2
  28. package/dist/src/components/NumberInput/NumberInput.d.ts +14 -2
  29. package/dist/src/components/Pagination/Pagination.d.ts +44 -2
  30. package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
  31. package/dist/src/components/Panel/Panel.d.ts +65 -3
  32. package/dist/src/components/Radio/Radio.d.ts +13 -3
  33. package/dist/src/components/Radio/RadioGroup.d.ts +13 -0
  34. package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
  35. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +7 -2
  36. package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
  37. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  38. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
  39. package/dist/src/components/ReadOnlyField/index.d.ts +1 -0
  40. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +31 -3
  41. package/dist/src/components/Slider/Slider.d.ts +28 -2
  42. package/dist/src/components/Stepper/Stepper.d.ts +21 -2
  43. package/dist/src/components/Switch/Switch.d.ts +10 -3
  44. package/dist/src/components/Switch/SwitchGroup.d.ts +13 -0
  45. package/dist/src/components/Tabs/Tabs.d.ts +35 -3
  46. package/dist/src/components/Text/Text.d.ts +1 -1
  47. package/dist/src/components/TextArea/TextArea.d.ts +18 -2
  48. package/dist/src/components/TextField/TextField.d.ts +16 -2
  49. package/dist/src/components/Timeline/Timeline.d.ts +14 -2
  50. package/dist/src/components/Timeline/TimelineItem.d.ts +29 -0
  51. package/dist/src/components/Title/Title.d.ts +1 -1
  52. package/dist/src/components/Toast/Toast.d.ts +25 -2
  53. package/dist/src/components/Tooltip/Tooltip.d.ts +42 -3
  54. package/dist/src/components/Typography/Typography.d.ts +1 -1
  55. package/dist/src/components/index.d.ts +1 -0
  56. package/package.json +12 -2
  57. package/src/GlobalExemptions.modules.css +13 -0
  58. package/src/components/Accordion/Accordion.module.css +295 -0
  59. package/src/components/Accordion/Accordion.stories.tsx +149 -21
  60. package/src/components/Accordion/Accordion.tsx +264 -4
  61. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
  62. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +76 -19
  63. package/src/components/AssistiveElement/AssistiveElement.tsx +85 -4
  64. package/src/components/Autocomplete/Autocomplete.module.css +325 -0
  65. package/src/components/Autocomplete/Autocomplete.stories.tsx +196 -0
  66. package/src/components/Autocomplete/Autocomplete.tsx +201 -0
  67. package/src/components/Autocomplete/index.ts +1 -0
  68. package/src/components/Avatar/Avatar.module.css +344 -0
  69. package/src/components/Avatar/Avatar.stories.tsx +94 -22
  70. package/src/components/Avatar/Avatar.tsx +110 -5
  71. package/src/components/Badge/Badge.module.css +127 -0
  72. package/src/components/Badge/Badge.stories.tsx +65 -22
  73. package/src/components/Badge/Badge.tsx +70 -5
  74. package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
  75. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
  76. package/src/components/Breadcrumb/Breadcrumb.tsx +62 -5
  77. package/src/components/Button/Button.module.css +113 -20
  78. package/src/components/Button/Button.stories.tsx +3 -0
  79. package/src/components/Button/Button.tsx +10 -3
  80. package/src/components/Card/Card.module.css +118 -0
  81. package/src/components/Card/Card.stories.tsx +117 -19
  82. package/src/components/Card/Card.tsx +179 -4
  83. package/src/components/Checkbox/Checkbox.module.css +232 -0
  84. package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
  85. package/src/components/Checkbox/Checkbox.tsx +146 -4
  86. package/src/components/Checkbox/CheckboxGroup.tsx +117 -0
  87. package/src/components/Checkbox/index.ts +6 -1
  88. package/src/components/Chip/Chip.module.css +236 -0
  89. package/src/components/Chip/Chip.stories.tsx +101 -21
  90. package/src/components/Chip/Chip.tsx +138 -5
  91. package/src/components/DatePicker/DatePicker.module.css +42 -0
  92. package/src/components/DatePicker/DatePicker.tsx +1 -0
  93. package/src/components/Dropdown/Dropdown.module.css +296 -0
  94. package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
  95. package/src/components/Dropdown/Dropdown.tsx +182 -5
  96. package/src/components/FileInput/FileInput.module.css +47 -0
  97. package/src/components/FileInput/FileInput.tsx +1 -0
  98. package/src/components/FileUpload/FileUpload.module.css +40 -0
  99. package/src/components/FileUpload/FileUpload.tsx +1 -0
  100. package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
  101. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +74 -19
  102. package/src/components/FormControlLayout/FormControlLayout.tsx +58 -4
  103. package/src/components/FormControlWrapper/FormControlWrapper.module.css +96 -0
  104. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +122 -19
  105. package/src/components/FormControlWrapper/FormControlWrapper.tsx +145 -6
  106. package/src/components/HoverCard/HoverCard.module.css +91 -0
  107. package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
  108. package/src/components/HoverCard/HoverCard.tsx +150 -4
  109. package/src/components/Label/Label.module.css +136 -0
  110. package/src/components/Label/Label.stories.tsx +98 -17
  111. package/src/components/Label/Label.tsx +88 -4
  112. package/src/components/Link/Link.module.css +8 -0
  113. package/src/components/Menu/Menu.module.css +287 -0
  114. package/src/components/Menu/Menu.stories.tsx +307 -21
  115. package/src/components/Menu/Menu.tsx +318 -4
  116. package/src/components/Modal/Modal.module.css +172 -0
  117. package/src/components/Modal/Modal.stories.tsx +66 -22
  118. package/src/components/Modal/Modal.tsx +216 -3
  119. package/src/components/NumberInput/NumberInput.module.css +281 -0
  120. package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
  121. package/src/components/NumberInput/NumberInput.tsx +148 -5
  122. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  123. package/src/components/Pagination/Pagination.module.css +307 -0
  124. package/src/components/Pagination/Pagination.stories.tsx +42 -21
  125. package/src/components/Pagination/Pagination.tsx +193 -4
  126. package/src/components/Panel/Panel.module.css +206 -0
  127. package/src/components/Panel/Panel.stories.tsx +214 -22
  128. package/src/components/Panel/Panel.tsx +153 -4
  129. package/src/components/Radio/Radio.module.css +220 -0
  130. package/src/components/Radio/Radio.stories.tsx +77 -19
  131. package/src/components/Radio/Radio.tsx +178 -4
  132. package/src/components/Radio/RadioGroup.tsx +111 -0
  133. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  134. package/src/components/ReadOnlyField/ReadOnlyField.module.css +54 -0
  135. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +175 -16
  136. package/src/components/ReadOnlyField/ReadOnlyField.tsx +109 -4
  137. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  138. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  139. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  140. package/src/components/ReadOnlyField/index.ts +1 -0
  141. package/src/components/SegmentedControl/SegmentedControl.module.css +203 -0
  142. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
  143. package/src/components/SegmentedControl/SegmentedControl.tsx +110 -5
  144. package/src/components/Slider/Slider.module.css +542 -0
  145. package/src/components/Slider/Slider.stories.tsx +157 -19
  146. package/src/components/Slider/Slider.tsx +282 -4
  147. package/src/components/Stepper/Stepper.module.css +410 -0
  148. package/src/components/Stepper/Stepper.stories.tsx +132 -19
  149. package/src/components/Stepper/Stepper.tsx +145 -5
  150. package/src/components/Switch/Switch.module.css +238 -0
  151. package/src/components/Switch/Switch.stories.tsx +98 -19
  152. package/src/components/Switch/Switch.tsx +153 -5
  153. package/src/components/Switch/SwitchGroup.tsx +111 -0
  154. package/src/components/Tabs/Tabs.module.css +422 -0
  155. package/src/components/Tabs/Tabs.stories.tsx +138 -19
  156. package/src/components/Tabs/Tabs.tsx +103 -5
  157. package/src/components/TextArea/TextArea.module.css +160 -0
  158. package/src/components/TextArea/TextArea.stories.tsx +80 -21
  159. package/src/components/TextArea/TextArea.tsx +156 -5
  160. package/src/components/TextField/TextField.module.css +266 -0
  161. package/src/components/TextField/TextField.stories.tsx +168 -15
  162. package/src/components/TextField/TextField.tsx +171 -5
  163. package/src/components/TimePicker/TimePicker.module.css +41 -0
  164. package/src/components/TimePicker/TimePicker.tsx +1 -0
  165. package/src/components/Timeline/Timeline.module.css +367 -0
  166. package/src/components/Timeline/Timeline.stories.tsx +114 -21
  167. package/src/components/Timeline/Timeline.tsx +80 -4
  168. package/src/components/Timeline/TimelineItem.tsx +101 -0
  169. package/src/components/Toast/Toast.module.css +170 -0
  170. package/src/components/Toast/Toast.stories.tsx +54 -22
  171. package/src/components/Toast/Toast.tsx +90 -4
  172. package/src/components/Tooltip/Tooltip.module.css +90 -0
  173. package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
  174. package/src/components/Tooltip/Tooltip.tsx +114 -4
  175. package/src/components/TransferList/TransferList.module.css +38 -0
  176. package/src/components/TransferList/TransferList.tsx +1 -0
  177. package/src/components/index.ts +1 -0
@@ -0,0 +1,170 @@
1
+ /* EXEMPTIONS:
2
+ - elevation levels layer-1, layer-2, and layer-3 are ignored because all toasts explicitly use the standard
3
+ layer-0 elevation shadow for styling consistency. */
4
+ /* recursica-ignore: --recursica_ui-kit_components_toast_properties_elevation_layer-1 */
5
+ /* recursica-ignore: --recursica_ui-kit_components_toast_properties_elevation_layer-2 */
6
+ /* recursica-ignore: --recursica_ui-kit_components_toast_properties_elevation_layer-3 */
7
+
8
+ /* HARDCODED VALUES:
9
+ - border-style: none. To ensure the notification doesn't render unwanted borders unless specified.
10
+ */
11
+
12
+ /* ======================================
13
+ TOAST / NOTIFICATION ROOT
14
+ ====================================== */
15
+
16
+ .root {
17
+ border-style: none; /* HARDCODE: Reset to ensure clean shadow boundaries */
18
+ box-shadow: var(
19
+ --recursica_ui-kit_components_toast_properties_elevation_layer-0
20
+ );
21
+ padding: var(--recursica_ui-kit_components_toast_properties_vertical-padding)
22
+ var(--recursica_ui-kit_components_toast_properties_horizontal-padding);
23
+ min-width: var(--recursica_ui-kit_components_toast_properties_min-width);
24
+ max-width: var(--recursica_ui-kit_components_toast_properties_max-width);
25
+ min-height: var(--recursica_ui-kit_components_toast_properties_min-height);
26
+
27
+ /* Default Variant (Base) */
28
+ background-color: var(
29
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_background
30
+ );
31
+ gap: var(--recursica_ui-kit_components_toast_properties_spacing);
32
+
33
+ /* Hide Mantine's native colored vertical line */
34
+ &::before {
35
+ display: none;
36
+ content: none;
37
+ }
38
+
39
+ & .icon {
40
+ width: var(--recursica_ui-kit_components_toast_properties_icon) !important;
41
+ height: var(--recursica_ui-kit_components_toast_properties_icon) !important;
42
+ margin-right: 0 !important; /* Override Mantine's native spacing in favor of flex gap */
43
+ background-color: transparent !important; /* Remove Mantine's native circle background */
44
+
45
+ color: var(
46
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_text
47
+ );
48
+ }
49
+
50
+ & .loader {
51
+ margin-right: 0 !important; /* Override native spacing */
52
+ }
53
+ & .title,
54
+ & .description {
55
+ color: var(
56
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_text
57
+ );
58
+ }
59
+ & .closeButton {
60
+ color: var(
61
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_button
62
+ );
63
+ }
64
+
65
+ /* Error Variant styling */
66
+ &[data-variant="error"] {
67
+ background-color: var(
68
+ --recursica_ui-kit_components_toast_variants_styles_error_properties_colors_background
69
+ );
70
+
71
+ & .icon {
72
+ color: var(
73
+ --recursica_ui-kit_components_toast_variants_styles_error_properties_colors_text
74
+ ) !important;
75
+ }
76
+ & .title,
77
+ & .description {
78
+ color: var(
79
+ --recursica_ui-kit_components_toast_variants_styles_error_properties_colors_text
80
+ );
81
+ }
82
+ & .closeButton {
83
+ color: var(
84
+ --recursica_ui-kit_components_toast_variants_styles_error_properties_colors_button
85
+ );
86
+ }
87
+ }
88
+
89
+ /* Success Variant styling */
90
+ &[data-variant="success"] {
91
+ background-color: var(
92
+ --recursica_ui-kit_components_toast_variants_styles_success_properties_colors_background
93
+ );
94
+
95
+ & .icon {
96
+ color: var(
97
+ --recursica_ui-kit_components_toast_variants_styles_success_properties_colors_text
98
+ ) !important;
99
+ }
100
+ & .title,
101
+ & .description {
102
+ color: var(
103
+ --recursica_ui-kit_components_toast_variants_styles_success_properties_colors_text
104
+ );
105
+ }
106
+ & .closeButton {
107
+ color: var(
108
+ --recursica_ui-kit_components_toast_variants_styles_success_properties_colors_button
109
+ );
110
+ }
111
+ }
112
+ }
113
+
114
+ /* ======================================
115
+ TOAST BODY
116
+ ====================================== */
117
+
118
+ .body {
119
+ /* No extra gap here, root handles icon-to-text, body can handle title-to-description if needed */
120
+ }
121
+
122
+ .title {
123
+ font-family: var(
124
+ --recursica_ui-kit_components_toast_properties_text_font-family
125
+ );
126
+ font-size: var(--recursica_ui-kit_components_toast_properties_text_font-size);
127
+ font-style: var(
128
+ --recursica_ui-kit_components_toast_properties_text_font-style
129
+ );
130
+ font-weight: var(
131
+ --recursica_ui-kit_components_toast_properties_text_font-weight
132
+ );
133
+ letter-spacing: var(
134
+ --recursica_ui-kit_components_toast_properties_text_letter-spacing
135
+ );
136
+ line-height: var(
137
+ --recursica_ui-kit_components_toast_properties_text_line-height
138
+ );
139
+ text-decoration: var(
140
+ --recursica_ui-kit_components_toast_properties_text_text-decoration
141
+ );
142
+ text-transform: var(
143
+ --recursica_ui-kit_components_toast_properties_text_text-transform
144
+ );
145
+ }
146
+
147
+ .description {
148
+ font-family: var(
149
+ --recursica_ui-kit_components_toast_properties_text_font-family
150
+ );
151
+ font-size: var(--recursica_ui-kit_components_toast_properties_text_font-size);
152
+ font-style: var(
153
+ --recursica_ui-kit_components_toast_properties_text_font-style
154
+ );
155
+ font-weight: var(
156
+ --recursica_ui-kit_components_toast_properties_text_font-weight
157
+ );
158
+ letter-spacing: var(
159
+ --recursica_ui-kit_components_toast_properties_text_letter-spacing
160
+ );
161
+ line-height: var(
162
+ --recursica_ui-kit_components_toast_properties_text_line-height
163
+ );
164
+ text-decoration: var(
165
+ --recursica_ui-kit_components_toast_properties_text_text-decoration
166
+ );
167
+ text-transform: var(
168
+ --recursica_ui-kit_components_toast_properties_text_text-transform
169
+ );
170
+ }
@@ -1,35 +1,67 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import { Toast } from "./Toast";
3
- import { ComingSoon } from "@recursica/storybook-template";
4
3
 
5
- const meta: Meta<typeof Toast> = {
6
- title: "UI-Kit/🚧 Toast",
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ type ToastStoryArgs = Record<string, any>;
6
+
7
+ const meta = {
8
+ title: "UI-Kit/Toast",
7
9
  component: Toast,
8
10
  tags: ["autodocs"],
9
11
  parameters: {
10
- controls: {
11
- include: [
12
- "layer",
13
- "withLayer",
14
- "children",
15
- "component",
16
- "variant",
17
- "size",
18
- "icon",
19
- "disabled",
20
- "href",
21
- "onClick",
22
- "onChange",
23
- "value",
24
- "checked",
25
- ],
12
+ docs: {
13
+ description: {
14
+ component:
15
+ "The `Toast` component is a standalone visual component wrapping Mantine's `Notification`. Note that this component is visually decoupled from `@mantine/notifications` and is meant to be used when you need to render a static or manually-controlled notification panel. If you need dynamic notification popups, you should use `@mantine/notifications` and configure its provider to use our styles.",
16
+ },
26
17
  },
27
18
  },
28
- };
19
+ argTypes: {
20
+ title: {
21
+ control: "text",
22
+ description: "Title displayed above the message body",
23
+ },
24
+ children: {
25
+ control: "text",
26
+ description: "Main notification message",
27
+ },
28
+ withCloseButton: {
29
+ control: "boolean",
30
+ description: "Whether the close button is visible",
31
+ },
32
+ },
33
+ } satisfies Meta<typeof Toast>;
29
34
 
30
35
  export default meta;
31
- type Story = StoryObj<typeof Toast>;
36
+ type Story = StoryObj<typeof meta>;
32
37
 
33
38
  export const Default: Story = {
34
- render: () => <ComingSoon componentName="Toast" />,
39
+ args: {
40
+ variant: "default",
41
+ title: "Update Available",
42
+ children:
43
+ "A new version of the application is available to download. Please restart your browser to apply the latest security patches and feature updates. If you ignore this message, the update will automatically install during your next session.",
44
+ withCloseButton: true,
45
+ },
46
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
47
+ render: ({ withLayer, layer, ...args }: ToastStoryArgs) => {
48
+ return <Toast {...args} />;
49
+ },
50
+ };
51
+
52
+ export const WithIcon: Story = {
53
+ args: {
54
+ variant: "default",
55
+ title: "Action Required",
56
+ children:
57
+ "You must complete your profile setup before accessing this feature.",
58
+ icon: "⚠️",
59
+ },
60
+ parameters: {
61
+ controls: { disable: true },
62
+ },
63
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
+ render: ({ withLayer, layer, ...args }: ToastStoryArgs) => {
65
+ return <Toast {...args} />;
66
+ },
35
67
  };
@@ -1,7 +1,93 @@
1
1
  import React from "react";
2
+ import {
3
+ Snackbar as MuiNotification,
4
+ type SnackbarProps as MuiNotificationProps,
5
+ } from "@mui/material";
6
+ import {
7
+ filterStylingProps,
8
+ type RecursicaOverStyled,
9
+ } from "../../utils/filterStylingProps";
10
+ import styles from "./Toast.module.css";
2
11
 
3
- export type ToastProps = React.HTMLAttributes<HTMLDivElement>;
12
+ export interface RecursicaToastProps {
13
+ /**
14
+ * The visual variant of the toast.
15
+ * @default "default"
16
+ */
17
+ variant?: "default" | "error" | "success";
4
18
 
5
- export const Toast: React.FC<ToastProps> = (props) => {
6
- return <div {...props}>Toast</div>;
7
- };
19
+ /**
20
+ * Loading state is natively unsupported by Recursica UI Kit.
21
+ * If a loading state is required, pass a `<Loader size="sm" />` directly into the `icon` prop.
22
+ */
23
+ loading?: false;
24
+ }
25
+
26
+ /**
27
+ * Toast component wrapping Mui's Notification.
28
+ *
29
+ * Can be used as a standalone visual component to display a notification or message.
30
+ */
31
+ export type ToastProps = RecursicaOverStyled<
32
+ Omit<MuiNotificationProps, "color" | "radius" | "variant" | "loading"> &
33
+ RecursicaToastProps
34
+ >;
35
+
36
+ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
37
+ function Toast(
38
+ {
39
+ overStyled = false,
40
+ variant = "default",
41
+ withCloseButton = true,
42
+ ...rest
43
+ },
44
+ ref,
45
+ ) {
46
+ const sanitizedProps = filterStylingProps(rest, overStyled);
47
+
48
+ // Bind CSS module classes to Mui's internal classNames API
49
+ const mergedClassNames: Partial<Record<string, string>> = {
50
+ root: styles.root,
51
+ body: styles.body,
52
+ title: styles.title,
53
+ description: styles.description,
54
+ closeButton: styles.closeButton,
55
+ icon: styles.icon,
56
+ loader: styles.loader,
57
+ };
58
+
59
+ const classNamesProp = (sanitizedProps as Record<string, unknown>)
60
+ .classNames;
61
+ if (
62
+ classNamesProp &&
63
+ typeof classNamesProp === "object" &&
64
+ !Array.isArray(classNamesProp)
65
+ ) {
66
+ const o = classNamesProp as Record<string, string>;
67
+ Object.keys(o).forEach((key) => {
68
+ if (mergedClassNames[key]) {
69
+ mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
70
+ } else {
71
+ mergedClassNames[key] = o[key];
72
+ }
73
+ });
74
+ }
75
+
76
+ return (
77
+ <MuiNotification
78
+ ref={ref}
79
+ withCloseButton={withCloseButton}
80
+ withBorder={false} // Border is handled via CSS or tokens if needed
81
+ data-variant={variant}
82
+ classes={mergedClassNames}
83
+ loading={false}
84
+ {...(sanitizedProps as unknown as Omit<
85
+ MuiNotificationProps,
86
+ "color" | "radius" | "variant" | "loading"
87
+ >)}
88
+ />
89
+ );
90
+ },
91
+ );
92
+
93
+ Toast.displayName = "Toast";
@@ -0,0 +1,90 @@
1
+ /* EXEMPTIONS:
2
+ - beak-inset is ignored because Tooltip positioning calculations are handled dynamically by Mantine/Floating UI at the React runtime.
3
+ - beak-size is ignored because Mantine's tooltip arrows compute their sizing and positional offsets
4
+ dynamically within the React rendering engine (requires inline pixel number rather than standard CSS variables).
5
+ The beak size is checked in JS against a fixed value of 16px. If this variable changes, the TSX components
6
+ need to be reviewed/re-compiled. */
7
+ /* recursica-ignore: --recursica_ui-kit_components_tooltip_properties_beak-inset = 8px */
8
+ /* recursica-ignore: --recursica_ui-kit_components_tooltip_properties_beak-size = 16px */
9
+
10
+ /* HARDCODED VALUES:
11
+ - border-style: solid. Structural rendering rule for the tooltip border (Mantine uses Box
12
+ which may not set border-style natively). Same pattern as Menu / HoverCard.
13
+ - arrowSize defaults to 16 in Tooltip.tsx. Mantine uses arrowSize for inline width/height
14
+ and positioning (-arrowSize/2) calculations that cannot be CSS-driven. The default matches
15
+ the Recursica beak-size token (16px). See COMPONENT_ISSUES.md for details.
16
+ - All structural layout (display, position, overflow) is deferred to Mantine's native
17
+ behavior. We only override visual design tokens (colors, typography, spacing, borders).
18
+ */
19
+
20
+ /* ======================================
21
+ TOOLTIP CONTAINER
22
+ ====================================== */
23
+
24
+ .tooltip {
25
+ background-color: var(
26
+ --recursica_ui-kit_components_tooltip_properties_colors_background
27
+ );
28
+ border-style: solid; /* HARDCODE: Mantine Box does not set border-style natively */
29
+ border-width: var(
30
+ --recursica_ui-kit_components_tooltip_properties_border-size
31
+ );
32
+ border-color: var(
33
+ --recursica_ui-kit_components_tooltip_properties_colors_border-color
34
+ );
35
+ border-radius: var(
36
+ --recursica_ui-kit_components_tooltip_properties_border-radius
37
+ );
38
+ box-shadow: var(--recursica_ui-kit_components_tooltip_properties_elevation);
39
+
40
+ min-width: var(--recursica_ui-kit_components_tooltip_properties_min-width);
41
+ min-height: var(--recursica_ui-kit_components_tooltip_properties_min-height);
42
+ max-width: var(--recursica_ui-kit_components_tooltip_properties_max-width);
43
+
44
+ padding: var(
45
+ --recursica_ui-kit_components_tooltip_properties_vertical-padding
46
+ )
47
+ var(--recursica_ui-kit_components_tooltip_properties_horizontal-padding);
48
+
49
+ /* Vertically center text within min-height container */
50
+ display: flex;
51
+ align-items: center;
52
+
53
+ /* Typography */
54
+ font-family: var(
55
+ --recursica_ui-kit_components_tooltip_properties_text_font-family
56
+ );
57
+ font-size: var(
58
+ --recursica_ui-kit_components_tooltip_properties_text_font-size
59
+ );
60
+ font-style: var(
61
+ --recursica_ui-kit_components_tooltip_properties_text_font-style
62
+ );
63
+ font-weight: var(
64
+ --recursica_ui-kit_components_tooltip_properties_text_font-weight
65
+ );
66
+ letter-spacing: var(
67
+ --recursica_ui-kit_components_tooltip_properties_text_letter-spacing
68
+ );
69
+ line-height: var(
70
+ --recursica_ui-kit_components_tooltip_properties_text_line-height
71
+ );
72
+ text-decoration: var(
73
+ --recursica_ui-kit_components_tooltip_properties_text_text-decoration
74
+ );
75
+ text-transform: var(
76
+ --recursica_ui-kit_components_tooltip_properties_text_text-transform
77
+ );
78
+
79
+ color: var(--recursica_ui-kit_components_tooltip_properties_colors_text);
80
+ }
81
+
82
+ /* ======================================
83
+ ARROW / BEAK
84
+ ====================================== */
85
+
86
+ .arrow {
87
+ border-color: var(
88
+ --recursica_ui-kit_components_tooltip_properties_colors_border-color
89
+ );
90
+ }
@@ -1,35 +1,165 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
- import { Tooltip } from "./Tooltip";
3
- import { ComingSoon } from "@recursica/storybook-template";
2
+ import { Tooltip, type TooltipProps } from "./Tooltip";
3
+ import { Button } from "../Button";
4
4
 
5
- const meta: Meta<typeof Tooltip> = {
6
- title: "UI-Kit/🚧 Tooltip",
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"],
9
- parameters: {
10
- controls: {
11
- include: [
12
- "layer",
13
- "withLayer",
14
- "children",
15
- "component",
16
- "variant",
17
- "size",
18
- "icon",
19
- "disabled",
20
- "href",
21
- "onClick",
22
- "onChange",
23
- "value",
24
- "checked",
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",
25
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
+ },
26
103
  },
27
104
  },
28
105
  };
29
106
 
30
107
  export default meta;
31
- type Story = StoryObj<typeof Tooltip>;
108
+
109
+ type Story = StoryObj<TooltipStoryArgs>;
32
110
 
33
111
  export const Default: Story = {
34
- render: () => <ComingSoon componentName="Tooltip" />,
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
+ },
35
165
  };