@livechat/design-system-react-components 1.0.0-alpha.4 → 1.0.0-alpha.7

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 (233) hide show
  1. package/dist/dsrc.cjs.js +1 -0
  2. package/dist/dsrc.es.js +2213 -0
  3. package/dist/dsrc.umd.js +1 -0
  4. package/dist/src/components/Alert/Alert.d.ts +19 -0
  5. package/{src/components/Alert/index.ts → dist/src/components/Alert/index.d.ts} +0 -0
  6. package/dist/src/components/Badge/Badge.d.ts +5 -0
  7. package/{src/components/Badge/index.ts → dist/src/components/Badge/index.d.ts} +0 -0
  8. package/dist/src/components/Button/Button.d.ts +13 -0
  9. package/{src/components/Button/index.ts → dist/src/components/Button/index.d.ts} +0 -0
  10. package/dist/src/components/ButtonGroup/ButtonGroup.d.ts +11 -0
  11. package/{src/components/ButtonGroup/index.ts → dist/src/components/ButtonGroup/index.d.ts} +0 -0
  12. package/dist/src/components/Card/Card.d.ts +6 -0
  13. package/{src/components/Card/index.ts → dist/src/components/Card/index.d.ts} +0 -0
  14. package/dist/src/components/Checkbox/Checkbox.d.ts +7 -0
  15. package/dist/src/components/Checkbox/CheckboxField.d.ts +7 -0
  16. package/{src/components/Checkbox/index.ts → dist/src/components/Checkbox/index.d.ts} +0 -0
  17. package/dist/src/components/FieldDescription/FieldDescription.d.ts +3 -0
  18. package/{src/components/FieldDescription/index.ts → dist/src/components/FieldDescription/index.d.ts} +0 -0
  19. package/dist/src/components/FieldError/FieldError.d.ts +3 -0
  20. package/{src/components/FieldError/index.ts → dist/src/components/FieldError/index.d.ts} +0 -0
  21. package/dist/src/components/FieldGroup/FieldGroup.d.ts +8 -0
  22. package/{src/components/FieldGroup/index.ts → dist/src/components/FieldGroup/index.d.ts} +0 -0
  23. package/dist/src/components/Form/Form.d.ts +7 -0
  24. package/{src/components/Form/index.ts → dist/src/components/Form/index.d.ts} +0 -0
  25. package/dist/src/components/FormGroup/FormGroup.d.ts +7 -0
  26. package/{src/components/FormGroup/index.ts → dist/src/components/FormGroup/index.d.ts} +0 -0
  27. package/dist/src/components/Icon/Icon.d.ts +70 -0
  28. package/{src/components/Icon/index.ts → dist/src/components/Icon/index.d.ts} +0 -0
  29. package/dist/src/components/InputField/InputField.d.ts +15 -0
  30. package/{src/components/InputField/index.ts → dist/src/components/InputField/index.d.ts} +0 -0
  31. package/{src/components/Link/Link.tsx → dist/src/components/Link/Link.d.ts} +3 -26
  32. package/{src/components/Link/index.ts → dist/src/components/Link/index.d.ts} +0 -0
  33. package/dist/src/components/Loader/Loader.d.ts +10 -0
  34. package/{src/components/Loader/index.ts → dist/src/components/Loader/index.d.ts} +0 -0
  35. package/dist/src/components/Modal/ActionModal.d.ts +8 -0
  36. package/dist/src/components/Modal/Modal.d.ts +7 -0
  37. package/dist/src/components/Modal/ModalBase.d.ts +6 -0
  38. package/dist/src/components/Modal/ModalCloseButton.d.ts +3 -0
  39. package/dist/src/components/Modal/ModalPortal.d.ts +7 -0
  40. package/{src/components/Modal/index.ts → dist/src/components/Modal/index.d.ts} +0 -1
  41. package/dist/src/components/NumericInput/NumericInput.d.ts +14 -0
  42. package/dist/src/components/NumericInput/NumericInputField.d.ts +19 -0
  43. package/{src/components/NumericInput/index.ts → dist/src/components/NumericInput/index.d.ts} +0 -0
  44. package/dist/src/components/Popover/Popover.d.ts +15 -0
  45. package/{src/components/Popover/index.ts → dist/src/components/Popover/index.d.ts} +0 -0
  46. package/dist/src/components/Progress/ProgressCircle.d.ts +9 -0
  47. package/dist/src/components/Progress/constants.d.ts +12 -0
  48. package/dist/src/components/Progress/helpers.d.ts +3 -0
  49. package/{src/components/Progress/index.ts → dist/src/components/Progress/index.d.ts} +0 -0
  50. package/dist/src/components/PromoBanner/PromoBanner.d.ts +19 -0
  51. package/{src/components/PromoBanner/index.ts → dist/src/components/PromoBanner/index.d.ts} +0 -0
  52. package/dist/src/components/RadioButton/RadioButton.d.ts +7 -0
  53. package/{src/components/RadioButton/index.ts → dist/src/components/RadioButton/index.d.ts} +0 -0
  54. package/dist/src/components/Switch/Switch.d.ts +20 -0
  55. package/{src/components/Switch/index.ts → dist/src/components/Switch/index.d.ts} +0 -0
  56. package/dist/src/components/Tab/Tab.d.ts +12 -0
  57. package/dist/src/components/Tab/TabsWrapper.d.ts +3 -0
  58. package/{src/components/Tab/index.ts → dist/src/components/Tab/index.d.ts} +0 -0
  59. package/dist/src/components/Tag/Tag.d.ts +12 -0
  60. package/{src/components/Tag/index.ts → dist/src/components/Tag/index.d.ts} +0 -0
  61. package/dist/src/components/TagInput/EditableTag.d.ts +11 -0
  62. package/dist/src/components/TagInput/EditableTagContent.d.ts +11 -0
  63. package/dist/src/components/TagInput/EmailTagInput.d.ts +5 -0
  64. package/dist/src/components/TagInput/TagInput.d.ts +12 -0
  65. package/{src/components/TagInput/index.ts → dist/src/components/TagInput/index.d.ts} +0 -0
  66. package/dist/src/components/TextField/TextField.d.ts +13 -0
  67. package/{src/components/TextField/index.ts → dist/src/components/TextField/index.d.ts} +0 -0
  68. package/dist/src/components/Toast/Toast.d.ts +22 -0
  69. package/dist/src/components/Toast/ToastWrapper.d.ts +27 -0
  70. package/{src/components/Toast/index.ts → dist/src/components/Toast/index.d.ts} +0 -0
  71. package/dist/src/components/Typography/Heading.d.ts +11 -0
  72. package/dist/src/components/Typography/Text.d.ts +15 -0
  73. package/{src/components/Typography/index.ts → dist/src/components/Typography/index.d.ts} +0 -0
  74. package/{src/index.ts → dist/src/index.d.ts} +0 -3
  75. package/dist/src/themes/designTokens.d.ts +126 -0
  76. package/dist/src/utils/keyCodes.d.ts +12 -0
  77. package/dist/src/utils/noop.d.ts +1 -0
  78. package/{src → dist/src}/vite-env.d.ts +0 -0
  79. package/dist/style.css +1 -0
  80. package/{src/themes/dark.scss → dist/themes/dark.css} +2 -0
  81. package/dist/themes/dark.css.map +1 -0
  82. package/{src/themes/legacy.scss → dist/themes/legacy.css} +2 -0
  83. package/dist/themes/legacy.css.map +1 -0
  84. package/{src/themes/light.scss → dist/themes/light.css} +2 -0
  85. package/dist/themes/light.css.map +1 -0
  86. package/package.json +8 -5
  87. package/.eslintrc +0 -9
  88. package/.storybook/main.js +0 -20
  89. package/.storybook/preview-head.html +0 -31
  90. package/.storybook/preview.js +0 -21
  91. package/src/components/Alert/Alert.module.scss +0 -88
  92. package/src/components/Alert/Alert.spec.tsx +0 -78
  93. package/src/components/Alert/Alert.stories.tsx +0 -73
  94. package/src/components/Alert/Alert.tsx +0 -94
  95. package/src/components/Badge/Badge.module.scss +0 -23
  96. package/src/components/Badge/Badge.spec.tsx +0 -12
  97. package/src/components/Badge/Badge.stories.tsx +0 -24
  98. package/src/components/Badge/Badge.tsx +0 -24
  99. package/src/components/Button/Button.module.scss +0 -257
  100. package/src/components/Button/Button.spec.tsx +0 -110
  101. package/src/components/Button/Button.stories.tsx +0 -152
  102. package/src/components/Button/Button.tsx +0 -88
  103. package/src/components/ButtonGroup/ButtonGroup.module.scss +0 -31
  104. package/src/components/ButtonGroup/ButtonGroup.spec.tsx +0 -61
  105. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -53
  106. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -75
  107. package/src/components/Card/Card.module.scss +0 -31
  108. package/src/components/Card/Card.spec.tsx +0 -38
  109. package/src/components/Card/Card.stories.tsx +0 -30
  110. package/src/components/Card/Card.tsx +0 -34
  111. package/src/components/Checkbox/Checkbox.module.scss +0 -99
  112. package/src/components/Checkbox/Checkbox.tsx +0 -39
  113. package/src/components/Checkbox/CheckboxField.spec.tsx +0 -58
  114. package/src/components/Checkbox/CheckboxField.stories.tsx +0 -30
  115. package/src/components/Checkbox/CheckboxField.tsx +0 -46
  116. package/src/components/FieldDescription/FieldDescription.module.scss +0 -5
  117. package/src/components/FieldDescription/FieldDescription.tsx +0 -23
  118. package/src/components/FieldError/FieldError.module.scss +0 -5
  119. package/src/components/FieldError/FieldError.tsx +0 -23
  120. package/src/components/FieldGroup/FieldGroup.module.scss +0 -25
  121. package/src/components/FieldGroup/FieldGroup.spec.tsx +0 -42
  122. package/src/components/FieldGroup/FieldGroup.stories.tsx +0 -34
  123. package/src/components/FieldGroup/FieldGroup.tsx +0 -38
  124. package/src/components/Form/Form.module.scss +0 -22
  125. package/src/components/Form/Form.spec.tsx +0 -38
  126. package/src/components/Form/Form.stories.tsx +0 -42
  127. package/src/components/Form/Form.tsx +0 -46
  128. package/src/components/FormGroup/FormGroup.module.scss +0 -20
  129. package/src/components/FormGroup/FormGroup.spec.tsx +0 -34
  130. package/src/components/FormGroup/FormGroup.stories.tsx +0 -30
  131. package/src/components/FormGroup/FormGroup.tsx +0 -44
  132. package/src/components/Icon/Icon.module.scss +0 -70
  133. package/src/components/Icon/Icon.stories.tsx +0 -53
  134. package/src/components/Icon/Icon.tsx +0 -118
  135. package/src/components/InputField/InputField.module.scss +0 -37
  136. package/src/components/InputField/InputField.spec.tsx +0 -53
  137. package/src/components/InputField/InputField.stories.tsx +0 -73
  138. package/src/components/InputField/InputField.tsx +0 -72
  139. package/src/components/Link/Link.module.scss +0 -18
  140. package/src/components/Link/Link.stories.tsx +0 -17
  141. package/src/components/Loader/Loader.module.scss +0 -66
  142. package/src/components/Loader/Loader.spec.tsx +0 -64
  143. package/src/components/Loader/Loader.stories.tsx +0 -25
  144. package/src/components/Loader/Loader.tsx +0 -48
  145. package/src/components/Modal/ActionModal.tsx +0 -37
  146. package/src/components/Modal/Modal.module.scss +0 -131
  147. package/src/components/Modal/Modal.stories.tsx +0 -85
  148. package/src/components/Modal/Modal.tsx +0 -41
  149. package/src/components/Modal/ModalBase.spec.tsx +0 -58
  150. package/src/components/Modal/ModalBase.tsx +0 -66
  151. package/src/components/Modal/ModalCloseButton.tsx +0 -20
  152. package/src/components/Modal/ModalPortal.tsx +0 -35
  153. package/src/components/NumericInput/NumericInput.module.scss +0 -110
  154. package/src/components/NumericInput/NumericInput.spec.tsx +0 -129
  155. package/src/components/NumericInput/NumericInput.stories.tsx +0 -56
  156. package/src/components/NumericInput/NumericInput.tsx +0 -161
  157. package/src/components/NumericInput/NumericInputField.stories.tsx +0 -58
  158. package/src/components/NumericInput/NumericInputField.tsx +0 -57
  159. package/src/components/Popover/Popover.module.scss +0 -16
  160. package/src/components/Popover/Popover.spec.tsx +0 -39
  161. package/src/components/Popover/Popover.stories.css +0 -23
  162. package/src/components/Popover/Popover.stories.tsx +0 -164
  163. package/src/components/Popover/Popover.tsx +0 -124
  164. package/src/components/Progress/ProgressBar.module.scss +0 -48
  165. package/src/components/Progress/ProgressBar.spec.tsx +0 -33
  166. package/src/components/Progress/ProgressBar.stories.tsx +0 -23
  167. package/src/components/Progress/ProgressBar.tsx +0 -62
  168. package/src/components/Progress/ProgressCircle.module.scss +0 -64
  169. package/src/components/Progress/ProgressCircle.spec.tsx +0 -34
  170. package/src/components/Progress/ProgressCircle.stories.tsx +0 -28
  171. package/src/components/Progress/ProgressCircle.tsx +0 -104
  172. package/src/components/Progress/constants.ts +0 -23
  173. package/src/components/Progress/helpers.ts +0 -23
  174. package/src/components/PromoBanner/PromoBanner.module.scss +0 -121
  175. package/src/components/PromoBanner/PromoBanner.spec.tsx +0 -119
  176. package/src/components/PromoBanner/PromoBanner.stories.tsx +0 -125
  177. package/src/components/PromoBanner/PromoBanner.tsx +0 -99
  178. package/src/components/RadioButton/RadioButton.module.scss +0 -100
  179. package/src/components/RadioButton/RadioButton.spec.tsx +0 -70
  180. package/src/components/RadioButton/RadioButton.stories.tsx +0 -34
  181. package/src/components/RadioButton/RadioButton.tsx +0 -54
  182. package/src/components/Switch/Switch.module.scss +0 -126
  183. package/src/components/Switch/Switch.spec.tsx +0 -40
  184. package/src/components/Switch/Switch.stories.tsx +0 -23
  185. package/src/components/Switch/Switch.tsx +0 -100
  186. package/src/components/Tab/Tab.module.scss +0 -56
  187. package/src/components/Tab/Tab.spec.tsx +0 -34
  188. package/src/components/Tab/Tab.stories.tsx +0 -20
  189. package/src/components/Tab/Tab.tsx +0 -49
  190. package/src/components/Tab/TabsWrapper.module.scss +0 -11
  191. package/src/components/Tab/TabsWrapper.spec.tsx +0 -19
  192. package/src/components/Tab/TabsWrapper.stories.tsx +0 -46
  193. package/src/components/Tab/TabsWrapper.tsx +0 -24
  194. package/src/components/Tag/Tag.module.scss +0 -131
  195. package/src/components/Tag/Tag.spec.tsx +0 -93
  196. package/src/components/Tag/Tag.stories.tsx +0 -151
  197. package/src/components/Tag/Tag.tsx +0 -129
  198. package/src/components/TagInput/EditableTag.tsx +0 -54
  199. package/src/components/TagInput/EditableTagContent.tsx +0 -81
  200. package/src/components/TagInput/EmailTagInput.tsx +0 -31
  201. package/src/components/TagInput/TagInput.module.scss +0 -81
  202. package/src/components/TagInput/TagInput.spec.tsx +0 -58
  203. package/src/components/TagInput/TagInput.stories.tsx +0 -49
  204. package/src/components/TagInput/TagInput.tsx +0 -133
  205. package/src/components/TextField/TextField.module.scss +0 -90
  206. package/src/components/TextField/TextField.spec.tsx +0 -40
  207. package/src/components/TextField/TextField.stories.tsx +0 -60
  208. package/src/components/TextField/TextField.tsx +0 -100
  209. package/src/components/Toast/Toast.module.scss +0 -218
  210. package/src/components/Toast/Toast.spec.tsx +0 -96
  211. package/src/components/Toast/Toast.stories.tsx +0 -64
  212. package/src/components/Toast/Toast.tsx +0 -121
  213. package/src/components/Toast/ToastWrapper.spec.tsx +0 -13
  214. package/src/components/Toast/ToastWrapper.stories.tsx +0 -55
  215. package/src/components/Toast/ToastWrapper.tsx +0 -87
  216. package/src/components/Typography/Heading.tsx +0 -36
  217. package/src/components/Typography/Text.tsx +0 -49
  218. package/src/components/Typography/Typography.module.scss +0 -132
  219. package/src/index.scss +0 -9
  220. package/src/stories/ColorTokens.stories.mdx +0 -10
  221. package/src/stories/Icons.stories.mdx +0 -12
  222. package/src/stories/Typography.stories.mdx +0 -65
  223. package/src/stories/components/ColorTokens.tsx +0 -99
  224. package/src/stories/components/IconsShowcase.tsx +0 -25
  225. package/src/stories/components/iconsShowcase.css +0 -13
  226. package/src/test/setup.ts +0 -1
  227. package/src/test/utils.ts +0 -3
  228. package/src/themes/designTokens.ts +0 -126
  229. package/src/utils/keyCodes.ts +0 -12
  230. package/src/utils/noop.ts +0 -2
  231. package/tsconfig.json +0 -25
  232. package/tsconfig.node.json +0 -8
  233. package/vite.config.ts +0 -44
@@ -1,110 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { render } from 'test-utils';
4
- import { Icon } from '../Icon';
5
-
6
- import { Button } from './Button';
7
- import styles from './Button.module.scss';
8
-
9
- describe('<Button> component', () => {
10
- function renderButton(props = {}) {
11
- const result = render(<Button {...props} />);
12
-
13
- return {
14
- ...result,
15
- btnEl: result.container.firstChild,
16
- };
17
- }
18
-
19
- it('should have default set of classNames', () => {
20
- const { btnEl } = renderButton();
21
-
22
- const expectedClasses = ['btn', 'btn--basic', 'btn--medium'].map(
23
- (cls) => styles[cls]
24
- );
25
- const notExpectedClasses = [
26
- 'btn--loading',
27
- 'btn--full-width',
28
- 'btn--icon-only',
29
- ].map((cls) => styles[cls]);
30
-
31
- expect(btnEl).toHaveClass(...expectedClasses);
32
- expect(btnEl).not.toHaveClass(...notExpectedClasses);
33
- });
34
-
35
- it('should allow to pass custom className', () => {
36
- const { btnEl } = renderButton({ className: 'my-class' });
37
-
38
- expect(btnEl).toHaveClass('my-class');
39
- });
40
-
41
- it('should not show loader by deafult', () => {
42
- const { container, btnEl } = renderButton();
43
-
44
- expect(btnEl).not.toHaveClass(styles['btn--loading']);
45
- expect(
46
- container.querySelector(`.${styles['btn__loader']}`)
47
- ).not.toBeInTheDocument();
48
- });
49
-
50
- it('should show loader when "loading" prop is true', () => {
51
- const { container, btnEl } = renderButton({ loading: true });
52
-
53
- expect(btnEl).toHaveClass(styles['btn--loading']);
54
- expect(container.querySelector(`.${styles['btn__loader']}`)).toBeVisible();
55
- });
56
-
57
- it('should not show icon by default', () => {
58
- const { container } = renderButton();
59
-
60
- expect(
61
- container.querySelector(`.${styles['btn__icon']}`)
62
- ).not.toBeInTheDocument();
63
- });
64
-
65
- it('should show icon component when "icon" prop has been passed', () => {
66
- const { container } = renderButton({
67
- icon: <Icon source="span" />,
68
- });
69
-
70
- const iconEl = container.querySelector(`.${styles['btn__icon']}`);
71
-
72
- expect(iconEl).toBeVisible();
73
- expect(iconEl).toHaveClass(styles['btn__icon--left']);
74
- });
75
-
76
- it('should show icon component on right side', () => {
77
- const { container } = renderButton({
78
- icon: <Icon source="span" />,
79
- iconPosition: 'right',
80
- });
81
-
82
- const iconEl = container.querySelector(`.${styles['btn__icon']}`);
83
-
84
- expect(iconEl).toBeVisible();
85
- expect(iconEl).toHaveClass(styles['btn__icon--right']);
86
- });
87
-
88
- it('should allow to take "fullWidth"', () => {
89
- const { btnEl } = renderButton({ fullWidth: true });
90
-
91
- expect(btnEl).toHaveClass(styles['btn--full-width']);
92
- });
93
-
94
- it('should allow for "icon-only" content', () => {
95
- const { btnEl } = renderButton({
96
- children: null,
97
- icon: <Icon source="span" />,
98
- });
99
-
100
- expect(btnEl).toHaveClass(styles['btn--icon-only']);
101
- });
102
-
103
- it('should render as an anchor element if href is passed', () => {
104
- const { btnEl: linkEl } = renderButton({ href: 'https://example.com' });
105
- const { btnEl } = renderButton({ href: '' });
106
-
107
- expect((btnEl as HTMLElement).tagName).toBe('BUTTON');
108
- expect((linkEl as HTMLElement).tagName).toBe('A');
109
- });
110
- });
@@ -1,152 +0,0 @@
1
- import * as React from 'react';
2
- import { ComponentMeta } from '@storybook/react';
3
-
4
- import * as MaterialIcons from '@livechat/design-system-icons/react/material';
5
-
6
- import { Icon } from '../Icon';
7
- import { Button, ButtonProps } from './Button';
8
-
9
- const icons = Object.fromEntries(
10
- Object.entries(MaterialIcons).map(([key, source]) => [
11
- key,
12
- <Icon source={source as React.FC} />,
13
- ])
14
- );
15
-
16
- const iterator = Object.keys(icons);
17
-
18
- export default {
19
- title: 'Components/Button',
20
- component: Button,
21
- argTypes: {
22
- icon: {
23
- options: ['None', ...iterator],
24
- mapping: Object.assign(icons, { None: null }),
25
- control: {
26
- type: 'select',
27
- labels: iterator,
28
- },
29
- },
30
- },
31
- parameters: {
32
- controls: {
33
- sort: 'alpha',
34
- },
35
- },
36
- } as ComponentMeta<typeof Button>;
37
-
38
- export const button = (args: ButtonProps): React.ReactElement => (
39
- <Button {...args} />
40
- );
41
- button.args = {
42
- loading: false,
43
- disabled: false,
44
- size: 'medium',
45
- kind: 'primary',
46
- children: 'Button Text',
47
- fullWidth: false,
48
- iconPosition: 'left',
49
- icon: 'None',
50
- };
51
-
52
- export const kinds = (): React.ReactElement => (
53
- <div>
54
- <div className="spacer">
55
- <Button>Basic</Button>
56
- <Button kind="primary">Primary</Button>
57
- <Button kind="secondary">Secondary</Button>
58
- <Button kind="destructive">Destructive</Button>
59
- <Button kind="text">Text</Button>
60
- <Button kind="plain">Plain</Button>
61
- <Button kind="plain-light">Plain light</Button>
62
- </div>
63
- </div>
64
- );
65
-
66
- export const states = (): React.ReactElement => (
67
- <div>
68
- <div className="spacer">
69
- <Button disabled>Disabled</Button>
70
- <Button disabled kind="primary">
71
- Disabled
72
- </Button>
73
- <Button disabled kind="secondary">
74
- Disabled
75
- </Button>
76
- <Button disabled kind="destructive">
77
- Disabled
78
- </Button>
79
- <Button disabled kind="text">
80
- Disabled
81
- </Button>
82
- <Button disabled kind="plain">
83
- Disabled
84
- </Button>
85
- <Button disabled kind="plain-light">
86
- Disabled
87
- </Button>
88
- </div>
89
- <div className="spacer">
90
- <Button loading>Loading</Button>
91
- <Button loading kind="primary">
92
- Loading
93
- </Button>
94
- <Button loading kind="secondary">
95
- Loading
96
- </Button>
97
- <Button loading kind="destructive">
98
- Loading
99
- </Button>
100
- <Button loading kind="text">
101
- Loading
102
- </Button>
103
- <Button loading kind="plain">
104
- Loading
105
- </Button>
106
- <Button loading kind="plain-light">
107
- Loading
108
- </Button>
109
- </div>
110
- </div>
111
- );
112
-
113
- export const sizes = (): React.ReactElement => (
114
- <>
115
- <div className="spacer">
116
- <Button size="compact" kind="primary">
117
- Compact
118
- </Button>
119
- <Button size="medium" kind="primary">
120
- Medium (default)
121
- </Button>
122
- <Button size="large" kind="primary">
123
- Large
124
- </Button>
125
- </div>
126
- <div className="spacer">
127
- <Button
128
- icon={<Icon source={MaterialIcons.AddCircle} />}
129
- size="compact"
130
- kind="primary"
131
- />
132
- <Button
133
- icon={<Icon source={MaterialIcons.AddCircle} />}
134
- size="medium"
135
- kind="primary"
136
- />
137
- <Button
138
- icon={<Icon source={MaterialIcons.AddCircle} />}
139
- size="large"
140
- kind="primary"
141
- />
142
- </div>
143
- </>
144
- );
145
-
146
- export const buttonAsLink = (args: ButtonProps): React.ReactElement => (
147
- <Button href="https://livechat.com" target="_blank" kind="primary" {...args}>
148
- Button as an external link to livechat.com
149
- </Button>
150
- );
151
-
152
- buttonAsLink.args = { ...button.args, href: 'https://livechat.com' };
@@ -1,88 +0,0 @@
1
- import * as React from 'react';
2
- import cx from 'clsx';
3
- import { Loader } from '../Loader';
4
-
5
- import styles from './Button.module.scss';
6
-
7
- export type ButtonSize = 'compact' | 'medium' | 'large';
8
-
9
- export type ButtonProps = {
10
- kind?:
11
- | 'basic'
12
- | 'primary'
13
- | 'secondary'
14
- | 'destructive'
15
- | 'text'
16
- | 'plain'
17
- | 'plain-light';
18
- size?: ButtonSize;
19
- disabled?: boolean;
20
- loading?: boolean;
21
- fullWidth?: boolean;
22
- loaderLabel?: string;
23
- icon?: React.ReactElement;
24
- iconPosition?: 'left' | 'right';
25
- } & React.ButtonHTMLAttributes<HTMLButtonElement> &
26
- React.AnchorHTMLAttributes<HTMLAnchorElement>;
27
-
28
- const baseClass = 'btn';
29
-
30
- export const Button: React.FC<ButtonProps> = ({
31
- loading = false,
32
- disabled = false,
33
- type = 'button',
34
- fullWidth = false,
35
- kind = 'basic',
36
- size = 'medium',
37
- icon = null,
38
- iconPosition = 'left',
39
- loaderLabel,
40
- className,
41
- children,
42
- href,
43
- ...props
44
- }) => {
45
- const isDisabled = loading || disabled;
46
-
47
- const Component = href ? 'a' : 'button';
48
-
49
- const mergedClassNames = cx(
50
- className,
51
- styles[baseClass],
52
- styles[`${baseClass}--${kind}`],
53
- styles[`${baseClass}--${size}`],
54
- {
55
- [styles[`${baseClass}--loading`]]: loading,
56
- [styles[`${baseClass}--full-width`]]: fullWidth,
57
- [styles[`${baseClass}--icon-only`]]: !children && icon,
58
- [styles[`${baseClass}--disabled`]]: isDisabled,
59
- }
60
- );
61
-
62
- return (
63
- <Component
64
- className={mergedClassNames}
65
- disabled={isDisabled}
66
- type={type}
67
- href={isDisabled ? undefined : href}
68
- {...props}
69
- >
70
- {loading && (
71
- <Loader
72
- size="small"
73
- label={loaderLabel}
74
- className={styles[`${baseClass}__loader`]}
75
- />
76
- )}
77
- {icon &&
78
- React.cloneElement(icon, {
79
- className: cx(
80
- styles[`${baseClass}__icon`],
81
- styles[`${baseClass}__icon--${iconPosition}`]
82
- ),
83
- disabled,
84
- })}
85
- <div className={styles[`${baseClass}__content`]}>{children}</div>
86
- </Component>
87
- );
88
- };
@@ -1,31 +0,0 @@
1
- .btn-group {
2
- border: 1px solid var(--border-subtle);
3
- border-radius: 4px;
4
- display: inline-flex;
5
- flex-direction: row;
6
- padding: 3px;
7
- vertical-align: middle;
8
-
9
- .btn {
10
- border-color: transparent;
11
- color: var(--content-default);
12
-
13
- &--active {
14
- background-color: var(--surface-basic-active);
15
- }
16
-
17
- &--compact {
18
- height: 24px;
19
- }
20
- &--medium {
21
- height: 28px;
22
- }
23
- &--large {
24
- height: 34px;
25
- }
26
- }
27
-
28
- .btn + .btn {
29
- margin-left: 2px;
30
- }
31
- }
@@ -1,61 +0,0 @@
1
- import * as React from 'react';
2
- import { render, userEvent, vi } from 'test-utils';
3
- import noop from '../../utils/noop';
4
- import { Button } from '../Button';
5
- import { ButtonGroup } from './ButtonGroup';
6
-
7
- import styles from './ButtonGroup.module.scss';
8
-
9
- describe('<ButtonGroup> component', () => {
10
- function renderComponent(props = {}, onButtonClick = noop) {
11
- return render(
12
- <ButtonGroup {...props}>
13
- <Button onClick={onButtonClick}>First button</Button>
14
- <Button>Second button</Button>
15
- </ButtonGroup>
16
- );
17
- }
18
-
19
- it('should have custom css class', () => {
20
- const className = 'my-custom-class';
21
- const {
22
- container: { firstChild: el },
23
- } = renderComponent({ className });
24
-
25
- expect(el).toHaveClass(className);
26
- });
27
-
28
- it('should allow for controlled version of component by passing "currentIndex" prop', () => {
29
- const { getAllByRole } = renderComponent({ currentIndex: 1 });
30
-
31
- const [firstButton, secondButton] = getAllByRole('button');
32
-
33
- expect(firstButton).not.toHaveClass(styles['btn--active']);
34
- expect(secondButton).toHaveClass(styles['btn--active']);
35
- });
36
-
37
- it('should not have active button by default in unconrolled version', () => {
38
- const { getAllByRole } = renderComponent();
39
-
40
- const [firstButton, secondButton] = getAllByRole('button');
41
-
42
- expect(firstButton).not.toHaveClass(styles['btn--active']);
43
- expect(secondButton).not.toHaveClass(styles['btn--active']);
44
- });
45
-
46
- it('should call "onIndexChange" with index of current selected button on click', () => {
47
- const onIndexChange = vi.fn();
48
- const onButtonClick = vi.fn();
49
- const { getAllByRole } = renderComponent({ onIndexChange }, onButtonClick);
50
-
51
- const [firstButton] = getAllByRole('button');
52
-
53
- expect(firstButton).not.toHaveClass(styles['btn--active']);
54
-
55
- userEvent.click(firstButton);
56
-
57
- expect(onIndexChange).toHaveBeenCalledWith(0, expect.anything());
58
- expect(onButtonClick).toHaveBeenCalled();
59
- expect(firstButton).toHaveClass(styles['btn--active']);
60
- });
61
- });
@@ -1,53 +0,0 @@
1
- import * as React from 'react';
2
- import { ComponentMeta } from '@storybook/react';
3
-
4
- import {
5
- ButtonGroup as ButtonGroupComponent,
6
- ButtonGroupProps,
7
- } from './ButtonGroup';
8
-
9
- import { Button } from '../Button';
10
-
11
- export default {
12
- title: 'Components/Button Group',
13
- component: ButtonGroupComponent,
14
- } as ComponentMeta<typeof ButtonGroupComponent>;
15
-
16
- export const controlled = (args: ButtonGroupProps): React.ReactElement => {
17
- return (
18
- <ButtonGroupComponent {...args}>
19
- <Button>First option</Button>
20
- <Button>Second option</Button>
21
- </ButtonGroupComponent>
22
- );
23
- };
24
-
25
- controlled.args = {
26
- currentIndex: 1,
27
- };
28
-
29
- export const uncontrolledEmptySelection = (
30
- args: ButtonGroupProps
31
- ): React.ReactElement => {
32
- return (
33
- <ButtonGroupComponent {...args}>
34
- <Button>First option</Button>
35
- <Button>Second option</Button>
36
- </ButtonGroupComponent>
37
- );
38
- };
39
-
40
- export const uncontrolledWithInitialSelection = (
41
- args: ButtonGroupProps
42
- ): React.ReactElement => {
43
- return (
44
- <ButtonGroupComponent {...args}>
45
- <Button>First option</Button>
46
- <Button>Second option</Button>
47
- </ButtonGroupComponent>
48
- );
49
- };
50
-
51
- uncontrolledWithInitialSelection.args = {
52
- initialIndex: 1,
53
- };
@@ -1,75 +0,0 @@
1
- import * as React from 'react';
2
- import cx from 'clsx';
3
-
4
- import { ButtonSize, ButtonProps } from '../Button';
5
-
6
- import styles from './ButtonGroup.module.scss';
7
-
8
- import noop from '../../utils/noop';
9
-
10
- const baseClass = 'btn-group';
11
-
12
- export interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {
13
- currentIndex?: number;
14
- initialIndex?: number;
15
- fullWidth?: boolean;
16
- size?: ButtonSize;
17
- children: ReadonlyArray<
18
- React.ReactElement<React.PropsWithChildren<ButtonProps>>
19
- >;
20
- onIndexChange?: (
21
- currentIndex: number,
22
- event: React.MouseEvent<HTMLButtonElement>
23
- ) => void;
24
- }
25
-
26
- export const ButtonGroup: React.FC<ButtonGroupProps> = ({
27
- size = 'medium',
28
- fullWidth = false,
29
- onIndexChange = noop,
30
- className,
31
- children,
32
- currentIndex,
33
- initialIndex = -1,
34
- ...restProps
35
- }) => {
36
- const mergedClassName = cx(styles[baseClass], className);
37
- const [currentStateIndex, setCurrentStateIndex] =
38
- React.useState(initialIndex);
39
-
40
- const isControlled = typeof currentIndex === 'number';
41
-
42
- const _currentIndex = isControlled ? currentIndex : currentStateIndex;
43
-
44
- const handleClick = (index: number, event: any) => {
45
- if (!isControlled) {
46
- setCurrentStateIndex(index);
47
- }
48
-
49
- onIndexChange(index, event);
50
- };
51
-
52
- return (
53
- <div role="group" className={mergedClassName} {...restProps}>
54
- {React.Children.map(children, (child, i) =>
55
- React.cloneElement(child, {
56
- fullWidth,
57
- size,
58
- kind: 'secondary',
59
- type: 'button',
60
- onClick: (event: any) => {
61
- handleClick(i, event);
62
- if (child.props.onClick) {
63
- child.props.onClick(event);
64
- }
65
- },
66
- className: cx(
67
- styles['btn'],
68
- styles[`btn--${size as string}`],
69
- i === _currentIndex && styles['btn--active']
70
- ),
71
- })
72
- )}
73
- </div>
74
- );
75
- };
@@ -1,31 +0,0 @@
1
- .card {
2
- background-color: var(--surface-basic-default);
3
- border: solid 1px var(--border-subtle);
4
- border-radius: 4px;
5
- color: var(--content-default);
6
- margin-top: 8px;
7
- overflow: hidden;
8
- padding: 16px;
9
-
10
- &__title {
11
- align-items: center;
12
- display: flex;
13
- margin-bottom: 14px;
14
- }
15
-
16
- &__text {
17
- color: var(--content-default);
18
- overflow: hidden;
19
- text-overflow: ellipsis;
20
- white-space: nowrap;
21
- width: 100%;
22
- }
23
-
24
- &__img {
25
- border-radius: 4px;
26
- display: inline-block;
27
- height: 24px;
28
- margin-right: 10px;
29
- width: 24px;
30
- }
31
- }
@@ -1,38 +0,0 @@
1
- import * as React from 'react';
2
- import { render } from 'test-utils';
3
- import { Card } from './Card';
4
-
5
- describe('<Card /> component', () => {
6
- it('should render only title if image is not provided', () => {
7
- const { getByText, getByRole } = render(<Card title="Hello" />);
8
- expect(getByText('Hello')).toBeVisible();
9
- expect(() => getByRole('img')).toThrow();
10
- });
11
-
12
- it('should render title and image if provided', () => {
13
- const { getByText, getByRole } = render(
14
- <Card title="Hello" img="https://via.placeholder.com/100" />
15
- );
16
- expect(getByText('Hello')).toBeVisible();
17
- expect(getByRole('img')).toBeVisible();
18
- });
19
-
20
- it('should render text children', () => {
21
- const { getByText } = render(<Card title="Hello">Lorem ipsum</Card>);
22
- expect(getByText('Lorem ipsum')).toBeVisible();
23
- });
24
-
25
- it('should render nested elements as children', () => {
26
- const { getByRole } = render(
27
- <Card title="Hello">
28
- <div>
29
- <h3>Lorem ipsum</h3>
30
- </div>
31
- </Card>
32
- );
33
-
34
- const heading = getByRole('heading');
35
- expect(heading).toBeVisible();
36
- expect(heading).toHaveTextContent('Lorem ipsum');
37
- });
38
- });
@@ -1,30 +0,0 @@
1
- import * as React from 'react';
2
- import { ComponentMeta } from '@storybook/react';
3
-
4
- import { Card as CardComponent, CardProps } from '../Card';
5
-
6
- export default {
7
- title: 'Components/Card',
8
- component: CardComponent,
9
- } as ComponentMeta<typeof CardComponent>;
10
-
11
- type ICardArgs = CardProps;
12
-
13
- export const Card = (args: ICardArgs): React.ReactElement => {
14
- return (
15
- <div style={{ width: '300px' }}>
16
- <CardComponent {...args} />
17
- </div>
18
- );
19
- };
20
-
21
- Card.args = {
22
- title: 'Title goes here',
23
- img: 'https://via.placeholder.com/100',
24
- children: (
25
- <p style={{ margin: 0 }}>
26
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
27
- tempor incididunt ut labore
28
- </p>
29
- ),
30
- } as ICardArgs;