@memori.ai/ui 1.0.0-alpha

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 (274) hide show
  1. package/README.md +105 -0
  2. package/dist/components/Alert/Alert.d.ts +18 -0
  3. package/dist/components/Alert/index.d.ts +2 -0
  4. package/dist/components/Button/Button.d.ts +27 -0
  5. package/dist/components/Button/index.d.ts +2 -0
  6. package/dist/components/ButtonBase/ButtonBase.d.ts +28 -0
  7. package/dist/components/ButtonBase/index.d.ts +3 -0
  8. package/dist/components/Card/Card.d.ts +13 -0
  9. package/dist/components/Card/index.d.ts +2 -0
  10. package/dist/components/Checkbox/Checkbox.d.ts +11 -0
  11. package/dist/components/Checkbox/index.d.ts +2 -0
  12. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +12 -0
  13. package/dist/components/ConfirmDialog/index.d.ts +2 -0
  14. package/dist/components/Drawer/Drawer.d.ts +32 -0
  15. package/dist/components/Drawer/index.d.ts +2 -0
  16. package/dist/components/Dropdown/Dropdown.d.ts +11 -0
  17. package/dist/components/Dropdown/index.d.ts +2 -0
  18. package/dist/components/Expandable/Expandable.d.ts +15 -0
  19. package/dist/components/Expandable/helpers.d.ts +3 -0
  20. package/dist/components/Expandable/index.d.ts +2 -0
  21. package/dist/components/InputBase/InputBase.d.ts +49 -0
  22. package/dist/components/InputBase/index.d.ts +3 -0
  23. package/dist/components/Modal/Modal.d.ts +16 -0
  24. package/dist/components/Modal/index.d.ts +2 -0
  25. package/dist/components/Select/Select.d.ts +16 -0
  26. package/dist/components/Select/index.d.ts +2 -0
  27. package/dist/components/Slider/Slider.d.ts +12 -0
  28. package/dist/components/Slider/index.d.ts +2 -0
  29. package/dist/components/Spin/Spin.d.ts +9 -0
  30. package/dist/components/Spin/index.d.ts +2 -0
  31. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  32. package/dist/components/Tooltip/index.d.ts +2 -0
  33. package/dist/i18n/I18nWrapper.d.ts +6 -0
  34. package/dist/icons/AI.d.ts +5 -0
  35. package/dist/icons/Alert.d.ts +5 -0
  36. package/dist/icons/ArrowUp.d.ts +5 -0
  37. package/dist/icons/Bug.d.ts +5 -0
  38. package/dist/icons/Chat.d.ts +5 -0
  39. package/dist/icons/ChevronDown.d.ts +5 -0
  40. package/dist/icons/ChevronLeft.d.ts +5 -0
  41. package/dist/icons/ChevronRight.d.ts +5 -0
  42. package/dist/icons/ChevronUp.d.ts +5 -0
  43. package/dist/icons/Clear.d.ts +5 -0
  44. package/dist/icons/Close.d.ts +6 -0
  45. package/dist/icons/Code.d.ts +5 -0
  46. package/dist/icons/Copy.d.ts +5 -0
  47. package/dist/icons/DeepThought.d.ts +5 -0
  48. package/dist/icons/Delete.d.ts +5 -0
  49. package/dist/icons/Document.d.ts +5 -0
  50. package/dist/icons/Download.d.ts +5 -0
  51. package/dist/icons/Edit.d.ts +5 -0
  52. package/dist/icons/Expand.d.ts +5 -0
  53. package/dist/icons/Eye.d.ts +5 -0
  54. package/dist/icons/EyeInvisible.d.ts +5 -0
  55. package/dist/icons/Facebook.d.ts +5 -0
  56. package/dist/icons/Feedback.d.ts +5 -0
  57. package/dist/icons/File.d.ts +5 -0
  58. package/dist/icons/FileExcel.d.ts +5 -0
  59. package/dist/icons/FilePdf.d.ts +5 -0
  60. package/dist/icons/FileWord.d.ts +5 -0
  61. package/dist/icons/Fullscreen.d.ts +5 -0
  62. package/dist/icons/FullscreenExit.d.ts +5 -0
  63. package/dist/icons/Group.d.ts +5 -0
  64. package/dist/icons/History.d.ts +6 -0
  65. package/dist/icons/Image.d.ts +4 -0
  66. package/dist/icons/Info.d.ts +5 -0
  67. package/dist/icons/Link.d.ts +5 -0
  68. package/dist/icons/Linkedin.d.ts +5 -0
  69. package/dist/icons/Loading.d.ts +6 -0
  70. package/dist/icons/Logout.d.ts +5 -0
  71. package/dist/icons/Mail.d.ts +5 -0
  72. package/dist/icons/MapMarker.d.ts +5 -0
  73. package/dist/icons/MenuHorizontal.d.ts +6 -0
  74. package/dist/icons/MenuVertical.d.ts +6 -0
  75. package/dist/icons/Message.d.ts +5 -0
  76. package/dist/icons/Microphone.d.ts +5 -0
  77. package/dist/icons/Minus.d.ts +5 -0
  78. package/dist/icons/MinusCircle.d.ts +5 -0
  79. package/dist/icons/PaperClip.d.ts +5 -0
  80. package/dist/icons/Picture.d.ts +5 -0
  81. package/dist/icons/Plus.d.ts +5 -0
  82. package/dist/icons/Preview.d.ts +4 -0
  83. package/dist/icons/Print.d.ts +6 -0
  84. package/dist/icons/QuestionHelp.d.ts +5 -0
  85. package/dist/icons/Refresh.d.ts +5 -0
  86. package/dist/icons/SelectIcon.d.ts +5 -0
  87. package/dist/icons/Send.d.ts +5 -0
  88. package/dist/icons/Setting.d.ts +5 -0
  89. package/dist/icons/Share.d.ts +5 -0
  90. package/dist/icons/Sound.d.ts +5 -0
  91. package/dist/icons/SoundDeactivated.d.ts +5 -0
  92. package/dist/icons/Telegram.d.ts +5 -0
  93. package/dist/icons/ThumbDown.d.ts +5 -0
  94. package/dist/icons/ThumbUp.d.ts +5 -0
  95. package/dist/icons/Translation.d.ts +5 -0
  96. package/dist/icons/Twitter.d.ts +5 -0
  97. package/dist/icons/Upload.d.ts +4 -0
  98. package/dist/icons/User.d.ts +5 -0
  99. package/dist/icons/Warning.d.ts +5 -0
  100. package/dist/icons/WhatsApp.d.ts +5 -0
  101. package/dist/index.d.ts +13 -0
  102. package/dist/memori-ai-ui.css +2 -0
  103. package/dist/memori-ai-ui.es.js +6400 -0
  104. package/dist/memori-ai-ui.umd.js +23 -0
  105. package/package.json +97 -0
  106. package/src/components/Alert/Alert.css +95 -0
  107. package/src/components/Alert/Alert.stories.tsx +156 -0
  108. package/src/components/Alert/Alert.test.tsx +122 -0
  109. package/src/components/Alert/Alert.tsx +124 -0
  110. package/src/components/Alert/__snapshots__/Alert.test.tsx.snap +67 -0
  111. package/src/components/Alert/index.tsx +2 -0
  112. package/src/components/Button/Button.css +173 -0
  113. package/src/components/Button/Button.stories.tsx +173 -0
  114. package/src/components/Button/Button.test.tsx +80 -0
  115. package/src/components/Button/Button.tsx +104 -0
  116. package/src/components/Button/__snapshots__/Button.test.tsx.snap +204 -0
  117. package/src/components/Button/index.tsx +2 -0
  118. package/src/components/ButtonBase/ButtonBase.stories.tsx +194 -0
  119. package/src/components/ButtonBase/ButtonBase.tsx +84 -0
  120. package/src/components/ButtonBase/index.tsx +3 -0
  121. package/src/components/ButtonBase/styles.module.css +135 -0
  122. package/src/components/Card/Card.css +67 -0
  123. package/src/components/Card/Card.stories.tsx +104 -0
  124. package/src/components/Card/Card.test.tsx +67 -0
  125. package/src/components/Card/Card.tsx +58 -0
  126. package/src/components/Card/__snapshots__/Card.test.tsx.snap +321 -0
  127. package/src/components/Card/index.tsx +2 -0
  128. package/src/components/Checkbox/Checkbox.css +114 -0
  129. package/src/components/Checkbox/Checkbox.stories.tsx +77 -0
  130. package/src/components/Checkbox/Checkbox.test.tsx +50 -0
  131. package/src/components/Checkbox/Checkbox.tsx +61 -0
  132. package/src/components/Checkbox/__snapshots__/Checkbox.test.tsx.snap +131 -0
  133. package/src/components/Checkbox/index.tsx +2 -0
  134. package/src/components/ConfirmDialog/ConfirmDialog.css +44 -0
  135. package/src/components/ConfirmDialog/ConfirmDialog.stories.tsx +235 -0
  136. package/src/components/ConfirmDialog/ConfirmDialog.test.tsx +129 -0
  137. package/src/components/ConfirmDialog/ConfirmDialog.tsx +73 -0
  138. package/src/components/ConfirmDialog/__snapshots__/ConfirmDialog.test.tsx.snap +11 -0
  139. package/src/components/ConfirmDialog/index.tsx +2 -0
  140. package/src/components/Details/Details.css +66 -0
  141. package/src/components/Details/Details.stories.tsx +67 -0
  142. package/src/components/Drawer/Drawer.css +210 -0
  143. package/src/components/Drawer/Drawer.stories.tsx +275 -0
  144. package/src/components/Drawer/Drawer.test.tsx +158 -0
  145. package/src/components/Drawer/Drawer.tsx +242 -0
  146. package/src/components/Drawer/__snapshots__/Drawer.test.tsx.snap +21 -0
  147. package/src/components/Drawer/index.tsx +2 -0
  148. package/src/components/Dropdown/Dropdown.css +177 -0
  149. package/src/components/Dropdown/Dropdown.stories.tsx +73 -0
  150. package/src/components/Dropdown/Dropdown.test.tsx +88 -0
  151. package/src/components/Dropdown/Dropdown.tsx +88 -0
  152. package/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap +141 -0
  153. package/src/components/Dropdown/index.tsx +2 -0
  154. package/src/components/Expandable/Expandable.css +15 -0
  155. package/src/components/Expandable/Expandable.stories.tsx +196 -0
  156. package/src/components/Expandable/Expandable.test.tsx +143 -0
  157. package/src/components/Expandable/Expandable.tsx +122 -0
  158. package/src/components/Expandable/__snapshots__/Expandable.test.tsx.snap +199 -0
  159. package/src/components/Expandable/helpers.ts +16 -0
  160. package/src/components/Expandable/index.tsx +2 -0
  161. package/src/components/InputBase/InputBase.stories.tsx +237 -0
  162. package/src/components/InputBase/InputBase.tsx +105 -0
  163. package/src/components/InputBase/index.tsx +3 -0
  164. package/src/components/InputBase/styles.module.css +96 -0
  165. package/src/components/Modal/Modal.css +95 -0
  166. package/src/components/Modal/Modal.stories.tsx +184 -0
  167. package/src/components/Modal/Modal.test.tsx +129 -0
  168. package/src/components/Modal/Modal.tsx +124 -0
  169. package/src/components/Modal/__snapshots__/Modal.test.tsx.snap +17 -0
  170. package/src/components/Modal/index.tsx +2 -0
  171. package/src/components/Select/Select.css +134 -0
  172. package/src/components/Select/Select.stories.tsx +85 -0
  173. package/src/components/Select/Select.test.tsx +85 -0
  174. package/src/components/Select/Select.tsx +84 -0
  175. package/src/components/Select/__snapshots__/Select.test.tsx.snap +261 -0
  176. package/src/components/Select/index.tsx +2 -0
  177. package/src/components/Slider/Slider.css +194 -0
  178. package/src/components/Slider/Slider.stories.tsx +85 -0
  179. package/src/components/Slider/Slider.test.tsx +55 -0
  180. package/src/components/Slider/Slider.tsx +157 -0
  181. package/src/components/Slider/__snapshots__/Slider.test.tsx.snap +419 -0
  182. package/src/components/Slider/index.tsx +2 -0
  183. package/src/components/Spin/Spin.css +31 -0
  184. package/src/components/Spin/Spin.stories.tsx +65 -0
  185. package/src/components/Spin/Spin.test.tsx +47 -0
  186. package/src/components/Spin/Spin.tsx +34 -0
  187. package/src/components/Spin/__snapshots__/Spin.test.tsx.snap +193 -0
  188. package/src/components/Spin/index.tsx +2 -0
  189. package/src/components/Table/Table.css +130 -0
  190. package/src/components/Table/Table.stories.tsx +274 -0
  191. package/src/components/Tooltip/Tooltip.css +160 -0
  192. package/src/components/Tooltip/Tooltip.stories.tsx +136 -0
  193. package/src/components/Tooltip/Tooltip.test.tsx +110 -0
  194. package/src/components/Tooltip/Tooltip.tsx +46 -0
  195. package/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap +163 -0
  196. package/src/components/Tooltip/index.tsx +2 -0
  197. package/src/components/definitions.stories.tsx +150 -0
  198. package/src/i18n/I18nWrapper.tsx +13 -0
  199. package/src/i18n/i18n.ts +34 -0
  200. package/src/icons/AI.tsx +38 -0
  201. package/src/icons/Alert.tsx +31 -0
  202. package/src/icons/ArrowUp.tsx +28 -0
  203. package/src/icons/Bug.tsx +81 -0
  204. package/src/icons/Chat.tsx +30 -0
  205. package/src/icons/ChevronDown.tsx +26 -0
  206. package/src/icons/ChevronLeft.tsx +28 -0
  207. package/src/icons/ChevronRight.tsx +28 -0
  208. package/src/icons/ChevronUp.tsx +24 -0
  209. package/src/icons/Clear.tsx +23 -0
  210. package/src/icons/Close.tsx +30 -0
  211. package/src/icons/Code.tsx +30 -0
  212. package/src/icons/Copy.tsx +30 -0
  213. package/src/icons/DeepThought.tsx +38 -0
  214. package/src/icons/Delete.tsx +23 -0
  215. package/src/icons/Document.tsx +52 -0
  216. package/src/icons/Download.tsx +23 -0
  217. package/src/icons/Edit.tsx +17 -0
  218. package/src/icons/Expand.tsx +23 -0
  219. package/src/icons/Eye.tsx +17 -0
  220. package/src/icons/EyeInvisible.tsx +24 -0
  221. package/src/icons/Facebook.tsx +23 -0
  222. package/src/icons/Feedback.tsx +27 -0
  223. package/src/icons/File.tsx +17 -0
  224. package/src/icons/FileExcel.tsx +23 -0
  225. package/src/icons/FilePdf.tsx +23 -0
  226. package/src/icons/FileWord.tsx +23 -0
  227. package/src/icons/Fullscreen.tsx +23 -0
  228. package/src/icons/FullscreenExit.tsx +23 -0
  229. package/src/icons/Group.tsx +30 -0
  230. package/src/icons/History.tsx +33 -0
  231. package/src/icons/Image.tsx +37 -0
  232. package/src/icons/Info.tsx +37 -0
  233. package/src/icons/Link.tsx +17 -0
  234. package/src/icons/Linkedin.tsx +23 -0
  235. package/src/icons/Loading.tsx +28 -0
  236. package/src/icons/Logout.tsx +33 -0
  237. package/src/icons/Mail.tsx +17 -0
  238. package/src/icons/MapMarker.tsx +26 -0
  239. package/src/icons/MenuHorizontal.tsx +29 -0
  240. package/src/icons/MenuVertical.tsx +29 -0
  241. package/src/icons/Message.tsx +23 -0
  242. package/src/icons/Microphone.tsx +23 -0
  243. package/src/icons/Minus.tsx +23 -0
  244. package/src/icons/MinusCircle.tsx +24 -0
  245. package/src/icons/PaperClip.tsx +23 -0
  246. package/src/icons/Picture.tsx +23 -0
  247. package/src/icons/Plus.tsx +18 -0
  248. package/src/icons/Preview.tsx +31 -0
  249. package/src/icons/Print.tsx +37 -0
  250. package/src/icons/QuestionHelp.tsx +34 -0
  251. package/src/icons/Refresh.tsx +30 -0
  252. package/src/icons/SelectIcon.tsx +28 -0
  253. package/src/icons/Send.tsx +17 -0
  254. package/src/icons/Setting.tsx +23 -0
  255. package/src/icons/Share.tsx +23 -0
  256. package/src/icons/Sound.tsx +23 -0
  257. package/src/icons/SoundDeactivated.tsx +27 -0
  258. package/src/icons/Telegram.tsx +26 -0
  259. package/src/icons/ThumbDown.tsx +29 -0
  260. package/src/icons/ThumbUp.tsx +29 -0
  261. package/src/icons/Translation.tsx +24 -0
  262. package/src/icons/Twitter.tsx +23 -0
  263. package/src/icons/Upload.tsx +34 -0
  264. package/src/icons/User.tsx +17 -0
  265. package/src/icons/Warning.tsx +27 -0
  266. package/src/icons/WhatsApp.tsx +24 -0
  267. package/src/icons/icons.stories.css +5 -0
  268. package/src/icons/icons.stories.tsx +110 -0
  269. package/src/icons/loading.css +14 -0
  270. package/src/index.ts +15 -0
  271. package/src/styles/utils.css +17 -0
  272. package/src/styles.css +4 -0
  273. package/src/theme/variables.css +110 -0
  274. package/src/vite-env.d.ts +6 -0
@@ -0,0 +1,194 @@
1
+ import React from 'react'
2
+ import type { Meta, StoryObj } from '@storybook/react-vite'
3
+ import { ButtonBase } from './ButtonBase'
4
+ import { fn } from 'storybook/test'
5
+
6
+ const meta = {
7
+ title: 'UI/ButtonBase',
8
+ component: ButtonBase,
9
+ tags: ['autodocs'],
10
+ argTypes: {
11
+ variant: {
12
+ control: {
13
+ type: 'select',
14
+ },
15
+ options: ['primary', 'secondary', 'outline'],
16
+ description: 'Button variant style',
17
+ },
18
+ size: {
19
+ control: {
20
+ type: 'select',
21
+ },
22
+ options: ['sm', 'md', 'lg'],
23
+ description: 'Button size',
24
+ },
25
+ fullWidth: {
26
+ control: {
27
+ type: 'boolean',
28
+ },
29
+ description: 'Whether the button should take full width',
30
+ },
31
+ disabled: {
32
+ control: {
33
+ type: 'boolean',
34
+ },
35
+ description: 'Whether the button is disabled',
36
+ },
37
+ children: {
38
+ control: {
39
+ type: 'text',
40
+ },
41
+ description: 'Button content',
42
+ },
43
+ onClick: {
44
+ description: 'Click handler',
45
+ },
46
+ },
47
+ parameters: {
48
+ controls: { expanded: true },
49
+ },
50
+ args: {
51
+ onClick: fn(),
52
+ },
53
+ } satisfies Meta<typeof ButtonBase>
54
+
55
+ export default meta
56
+
57
+ type Story = StoryObj<typeof meta>
58
+
59
+ /**
60
+ * Primary variant is the default button style with solid background.
61
+ */
62
+ export const Primary: Story = {
63
+ args: {
64
+ children: 'Primary Button',
65
+ variant: 'primary',
66
+ },
67
+ }
68
+
69
+ /**
70
+ * Secondary variant uses the secondary color palette.
71
+ */
72
+ export const Secondary: Story = {
73
+ args: {
74
+ children: 'Secondary Button',
75
+ variant: 'secondary',
76
+ },
77
+ }
78
+
79
+ /**
80
+ * Outline variant has a transparent background with a border.
81
+ */
82
+ export const Outline: Story = {
83
+ args: {
84
+ children: 'Outline Button',
85
+ variant: 'outline',
86
+ },
87
+ }
88
+
89
+ /**
90
+ * Small size button.
91
+ */
92
+ export const Small: Story = {
93
+ args: {
94
+ children: 'Small Button',
95
+ variant: 'primary',
96
+ size: 'sm',
97
+ },
98
+ }
99
+
100
+ /**
101
+ * Medium size button (default).
102
+ */
103
+ export const Medium: Story = {
104
+ args: {
105
+ children: 'Medium Button',
106
+ variant: 'primary',
107
+ size: 'md',
108
+ },
109
+ }
110
+
111
+ /**
112
+ * Large size button.
113
+ */
114
+ export const Large: Story = {
115
+ args: {
116
+ children: 'Large Button',
117
+ variant: 'primary',
118
+ size: 'lg',
119
+ },
120
+ }
121
+
122
+ /**
123
+ * Full width button that spans the entire container.
124
+ */
125
+ export const FullWidth: Story = {
126
+ args: {
127
+ children: 'Full Width Button',
128
+ variant: 'primary',
129
+ fullWidth: true,
130
+ },
131
+ }
132
+
133
+ /**
134
+ * Disabled button state.
135
+ */
136
+ export const Disabled: Story = {
137
+ args: {
138
+ children: 'Disabled Button',
139
+ variant: 'primary',
140
+ disabled: true,
141
+ },
142
+ }
143
+
144
+ /**
145
+ * Disabled outline button.
146
+ */
147
+ export const DisabledOutline: Story = {
148
+ args: {
149
+ children: 'Disabled Outline',
150
+ variant: 'outline',
151
+ disabled: true,
152
+ },
153
+ }
154
+
155
+ /**
156
+ * All variants displayed together for comparison.
157
+ */
158
+ export const AllVariants: Story = {
159
+ render: () => (
160
+ <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>
161
+ <ButtonBase variant="primary">Primary</ButtonBase>
162
+ <ButtonBase variant="secondary">Secondary</ButtonBase>
163
+ <ButtonBase variant="outline">Outline</ButtonBase>
164
+ </div>
165
+ ),
166
+ }
167
+
168
+ /**
169
+ * All sizes displayed together for comparison.
170
+ */
171
+ export const AllSizes: Story = {
172
+ render: () => (
173
+ <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
174
+ <ButtonBase
175
+ variant="primary"
176
+ size="sm"
177
+ >
178
+ Small
179
+ </ButtonBase>
180
+ <ButtonBase
181
+ variant="primary"
182
+ size="md"
183
+ >
184
+ Medium
185
+ </ButtonBase>
186
+ <ButtonBase
187
+ variant="primary"
188
+ size="lg"
189
+ >
190
+ Large
191
+ </ButtonBase>
192
+ </div>
193
+ ),
194
+ }
@@ -0,0 +1,84 @@
1
+ import React from 'react'
2
+ import { Button as BaseButton } from '@base-ui/react/button'
3
+ import type { ButtonProps as BaseButtonProps } from '@base-ui/react/button'
4
+ import cx from 'classnames'
5
+ import styles from './styles.module.css'
6
+
7
+ export interface ButtonProps extends Omit<BaseButtonProps, 'className'> {
8
+ /**
9
+ * Button variant
10
+ * @default 'primary'
11
+ */
12
+ variant?: 'primary' | 'secondary' | 'outline'
13
+ /**
14
+ * Button size
15
+ * @default 'md'
16
+ */
17
+ size?: 'sm' | 'md' | 'lg'
18
+ /**
19
+ * Whether the button should take full width
20
+ */
21
+ fullWidth?: boolean
22
+ /**
23
+ * Additional CSS class name
24
+ */
25
+ className?: string
26
+ /**
27
+ * Button content
28
+ */
29
+ children?: React.ReactNode
30
+ }
31
+
32
+ export const ButtonBase = React.forwardRef<HTMLButtonElement, ButtonProps>(
33
+ (
34
+ {
35
+ variant = 'primary',
36
+ size = 'md',
37
+ fullWidth = false,
38
+ className,
39
+ children,
40
+ disabled,
41
+ ...props
42
+ },
43
+ ref,
44
+ ) => {
45
+ const variantClass =
46
+ variant === 'primary'
47
+ ? styles['button--primary']
48
+ : variant === 'secondary'
49
+ ? styles['button--secondary']
50
+ : styles['button--outline']
51
+
52
+ const sizeClass =
53
+ size === 'sm'
54
+ ? styles['button--sm']
55
+ : size === 'lg'
56
+ ? styles['button--lg']
57
+ : styles['button--md']
58
+
59
+ const fullWidthClass = fullWidth ? styles['button--full-width'] : undefined
60
+ const disabledClass = disabled ? styles['button--disabled'] : undefined
61
+
62
+ return (
63
+ <BaseButton
64
+ ref={ref}
65
+ disabled={disabled}
66
+ className={cx(
67
+ styles.button,
68
+ variantClass,
69
+ sizeClass,
70
+ fullWidthClass,
71
+ disabledClass,
72
+ className,
73
+ )}
74
+ {...props}
75
+ >
76
+ {children}
77
+ </BaseButton>
78
+ )
79
+ },
80
+ )
81
+
82
+ ButtonBase.displayName = 'ButtonBase'
83
+
84
+ export default ButtonBase
@@ -0,0 +1,3 @@
1
+ export { ButtonBase } from './ButtonBase'
2
+ export type { ButtonProps } from './ButtonBase'
3
+ export { ButtonBase as default } from './ButtonBase'
@@ -0,0 +1,135 @@
1
+ .button {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ border: 1px solid transparent;
6
+ border-radius: var(--border-radius-md);
7
+ cursor: pointer;
8
+ font-family: var(--typography-font-family-base);
9
+ font-weight: var(--typography-font-weight-medium);
10
+ line-height: var(--typography-line-height-normal);
11
+ outline: none;
12
+ transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
13
+ }
14
+
15
+ .button:focus-visible {
16
+ outline: 2px solid var(--color-primary-500);
17
+ outline-offset: 2px;
18
+ }
19
+
20
+ /* ============================================
21
+ VARIANTS
22
+ ============================================ */
23
+
24
+ /* Primary Variant */
25
+ .button--primary {
26
+ border-color: var(--color-primary-500);
27
+ background-color: var(--color-primary-500);
28
+ color: var(--color-neutral-white);
29
+ }
30
+
31
+ .button--primary:hover:not(:disabled) {
32
+ border-color: var(--color-primary-600);
33
+ background-color: var(--color-primary-600);
34
+ }
35
+
36
+ .button--primary:active:not(:disabled) {
37
+ border-color: var(--color-primary-700);
38
+ background-color: var(--color-primary-700);
39
+ }
40
+
41
+ /* Secondary Variant */
42
+ .button--secondary {
43
+ border-color: var(--color-secondary-500);
44
+ background-color: var(--color-secondary-500);
45
+ color: var(--color-neutral-white);
46
+ }
47
+
48
+ .button--secondary:hover:not(:disabled) {
49
+ border-color: var(--color-secondary-600);
50
+ background-color: var(--color-secondary-600);
51
+ }
52
+
53
+ .button--secondary:active:not(:disabled) {
54
+ border-color: var(--color-secondary-700);
55
+ background-color: var(--color-secondary-700);
56
+ }
57
+
58
+ /* Outline Variant */
59
+ .button--outline {
60
+ border-color: var(--color-primary-500);
61
+ background-color: transparent;
62
+ color: var(--color-primary-500);
63
+ }
64
+
65
+ /* Outline variant disabled state */
66
+ .button--outline.button--disabled,
67
+ .button--outline:disabled {
68
+ border-color: var(--color-neutral-400);
69
+ background-color: transparent;
70
+ color: var(--color-neutral-500);
71
+ }
72
+
73
+ .button--outline:hover:not(:disabled) {
74
+ background-color: var(--color-primary-500);
75
+ color: var(--color-neutral-white);
76
+ }
77
+
78
+ .button--outline:active:not(:disabled) {
79
+ border-color: var(--color-primary-600);
80
+ background-color: var(--color-primary-600);
81
+ color: var(--color-neutral-white);
82
+ }
83
+
84
+ /* ============================================
85
+ SIZES
86
+ ============================================ */
87
+
88
+ .button--sm {
89
+ min-height: 32px;
90
+ padding: var(--spacing-xs) var(--spacing-sm);
91
+ font-size: var(--typography-font-size-sm);
92
+ }
93
+
94
+ .button--md {
95
+ min-height: 40px;
96
+ padding: var(--spacing-sm) var(--spacing-md);
97
+ font-size: var(--typography-font-size-base);
98
+ }
99
+
100
+ .button--lg {
101
+ min-height: 48px;
102
+ padding: var(--spacing-md) var(--spacing-lg);
103
+ font-size: var(--typography-font-size-lg);
104
+ }
105
+
106
+ /* ============================================
107
+ STATES
108
+ ============================================ */
109
+
110
+ .button--full-width {
111
+ width: 100%;
112
+ }
113
+
114
+ .button--disabled,
115
+ .button:disabled {
116
+ border-color: var(--color-neutral-400);
117
+ background-color: var(--color-neutral-300);
118
+ color: var(--color-neutral-500);
119
+ cursor: not-allowed;
120
+ opacity: 0.6;
121
+ }
122
+
123
+ .button--disabled:hover,
124
+ .button:disabled:hover {
125
+ border-color: var(--color-neutral-400);
126
+ background-color: var(--color-neutral-300);
127
+ color: var(--color-neutral-500);
128
+ }
129
+
130
+ .button--outline.button--disabled:hover,
131
+ .button--outline:disabled:hover {
132
+ border-color: var(--color-neutral-400);
133
+ background-color: transparent;
134
+ color: var(--color-neutral-500);
135
+ }
@@ -0,0 +1,67 @@
1
+ .memori-card {
2
+ display: flex;
3
+ overflow: hidden;
4
+ flex-direction: column;
5
+ border-radius: 10px;
6
+ margin: 0 0 1rem;
7
+ background-color: #fff;
8
+ box-shadow: 0 0.5rem 1rem 0 rgb(0 0 0 / 10%);
9
+ }
10
+
11
+ .memori-card--hoverable {
12
+ transition: box-shadow 0.3s;
13
+ }
14
+
15
+ .memori-card--hoverable:hover {
16
+ box-shadow:
17
+ 0 0.2rem 0 rgb(0 0 0 / 10%),
18
+ 0 0.5rem 1rem 0 rgb(0 0 0 / 20%);
19
+ }
20
+
21
+ .memori-card--hoverable:focus,
22
+ .memori-card--hoverable:focus-within {
23
+ outline-color: var(--memori-primary);
24
+ }
25
+
26
+ .memori-card--cover {
27
+ display: flex;
28
+ overflow: hidden;
29
+ height: 200px;
30
+ align-items: center;
31
+ justify-content: center;
32
+ border-radius: 10px 10px 0 0;
33
+ background-color: #eee;
34
+ }
35
+
36
+ .memori-card--cover img {
37
+ min-width: 100%;
38
+ min-height: 100%;
39
+ object-fit: cover;
40
+ object-position: center;
41
+ }
42
+
43
+ .memori-card--content {
44
+ z-index: 0;
45
+ display: flex;
46
+ flex: 1;
47
+ flex-direction: column;
48
+ justify-content: space-between;
49
+ padding: 1.5rem 1rem;
50
+ }
51
+
52
+ .memori-card--title {
53
+ margin: 0 0 0.5rem;
54
+ font-size: 1.25rem;
55
+ font-weight: 600;
56
+ }
57
+
58
+ .memori-card--description {
59
+ margin: 0;
60
+ color: #999;
61
+ font-size: 0.875rem;
62
+ font-weight: 400;
63
+ }
64
+
65
+ .memori-card--pointer {
66
+ cursor: pointer;
67
+ }
@@ -0,0 +1,104 @@
1
+ import React from 'react'
2
+ import type { Meta, StoryObj } from '@storybook/react'
3
+ import Card from './Card'
4
+ import Button from '../Button/Button'
5
+
6
+ const meta = {
7
+ title: 'UI/Card',
8
+ component: Card,
9
+ tags: ['autodocs'],
10
+ argTypes: {
11
+ title: {
12
+ control: {
13
+ type: 'text',
14
+ },
15
+ },
16
+ description: {
17
+ control: {
18
+ type: 'text',
19
+ },
20
+ },
21
+ children: {
22
+ control: {
23
+ type: 'text',
24
+ },
25
+ },
26
+ className: {
27
+ control: {
28
+ type: 'text',
29
+ },
30
+ },
31
+ loading: {
32
+ control: {
33
+ type: 'boolean',
34
+ },
35
+ },
36
+ },
37
+ parameters: {
38
+ controls: { expanded: true },
39
+ },
40
+ } satisfies Meta<typeof Card>
41
+
42
+ export default meta
43
+
44
+ type Story = StoryObj<typeof meta>
45
+
46
+ export const Default: Story = {
47
+ args: {
48
+ title: 'Card title',
49
+ loading: false,
50
+ },
51
+ }
52
+
53
+ export const WithTitleAndDescription: Story = {
54
+ args: {
55
+ title: 'Card title',
56
+ description: 'Card description',
57
+ loading: false,
58
+ },
59
+ }
60
+
61
+ export const Loading: Story = {
62
+ args: {
63
+ title: 'Card title',
64
+ description: 'Card description',
65
+ loading: true,
66
+ },
67
+ }
68
+
69
+ export const WithCover: Story = {
70
+ args: {
71
+ title: 'Card title',
72
+ description: 'Card description',
73
+ cover: (
74
+ <img
75
+ src="https://picsum.photos/200/300"
76
+ alt="cover"
77
+ />
78
+ ),
79
+ loading: false,
80
+ },
81
+ }
82
+
83
+ export const WithChildren: Story = {
84
+ args: {
85
+ title: 'Card title',
86
+ description: 'Card description',
87
+ children: (
88
+ <div>
89
+ <p>Some text</p>
90
+ <Button primary>Show more</Button>
91
+ </div>
92
+ ),
93
+ loading: false,
94
+ },
95
+ }
96
+
97
+ export const Hoverable: Story = {
98
+ args: {
99
+ title: 'Card title',
100
+ description: 'Card description',
101
+ loading: false,
102
+ hoverable: true,
103
+ },
104
+ }
@@ -0,0 +1,67 @@
1
+ import React from 'react'
2
+ import { it, expect } from 'vitest'
3
+ import { render } from '@testing-library/react'
4
+ import Card from './Card'
5
+
6
+ it('renders Card unchanged', () => {
7
+ const { container } = render(<Card />)
8
+ expect(container).toMatchSnapshot()
9
+ })
10
+
11
+ it('renders Card with title unchanged', () => {
12
+ const { container } = render(<Card title="Card title" />)
13
+ expect(container).toMatchSnapshot()
14
+ })
15
+
16
+ it('renders Card with description unchanged', () => {
17
+ const { container } = render(<Card description="Card description" />)
18
+ expect(container).toMatchSnapshot()
19
+ })
20
+
21
+ it('renders Card with cover unchanged', () => {
22
+ const { container } = render(
23
+ <Card
24
+ cover={
25
+ <img
26
+ src="#"
27
+ alt=""
28
+ />
29
+ }
30
+ />,
31
+ )
32
+ expect(container).toMatchSnapshot()
33
+ })
34
+
35
+ it('renders Card with children unchanged', () => {
36
+ const { container } = render(
37
+ <Card>
38
+ <p>Ciao</p>
39
+ </Card>,
40
+ )
41
+ expect(container).toMatchSnapshot()
42
+ })
43
+
44
+ it('renders Card loading unchanged', () => {
45
+ const { container } = render(
46
+ <Card
47
+ title="Card title"
48
+ loading
49
+ />,
50
+ )
51
+ expect(container).toMatchSnapshot()
52
+ })
53
+
54
+ it('renders Card with custom CSS class unchanged', () => {
55
+ const { container } = render(<Card className="lorem-ipsum" />)
56
+ expect(container).toMatchSnapshot()
57
+ })
58
+
59
+ it('renders Card hoverable unchanged', () => {
60
+ const { container } = render(
61
+ <Card
62
+ title="lorem-ipsum"
63
+ hoverable
64
+ />,
65
+ )
66
+ expect(container).toMatchSnapshot()
67
+ })
@@ -0,0 +1,58 @@
1
+ import type { FC, JSX } from 'react'
2
+ import React from 'react'
3
+ import cx from 'classnames'
4
+ import Spin from '../Spin/Spin'
5
+
6
+ import './Card.css'
7
+
8
+ export interface Props {
9
+ children?: React.ReactNode
10
+ loading?: boolean
11
+ className?: string
12
+ title?: string
13
+ description?: string
14
+ cover?: JSX.Element | React.ReactNode | string
15
+ hoverable?: boolean
16
+ onClick?: () => void
17
+ }
18
+
19
+ const Card: FC<Props> = ({
20
+ loading = false,
21
+ className,
22
+ title,
23
+ description,
24
+ cover,
25
+ hoverable = false,
26
+ children,
27
+ onClick,
28
+ }) => (
29
+ <div
30
+ onClick={onClick}
31
+ onKeyDown={e => {
32
+ if ((e.key === 'Enter' || e.key === 'Space') && onClick) {
33
+ onClick()
34
+ }
35
+ }}
36
+ role={onClick ? 'button' : undefined}
37
+ tabIndex={onClick ? 0 : undefined}
38
+ className={cx('memori-card', className, {
39
+ 'memori-card--loading': loading,
40
+ 'memori-card--with-cover': cover,
41
+ 'memori-card--hoverable': hoverable,
42
+ 'memori-card--pointer': !!onClick,
43
+ })}
44
+ >
45
+ <Spin spinning={loading}>
46
+ {cover && <div className="memori-card--cover">{cover}</div>}
47
+ <div className="memori-card--content">
48
+ {title && <h3 className="memori-card--title">{title}</h3>}
49
+ {description && (
50
+ <p className="memori-card--description">{description}</p>
51
+ )}
52
+ <div className="memori-card--children">{children}</div>
53
+ </div>
54
+ </Spin>
55
+ </div>
56
+ )
57
+
58
+ export default Card