@recursica/mui-adapter 0.5.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 (159) hide show
  1. package/CHANGELOG.md +9 -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 +6652 -204
  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 +16 -2
  10. package/dist/src/components/Avatar/Avatar.d.ts +14 -2
  11. package/dist/src/components/Badge/Badge.d.ts +13 -3
  12. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +10 -3
  13. package/dist/src/components/Button/Button.d.ts +1 -1
  14. package/dist/src/components/Card/Card.d.ts +40 -3
  15. package/dist/src/components/Checkbox/Checkbox.d.ts +15 -2
  16. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +16 -0
  17. package/dist/src/components/Checkbox/index.d.ts +5 -1
  18. package/dist/src/components/Chip/Chip.d.ts +18 -2
  19. package/dist/src/components/Dropdown/Dropdown.d.ts +23 -3
  20. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +10 -2
  21. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +24 -2
  22. package/dist/src/components/HoverCard/HoverCard.d.ts +55 -3
  23. package/dist/src/components/Label/Label.d.ts +13 -2
  24. package/dist/src/components/Link/Link.d.ts +1 -1
  25. package/dist/src/components/Menu/Menu.d.ts +99 -3
  26. package/dist/src/components/Modal/Modal.d.ts +36 -2
  27. package/dist/src/components/NumberInput/NumberInput.d.ts +14 -2
  28. package/dist/src/components/Pagination/Pagination.d.ts +44 -2
  29. package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
  30. package/dist/src/components/Panel/Panel.d.ts +65 -3
  31. package/dist/src/components/Radio/Radio.d.ts +13 -3
  32. package/dist/src/components/Radio/RadioGroup.d.ts +13 -0
  33. package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
  34. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +7 -2
  35. package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
  36. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  37. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
  38. package/dist/src/components/ReadOnlyField/index.d.ts +1 -0
  39. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +31 -3
  40. package/dist/src/components/Slider/Slider.d.ts +28 -2
  41. package/dist/src/components/Stepper/Stepper.d.ts +21 -2
  42. package/dist/src/components/Switch/Switch.d.ts +10 -3
  43. package/dist/src/components/Switch/SwitchGroup.d.ts +13 -0
  44. package/dist/src/components/Tabs/Tabs.d.ts +35 -3
  45. package/dist/src/components/Text/Text.d.ts +1 -1
  46. package/dist/src/components/TextArea/TextArea.d.ts +18 -2
  47. package/dist/src/components/TextField/TextField.d.ts +16 -2
  48. package/dist/src/components/Timeline/Timeline.d.ts +14 -2
  49. package/dist/src/components/Timeline/TimelineItem.d.ts +29 -0
  50. package/dist/src/components/Title/Title.d.ts +1 -1
  51. package/dist/src/components/Toast/Toast.d.ts +25 -2
  52. package/dist/src/components/Tooltip/Tooltip.d.ts +42 -3
  53. package/dist/src/components/Typography/Typography.d.ts +1 -1
  54. package/package.json +9 -2
  55. package/src/components/Accordion/Accordion.module.css +295 -56
  56. package/src/components/Accordion/Accordion.stories.tsx +149 -21
  57. package/src/components/Accordion/Accordion.tsx +264 -5
  58. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -20
  59. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +76 -19
  60. package/src/components/AssistiveElement/AssistiveElement.tsx +85 -5
  61. package/src/components/Autocomplete/Autocomplete.module.css +320 -42
  62. package/src/components/Autocomplete/Autocomplete.stories.tsx +180 -19
  63. package/src/components/Autocomplete/Autocomplete.tsx +199 -6
  64. package/src/components/Avatar/Avatar.module.css +343 -73
  65. package/src/components/Avatar/Avatar.stories.tsx +94 -22
  66. package/src/components/Avatar/Avatar.tsx +110 -6
  67. package/src/components/Badge/Badge.module.css +127 -29
  68. package/src/components/Badge/Badge.stories.tsx +65 -22
  69. package/src/components/Badge/Badge.tsx +70 -6
  70. package/src/components/Breadcrumb/Breadcrumb.module.css +25 -5
  71. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
  72. package/src/components/Breadcrumb/Breadcrumb.tsx +62 -6
  73. package/src/components/Button/Button.module.css +3 -3
  74. package/src/components/Card/Card.module.css +118 -38
  75. package/src/components/Card/Card.stories.tsx +117 -19
  76. package/src/components/Card/Card.tsx +179 -5
  77. package/src/components/Checkbox/Checkbox.module.css +232 -39
  78. package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
  79. package/src/components/Checkbox/Checkbox.tsx +146 -5
  80. package/src/components/Checkbox/CheckboxGroup.tsx +117 -0
  81. package/src/components/Checkbox/index.ts +6 -1
  82. package/src/components/Chip/Chip.module.css +228 -43
  83. package/src/components/Chip/Chip.stories.tsx +101 -21
  84. package/src/components/Chip/Chip.tsx +138 -6
  85. package/src/components/Dropdown/Dropdown.module.css +291 -41
  86. package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
  87. package/src/components/Dropdown/Dropdown.tsx +182 -6
  88. package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
  89. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +74 -19
  90. package/src/components/FormControlLayout/FormControlLayout.tsx +58 -4
  91. package/src/components/FormControlWrapper/FormControlWrapper.module.css +96 -0
  92. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +122 -19
  93. package/src/components/FormControlWrapper/FormControlWrapper.tsx +145 -6
  94. package/src/components/HoverCard/HoverCard.module.css +90 -22
  95. package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
  96. package/src/components/HoverCard/HoverCard.tsx +150 -5
  97. package/src/components/Label/Label.module.css +136 -35
  98. package/src/components/Label/Label.stories.tsx +98 -17
  99. package/src/components/Label/Label.tsx +88 -5
  100. package/src/components/Menu/Menu.module.css +285 -51
  101. package/src/components/Menu/Menu.stories.tsx +307 -21
  102. package/src/components/Menu/Menu.tsx +318 -5
  103. package/src/components/Modal/Modal.module.css +171 -35
  104. package/src/components/Modal/Modal.stories.tsx +66 -22
  105. package/src/components/Modal/Modal.tsx +216 -4
  106. package/src/components/NumberInput/NumberInput.module.css +276 -42
  107. package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
  108. package/src/components/NumberInput/NumberInput.tsx +148 -6
  109. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  110. package/src/components/Pagination/Pagination.module.css +246 -20
  111. package/src/components/Pagination/Pagination.stories.tsx +42 -21
  112. package/src/components/Pagination/Pagination.tsx +193 -5
  113. package/src/components/Panel/Panel.module.css +206 -38
  114. package/src/components/Panel/Panel.stories.tsx +214 -22
  115. package/src/components/Panel/Panel.tsx +153 -5
  116. package/src/components/Radio/Radio.module.css +220 -37
  117. package/src/components/Radio/Radio.stories.tsx +77 -19
  118. package/src/components/Radio/Radio.tsx +178 -5
  119. package/src/components/Radio/RadioGroup.tsx +111 -0
  120. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  121. package/src/components/ReadOnlyField/ReadOnlyField.module.css +53 -15
  122. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +175 -16
  123. package/src/components/ReadOnlyField/ReadOnlyField.tsx +109 -5
  124. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  125. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  126. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  127. package/src/components/ReadOnlyField/index.ts +1 -0
  128. package/src/components/SegmentedControl/SegmentedControl.module.css +203 -47
  129. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
  130. package/src/components/SegmentedControl/SegmentedControl.tsx +110 -6
  131. package/src/components/Slider/Slider.module.css +542 -86
  132. package/src/components/Slider/Slider.stories.tsx +157 -19
  133. package/src/components/Slider/Slider.tsx +282 -5
  134. package/src/components/Stepper/Stepper.module.css +410 -71
  135. package/src/components/Stepper/Stepper.stories.tsx +132 -19
  136. package/src/components/Stepper/Stepper.tsx +145 -6
  137. package/src/components/Switch/Switch.module.css +238 -39
  138. package/src/components/Switch/Switch.stories.tsx +98 -19
  139. package/src/components/Switch/Switch.tsx +153 -6
  140. package/src/components/Switch/SwitchGroup.tsx +111 -0
  141. package/src/components/Tabs/Tabs.module.css +422 -79
  142. package/src/components/Tabs/Tabs.stories.tsx +138 -19
  143. package/src/components/Tabs/Tabs.tsx +103 -6
  144. package/src/components/TextArea/TextArea.module.css +155 -32
  145. package/src/components/TextArea/TextArea.stories.tsx +80 -21
  146. package/src/components/TextArea/TextArea.tsx +156 -6
  147. package/src/components/TextField/TextField.module.css +261 -42
  148. package/src/components/TextField/TextField.stories.tsx +168 -15
  149. package/src/components/TextField/TextField.tsx +171 -6
  150. package/src/components/Timeline/Timeline.module.css +365 -76
  151. package/src/components/Timeline/Timeline.stories.tsx +114 -21
  152. package/src/components/Timeline/Timeline.tsx +80 -5
  153. package/src/components/Timeline/TimelineItem.tsx +101 -0
  154. package/src/components/Toast/Toast.module.css +166 -28
  155. package/src/components/Toast/Toast.stories.tsx +54 -22
  156. package/src/components/Toast/Toast.tsx +90 -5
  157. package/src/components/Tooltip/Tooltip.module.css +89 -24
  158. package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
  159. package/src/components/Tooltip/Tooltip.tsx +114 -5
@@ -1,53 +1,287 @@
1
1
  /* EXEMPTIONS:
2
- This component is a placeholder stub. Once fully implemented, its specific
3
- tokens will be fully wired up to direct styles. */
4
-
5
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_border-radius */
6
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_background */
7
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-color */
8
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-opacity */
9
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_leading-icon-color */
2
+ - colors_selected-item_supporting-text-color is ignored because selected menu items do not render
3
+ supporting secondary text, making selected state overrides for supporting text colors obsolete. */
10
4
  /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_supporting-text-color */
11
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_text */
12
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_trailing-icon-color */
13
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background */
14
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-color */
15
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-opacity */
16
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_leading-icon-color */
17
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_supporting-text-color */
18
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_text */
19
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_trailing-icon-color */
20
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_disabled-opacity */
21
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_horizontal-padding */
22
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_icon-leading-size */
23
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_icon-text-gap */
24
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_icon-trailing-size */
25
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-family */
26
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-size */
27
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-style */
28
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-weight */
29
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_letter-spacing */
30
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_line-height */
31
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_text-decoration */
32
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_text-transform */
33
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text-gap */
34
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-family */
35
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-size */
36
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-style */
37
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-weight */
38
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_letter-spacing */
39
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_line-height */
40
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_text-decoration */
41
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_text-transform */
42
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_vertical-padding */
43
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_border-radius */
44
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_border-size */
45
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_colors_background */
46
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_colors_border-color */
47
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_colors_divider-color */
48
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_divider-height */
49
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_divider-opacity */
50
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_elevation */
51
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_max-height */
52
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_max-width */
53
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_min-width */
5
+
6
+ /* HARDCODED VALUES:
7
+ - border-style: solid. Structural rendering rule for the dropdown border (Mantine uses Paper which may not set border natively).
8
+ - opacity: 0.5 on disabled items. Recursica has no dedicated disabled-opacity token for menu items.
9
+ - NOTE: overflow is intentionally NOT set on .dropdown. Mantine renders sub-menu dropdowns
10
+ inside the parent dropdown DOM tree using Floating UI absolute positioning. Setting
11
+ overflow: hidden clips sub-menus; overflow-y: auto causes unwanted scrollbars.
12
+ - All structural layout (flex, cursor, pointer-events on disabled) is deferred to Mantine's
13
+ native behavior. We only override visual design tokens (colors, typography, spacing, borders).
14
+ */
15
+
16
+ /* ======================================
17
+ DROPDOWN CONTAINER
18
+ ====================================== */
19
+
20
+ .dropdown {
21
+ background-color: var(
22
+ --recursica_ui-kit_components_menu_properties_colors_background
23
+ );
24
+ border-style: solid; /* HARDCODE: Mantine Paper does not set border-style natively */
25
+ border-width: var(--recursica_ui-kit_components_menu_properties_border-size);
26
+ border-color: var(
27
+ --recursica_ui-kit_components_menu_properties_colors_border-color
28
+ );
29
+ border-radius: var(
30
+ --recursica_ui-kit_components_menu_properties_border-radius
31
+ );
32
+ box-shadow: var(--recursica_ui-kit_components_menu_properties_elevation);
33
+
34
+ min-width: var(--recursica_ui-kit_components_menu_properties_min-width);
35
+ max-height: var(--recursica_ui-kit_components_menu_properties_max-height);
36
+ max-width: var(--recursica_ui-kit_components_menu_properties_max-width);
37
+
38
+ /* HARDCODE: Figma UI Kit does not export padding tokens for the Menu container itself.
39
+ If added in the future, it would be mapped here. */
40
+ padding: 8px;
41
+ }
42
+
43
+ /* ======================================
44
+ MENU ITEM
45
+ ====================================== */
46
+
47
+ .item {
48
+ position: relative;
49
+
50
+ /* Geometry */
51
+ padding: var(
52
+ --recursica_ui-kit_components_menu-item_properties_vertical-padding
53
+ )
54
+ var(--recursica_ui-kit_components_menu-item_properties_horizontal-padding);
55
+ border-radius: var(
56
+ --recursica_ui-kit_components_menu-item_properties_border-radius
57
+ );
58
+
59
+ /* Typography */
60
+ font-family: var(
61
+ --recursica_ui-kit_components_menu-item_properties_text_font-family
62
+ );
63
+ font-size: var(
64
+ --recursica_ui-kit_components_menu-item_properties_text_font-size
65
+ );
66
+ font-style: var(
67
+ --recursica_ui-kit_components_menu-item_properties_text_font-style
68
+ );
69
+ font-weight: var(
70
+ --recursica_ui-kit_components_menu-item_properties_text_font-weight
71
+ );
72
+ letter-spacing: var(
73
+ --recursica_ui-kit_components_menu-item_properties_text_letter-spacing
74
+ );
75
+ line-height: var(
76
+ --recursica_ui-kit_components_menu-item_properties_text_line-height
77
+ );
78
+ text-decoration: var(
79
+ --recursica_ui-kit_components_menu-item_properties_text_text-decoration
80
+ );
81
+ text-transform: var(
82
+ --recursica_ui-kit_components_menu-item_properties_text_text-transform
83
+ );
84
+
85
+ /* Default State: Unselected */
86
+ background-color: var(
87
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background
88
+ );
89
+ color: var(
90
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_text
91
+ );
92
+ opacity: 1;
93
+ }
94
+
95
+ /* Override Mantine's native hover background to use our overlay technique */
96
+ .item:hover {
97
+ background-color: var(
98
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background
99
+ );
100
+ }
101
+
102
+ /* Hover overlay using ::after pseudo-element (same technique as Accordion) */
103
+ .item::after {
104
+ content: "";
105
+ position: absolute;
106
+ inset: 0;
107
+ border-radius: inherit;
108
+ z-index: 0;
109
+ pointer-events: none;
110
+ background-color: var(
111
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-color
112
+ );
113
+ opacity: 0;
114
+ transition: opacity 150ms ease;
115
+ }
116
+
117
+ .item:hover:not([data-disabled])::after {
118
+ opacity: var(
119
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-opacity
120
+ );
121
+ }
122
+
123
+ /* Selected item state */
124
+ .item[data-selected] {
125
+ background-color: var(
126
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_background
127
+ );
128
+ color: var(
129
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_text
130
+ );
131
+ opacity: 1;
132
+ }
133
+
134
+ .item[data-selected]::after {
135
+ background-color: var(
136
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-color
137
+ );
138
+ }
139
+
140
+ /* Hovered item state (keyboard navigation) */
141
+ .item[data-hovered] {
142
+ background-color: var(
143
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background
144
+ );
145
+ }
146
+ .item[data-hovered]::after {
147
+ opacity: var(
148
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-opacity
149
+ );
150
+ }
151
+
152
+ .item[data-hovered][data-selected]::after {
153
+ opacity: var(
154
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-opacity
155
+ );
156
+ }
157
+
158
+ /* Disabled item */
159
+ .item[data-disabled] {
160
+ opacity: var(
161
+ --recursica_ui-kit_components_menu-item_properties_disabled-opacity
162
+ );
163
+ }
164
+
165
+ /* ======================================
166
+ ITEM LABEL
167
+ ====================================== */
168
+
169
+ .itemLabel {
170
+ position: relative;
171
+ z-index: 1;
172
+ color: inherit;
173
+ }
174
+
175
+ /* ======================================
176
+ ITEM SECTION (LEFT / RIGHT ICONS)
177
+ ====================================== */
178
+
179
+ .itemSection {
180
+ position: relative;
181
+ z-index: 1;
182
+ }
183
+
184
+ .itemSection[data-position="left"] {
185
+ width: var(
186
+ --recursica_ui-kit_components_menu-item_properties_icon-leading-size
187
+ );
188
+ height: var(
189
+ --recursica_ui-kit_components_menu-item_properties_icon-leading-size
190
+ );
191
+ margin-right: var(
192
+ --recursica_ui-kit_components_menu-item_properties_icon-text-gap
193
+ );
194
+ color: var(
195
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_leading-icon-color
196
+ );
197
+ }
198
+
199
+ .itemSection[data-position="right"] {
200
+ width: var(
201
+ --recursica_ui-kit_components_menu-item_properties_icon-trailing-size
202
+ );
203
+ height: var(
204
+ --recursica_ui-kit_components_menu-item_properties_icon-trailing-size
205
+ );
206
+ margin-left: var(--recursica_ui-kit_components_menu-item_properties_text-gap);
207
+ color: var(
208
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_trailing-icon-color
209
+ );
210
+ }
211
+
212
+ .item[data-selected] .itemSection[data-position="left"] {
213
+ color: var(
214
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_leading-icon-color
215
+ );
216
+ }
217
+
218
+ .item[data-selected] .itemSection[data-position="right"] {
219
+ color: var(
220
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_trailing-icon-color
221
+ );
222
+ }
223
+
224
+ /* ======================================
225
+ DIVIDER
226
+ ====================================== */
227
+
228
+ .divider {
229
+ height: var(--recursica_ui-kit_components_menu_properties_divider-height);
230
+ background-color: var(
231
+ --recursica_ui-kit_components_menu_properties_colors_divider-color
232
+ );
233
+ opacity: var(--recursica_ui-kit_components_menu_properties_divider-opacity);
234
+ margin: 8px 0;
235
+ }
236
+
237
+ /* ======================================
238
+ SECTION LABEL
239
+ ====================================== */
240
+
241
+ .label {
242
+ padding: var(
243
+ --recursica_ui-kit_components_menu-item_properties_vertical-padding
244
+ )
245
+ var(--recursica_ui-kit_components_menu-item_properties_horizontal-padding);
246
+
247
+ /* Supporting Text Typography */
248
+ font-family: var(
249
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-family
250
+ );
251
+ font-size: var(
252
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-size
253
+ );
254
+ font-style: var(
255
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-style
256
+ );
257
+ font-weight: var(
258
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-weight
259
+ );
260
+ letter-spacing: var(
261
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_letter-spacing
262
+ );
263
+ line-height: var(
264
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_line-height
265
+ );
266
+ text-decoration: var(
267
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_text-decoration
268
+ );
269
+ text-transform: var(
270
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_text-transform
271
+ );
272
+
273
+ color: var(
274
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_supporting-text-color
275
+ );
276
+ opacity: 0.7;
277
+ }
278
+
279
+ /* ======================================
280
+ SUB-MENU CHEVRON
281
+ ====================================== */
282
+
283
+ .chevron {
284
+ position: relative;
285
+ z-index: 1;
286
+ color: inherit;
287
+ }
@@ -1,35 +1,321 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import { Menu } from "./Menu";
3
- import { ComingSoon } from "@recursica/storybook-template";
3
+ import { Button } from "../Button";
4
4
 
5
- const meta: Meta<typeof Menu> = {
6
- title: "UI-Kit/🚧 Menu",
5
+ /**
6
+ * Menu story axes:
7
+ * - trigger: click (default) vs hover behavior
8
+ * - position: dropdown alignment relative to target
9
+ * - withArrow: arrow indicator on the dropdown
10
+ * - content variations: icons, dividers, labels, disabled items, submenus
11
+ * - layer: tested via the global Layer decorator (withLayer/layer args)
12
+ */
13
+
14
+ const SettingsIcon = () => (
15
+ <svg
16
+ xmlns="http://www.w3.org/2000/svg"
17
+ width="14"
18
+ height="14"
19
+ viewBox="0 0 24 24"
20
+ fill="none"
21
+ stroke="currentColor"
22
+ strokeWidth="2"
23
+ strokeLinecap="round"
24
+ strokeLinejoin="round"
25
+ >
26
+ <circle cx="12" cy="12" r="3" />
27
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
28
+ </svg>
29
+ );
30
+
31
+ const SearchIcon = () => (
32
+ <svg
33
+ xmlns="http://www.w3.org/2000/svg"
34
+ width="14"
35
+ height="14"
36
+ viewBox="0 0 24 24"
37
+ fill="none"
38
+ stroke="currentColor"
39
+ strokeWidth="2"
40
+ strokeLinecap="round"
41
+ strokeLinejoin="round"
42
+ >
43
+ <circle cx="11" cy="11" r="8" />
44
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
45
+ </svg>
46
+ );
47
+
48
+ const MessageIcon = () => (
49
+ <svg
50
+ xmlns="http://www.w3.org/2000/svg"
51
+ width="14"
52
+ height="14"
53
+ viewBox="0 0 24 24"
54
+ fill="none"
55
+ stroke="currentColor"
56
+ strokeWidth="2"
57
+ strokeLinecap="round"
58
+ strokeLinejoin="round"
59
+ >
60
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
61
+ </svg>
62
+ );
63
+
64
+ const ImageIcon = () => (
65
+ <svg
66
+ xmlns="http://www.w3.org/2000/svg"
67
+ width="14"
68
+ height="14"
69
+ viewBox="0 0 24 24"
70
+ fill="none"
71
+ stroke="currentColor"
72
+ strokeWidth="2"
73
+ strokeLinecap="round"
74
+ strokeLinejoin="round"
75
+ >
76
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
77
+ <circle cx="8.5" cy="8.5" r="1.5" />
78
+ <polyline points="21 15 16 10 5 21" />
79
+ </svg>
80
+ );
81
+
82
+ const TrashIcon = () => (
83
+ <svg
84
+ xmlns="http://www.w3.org/2000/svg"
85
+ width="14"
86
+ height="14"
87
+ viewBox="0 0 24 24"
88
+ fill="none"
89
+ stroke="currentColor"
90
+ strokeWidth="2"
91
+ strokeLinecap="round"
92
+ strokeLinejoin="round"
93
+ >
94
+ <polyline points="3 6 5 6 21 6" />
95
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
96
+ </svg>
97
+ );
98
+
99
+ const ArrowsIcon = () => (
100
+ <svg
101
+ xmlns="http://www.w3.org/2000/svg"
102
+ width="14"
103
+ height="14"
104
+ viewBox="0 0 24 24"
105
+ fill="none"
106
+ stroke="currentColor"
107
+ strokeWidth="2"
108
+ strokeLinecap="round"
109
+ strokeLinejoin="round"
110
+ >
111
+ <polyline points="17 1 21 5 17 9" />
112
+ <path d="M3 11V9a4 4 0 0 1 4-4h14" />
113
+ <polyline points="7 23 3 19 7 15" />
114
+ <path d="M21 13v2a4 4 0 0 1-4 4H3" />
115
+ </svg>
116
+ );
117
+
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
+ type MenuStoryArgs = Record<string, any>;
120
+
121
+ const meta: Meta = {
122
+ title: "UI-Kit/Menu",
7
123
  component: Menu,
8
124
  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",
125
+ argTypes: {
126
+ trigger: {
127
+ control: "select",
128
+ options: ["click", "hover", "click-hover"],
129
+ description:
130
+ "Determines how the menu is triggered: click (default), hover, or both.",
131
+ },
132
+ position: {
133
+ control: "select",
134
+ options: [
135
+ "bottom",
136
+ "bottom-start",
137
+ "bottom-end",
138
+ "top",
139
+ "top-start",
140
+ "top-end",
141
+ "left",
142
+ "left-start",
143
+ "left-end",
144
+ "right",
145
+ "right-start",
146
+ "right-end",
25
147
  ],
148
+ description: "The position of the dropdown relative to the target.",
149
+ },
150
+ withArrow: {
151
+ control: "boolean",
152
+ description: "Whether to display an arrow pointing to the target.",
153
+ },
154
+ offset: {
155
+ control: "number",
156
+ description:
157
+ "Distance in px between the dropdown and the target element.",
158
+ },
159
+ opened: {
160
+ control: "boolean",
161
+ description:
162
+ "Controlled open state. Leave undefined for uncontrolled behavior.",
163
+ },
164
+ },
165
+ parameters: {
166
+ docs: {
167
+ description: {
168
+ component: `
169
+ The \`Menu\` component combines a list of secondary actions into a single interactive overlay area, wrapping Mantine's composable \`Menu\` while enforcing strict Recursica design token styling.
170
+
171
+ ### Composable API
172
+
173
+ Menu uses a dot-notation composition pattern:
174
+ - \`<Menu>\` — Root container managing open/close state
175
+ - \`<Menu.Target>\` — Wrapper for the trigger element (must be a single element supporting ref)
176
+ - \`<Menu.Dropdown>\` — The popup panel
177
+ - \`<Menu.Item>\` — An actionable item with optional \`leftSection\` / \`rightSection\`
178
+ - \`<Menu.Divider>\` — A visual separator
179
+ - \`<Menu.Label>\` — A non-interactive section header
180
+
181
+ ### Sub-menus
182
+ Nested menus are supported via \`<Menu.Sub>\`, \`<Menu.Sub.Target>\`, \`<Menu.Sub.Item>\`, and \`<Menu.Sub.Dropdown>\`.
183
+
184
+ ### Design Token Limitations
185
+ Mantine's \`color\` prop on \`Menu.Item\` is stripped in strict mode to enforce design token adherence. Use \`overStyled={true}\` to bypass this restriction.
186
+ `,
187
+ },
26
188
  },
27
189
  },
28
190
  };
29
191
 
30
192
  export default meta;
31
- type Story = StoryObj<typeof Menu>;
193
+
194
+ type Story = StoryObj<MenuStoryArgs>;
32
195
 
33
196
  export const Default: Story = {
34
- render: () => <ComingSoon componentName="Menu" />,
197
+ args: {
198
+ trigger: "click",
199
+ position: "bottom-start",
200
+ withArrow: false,
201
+ offset: 5,
202
+ opened: undefined,
203
+ },
204
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
205
+ render: ({ withLayer, layer, ...args }: MenuStoryArgs) => {
206
+ return (
207
+ <Menu {...args}>
208
+ <Menu.Target>
209
+ <Button variant="solid">Toggle Menu</Button>
210
+ </Menu.Target>
211
+
212
+ <Menu.Dropdown>
213
+ <Menu.Label>Application</Menu.Label>
214
+ <Menu.Item leftSection={<SettingsIcon />}>Settings</Menu.Item>
215
+ <Menu.Item leftSection={<MessageIcon />}>Messages</Menu.Item>
216
+ <Menu.Item leftSection={<ImageIcon />}>Gallery</Menu.Item>
217
+ <Menu.Item leftSection={<SearchIcon />}>Search</Menu.Item>
218
+
219
+ <Menu.Divider />
220
+
221
+ <Menu.Label>Danger zone</Menu.Label>
222
+ <Menu.Item leftSection={<ArrowsIcon />}>Transfer my data</Menu.Item>
223
+ <Menu.Item leftSection={<TrashIcon />}>Delete my account</Menu.Item>
224
+ </Menu.Dropdown>
225
+ </Menu>
226
+ );
227
+ },
228
+ };
229
+
230
+ export const WithDisabledItems: Story = {
231
+ args: {
232
+ position: "bottom-start",
233
+ },
234
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
235
+ render: ({ withLayer, layer, ...args }: MenuStoryArgs) => {
236
+ return (
237
+ <Menu {...args}>
238
+ <Menu.Target>
239
+ <Button variant="solid">Menu with Disabled</Button>
240
+ </Menu.Target>
241
+
242
+ <Menu.Dropdown>
243
+ <Menu.Item leftSection={<SettingsIcon />}>Settings</Menu.Item>
244
+ <Menu.Item leftSection={<SearchIcon />} disabled>
245
+ Search (disabled)
246
+ </Menu.Item>
247
+ <Menu.Item leftSection={<MessageIcon />}>Messages</Menu.Item>
248
+ <Menu.Item leftSection={<TrashIcon />} disabled>
249
+ Delete (disabled)
250
+ </Menu.Item>
251
+ </Menu.Dropdown>
252
+ </Menu>
253
+ );
254
+ },
255
+ };
256
+
257
+ export const WithSubmenus: Story = {
258
+ args: {
259
+ position: "bottom-start",
260
+ width: 200,
261
+ },
262
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
263
+ render: ({ withLayer, layer, ...args }: MenuStoryArgs) => {
264
+ return (
265
+ <Menu {...args}>
266
+ <Menu.Target>
267
+ <Button variant="solid">Menu with Submenus</Button>
268
+ </Menu.Target>
269
+
270
+ <Menu.Dropdown>
271
+ <Menu.Item>Dashboard</Menu.Item>
272
+ <Menu.Sub>
273
+ <Menu.Sub.Target>
274
+ <Menu.Sub.Item>Products</Menu.Sub.Item>
275
+ </Menu.Sub.Target>
276
+ <Menu.Sub.Dropdown>
277
+ <Menu.Item>All products</Menu.Item>
278
+ <Menu.Item>Categories</Menu.Item>
279
+ <Menu.Item>Tags</Menu.Item>
280
+ </Menu.Sub.Dropdown>
281
+ </Menu.Sub>
282
+ <Menu.Sub>
283
+ <Menu.Sub.Target>
284
+ <Menu.Sub.Item>Orders</Menu.Sub.Item>
285
+ </Menu.Sub.Target>
286
+ <Menu.Sub.Dropdown>
287
+ <Menu.Item>Open</Menu.Item>
288
+ <Menu.Item>Completed</Menu.Item>
289
+ <Menu.Item>Cancelled</Menu.Item>
290
+ </Menu.Sub.Dropdown>
291
+ </Menu.Sub>
292
+ </Menu.Dropdown>
293
+ </Menu>
294
+ );
295
+ },
296
+ };
297
+
298
+ export const HoverTrigger: Story = {
299
+ args: {
300
+ trigger: "click-hover",
301
+ position: "bottom-start",
302
+ openDelay: 100,
303
+ closeDelay: 400,
304
+ },
305
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
306
+ render: ({ withLayer, layer, ...args }: MenuStoryArgs) => {
307
+ return (
308
+ <Menu {...args}>
309
+ <Menu.Target>
310
+ <Button variant="solid">Hover or Click</Button>
311
+ </Menu.Target>
312
+
313
+ <Menu.Dropdown>
314
+ <Menu.Item leftSection={<SettingsIcon />}>Settings</Menu.Item>
315
+ <Menu.Item leftSection={<MessageIcon />}>Messages</Menu.Item>
316
+ <Menu.Item leftSection={<ImageIcon />}>Gallery</Menu.Item>
317
+ </Menu.Dropdown>
318
+ </Menu>
319
+ );
320
+ },
35
321
  };