@recursica/mantine-adapter 0.6.0 → 0.7.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 (140) hide show
  1. package/.storybook/commonArgTypes.ts +148 -0
  2. package/CHANGELOG.md +69 -0
  3. package/dist/mantine-adapter.cjs +1 -1
  4. package/dist/mantine-adapter.cjs.map +1 -1
  5. package/dist/mantine-adapter.css +1 -1
  6. package/dist/mantine-adapter.js +660 -586
  7. package/dist/mantine-adapter.js.map +1 -1
  8. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +1 -1
  9. package/dist/src/components/Chip/Chip.d.ts +14 -2
  10. package/package.json +5 -2
  11. package/src/OverStyling.stories.tsx +174 -0
  12. package/src/Version.stories.tsx +56 -0
  13. package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +48 -0
  14. package/src/components/Accordion/Accordion.module.css +261 -0
  15. package/src/components/Accordion/Accordion.stories.tsx +145 -0
  16. package/src/components/Accordion/Accordion.tsx +200 -0
  17. package/src/components/Accordion/index.ts +1 -0
  18. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
  19. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +73 -0
  20. package/src/components/AssistiveElement/AssistiveElement.tsx +91 -0
  21. package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +24 -0
  22. package/src/components/Avatar/Avatar.module.css +340 -0
  23. package/src/components/Avatar/Avatar.stories.tsx +102 -0
  24. package/src/components/Avatar/Avatar.tsx +100 -0
  25. package/src/components/Avatar/index.ts +1 -0
  26. package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
  27. package/src/components/Badge/Badge.module.css +124 -0
  28. package/src/components/Badge/Badge.stories.tsx +77 -0
  29. package/src/components/Badge/Badge.tsx +66 -0
  30. package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +14 -0
  31. package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
  32. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +77 -0
  33. package/src/components/Breadcrumb/Breadcrumb.tsx +64 -0
  34. package/src/components/Button/Button.module.css +275 -0
  35. package/src/components/Button/Button.stories.tsx +105 -0
  36. package/src/components/Button/Button.tsx +122 -0
  37. package/src/components/Button/IMPLEMENTATION_NOTES.md +45 -0
  38. package/src/components/Button/index.ts +1 -0
  39. package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +10 -0
  40. package/src/components/Card/Card.module.css +60 -0
  41. package/src/components/Card/Card.stories.tsx +141 -0
  42. package/src/components/Card/Card.tsx +176 -0
  43. package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
  44. package/src/components/Checkbox/Checkbox.module.css +204 -0
  45. package/src/components/Checkbox/Checkbox.stories.tsx +73 -0
  46. package/src/components/Checkbox/Checkbox.tsx +111 -0
  47. package/src/components/Checkbox/CheckboxGroup.stories.tsx +138 -0
  48. package/src/components/Checkbox/CheckboxGroup.tsx +140 -0
  49. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +35 -0
  50. package/src/components/Chip/Chip.module.css +218 -0
  51. package/src/components/Chip/Chip.stories.tsx +115 -0
  52. package/src/components/Chip/Chip.tsx +143 -0
  53. package/src/components/DatePicker/DatePicker.stories.tsx +22 -0
  54. package/src/components/DatePicker/DatePicker.tsx +7 -0
  55. package/src/components/Dropdown/Dropdown.stories.tsx +22 -0
  56. package/src/components/Dropdown/Dropdown.tsx +7 -0
  57. package/src/components/FileInput/FileInput.stories.tsx +22 -0
  58. package/src/components/FileInput/FileInput.tsx +7 -0
  59. package/src/components/FileUpload/FileUpload.stories.tsx +22 -0
  60. package/src/components/FileUpload/FileUpload.tsx +7 -0
  61. package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
  62. package/src/components/FormControlWrapper/FormControlWrapper.module.css +46 -0
  63. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -0
  64. package/src/components/FormControlWrapper/FormControlWrapper.tsx +170 -0
  65. package/src/components/HoverCard/HoverCard.stories.tsx +17 -0
  66. package/src/components/HoverCard/HoverCard.tsx +7 -0
  67. package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
  68. package/src/components/Label/Label.module.css +177 -0
  69. package/src/components/Label/Label.stories.tsx +123 -0
  70. package/src/components/Label/Label.tsx +132 -0
  71. package/src/components/Label/index.ts +1 -0
  72. package/src/components/Link/Link.stories.tsx +17 -0
  73. package/src/components/Link/Link.tsx +7 -0
  74. package/src/components/Loader/Loader.stories.tsx +17 -0
  75. package/src/components/Loader/Loader.tsx +7 -0
  76. package/src/components/Menu/Menu.stories.tsx +17 -0
  77. package/src/components/Menu/Menu.tsx +7 -0
  78. package/src/components/Modal/Modal.stories.tsx +17 -0
  79. package/src/components/Modal/Modal.tsx +7 -0
  80. package/src/components/NumberInput/NumberInput.stories.tsx +22 -0
  81. package/src/components/NumberInput/NumberInput.tsx +7 -0
  82. package/src/components/Pagination/Pagination.stories.tsx +17 -0
  83. package/src/components/Pagination/Pagination.tsx +7 -0
  84. package/src/components/Panel/Panel.stories.tsx +17 -0
  85. package/src/components/Panel/Panel.tsx +7 -0
  86. package/src/components/Popover/Popover.stories.tsx +17 -0
  87. package/src/components/Popover/Popover.tsx +7 -0
  88. package/src/components/Radio/Radio.stories.tsx +22 -0
  89. package/src/components/Radio/Radio.tsx +7 -0
  90. package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
  91. package/src/components/ReadOnlyField/ReadOnlyField.module.css +49 -0
  92. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +120 -0
  93. package/src/components/ReadOnlyField/ReadOnlyField.tsx +75 -0
  94. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +46 -0
  95. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +85 -0
  96. package/src/components/ReadOnlyField/index.ts +3 -0
  97. package/src/components/Search/Search.stories.tsx +17 -0
  98. package/src/components/Search/Search.tsx +7 -0
  99. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +22 -0
  100. package/src/components/SegmentedControl/SegmentedControl.tsx +7 -0
  101. package/src/components/Slider/Slider.stories.tsx +22 -0
  102. package/src/components/Slider/Slider.tsx +7 -0
  103. package/src/components/Stepper/Stepper.stories.tsx +17 -0
  104. package/src/components/Stepper/Stepper.tsx +7 -0
  105. package/src/components/Switch/Switch.stories.tsx +22 -0
  106. package/src/components/Switch/Switch.tsx +7 -0
  107. package/src/components/Table/Table.stories.tsx +17 -0
  108. package/src/components/Table/Table.tsx +7 -0
  109. package/src/components/Tabs/Tabs.stories.tsx +17 -0
  110. package/src/components/Tabs/Tabs.tsx +7 -0
  111. package/src/components/Text/Text.stories.tsx +88 -0
  112. package/src/components/Text/Text.tsx +54 -0
  113. package/src/components/TextArea/TextArea.stories.tsx +22 -0
  114. package/src/components/TextArea/TextArea.tsx +7 -0
  115. package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
  116. package/src/components/TextField/TextField.module.css +225 -0
  117. package/src/components/TextField/TextField.stories.tsx +162 -0
  118. package/src/components/TextField/TextField.tsx +138 -0
  119. package/src/components/TimePicker/TimePicker.stories.tsx +22 -0
  120. package/src/components/TimePicker/TimePicker.tsx +7 -0
  121. package/src/components/Timeline/Timeline.stories.tsx +17 -0
  122. package/src/components/Timeline/Timeline.tsx +7 -0
  123. package/src/components/Title/Title.stories.tsx +63 -0
  124. package/src/components/Title/Title.tsx +45 -0
  125. package/src/components/Toast/Toast.stories.tsx +17 -0
  126. package/src/components/Toast/Toast.tsx +7 -0
  127. package/src/components/Tooltip/Tooltip.stories.tsx +17 -0
  128. package/src/components/Tooltip/Tooltip.tsx +7 -0
  129. package/src/components/TransferList/TransferList.stories.tsx +17 -0
  130. package/src/components/TransferList/TransferList.tsx +7 -0
  131. package/src/components/index.ts +39 -0
  132. package/src/env.d.ts +7 -0
  133. package/src/index.ts +3 -0
  134. package/src/types/index.ts +9 -0
  135. package/src/types/mantine.d.ts +7 -0
  136. package/src/types/scss-modules.d.ts +9 -0
  137. package/src/utils/ColorSchemeWrapper.tsx +27 -0
  138. package/src/utils/copyToClipboard.ts +36 -0
  139. package/src/utils/filterStylingProps.ts +139 -0
  140. package/src/utils/index.ts +1 -0
@@ -0,0 +1,77 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Badge } from "./Badge";
4
+ import { Layer } from "@recursica/adapter-common";
5
+
6
+ type BadgeStoryProps = React.ComponentProps<typeof Badge>;
7
+
8
+ const meta: Meta<BadgeStoryProps> = {
9
+ title: "UI-Kit/Badge",
10
+ component: Badge,
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ variant: {
14
+ control: "select",
15
+ options: ["alert", "primary-color", "success", "warning"],
16
+ description: "The style / intent mapping for the badge",
17
+ },
18
+ },
19
+ };
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<BadgeStoryProps>;
24
+
25
+ export const Default: Story = {
26
+ args: {
27
+ children: "Badge Label",
28
+ variant: "primary-color",
29
+ },
30
+ render: (args) => {
31
+ return <Badge {...args} />;
32
+ },
33
+ };
34
+
35
+ export const StaticAlert: Story = {
36
+ args: {
37
+ children: "Alert Badge",
38
+ variant: "alert",
39
+ },
40
+ render: (args: BadgeStoryProps) => <Badge {...args} />,
41
+ };
42
+
43
+ export const StaticPrimary: Story = {
44
+ args: {
45
+ children: "Primary Badge",
46
+ variant: "primary-color",
47
+ },
48
+ render: (args: BadgeStoryProps) => <Badge {...args} />,
49
+ };
50
+
51
+ export const StaticSuccess: Story = {
52
+ args: {
53
+ children: "Success Badge",
54
+ variant: "success",
55
+ },
56
+ render: (args: BadgeStoryProps) => <Badge {...args} />,
57
+ };
58
+
59
+ export const StaticWarning: Story = {
60
+ args: {
61
+ children: "Warning Badge",
62
+ variant: "warning",
63
+ },
64
+ render: (args: BadgeStoryProps) => <Badge {...args} />,
65
+ };
66
+
67
+ export const LayerOneAlert: Story = {
68
+ args: {
69
+ children: "Layer 1 Alert",
70
+ variant: "alert",
71
+ },
72
+ render: (args: BadgeStoryProps) => (
73
+ <Layer layer={1} style={{ padding: "24px" }}>
74
+ <Badge {...args} />
75
+ </Layer>
76
+ ),
77
+ };
@@ -0,0 +1,66 @@
1
+ import { forwardRef } from "react";
2
+ import {
3
+ Badge as MantineBadge,
4
+ type BadgeProps as MantineBadgeProps,
5
+ } from "@mantine/core";
6
+ import {
7
+ filterStylingProps,
8
+ type RecursicaOverStyled,
9
+ } from "../../utils/filterStylingProps";
10
+ import styles from "./Badge.module.css";
11
+
12
+ export interface RecursicaBadgeProps {
13
+ /** Map to the component styles defined in variables */
14
+ variant?: "alert" | "primary-color" | "success" | "warning";
15
+ }
16
+
17
+ export type BadgeProps = RecursicaOverStyled<
18
+ Omit<MantineBadgeProps, "variant" | "size" | "color" | "radius"> &
19
+ RecursicaBadgeProps
20
+ >;
21
+
22
+ export const Badge = forwardRef<HTMLDivElement, BadgeProps>(function Badge(
23
+ { variant = "primary-color", overStyled = false, ...rest },
24
+ ref,
25
+ ) {
26
+ // Strip all visual override injections unless developer has specifically opted into overStyling.
27
+ // External layout props like margins are safely preserved.
28
+ const sanitizedProps = filterStylingProps(rest, overStyled);
29
+
30
+ const mergedClassNames: Partial<Record<string, string>> = {
31
+ root: styles.root,
32
+ section: styles.section,
33
+ label: styles.label,
34
+ };
35
+
36
+ const classNamesProp = (sanitizedProps as Record<string, unknown>).classNames;
37
+ if (
38
+ classNamesProp &&
39
+ typeof classNamesProp === "object" &&
40
+ !Array.isArray(classNamesProp)
41
+ ) {
42
+ const o = classNamesProp as Partial<Record<string, string>>;
43
+ mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
44
+ mergedClassNames.section = o.section ?? styles.section;
45
+ mergedClassNames.label = o.label ?? styles.label;
46
+ }
47
+
48
+ const classNameProp = (sanitizedProps as Record<string, unknown>)
49
+ .className as string | undefined;
50
+ const finalClass = classNameProp
51
+ ? `${styles.root} ${classNameProp}`
52
+ : styles.root;
53
+
54
+ return (
55
+ <MantineBadge
56
+ ref={ref}
57
+ variant="filled" // We manage visual style purely through our CSS variables mapping
58
+ data-variant={variant}
59
+ {...sanitizedProps}
60
+ className={finalClass}
61
+ classNames={mergedClassNames}
62
+ />
63
+ );
64
+ });
65
+
66
+ Badge.displayName = "Badge";
@@ -0,0 +1,14 @@
1
+ # Breadcrumb Implementation Notes
2
+
3
+ ## Missing Variants and Sizes
4
+
5
+ The `Breadcrumb` currently does not establish any size (`xs`, `sm`, etc.) or variant variables in the underlying design tokens (`recursica_ui-kit.json`). Only basic structural definitions for `padding` and `item-gap` exist. Because of this, the `size` and `variant` properties have been explicitly omitted from the passed mantine props.
6
+
7
+ ## Gap Styling
8
+
9
+ We attach `gap` to `.root` directly within `.module.css`. Mantine's inner `separator` divs can natively accept our CSS variables for structural layout.
10
+
11
+ ## Composition and Separators
12
+
13
+ We preserve standard hierarchical composition based on Mantine's defaults. The component natively accepts typical anchor tags as children without wrapping them in structural spans, allowing developers to utilize `Link` wrappers as needed contextually.
14
+ The separator character is inherited natively from Mantine's default configuration (`/`) unless overridden by passing `separator={<Icon />}` to the component props.
@@ -0,0 +1,26 @@
1
+ /* HARDCODED VALUES:
2
+ - align-items: center
3
+ */
4
+
5
+ .root {
6
+ /* HARDCODE: Basic structural flex layout for breadcrumbs */
7
+ display: flex;
8
+ align-items: center;
9
+
10
+ /* Base style resets */
11
+ background-color: transparent;
12
+ color: inherit;
13
+
14
+ /* Apply global breadcrumb properties */
15
+ padding: var(--recursica_ui-kit_components_breadcrumb_properties_padding);
16
+
17
+ /* Mantine's breadcrumbs uses gap on the root or pseudo classes, but standard gap is safest since flex is used */
18
+ gap: var(--recursica_ui-kit_components_breadcrumb_properties_item-gap);
19
+ }
20
+
21
+ .separator {
22
+ /* Separator base resets if needed */
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ }
@@ -0,0 +1,77 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Breadcrumb } from "./Breadcrumb";
4
+
5
+ type BreadcrumbStoryProps = React.ComponentProps<typeof Breadcrumb> & {
6
+ items?: string[];
7
+ };
8
+
9
+ const meta: Meta<BreadcrumbStoryProps> = {
10
+ title: "UI-Kit/Breadcrumb",
11
+ component: Breadcrumb,
12
+ tags: ["autodocs"],
13
+ argTypes: {
14
+ children: {
15
+ table: {
16
+ disable: true,
17
+ },
18
+ },
19
+ items: {
20
+ control: "object",
21
+ description:
22
+ "Array of string labels used to dynamically generate the interactive Breadcrumb nodes.",
23
+ table: {
24
+ category: "Story Controls",
25
+ },
26
+ },
27
+ separator: {
28
+ control: "text",
29
+ description: "Custom separator between items",
30
+ },
31
+ },
32
+ args: {
33
+ items: ["Home", "Components", "Breadcrumbs"],
34
+ },
35
+ render: ({ items, children, ...args }) => {
36
+ const mappedChildren = items
37
+ ? items.map((label, index) => (
38
+ <a
39
+ href="#"
40
+ key={index}
41
+ style={{
42
+ color:
43
+ "var(--recursica_brand_palettes_primary_default_color_tone)",
44
+ textDecoration: "none",
45
+ }}
46
+ >
47
+ {label}
48
+ </a>
49
+ ))
50
+ : children;
51
+
52
+ return <Breadcrumb children={mappedChildren} {...args} />;
53
+ },
54
+ };
55
+
56
+ export default meta;
57
+
58
+ type Story = StoryObj<BreadcrumbStoryProps>;
59
+
60
+ export const Default: Story = {
61
+ args: {
62
+ items: ["Dashboard", "Settings", "Security"],
63
+ },
64
+ };
65
+
66
+ export const StaticExample: Story = {
67
+ args: {
68
+ items: ["Store", "Electronics", "Computers", "Laptops"],
69
+ },
70
+ };
71
+
72
+ export const CustomSeparator: Story = {
73
+ args: {
74
+ items: ["Root", "Branch", "Leaf"],
75
+ separator: "→",
76
+ },
77
+ };
@@ -0,0 +1,64 @@
1
+ import { forwardRef } from "react";
2
+ import {
3
+ Breadcrumbs as MantineBreadcrumbs,
4
+ type BreadcrumbsProps as MantineBreadcrumbsProps,
5
+ } from "@mantine/core";
6
+ import {
7
+ filterStylingProps,
8
+ type RecursicaOverStyled,
9
+ } from "../../utils/filterStylingProps";
10
+ import styles from "./Breadcrumb.module.css";
11
+
12
+ // Currently there are no Recursica prop additions specific to Breadcrumbs (like size or variant)
13
+ // according to recursica_ui-kit.json
14
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
15
+ export interface RecursicaBreadcrumbProps {}
16
+
17
+ export type BreadcrumbProps = RecursicaOverStyled<
18
+ Omit<MantineBreadcrumbsProps, "variant" | "size"> & RecursicaBreadcrumbProps
19
+ >;
20
+
21
+ export const Breadcrumb = forwardRef<HTMLDivElement, BreadcrumbProps>(
22
+ function Breadcrumb({ overStyled = false, separator = ">", ...rest }, ref) {
23
+ const sanitizedProps = filterStylingProps(
24
+ { separator, ...rest },
25
+ overStyled,
26
+ );
27
+
28
+ const mergedClassNames: Partial<Record<string, string>> = {
29
+ root: styles.root,
30
+ separator: styles.separator,
31
+ };
32
+
33
+ const classNamesProp = (sanitizedProps as Record<string, unknown>)
34
+ .classNames;
35
+ if (
36
+ classNamesProp &&
37
+ typeof classNamesProp === "object" &&
38
+ !Array.isArray(classNamesProp)
39
+ ) {
40
+ const o = classNamesProp as Partial<Record<string, string>>;
41
+ mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
42
+ mergedClassNames.separator = o.separator
43
+ ? `${styles.separator} ${o.separator}`
44
+ : styles.separator;
45
+ }
46
+
47
+ const classNameProp = (sanitizedProps as Record<string, unknown>)
48
+ .className as string | undefined;
49
+ const finalClass = classNameProp
50
+ ? `${styles.root} ${classNameProp}`
51
+ : styles.root;
52
+
53
+ return (
54
+ <MantineBreadcrumbs
55
+ ref={ref}
56
+ {...(sanitizedProps as unknown as MantineBreadcrumbsProps)}
57
+ className={finalClass}
58
+ classNames={mergedClassNames}
59
+ />
60
+ );
61
+ },
62
+ );
63
+
64
+ Breadcrumb.displayName = "Breadcrumb";
@@ -0,0 +1,275 @@
1
+ /* Baseline and Reset */
2
+ .root {
3
+ box-sizing: border-box;
4
+ margin: 0;
5
+ border-style: solid;
6
+ overflow: hidden; /* Truncation bounding box */
7
+ position: relative;
8
+ transition: all 0.2s ease;
9
+
10
+ /* Shared Defaults */
11
+ font-family: var(
12
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
13
+ );
14
+ font-size: var(
15
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
16
+ );
17
+ font-style: var(
18
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-style
19
+ );
20
+ font-weight: var(
21
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
22
+ );
23
+ letter-spacing: var(
24
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_letter-spacing
25
+ );
26
+ line-height: var(
27
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_line-height
28
+ );
29
+ text-decoration: var(
30
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-decoration
31
+ );
32
+ text-transform: var(
33
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-transform
34
+ );
35
+ }
36
+
37
+ /* Internal Mantine reset & layout logic for Truncation */
38
+ .root > * {
39
+ min-width: 0;
40
+ width: 100%;
41
+ position: relative;
42
+ z-index: 1;
43
+ }
44
+
45
+ .label {
46
+ display: flex;
47
+ align-items: center;
48
+ min-width: 0;
49
+ flex: 1 1 0;
50
+ }
51
+
52
+ .labelText {
53
+ display: block;
54
+ min-width: 0;
55
+ width: 100%;
56
+ overflow: hidden;
57
+ text-overflow: ellipsis;
58
+ white-space: nowrap;
59
+ font-size: inherit;
60
+ line-height: inherit;
61
+ }
62
+
63
+ /* ==== SIZES ==== */
64
+ .root[data-size="default"] {
65
+ border-radius: var(
66
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_border-radius
67
+ );
68
+ height: var(
69
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_height
70
+ );
71
+ min-width: var(
72
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_min-width
73
+ );
74
+ padding: 0
75
+ var(
76
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_horizontal-padding
77
+ );
78
+ }
79
+ .root[data-size="small"] {
80
+ border-radius: var(
81
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_border-radius
82
+ );
83
+ height: var(
84
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_height
85
+ );
86
+ min-width: var(
87
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_min-width
88
+ );
89
+ padding: 0
90
+ var(
91
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_horizontal-padding
92
+ );
93
+
94
+ /* Override specific typography for small */
95
+ font-family: var(
96
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-family,
97
+ var(
98
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
99
+ )
100
+ );
101
+ font-size: var(
102
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-size,
103
+ var(
104
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
105
+ )
106
+ );
107
+ font-weight: var(
108
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-weight,
109
+ var(
110
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
111
+ )
112
+ );
113
+ }
114
+
115
+ /* Icon Resets */
116
+ .iconWrapper {
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ flex-shrink: 0;
121
+ }
122
+ .iconWrapper > * {
123
+ width: 100%;
124
+ height: 100%;
125
+ object-fit: contain;
126
+ }
127
+ .root[data-size="default"] .iconWrapper {
128
+ width: var(
129
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_icon
130
+ );
131
+ height: var(
132
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_icon
133
+ );
134
+ }
135
+ .root[data-size="small"] .iconWrapper {
136
+ width: var(
137
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_icon
138
+ );
139
+ height: var(
140
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_icon
141
+ );
142
+ }
143
+
144
+ .section {
145
+ min-width: 0;
146
+ }
147
+ .root[data-size="default"] .section {
148
+ gap: var(
149
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_icon-text-gap
150
+ );
151
+ }
152
+ .root[data-size="small"] .section {
153
+ gap: var(
154
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_icon-text-gap
155
+ );
156
+ }
157
+
158
+ /* Icon-only logic overrides */
159
+ .root[data-icon-only] .section {
160
+ gap: 0;
161
+ }
162
+ .root[data-icon-only] .section[data-position="left"] {
163
+ margin-inline-end: 0;
164
+ }
165
+ .root[data-icon-only] .section[data-position="right"] {
166
+ margin-inline-start: 0;
167
+ }
168
+
169
+ /* Disabled */
170
+ .root:disabled {
171
+ opacity: var(--recursica_brand_states_disabled);
172
+ cursor: not-allowed;
173
+ }
174
+
175
+ /* Global Hover Hack Overlay */
176
+ .root::after {
177
+ content: "";
178
+ position: absolute;
179
+ inset: 0;
180
+ border-radius: inherit;
181
+ z-index: 0;
182
+ pointer-events: none;
183
+ transition: opacity 150ms ease;
184
+ opacity: 0;
185
+ }
186
+ .root[data-size="default"]::after {
187
+ background-color: var(
188
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_hover-color
189
+ );
190
+ }
191
+ .root[data-size="small"]::after {
192
+ background-color: var(
193
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_hover-color
194
+ );
195
+ }
196
+ .root:hover:not(:disabled)::after {
197
+ opacity: var(
198
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_hover-opacity,
199
+ 0.1
200
+ );
201
+ }
202
+
203
+ /* ==== VARIANTS ==== */
204
+
205
+ /* SOLID */
206
+ .root[data-variant="solid"] {
207
+ border-width: var(
208
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_border-size
209
+ );
210
+ box-shadow: var(
211
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_elevation
212
+ );
213
+ background-color: var(
214
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_background
215
+ );
216
+ border-color: var(
217
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_border-color
218
+ );
219
+ color: var(
220
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text
221
+ );
222
+ }
223
+ .root[data-variant="solid"]:hover:not(:disabled) {
224
+ color: var(
225
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text-hover
226
+ );
227
+ }
228
+
229
+ /* OUTLINE */
230
+ .root[data-variant="outline"] {
231
+ border-width: var(
232
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_border-size
233
+ );
234
+ box-shadow: var(
235
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_elevation
236
+ );
237
+ background-color: var(
238
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_background
239
+ );
240
+ border-color: var(
241
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_border-color
242
+ );
243
+ color: var(
244
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text
245
+ );
246
+ }
247
+ .root[data-variant="outline"]:hover:not(:disabled) {
248
+ color: var(
249
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text-hover
250
+ );
251
+ }
252
+
253
+ /* TEXT */
254
+ .root[data-variant="text"] {
255
+ border-width: var(
256
+ --recursica_ui-kit_components_button_variants_styles_text_properties_border-size
257
+ );
258
+ box-shadow: var(
259
+ --recursica_ui-kit_components_button_variants_styles_text_properties_elevation
260
+ );
261
+ background-color: var(
262
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_background
263
+ );
264
+ border-color: var(
265
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_border-color
266
+ );
267
+ color: var(
268
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_text
269
+ );
270
+ }
271
+ .root[data-variant="text"]:hover:not(:disabled) {
272
+ color: var(
273
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_text-hover
274
+ );
275
+ }
@@ -0,0 +1,105 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Button } from "./Button";
4
+ import { Layer } from "@recursica/adapter-common";
5
+
6
+ type ButtonStoryProps = React.ComponentProps<typeof Button>;
7
+
8
+ const meta: Meta<ButtonStoryProps> = {
9
+ title: "UI-Kit/Button",
10
+ component: Button,
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ variant: {
14
+ control: "select",
15
+ options: ["solid", "outline", "text"],
16
+ description: "The visual variant of the button",
17
+ },
18
+ size: {
19
+ control: "radio",
20
+ options: ["default", "small"],
21
+ description: "The size of the button",
22
+ },
23
+ disabled: {
24
+ control: "boolean",
25
+ },
26
+ },
27
+ };
28
+
29
+ export default meta;
30
+
31
+ type Story = StoryObj<ButtonStoryProps>;
32
+
33
+ export const Default: Story = {
34
+ args: {
35
+ children: "Explore Button",
36
+ variant: "solid",
37
+ size: "default",
38
+ disabled: false,
39
+ },
40
+ render: (args) => {
41
+ return <Button {...args} />;
42
+ },
43
+ };
44
+
45
+ export const SolidDefault: Story = {
46
+ args: {
47
+ children: "Solid Default",
48
+ variant: "solid",
49
+ size: "default",
50
+ },
51
+ };
52
+
53
+ export const OutlineSmall: Story = {
54
+ args: {
55
+ children: "Outline Small",
56
+ variant: "outline",
57
+ size: "small",
58
+ },
59
+ };
60
+
61
+ export const TextWithIcon: Story = {
62
+ args: {
63
+ children: "Text With Icon",
64
+ variant: "text",
65
+ size: "default",
66
+ icon: (
67
+ <svg
68
+ xmlns="http://www.w3.org/2000/svg"
69
+ width="24"
70
+ height="24"
71
+ viewBox="0 0 24 24"
72
+ fill="none"
73
+ stroke="currentColor"
74
+ strokeWidth="2"
75
+ strokeLinecap="round"
76
+ strokeLinejoin="round"
77
+ >
78
+ <circle cx="11" cy="11" r="8"></circle>
79
+ <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
80
+ </svg>
81
+ ),
82
+ },
83
+ };
84
+
85
+ export const LayerOneSolid: Story = {
86
+ args: {
87
+ children: "Layer 1 Solid",
88
+ variant: "solid",
89
+ size: "default",
90
+ },
91
+ render: (args: ButtonStoryProps) => (
92
+ <Layer layer={1} style={{ padding: "24px" }}>
93
+ <Button {...args} />
94
+ </Layer>
95
+ ),
96
+ };
97
+
98
+ export const DisabledSolid: Story = {
99
+ args: {
100
+ children: "Disabled Solid",
101
+ variant: "solid",
102
+ size: "default",
103
+ disabled: true,
104
+ },
105
+ };