@recursica/mantine-adapter 0.18.0 → 0.19.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 (37) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/mantine-adapter.cjs +1 -1
  3. package/dist/mantine-adapter.cjs.map +1 -1
  4. package/dist/mantine-adapter.css +1 -1
  5. package/dist/mantine-adapter.js +1642 -1357
  6. package/dist/mantine-adapter.js.map +1 -1
  7. package/dist/src/components/Modal/Modal.d.ts +39 -2
  8. package/dist/src/components/Modal/index.d.ts +1 -0
  9. package/dist/src/components/Popover/Popover.d.ts +55 -0
  10. package/dist/src/components/Popover/index.d.ts +1 -0
  11. package/dist/src/components/Timeline/Timeline.d.ts +14 -2
  12. package/dist/src/components/Timeline/TimelineItem.d.ts +25 -0
  13. package/dist/src/components/Toast/Toast.d.ts +21 -2
  14. package/dist/src/components/Toast/index.d.ts +1 -0
  15. package/dist/src/components/index.d.ts +2 -1
  16. package/package.json +1 -1
  17. package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +15 -0
  18. package/src/components/Modal/Modal.module.css +127 -0
  19. package/src/components/Modal/Modal.stories.tsx +66 -4
  20. package/src/components/Modal/Modal.tsx +218 -3
  21. package/src/components/Modal/index.ts +1 -0
  22. package/src/components/Popover/IMPLEMENTATION_NOTES.md +77 -0
  23. package/src/components/Popover/Popover.module.css +84 -0
  24. package/src/components/Popover/Popover.stories.tsx +133 -0
  25. package/src/components/Popover/Popover.tsx +156 -0
  26. package/src/components/Popover/index.ts +1 -0
  27. package/src/components/Timeline/TIMELINE_IMPLEMENTATION_NOTES.md +13 -0
  28. package/src/components/Timeline/Timeline.module.css +361 -0
  29. package/src/components/Timeline/Timeline.stories.tsx +114 -3
  30. package/src/components/Timeline/Timeline.tsx +81 -4
  31. package/src/components/Timeline/TimelineItem.tsx +102 -0
  32. package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +39 -0
  33. package/src/components/Toast/Toast.module.css +109 -0
  34. package/src/components/Toast/Toast.stories.tsx +57 -7
  35. package/src/components/Toast/Toast.tsx +90 -4
  36. package/src/components/Toast/index.ts +1 -0
  37. package/src/components/index.ts +2 -1
@@ -0,0 +1,39 @@
1
+ # Toast – Implementation Notes
2
+
3
+ Decisions and design tweaks tailored for the UI Kit's Toast wrapped against `@mantine/core`'s `Notification` component.
4
+
5
+ ---
6
+
7
+ ## 1. Standalone Visual Wrapper
8
+
9
+ **Decision:** We wrap `@mantine/core`'s standalone `Notification` component instead of wrapping the `@mantine/notifications` provider.
10
+
11
+ **Implementation:** The UI Kit provides variables for the `Toast` component itself (e.g., `--recursica_ui-kit_components_toast_*`). We use these variables to style the standard Mantine `Notification` element. This allows developers to use `<Toast>` manually if they want a static or inline message.
12
+
13
+ If dynamic popups are required, developers can configure `@mantine/notifications` to utilize this component or use its classes.
14
+
15
+ ---
16
+
17
+ ## 2. Variant Mapping via `data-variant`
18
+
19
+ **Decision:** `variant` props (`"default" | "error" | "success"`) are mapped directly to `data-variant` on the Mantine root `Box`.
20
+
21
+ **Implementation:** Mantine's `Notification` doesn't inherently support our custom variants out of the box in the way we want them styled. By passing `data-variant` directly to the `Box`, we can explicitly target the root element in our `Toast.module.css` (e.g., `.root[data-variant="success"]`) and pipe in the corresponding UI Kit layer colors.
22
+
23
+ ---
24
+
25
+ ## 3. Minimal CSS Override Philosophy
26
+
27
+ **Decision:** The CSS module only overrides visual design tokens (colors, typography, padding, borders, shadows).
28
+
29
+ **Implementation:** We defer layout structure, icon rendering, loader transitions, and close button mechanics to Mantine. The `border-style: none;` is hardcoded to reset any underlying styles from Mantine's defaults, ensuring a clean mapping of elevation and shadows.
30
+
31
+ ---
32
+
33
+ ## 4. Unsupported `loading` State
34
+
35
+ **Decision:** The native `loading` state is explicitly stripped and bypassed from the `<Toast />` component wrapper.
36
+
37
+ **Implementation:** Mantine's `Notification` inherently supports a `loading={true}` state that natively spins up a loader instead of an icon. However, Recursica's UI Kit strictly does not define structural tokens for loader states inside toasts.
38
+ Instead of attempting to tightly couple the internal `Loader` abstraction or mapping variables incorrectly, the `loading` property is explicitly omitted and `false`-enforced from the public API.
39
+ If consumers explicitly require a loading toast, they must manually inject a `<Loader />` component into the `icon` slot.
@@ -0,0 +1,109 @@
1
+ /* HARDCODED VALUES:
2
+ - border-style: none. To ensure the notification doesn't render unwanted borders unless specified.
3
+ */
4
+
5
+ /* ======================================
6
+ TOAST / NOTIFICATION ROOT
7
+ ====================================== */
8
+
9
+ .root {
10
+ border-style: none; /* HARDCODE: Reset to ensure clean shadow boundaries */
11
+ box-shadow: var(
12
+ --recursica_ui-kit_components_toast_properties_elevation_layer-0
13
+ );
14
+ padding: var(--recursica_ui-kit_components_toast_properties_vertical-padding)
15
+ var(--recursica_ui-kit_components_toast_properties_horizontal-padding);
16
+ min-width: var(--recursica_ui-kit_components_toast_properties_min-width);
17
+ max-width: var(--recursica_ui-kit_components_toast_properties_max-width);
18
+ min-height: var(--recursica_ui-kit_components_toast_properties_min-height);
19
+
20
+ /* Default Variant (Base) */
21
+ background-color: var(
22
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_background
23
+ );
24
+ gap: var(--recursica_ui-kit_components_toast_properties_spacing);
25
+
26
+ & .icon {
27
+ width: var(--recursica_ui-kit_components_toast_properties_icon) !important;
28
+ height: var(--recursica_ui-kit_components_toast_properties_icon) !important;
29
+ margin-right: 0 !important; /* Override Mantine's native spacing in favor of flex gap */
30
+ background-color: transparent !important; /* Remove Mantine's native circle background */
31
+
32
+ color: var(
33
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_text
34
+ );
35
+ }
36
+
37
+ & .loader {
38
+ margin-right: 0 !important; /* Override native spacing */
39
+ }
40
+ & .title,
41
+ & .description {
42
+ color: var(
43
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_text
44
+ );
45
+ }
46
+ & .closeButton {
47
+ color: var(
48
+ --recursica_ui-kit_components_toast_variants_styles_default_properties_colors_button
49
+ );
50
+ }
51
+ }
52
+
53
+ /* ======================================
54
+ TOAST BODY
55
+ ====================================== */
56
+
57
+ .body {
58
+ /* No extra gap here, root handles icon-to-text, body can handle title-to-description if needed */
59
+ }
60
+
61
+ .title {
62
+ font-family: var(
63
+ --recursica_ui-kit_components_toast_properties_text_font-family
64
+ );
65
+ font-size: var(--recursica_ui-kit_components_toast_properties_text_font-size);
66
+ font-style: var(
67
+ --recursica_ui-kit_components_toast_properties_text_font-style
68
+ );
69
+ font-weight: var(
70
+ --recursica_ui-kit_components_toast_properties_text_font-weight
71
+ );
72
+ letter-spacing: var(
73
+ --recursica_ui-kit_components_toast_properties_text_letter-spacing
74
+ );
75
+ line-height: var(
76
+ --recursica_ui-kit_components_toast_properties_text_line-height
77
+ );
78
+ text-decoration: var(
79
+ --recursica_ui-kit_components_toast_properties_text_text-decoration
80
+ );
81
+ text-transform: var(
82
+ --recursica_ui-kit_components_toast_properties_text_text-transform
83
+ );
84
+ }
85
+
86
+ .description {
87
+ font-family: var(
88
+ --recursica_ui-kit_components_toast_properties_text_font-family
89
+ );
90
+ font-size: var(--recursica_ui-kit_components_toast_properties_text_font-size);
91
+ font-style: var(
92
+ --recursica_ui-kit_components_toast_properties_text_font-style
93
+ );
94
+ font-weight: var(
95
+ --recursica_ui-kit_components_toast_properties_text_font-weight
96
+ );
97
+ letter-spacing: var(
98
+ --recursica_ui-kit_components_toast_properties_text_letter-spacing
99
+ );
100
+ line-height: var(
101
+ --recursica_ui-kit_components_toast_properties_text_line-height
102
+ );
103
+ text-decoration: var(
104
+ --recursica_ui-kit_components_toast_properties_text_text-decoration
105
+ );
106
+ text-transform: var(
107
+ --recursica_ui-kit_components_toast_properties_text_text-transform
108
+ );
109
+ }
@@ -1,17 +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: {
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
+ },
17
+ },
18
+ },
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>;
10
34
 
11
35
  export default meta;
12
-
13
- type Story = StoryObj<typeof Toast>;
36
+ type Story = StoryObj<typeof meta>;
14
37
 
15
38
  export const Default: Story = {
16
- 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
+ },
17
67
  };
@@ -1,7 +1,93 @@
1
1
  import React from "react";
2
+ import {
3
+ Notification as MantineNotification,
4
+ type NotificationProps as MantineNotificationProps,
5
+ } from "@mantine/core";
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";
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 Mantine'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<MantineNotificationProps, "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 Mantine'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
+ <MantineNotification
78
+ ref={ref}
79
+ withCloseButton={withCloseButton}
80
+ withBorder={false} // Border is handled via CSS or tokens if needed
81
+ data-variant={variant}
82
+ classNames={mergedClassNames}
83
+ loading={false}
84
+ {...(sanitizedProps as unknown as Omit<
85
+ MantineNotificationProps,
86
+ "color" | "radius" | "variant" | "loading"
87
+ >)}
88
+ />
89
+ );
90
+ },
91
+ );
92
+
93
+ Toast.displayName = "Toast";
@@ -0,0 +1 @@
1
+ export * from "./Toast";
@@ -24,6 +24,7 @@ export * from "./Modal/Modal";
24
24
  export * from "./NumberInput/NumberInput";
25
25
  export * from "./Pagination/Pagination";
26
26
  export * from "./Panel/Panel";
27
+ export * from "./Popover";
27
28
  export * from "./Radio/Radio";
28
29
  export * from "./Radio/RadioGroup";
29
30
  export * from "./ReadOnlyField";
@@ -41,6 +42,6 @@ export * from "./TextField/TextField";
41
42
  export * from "./TimePicker/TimePicker";
42
43
  export * from "./Timeline/Timeline";
43
44
  export * from "./Title/Title";
44
- export * from "./Toast/Toast";
45
+ export * from "./Toast";
45
46
  export * from "./Tooltip/Tooltip";
46
47
  export * from "./TransferList/TransferList";