@altruist03/ui 0.1.0 → 0.2.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 (207) hide show
  1. package/assets/images/noData.webp +0 -0
  2. package/dist/index.js +15237 -650
  3. package/dist/index.js.map +1 -1
  4. package/dist/noData-XPRHKMFR.webp +0 -0
  5. package/package.json +21 -7
  6. package/src/ThemeProvider/ThemeContext.tsx +75 -0
  7. package/src/ThemeProvider/index.ts +7 -0
  8. package/src/assets/images/noData.webp +0 -0
  9. package/src/assets.d.ts +10 -0
  10. package/src/components/Accordion/Accordion.stories.tsx +64 -0
  11. package/src/components/Accordion/Accordion.tsx +219 -0
  12. package/src/components/Accordion/Accordion.types.ts +16 -0
  13. package/src/components/Avatar/Avatar.stories.tsx +304 -0
  14. package/src/components/Avatar/Avatar.tsx +211 -0
  15. package/src/components/Avatar/Avatar.types.ts +33 -0
  16. package/src/components/Badge/Badge.stories.tsx +143 -0
  17. package/src/components/Badge/Badge.tsx +138 -0
  18. package/src/components/Badge/Badge.types.ts +24 -0
  19. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
  20. package/src/components/Breadcrumb/Breadcrumb.tsx +120 -0
  21. package/src/components/Breadcrumb/Breadcrumb.types.ts +22 -0
  22. package/src/components/Button/Button.stories.tsx +457 -0
  23. package/src/components/Button/Button.tsx +202 -0
  24. package/src/components/Button/Button.types.ts +18 -0
  25. package/src/components/Checkbox/Checkbox.stories.tsx +254 -0
  26. package/src/components/Checkbox/Checkbox.tsx +352 -0
  27. package/src/components/Checkbox/Checkbox.types.ts +123 -0
  28. package/src/components/CloseButton/CloseButton.stories.tsx +100 -0
  29. package/src/components/CloseButton/CloseButton.tsx +117 -0
  30. package/src/components/CloseButton/CloseButton.types.ts +15 -0
  31. package/src/components/CollapsibleSearch/CollapsibleSearch.tsx +120 -0
  32. package/src/components/DataTable/DataTable.stories.tsx +233 -0
  33. package/src/components/DataTable/DataTable.tsx +968 -0
  34. package/src/components/DataTable/DataTable.types.ts +49 -0
  35. package/src/components/DatePicker/DatePicker.stories.tsx +341 -0
  36. package/src/components/DatePicker/DatePicker.tsx +669 -0
  37. package/src/components/DatePicker/DatePicker.types.ts +105 -0
  38. package/src/components/DatePicker/DateTimePicker.tsx +35 -0
  39. package/src/components/DateRangePicker/DateRangePicker.tsx +179 -0
  40. package/src/components/DateRangePicker/DateRangePicker.types.ts +34 -0
  41. package/src/components/Drawer/Drawer.stories.tsx +243 -0
  42. package/src/components/Drawer/Drawer.tsx +196 -0
  43. package/src/components/Drawer/Drawer.types.ts +60 -0
  44. package/src/components/FileUpload/FileUpload.stories.tsx +162 -0
  45. package/src/components/FileUpload/FileUpload.tsx +216 -0
  46. package/src/components/FileUpload/FileUpload.types.ts +80 -0
  47. package/src/components/FilterPopover/FilterPopover.stories.tsx +173 -0
  48. package/src/components/FilterPopover/FilterPopover.tsx +310 -0
  49. package/src/components/FilterPopover/FilterPopover.types.ts +26 -0
  50. package/src/components/ImageViewer/ImageViewerToolbar.jsx +81 -0
  51. package/src/components/ImageViewer/useImagePanRotate.js +102 -0
  52. package/src/components/IpWhitelistField/IpWhitelistField.stories.tsx +138 -0
  53. package/src/components/IpWhitelistField/IpWhitelistField.tsx +164 -0
  54. package/src/components/IpWhitelistField/IpWhitelistField.types.ts +42 -0
  55. package/src/components/Loader/Loader.stories.tsx +95 -0
  56. package/src/components/Loader/Loader.tsx +132 -0
  57. package/src/components/Loader/Loader.types.ts +6 -0
  58. package/src/components/Menu/Menu.tsx +143 -0
  59. package/src/components/Menu/Menu.types.ts +28 -0
  60. package/src/components/MenuButton/MenuButton.stories.tsx +140 -0
  61. package/src/components/MenuButton/MenuButton.tsx +45 -0
  62. package/src/components/MenuButton/MenuButton.types.ts +21 -0
  63. package/src/components/Modal/Modal.stories.tsx +266 -0
  64. package/src/components/Modal/Modal.tsx +399 -0
  65. package/src/components/Modal/index.ts +2 -0
  66. package/src/components/Modal/types.ts +126 -0
  67. package/src/components/Pagination/Pagination.stories.tsx +167 -0
  68. package/src/components/Pagination/Pagination.tsx +266 -0
  69. package/src/components/Pagination/Pagination.types.ts +20 -0
  70. package/src/components/PeriodSelector/PeriodSelector.stories.tsx +50 -0
  71. package/src/components/PeriodSelector/PeriodSelector.tsx +47 -0
  72. package/src/components/PeriodSelector/PeriodSelector.types.ts +10 -0
  73. package/src/components/PhoneField/PhoneField.stories.tsx +141 -0
  74. package/src/components/PhoneField/PhoneField.tsx +284 -0
  75. package/src/components/PhoneField/PhoneField.types.ts +89 -0
  76. package/src/components/PhoneField/countryCodes.ts +236 -0
  77. package/src/components/Progress/Progress.stories.tsx +83 -0
  78. package/src/components/Progress/Progress.tsx +91 -0
  79. package/src/components/Progress/Progress.types.ts +22 -0
  80. package/src/components/RadioButton/RadioButton.stories.tsx +332 -0
  81. package/src/components/RadioButton/RadioButton.tsx +427 -0
  82. package/src/components/RadioButton/RadioButton.types.ts +117 -0
  83. package/src/components/ReportCard/ReportCard.tsx +183 -0
  84. package/src/components/ReportCard/ReportCard.types.ts +17 -0
  85. package/src/components/SectionIcon/SectionIcon.tsx +87 -0
  86. package/src/components/SectionIcon/SectionIcon.types.ts +23 -0
  87. package/src/components/SegmentedInputField/SegmentedInputField.stories.tsx +165 -0
  88. package/src/components/SegmentedInputField/SegmentedInputField.tsx +174 -0
  89. package/src/components/SegmentedInputField/SegmentedInputField.types.ts +51 -0
  90. package/src/components/SelectScroll/SelectScroll.stories.tsx +336 -0
  91. package/src/components/SelectScroll/SelectScroll.tsx +1119 -0
  92. package/src/components/SelectScroll/SelectScroll.types.ts +60 -0
  93. package/src/components/Selector/Selector.stories.tsx +382 -0
  94. package/src/components/Selector/Selector.tsx +1310 -0
  95. package/src/components/Selector/Selector.types.ts +71 -0
  96. package/src/components/Skeleton/Skeleton.stories.tsx +133 -0
  97. package/src/components/Skeleton/Skeleton.tsx +20 -0
  98. package/src/components/Skeleton/Skeleton.types.ts +3 -0
  99. package/src/components/Spinner/Spinner.stories.tsx +84 -0
  100. package/src/components/Spinner/Spinner.tsx +79 -0
  101. package/src/components/Spinner/Spinner.types.ts +8 -0
  102. package/src/components/StatCard/StatCard.stories.tsx +125 -0
  103. package/src/components/StatCard/StatCard.tsx +167 -0
  104. package/src/components/StatCard/StatCard.types.ts +20 -0
  105. package/src/components/StatusBadge/StatusBadge.stories.tsx +179 -0
  106. package/src/components/StatusBadge/StatusBadge.tsx +74 -0
  107. package/src/components/StatusBadge/StatusBadge.types.ts +23 -0
  108. package/src/components/Stepper/Stepper.stories.tsx +85 -0
  109. package/src/components/Stepper/Stepper.tsx +138 -0
  110. package/src/components/Stepper/Stepper.types.ts +16 -0
  111. package/src/components/SubTabs/SubTabs.stories.tsx +128 -0
  112. package/src/components/SubTabs/SubTabs.tsx +279 -0
  113. package/src/components/SubTabs/SubTabs.types.ts +44 -0
  114. package/src/components/SummaryCard/SummaryCard.stories.tsx +100 -0
  115. package/src/components/SummaryCard/SummaryCard.tsx +141 -0
  116. package/src/components/SummaryCard/SummaryCard.types.ts +22 -0
  117. package/src/components/Switch/Switch.stories.tsx +59 -0
  118. package/src/components/Switch/Switch.tsx +217 -0
  119. package/src/components/Switch/Switch.types.ts +22 -0
  120. package/src/components/Tabs/Tabs.stories.tsx +178 -0
  121. package/src/components/Tabs/Tabs.tsx +197 -0
  122. package/src/components/Tabs/Tabs.types.ts +34 -0
  123. package/src/components/TextField/TextField.stories.tsx +249 -0
  124. package/src/components/TextField/TextField.tsx +462 -0
  125. package/src/components/TextField/TextField.types.ts +141 -0
  126. package/src/components/Toast/Toast.stories.tsx +237 -0
  127. package/src/components/Toast/Toast.tsx +246 -0
  128. package/src/components/Toast/Toast.types.ts +31 -0
  129. package/src/components/ToggleButton/ToggleButton.stories.tsx +105 -0
  130. package/src/components/ToggleButton/ToggleButton.tsx +267 -0
  131. package/src/components/ToggleButton/ToggleButton.types.ts +19 -0
  132. package/src/components/UploadDropzone/UploadDropzone.jsx +78 -0
  133. package/src/components/UploadDropzone2/UploadDropzone.stories.tsx +94 -0
  134. package/src/components/UploadDropzone2/UploadDropzone.tsx +222 -0
  135. package/src/components/UploadDropzone2/UploadDropzone.types.ts +54 -0
  136. package/src/components/ViewEditToggle/ViewEditToggle.stories.tsx +40 -0
  137. package/src/components/ViewEditToggle/ViewEditToggle.tsx +239 -0
  138. package/src/components/ViewEditToggle/ViewEditToggle.types.ts +27 -0
  139. package/src/components/index.ts +157 -0
  140. package/src/icons/ReportDollarIcon.tsx +71 -0
  141. package/src/icons/index.ts +27 -0
  142. package/src/index.ts +214 -0
  143. package/src/storybook/preview.tsx +64 -0
  144. package/src/theme/index.ts +4 -0
  145. package/src/theme/types.d.ts +1 -0
  146. package/src/themes/cpc.ts +4 -0
  147. package/src/themes/firebird.ts +4 -0
  148. package/src/tokens/brands/cpc/themes/dark.json +82 -0
  149. package/src/tokens/brands/cpc/themes/light.json +1 -0
  150. package/src/tokens/brands/default/brand.json +20 -0
  151. package/src/tokens/brands/firebird/themes/dark.json +28 -0
  152. package/src/tokens/brands/firebird/themes/light.json +20 -0
  153. package/src/tokens/button.ts +24 -0
  154. package/src/tokens/components/accordion.json +52 -0
  155. package/src/tokens/components/avatar.json +40 -0
  156. package/src/tokens/components/badge.json +41 -0
  157. package/src/tokens/components/breadcrumb.json +13 -0
  158. package/src/tokens/components/button.json +67 -0
  159. package/src/tokens/components/card.json +39 -0
  160. package/src/tokens/components/checkbox.json +64 -0
  161. package/src/tokens/components/closebutton.json +55 -0
  162. package/src/tokens/components/datatable.json +40 -0
  163. package/src/tokens/components/datepicker.json +99 -0
  164. package/src/tokens/components/drawer.json +23 -0
  165. package/src/tokens/components/field.json +29 -0
  166. package/src/tokens/components/fileupload.json +57 -0
  167. package/src/tokens/components/filterpopover.json +29 -0
  168. package/src/tokens/components/input.json +31 -0
  169. package/src/tokens/components/ipwhitelistfield.json +16 -0
  170. package/src/tokens/components/loader.json +15 -0
  171. package/src/tokens/components/menu.json +21 -0
  172. package/src/tokens/components/modal.json +25 -0
  173. package/src/tokens/components/pagination.json +45 -0
  174. package/src/tokens/components/phonefield.json +41 -0
  175. package/src/tokens/components/progress.json +12 -0
  176. package/src/tokens/components/radio.json +87 -0
  177. package/src/tokens/components/reportcard.json +17 -0
  178. package/src/tokens/components/selector.json +87 -0
  179. package/src/tokens/components/selectscroll.json +65 -0
  180. package/src/tokens/components/skeleton.json +6 -0
  181. package/src/tokens/components/stepper.json +38 -0
  182. package/src/tokens/components/subtabs.json +45 -0
  183. package/src/tokens/components/switch.json +55 -0
  184. package/src/tokens/components/tabs.json +38 -0
  185. package/src/tokens/components/textfield.json +59 -0
  186. package/src/tokens/components/togglebutton.json +48 -0
  187. package/src/tokens/components/uploaddropzone.json +61 -0
  188. package/src/tokens/drawer.ts +37 -0
  189. package/src/tokens/foundation/breakpoints.json +10 -0
  190. package/src/tokens/foundation/colors.json +122 -0
  191. package/src/tokens/foundation/opacity.json +16 -0
  192. package/src/tokens/foundation/radius.json +14 -0
  193. package/src/tokens/foundation/size.json +38 -0
  194. package/src/tokens/foundation/spacing.json +19 -0
  195. package/src/tokens/foundation/typography.json +43 -0
  196. package/src/tokens/index.ts +3665 -0
  197. package/src/tokens/modal.ts +42 -0
  198. package/src/tokens/semantic/color.json +148 -0
  199. package/src/tokens/semantic/field.json +28 -0
  200. package/src/tokens/semantic/opacity.json +5 -0
  201. package/src/tokens/semantic/size.json +722 -0
  202. package/src/tokens/semantic/spacing.json +27 -0
  203. package/src/tokens/semantic/typography.json +87 -0
  204. package/src/utils/scrollLock.ts +44 -0
  205. package/dist/index.css +0 -514
  206. package/dist/index.css.map +0 -1
  207. package/dist/index.d.ts +0 -289
@@ -0,0 +1,457 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Button } from './Button';
3
+ import { SectionIcon } from '../SectionIcon/SectionIcon';
4
+ import { ReportDollarIcon } from '../../icons/ReportDollarIcon';
5
+ import AddIcon from '@mui/icons-material/Add';
6
+ import DownloadIcon from '@mui/icons-material/Download';
7
+ import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
8
+ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
9
+ import UploadIcon from '@mui/icons-material/Upload';
10
+ import SearchIcon from '@mui/icons-material/Search';
11
+ import RefreshIcon from '@mui/icons-material/Refresh';
12
+ import DescriptionOutlinedIcon from '@mui/icons-material/DescriptionOutlined';
13
+
14
+ const meta: Meta<typeof Button> = {
15
+ title: 'Design System/Button',
16
+ component: Button,
17
+ tags: [],
18
+ decorators: [(Story) => <Story />],
19
+ args: {
20
+ children: 'Button',
21
+ variant: 'blue',
22
+ size: 'md',
23
+ disabled: false,
24
+ fullWidth: false,
25
+ iconOnly: false,
26
+ },
27
+ argTypes: {
28
+ variant: {
29
+ control: { type: 'select' },
30
+ options: ['blue', 'red', 'grey'],
31
+ description: 'Button variant style',
32
+ table: {
33
+ type: { summary: 'blue | red | grey' },
34
+ defaultValue: { summary: 'blue' },
35
+ },
36
+ },
37
+ size: {
38
+ control: { type: 'select' },
39
+ options: ['sm', 'md', 'lg'],
40
+ description: 'Button size',
41
+ table: {
42
+ type: { summary: 'sm | md | lg' },
43
+ defaultValue: { summary: 'md' },
44
+ },
45
+ },
46
+ disabled: {
47
+ control: { type: 'boolean' },
48
+ description: 'Disable the button',
49
+ table: {
50
+ type: { summary: 'boolean' },
51
+ defaultValue: { summary: 'false' },
52
+ },
53
+ },
54
+ fullWidth: {
55
+ control: { type: 'boolean' },
56
+ description: 'Make button full width',
57
+ table: {
58
+ type: { summary: 'boolean' },
59
+ defaultValue: { summary: 'false' },
60
+ },
61
+ },
62
+ iconOnly: {
63
+ control: { type: 'boolean' },
64
+ description: 'Show only icon (no text)',
65
+ table: {
66
+ type: { summary: 'boolean' },
67
+ defaultValue: { summary: 'false' },
68
+ },
69
+ },
70
+ loading: {
71
+ control: { type: 'boolean' },
72
+ description: 'Show a loading state',
73
+ table: {
74
+ type: { summary: 'boolean' },
75
+ defaultValue: { summary: 'false' },
76
+ },
77
+ },
78
+ leftIcon: {
79
+ control: { type: 'select' },
80
+ options: ['none', 'download', 'add', 'upload', 'search', 'refresh'],
81
+ mapping: {
82
+ none: null,
83
+ download: <DownloadIcon />,
84
+ add: <AddIcon />,
85
+ upload: <UploadIcon />,
86
+ search: <SearchIcon />,
87
+ refresh: <RefreshIcon />,
88
+ },
89
+ description: 'Icon to display on the left side',
90
+ table: {
91
+ type: { summary: 'ReactNode' },
92
+ },
93
+ },
94
+ rightIcon: {
95
+ control: { type: 'select' },
96
+ options: ['none', 'arrowForward', 'arrowBack'],
97
+ mapping: {
98
+ none: null,
99
+ arrowForward: <ArrowForwardIcon />,
100
+ arrowBack: <ArrowBackIcon />,
101
+ },
102
+ description: 'Icon to display on the right side',
103
+ table: {
104
+ type: { summary: 'ReactNode' },
105
+ },
106
+ },
107
+ children: {
108
+ control: { type: 'text' },
109
+ description: 'Button text content',
110
+ table: {
111
+ type: { summary: 'ReactNode' },
112
+ },
113
+ },
114
+ onClick: { action: 'clicked' },
115
+ },
116
+ };
117
+
118
+ export default meta;
119
+
120
+ type Story = StoryObj<typeof Button>;
121
+
122
+ // Main interactive story with all controls
123
+ export const Playground: Story = {
124
+ args: {
125
+ variant: 'blue',
126
+ size: 'md',
127
+ children: 'Button',
128
+ disabled: false,
129
+ fullWidth: false,
130
+ iconOnly: false,
131
+ leftIcon: 'none',
132
+ rightIcon: 'none',
133
+ },
134
+ };
135
+
136
+ // Showcase story with multiple button examples
137
+ export const Showcase: Story = {
138
+ render: () => (
139
+ <div
140
+ style={{
141
+ display: 'flex',
142
+ flexDirection: 'column',
143
+ gap: '32px',
144
+ padding: '20px',
145
+ }}
146
+ >
147
+ {/* Variants Section */}
148
+ <div>
149
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
150
+ Button Variants
151
+ </h3>
152
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
153
+ <Button variant="blue">Blue Button</Button>
154
+ <Button variant="red">Red Button</Button>
155
+ <Button variant="grey">Grey Button</Button>
156
+ </div>
157
+ </div>
158
+
159
+ {/* Sizes Section */}
160
+ <div>
161
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>All Sizes</h3>
162
+ <div
163
+ style={{
164
+ display: 'flex',
165
+ gap: '12px',
166
+ alignItems: 'center',
167
+ flexWrap: 'wrap',
168
+ }}
169
+ >
170
+ <Button size="sm" variant="blue">
171
+ Small Button
172
+ </Button>
173
+ <Button size="md" variant="blue">
174
+ Medium Button
175
+ </Button>
176
+ <Button size="lg" variant="blue">
177
+ Large Button
178
+ </Button>
179
+ </div>
180
+ </div>
181
+
182
+ {/* Variants with All Sizes */}
183
+ <div>
184
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
185
+ Variants × Sizes
186
+ </h3>
187
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
188
+ <div
189
+ style={{
190
+ display: 'flex',
191
+ gap: '12px',
192
+ alignItems: 'center',
193
+ flexWrap: 'wrap',
194
+ }}
195
+ >
196
+ <span style={{ minWidth: '80px', fontSize: '14px' }}>Small:</span>
197
+ <Button size="sm" variant="blue">
198
+ Blue
199
+ </Button>
200
+ <Button size="sm" variant="red">
201
+ Red
202
+ </Button>
203
+ <Button size="sm" variant="grey">
204
+ Grey
205
+ </Button>
206
+ </div>
207
+ <div
208
+ style={{
209
+ display: 'flex',
210
+ gap: '12px',
211
+ alignItems: 'center',
212
+ flexWrap: 'wrap',
213
+ }}
214
+ >
215
+ <span style={{ minWidth: '80px', fontSize: '14px' }}>Medium:</span>
216
+ <Button size="md" variant="blue">
217
+ Blue
218
+ </Button>
219
+ <Button size="md" variant="red">
220
+ Red
221
+ </Button>
222
+ <Button size="md" variant="grey">
223
+ Grey
224
+ </Button>
225
+ </div>
226
+ <div
227
+ style={{
228
+ display: 'flex',
229
+ gap: '12px',
230
+ alignItems: 'center',
231
+ flexWrap: 'wrap',
232
+ }}
233
+ >
234
+ <span style={{ minWidth: '80px', fontSize: '14px' }}>Large:</span>
235
+ <Button size="lg" variant="blue">
236
+ Blue
237
+ </Button>
238
+ <Button size="lg" variant="red">
239
+ Red
240
+ </Button>
241
+ <Button size="lg" variant="grey">
242
+ Grey
243
+ </Button>
244
+ </div>
245
+ </div>
246
+ </div>
247
+
248
+ {/* Disabled States */}
249
+ <div>
250
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
251
+ Disabled States
252
+ </h3>
253
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
254
+ <Button variant="blue" disabled>
255
+ Disabled Blue
256
+ </Button>
257
+ <Button variant="red" disabled>
258
+ Disabled Red
259
+ </Button>
260
+ <Button variant="grey" disabled>
261
+ Disabled Grey
262
+ </Button>
263
+ </div>
264
+ </div>
265
+
266
+ {/* Loading States */}
267
+ <div>
268
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
269
+ Loading States
270
+ </h3>
271
+ <div
272
+ style={{
273
+ display: 'flex',
274
+ gap: '12px',
275
+ flexWrap: 'wrap',
276
+ alignItems: 'center',
277
+ }}
278
+ >
279
+ <Button variant="blue" loading>
280
+ Loading
281
+ </Button>
282
+ <Button variant="blue" leftIcon={<AddIcon />} loading>
283
+ Save
284
+ </Button>
285
+ <Button variant="grey" iconOnly loading>
286
+ <DownloadIcon />
287
+ </Button>
288
+ <Button variant="red" rightIcon={<ArrowForwardIcon />} loading>
289
+ Delete
290
+ </Button>
291
+ </div>
292
+ </div>
293
+
294
+ {/* Buttons with Icons */}
295
+ <div>
296
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
297
+ Buttons with Icons
298
+ </h3>
299
+ <div
300
+ style={{
301
+ display: 'flex',
302
+ flexDirection: 'column',
303
+ gap: '12px',
304
+ width: '300px',
305
+ }}
306
+ >
307
+ <Button variant="blue" leftIcon={<DownloadIcon />}>
308
+ Download
309
+ </Button>
310
+ <Button variant="blue" rightIcon={<ArrowForwardIcon />}>
311
+ Next
312
+ </Button>
313
+ <Button variant="blue" leftIcon={<AddIcon />}>
314
+ Add New
315
+ </Button>
316
+ <Button variant="red" leftIcon={<UploadIcon />}>
317
+ Upload
318
+ </Button>
319
+ <Button variant="grey" leftIcon={<SearchIcon />}>
320
+ Search
321
+ </Button>
322
+ </div>
323
+ </div>
324
+
325
+ {/* Icon Only Buttons */}
326
+ <div>
327
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
328
+ Icon Only Buttons
329
+ </h3>
330
+ <div
331
+ style={{
332
+ display: 'flex',
333
+ gap: '12px',
334
+ flexWrap: 'wrap',
335
+ alignItems: 'center',
336
+ }}
337
+ >
338
+ <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
339
+ <Button iconOnly variant="blue" size="sm">
340
+ <AddIcon />
341
+ </Button>
342
+ <Button iconOnly variant="blue" size="md">
343
+ <DownloadIcon />
344
+ </Button>
345
+ <Button iconOnly variant="blue" size="lg">
346
+ <UploadIcon />
347
+ </Button>
348
+ </div>
349
+ <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
350
+ <Button iconOnly variant="red" size="sm">
351
+ <SearchIcon />
352
+ </Button>
353
+ <Button iconOnly variant="red" size="md">
354
+ <RefreshIcon />
355
+ </Button>
356
+ <Button iconOnly variant="red" size="lg">
357
+ <ArrowForwardIcon />
358
+ </Button>
359
+ </div>
360
+ <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
361
+ <Button iconOnly variant="grey" size="sm">
362
+ <AddIcon />
363
+ </Button>
364
+ <Button iconOnly variant="grey" size="md">
365
+ <DownloadIcon />
366
+ </Button>
367
+ <Button iconOnly variant="grey" size="lg">
368
+ <UploadIcon />
369
+ </Button>
370
+ </div>
371
+ </div>
372
+ </div>
373
+
374
+ {/* Action Buttons Examples */}
375
+ <div>
376
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
377
+ Action Buttons
378
+ </h3>
379
+ <div
380
+ style={{
381
+ display: 'flex',
382
+ flexDirection: 'column',
383
+ gap: '12px',
384
+ width: '200px',
385
+ }}
386
+ >
387
+ <Button variant="blue">Save</Button>
388
+ <Button variant="blue">Submit</Button>
389
+ <Button variant="blue" disabled>
390
+ Disabled
391
+ </Button>
392
+ <Button variant="grey">Cancel</Button>
393
+ </div>
394
+ </div>
395
+
396
+ {/* Section Icon Tiles */}
397
+ <div>
398
+ <h3 style={{ fontSize: '18px', fontWeight: 'bold', marginBottom: '16px' }}>
399
+ Section Icon Tiles
400
+ </h3>
401
+ <div
402
+ style={{
403
+ display: 'flex',
404
+ flexDirection: 'column',
405
+ gap: '16px',
406
+ }}
407
+ >
408
+ <div
409
+ style={{
410
+ display: 'flex',
411
+ gap: '12px',
412
+ alignItems: 'center',
413
+ flexWrap: 'wrap',
414
+ }}
415
+ >
416
+ <span style={{ minWidth: '80px', fontSize: '14px' }}>Sizes:</span>
417
+ <SectionIcon size="sm" icon={<DescriptionOutlinedIcon />} />
418
+ <SectionIcon size="md" icon={<DescriptionOutlinedIcon />} />
419
+ <SectionIcon size="lg" icon={<DescriptionOutlinedIcon />} />
420
+ <SectionIcon size="xl" icon={<DescriptionOutlinedIcon />} />
421
+ </div>
422
+ <div
423
+ style={{
424
+ display: 'flex',
425
+ gap: '12px',
426
+ alignItems: 'center',
427
+ flexWrap: 'wrap',
428
+ }}
429
+ >
430
+ <span style={{ minWidth: '80px', fontSize: '14px' }}>Variants:</span>
431
+ <SectionIcon variant="green" icon={<DescriptionOutlinedIcon />} />
432
+ <SectionIcon variant="blue" icon={<DescriptionOutlinedIcon />} />
433
+ <SectionIcon variant="grey" icon={<DescriptionOutlinedIcon />} />
434
+ <SectionIcon variant="red" icon={<DescriptionOutlinedIcon />} />
435
+ <SectionIcon variant="yellow" icon={<DescriptionOutlinedIcon />} />
436
+ </div>
437
+ <div
438
+ style={{
439
+ display: 'flex',
440
+ gap: '12px',
441
+ alignItems: 'center',
442
+ flexWrap: 'wrap',
443
+ }}
444
+ >
445
+ <span style={{ minWidth: '80px', fontSize: '14px' }}>Icons:</span>
446
+ <SectionIcon icon={<DescriptionOutlinedIcon />} />
447
+ <SectionIcon icon={<ReportDollarIcon />} />
448
+ <SectionIcon variant="blue" icon={<DownloadIcon />} />
449
+ <SectionIcon variant="grey" icon={<SearchIcon />} />
450
+ <SectionIcon variant="yellow" icon={<RefreshIcon />} />
451
+ <SectionIcon variant="red" icon={<UploadIcon />} />
452
+ </div>
453
+ </div>
454
+ </div>
455
+ </div>
456
+ ),
457
+ };
@@ -0,0 +1,202 @@
1
+ import React, { ReactNode, cloneElement, isValidElement, useState, useCallback } from 'react';
2
+ import { getButtonTokensFromResolved } from '../../tokens';
3
+ import { useTokens } from '../../ThemeProvider/ThemeContext';
4
+ import type { ButtonVariant, ButtonSize, ButtonShape } from '../../tokens';
5
+ import { Spinner } from '../Spinner/Spinner';
6
+
7
+ interface CustomButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'color'> {
8
+ variant?: ButtonVariant;
9
+ size?: ButtonSize;
10
+ shape?: ButtonShape;
11
+ leftIcon?: ReactNode;
12
+ rightIcon?: ReactNode;
13
+ iconOnly?: boolean;
14
+ fullWidth?: boolean;
15
+ showBoderRadis?: boolean;
16
+ loading?: boolean;
17
+ }
18
+
19
+ export const Button = ({
20
+ variant = 'blue',
21
+ size = 'md',
22
+ shape,
23
+ children,
24
+ leftIcon,
25
+ rightIcon,
26
+ iconOnly = false,
27
+ disabled = false,
28
+ fullWidth = false,
29
+ showBoderRadis = true,
30
+ loading = false,
31
+ type = 'button',
32
+ onMouseEnter,
33
+ onMouseLeave,
34
+ style,
35
+ ...rest
36
+ }: CustomButtonProps) => {
37
+ // shape prop is kept for API compatibility but borderRadius now uses size-based values
38
+ void shape;
39
+ const [hovered, setHovered] = useState(false);
40
+ const resolvedTokens = useTokens();
41
+ const { colors, sizes } = getButtonTokensFromResolved(resolvedTokens);
42
+ const colorTokens = colors[variant];
43
+ const sizeTokens = sizes[size];
44
+
45
+ const hoverTextColor = colorTokens?.hoverTextColor ?? colorTokens?.color;
46
+ const disabledOpacity = disabled || loading ? 0.3 : 1;
47
+ const isHover = hovered && !disabled && !loading;
48
+
49
+ const handleMouseEnter = useCallback(
50
+ (e: React.MouseEvent<HTMLButtonElement>) => {
51
+ setHovered(true);
52
+ onMouseEnter?.(e);
53
+ },
54
+ [onMouseEnter]
55
+ );
56
+
57
+ const handleMouseLeave = useCallback(
58
+ (e: React.MouseEvent<HTMLButtonElement>) => {
59
+ setHovered(false);
60
+ onMouseLeave?.(e);
61
+ },
62
+ [onMouseLeave]
63
+ );
64
+
65
+ const getWidth = () => {
66
+ if (iconOnly) return sizeTokens?.height;
67
+ if (fullWidth) return '100%';
68
+ return sizeTokens?.width;
69
+ };
70
+
71
+ const iconColor =
72
+ disabled || loading ? colorTokens?.color
73
+ : isHover ? hoverTextColor
74
+ : colorTokens?.color;
75
+ const effectiveColor = (style as React.CSSProperties)?.color ?? iconColor;
76
+ const backgroundColor =
77
+ disabled || loading ? colorTokens?.background
78
+ : isHover ? colorTokens?.hover
79
+ : colorTokens?.background;
80
+
81
+ const cloneIconWithColor = (icon: ReactNode) => {
82
+ if (!icon) return null;
83
+ if (isValidElement(icon)) {
84
+ const iconSizePx = (sizeTokens?.fontSize ?? 0) + 4;
85
+ const iconSize = `${iconSizePx}px`;
86
+ const existingStyle =
87
+ (icon as React.ReactElement<{ style?: React.CSSProperties }>).props?.style || {};
88
+ return cloneElement(
89
+ icon as React.ReactElement<{
90
+ style?: React.CSSProperties;
91
+ sx?: any;
92
+ }>,
93
+ {
94
+ style: {
95
+ ...existingStyle,
96
+ color: effectiveColor,
97
+ fill: effectiveColor,
98
+ fontSize: iconSize,
99
+ width: iconSize,
100
+ height: iconSize,
101
+ display: 'flex',
102
+ alignItems: 'center',
103
+ justifyContent: 'center',
104
+ },
105
+ }
106
+ );
107
+ }
108
+ return icon;
109
+ };
110
+
111
+ const baseStyle: React.CSSProperties = {
112
+ backgroundColor,
113
+ color: iconColor,
114
+ height: sizeTokens?.height,
115
+ minHeight: sizeTokens?.height,
116
+ maxHeight: sizeTokens?.height,
117
+ minWidth:
118
+ iconOnly ? sizeTokens.height
119
+ : fullWidth ? '100%'
120
+ : undefined,
121
+ width: getWidth(),
122
+ padding: iconOnly ? 0 : sizeTokens?.padding,
123
+ fontSize: sizeTokens?.fontSize,
124
+ fontFamily: '"Roboto", sans-serif',
125
+ fontWeight: 500,
126
+ lineHeight: 1.5,
127
+ borderRadius: showBoderRadis ? sizeTokens?.borderRadius : 0,
128
+ border: colorTokens?.border || 'none',
129
+ textTransform: 'none',
130
+ boxSizing: 'border-box',
131
+ opacity: disabled || loading ? disabledOpacity : 1,
132
+ display: 'flex',
133
+ alignItems: 'center',
134
+ justifyContent: 'center',
135
+ gap:
136
+ !iconOnly && children && (leftIcon || rightIcon || loading) ?
137
+ (sizeTokens?.contentGap ?? 12)
138
+ : 0,
139
+ cursor: disabled || loading ? 'not-allowed' : 'pointer',
140
+ outline: 'none',
141
+ ...style,
142
+ };
143
+
144
+ return (
145
+ <button
146
+ {...rest}
147
+ type={type}
148
+ disabled={disabled || loading}
149
+ style={baseStyle}
150
+ onMouseEnter={handleMouseEnter}
151
+ onMouseLeave={handleMouseLeave}
152
+ >
153
+ {iconOnly ?
154
+ <span
155
+ style={{
156
+ display: 'flex',
157
+ alignItems: 'center',
158
+ justifyContent: 'center',
159
+ color: effectiveColor,
160
+ }}
161
+ >
162
+ {loading ?
163
+ cloneIconWithColor(<Spinner color={effectiveColor as string} />)
164
+ : cloneIconWithColor(leftIcon || rightIcon || children)}
165
+ </span>
166
+ : <>
167
+ {(loading || leftIcon) && (
168
+ <span
169
+ style={{
170
+ display: 'inline-flex',
171
+ alignItems: 'center',
172
+ justifyContent: 'center',
173
+ color: effectiveColor,
174
+ flexShrink: 0,
175
+ }}
176
+ >
177
+ {loading ?
178
+ cloneIconWithColor(<Spinner color={effectiveColor as string} />)
179
+ : cloneIconWithColor(leftIcon)}
180
+ </span>
181
+ )}
182
+ {children && (
183
+ <span style={{ color: effectiveColor, whiteSpace: 'nowrap' }}>{children}</span>
184
+ )}
185
+ {rightIcon && !loading && (
186
+ <span
187
+ style={{
188
+ display: 'inline-flex',
189
+ alignItems: 'center',
190
+ justifyContent: 'center',
191
+ color: effectiveColor,
192
+ flexShrink: 0,
193
+ }}
194
+ >
195
+ {cloneIconWithColor(rightIcon)}
196
+ </span>
197
+ )}
198
+ </>
199
+ }
200
+ </button>
201
+ );
202
+ };
@@ -0,0 +1,18 @@
1
+ export type ButtonVariant = "blue" | "red" | "grey";
2
+ export type ButtonSize = "sm" | "md" | "lg";
3
+ export type ButtonShape = "rounded" | "square" | "pill";
4
+
5
+ export interface ButtonProps {
6
+ variant?: ButtonVariant;
7
+ size?: ButtonSize;
8
+ shape?: ButtonShape;
9
+ children?: React.ReactNode;
10
+ leftIcon?: React.ReactNode;
11
+ rightIcon?: React.ReactNode;
12
+ iconOnly?: boolean;
13
+ disabled?: boolean;
14
+ fullWidth?: boolean;
15
+ showBoderRadis?: boolean;
16
+ onClick?: () => void;
17
+ loading?: boolean;
18
+ }