@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.
- package/CHANGELOG.md +6 -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 +1642 -1357
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/Modal/Modal.d.ts +39 -2
- package/dist/src/components/Modal/index.d.ts +1 -0
- package/dist/src/components/Popover/Popover.d.ts +55 -0
- package/dist/src/components/Popover/index.d.ts +1 -0
- package/dist/src/components/Timeline/Timeline.d.ts +14 -2
- package/dist/src/components/Timeline/TimelineItem.d.ts +25 -0
- package/dist/src/components/Toast/Toast.d.ts +21 -2
- package/dist/src/components/Toast/index.d.ts +1 -0
- package/dist/src/components/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/Modal/Modal.module.css +127 -0
- package/src/components/Modal/Modal.stories.tsx +66 -4
- package/src/components/Modal/Modal.tsx +218 -3
- package/src/components/Modal/index.ts +1 -0
- package/src/components/Popover/IMPLEMENTATION_NOTES.md +77 -0
- package/src/components/Popover/Popover.module.css +84 -0
- package/src/components/Popover/Popover.stories.tsx +133 -0
- package/src/components/Popover/Popover.tsx +156 -0
- package/src/components/Popover/index.ts +1 -0
- package/src/components/Timeline/TIMELINE_IMPLEMENTATION_NOTES.md +13 -0
- package/src/components/Timeline/Timeline.module.css +361 -0
- package/src/components/Timeline/Timeline.stories.tsx +114 -3
- package/src/components/Timeline/Timeline.tsx +81 -4
- package/src/components/Timeline/TimelineItem.tsx +102 -0
- package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +39 -0
- package/src/components/Toast/Toast.module.css +109 -0
- package/src/components/Toast/Toast.stories.tsx +57 -7
- package/src/components/Toast/Toast.tsx +90 -4
- package/src/components/Toast/index.ts +1 -0
- 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
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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
|
|
12
|
+
export interface RecursicaToastProps {
|
|
13
|
+
/**
|
|
14
|
+
* The visual variant of the toast.
|
|
15
|
+
* @default "default"
|
|
16
|
+
*/
|
|
17
|
+
variant?: "default";
|
|
4
18
|
|
|
5
|
-
|
|
6
|
-
|
|
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";
|
package/src/components/index.ts
CHANGED
|
@@ -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
|
|
45
|
+
export * from "./Toast";
|
|
45
46
|
export * from "./Tooltip/Tooltip";
|
|
46
47
|
export * from "./TransferList/TransferList";
|