@frontify/fondue-components 0.1.0-beta.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 (50) hide show
  1. package/.eslintignore +4 -0
  2. package/.eslintrc.cjs +33 -0
  3. package/.prettierignore +1 -0
  4. package/.prettierrc +17 -0
  5. package/.storybook/DocumentationTemplate.mdx +25 -0
  6. package/.storybook/main.ts +29 -0
  7. package/.storybook/preview.ts +53 -0
  8. package/CHANGELOG.md +7 -0
  9. package/package.json +91 -0
  10. package/playwright/index.html +12 -0
  11. package/playwright/index.ts +3 -0
  12. package/playwright.config.ts +29 -0
  13. package/postcss.config.cjs +8 -0
  14. package/scripts/createNewComponent.ts +42 -0
  15. package/scripts/templates/__tests__/component.ct.tsx +25 -0
  16. package/scripts/templates/__tests__/component.spec.tsx +24 -0
  17. package/scripts/templates/component.stories.ts +35 -0
  18. package/scripts/templates/component.ts +25 -0
  19. package/scripts/templates/index.ts +15 -0
  20. package/scripts/templates/styles/componentStyles.tsx +16 -0
  21. package/scripts/transforms.ts +13 -0
  22. package/scripts/types.ts +7 -0
  23. package/src/components/Button/Button.stories.tsx +57 -0
  24. package/src/components/Button/Button.tsx +111 -0
  25. package/src/components/Button/styles/buttonStyles.ts +175 -0
  26. package/src/components/Button/styles/iconStyles.ts +152 -0
  27. package/src/components/Button/styles/textStyles.ts +149 -0
  28. package/src/components/Button/tests/Button.ct.tsx +61 -0
  29. package/src/components/Button/tests/Button.spec.tsx +34 -0
  30. package/src/components/Divider/Divider.stories.ts +47 -0
  31. package/src/components/Divider/Divider.tsx +69 -0
  32. package/src/components/Divider/__tests__/Divider.spec.tsx +88 -0
  33. package/src/components/LoadingBar/LoadingBar.stories.tsx +32 -0
  34. package/src/components/LoadingBar/LoadingBar.tsx +68 -0
  35. package/src/components/LoadingBar/styles/loadingBarStyles.ts +38 -0
  36. package/src/components/LoadingBar/tests/LoadingBar.ct.tsx +39 -0
  37. package/src/components/Tag/Tag.ct.tsx +16 -0
  38. package/src/components/Tag/Tag.stories.ts +29 -0
  39. package/src/components/Tag/Tag.tsx +18 -0
  40. package/src/components/Tag/__tests__/tag.spec.tsx +13 -0
  41. package/src/index.ts +8 -0
  42. package/src/setupTests.ts +19 -0
  43. package/src/styles.css +35 -0
  44. package/src/utilities/focusStyle.ts +12 -0
  45. package/src/utilities/styleUtilities.ts +19 -0
  46. package/src/utilities/tests/styleUtilities.spec.ts +114 -0
  47. package/tailwind.config.ts +148 -0
  48. package/tsconfig.json +26 -0
  49. package/tsconfig.node.json +21 -0
  50. package/vite.config.ts +67 -0
@@ -0,0 +1,111 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { cloneElement, forwardRef, type ForwardedRef, type MouseEvent, type ReactElement, type ReactNode } from 'react';
4
+
5
+ import { buttonIconSizeMap, buttonStyles } from './styles/buttonStyles';
6
+ import { iconStyles } from './styles/iconStyles';
7
+ import { textStyles } from './styles/textStyles';
8
+
9
+ type ButtonRounding = 'medium' | 'full';
10
+
11
+ type ButtonStyle = 'default' | 'positive' | 'negative' | 'danger' | 'loud';
12
+
13
+ type ButtonSize = 'small' | 'medium' | 'large';
14
+
15
+ type ButtonType = 'button' | 'submit' | 'reset';
16
+
17
+ type ButtonEmphasis = 'default' | 'weak' | 'strong';
18
+
19
+ export type ButtonProps = {
20
+ /**
21
+ * @default null
22
+ */
23
+ type?: ButtonType;
24
+ /**
25
+ * @default null
26
+ */
27
+ title?: string;
28
+ /**
29
+ * @default 'default'
30
+ */
31
+ style?: ButtonStyle;
32
+ /**
33
+ * @default 'strong'
34
+ */
35
+ emphasis?: ButtonEmphasis;
36
+ /**
37
+ * @default false
38
+ */
39
+ hideLabel?: boolean;
40
+ /**
41
+ * @default 'medium'
42
+ */
43
+ size?: ButtonSize;
44
+ /**
45
+ * @default 'medium'
46
+ */
47
+ rounding?: ButtonRounding;
48
+ /**
49
+ * @default false
50
+ */
51
+ disabled?: boolean;
52
+ /**
53
+ * @default true
54
+ */
55
+ hugWidth?: boolean;
56
+ icon?: ReactElement;
57
+ children?: ReactNode;
58
+ onClick?: (event?: MouseEvent<HTMLButtonElement>) => void;
59
+ 'aria-label'?: string;
60
+ 'aria-describedby'?: string;
61
+ 'data-test-id'?: string;
62
+ };
63
+
64
+ export const Button = forwardRef<HTMLButtonElement | null, ButtonProps>(
65
+ (
66
+ {
67
+ icon,
68
+ children,
69
+ hideLabel,
70
+ style,
71
+ size = 'medium',
72
+ 'data-test-id': dataTestId = 'fondue-button',
73
+ ...props
74
+ }: ButtonProps,
75
+ ref: ForwardedRef<HTMLButtonElement | null>,
76
+ ) => {
77
+ return (
78
+ <button
79
+ ref={ref}
80
+ data-test-id={dataTestId}
81
+ className={buttonStyles({
82
+ iconOnly: (icon && !children) || hideLabel,
83
+ size,
84
+ style,
85
+ ...props,
86
+ })}
87
+ {...props}
88
+ >
89
+ {icon && (
90
+ <span
91
+ data-test-id={`${dataTestId}-icon`}
92
+ className={iconStyles({
93
+ iconSpacing: children && !hideLabel ? size : 'none',
94
+ style,
95
+ ...props,
96
+ })}
97
+ >
98
+ {cloneElement(icon, { size: buttonIconSizeMap[size] })}
99
+ </span>
100
+ )}
101
+ {children && (
102
+ <span className={textStyles({ hideLabel, style, ...props })} data-test-id={`${dataTestId}-text`}>
103
+ {children}
104
+ </span>
105
+ )}
106
+ </button>
107
+ );
108
+ },
109
+ );
110
+
111
+ Button.displayName = 'Button';
@@ -0,0 +1,175 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { type FondueIconProps } from '@frontify/fondue-icons';
4
+
5
+ import { sv } from '#/utilities/styleUtilities';
6
+
7
+ import { type ButtonProps } from '../Button';
8
+
9
+ export const buttonIconSizeMap: { [buttonSize in Exclude<ButtonProps['size'], undefined>]: FondueIconProps['size'] } = {
10
+ small: 16,
11
+ medium: 20,
12
+ large: 24,
13
+ };
14
+
15
+ export const buttonStyles = sv({
16
+ base: 'tw-group tw-border tw-box-box tw-relative tw-flex tw-items-center tw-justify-center tw-cursor-pointer tw-outline-none tw-font-body tw-font-medium',
17
+ variants: {
18
+ disabled: {
19
+ true: 'tw-not-allowed tw-pointer-events-none tw-border-transparent tw-text-box-disabled-inverse tw-bg-box-disabled',
20
+ },
21
+ rounding: {
22
+ medium: 'tw-rounded',
23
+ full: 'tw-rounded-full',
24
+ },
25
+ size: {
26
+ small: 'tw-px-2 tw-h-6 tw-text-body-small',
27
+ medium: 'tw-px-4 tw-h-9 tw-text-body-medium',
28
+ large: 'tw-px-6 tw-h-12 tw-text-body-large',
29
+ },
30
+ iconOnly: {
31
+ true: 'tw-aspect-square tw-px-0',
32
+ },
33
+ hugWidth: {
34
+ false: 'tw-w-full',
35
+ },
36
+ emphasis: {
37
+ default: '',
38
+ weak: '',
39
+ strong: '',
40
+ },
41
+ style: {
42
+ default: '',
43
+ positive: '',
44
+ negative: '',
45
+ danger: '',
46
+ loud: '',
47
+ },
48
+ },
49
+ compoundVariants: [
50
+ {
51
+ style: 'default',
52
+ emphasis: 'default',
53
+ class:
54
+ 'tw-bg-button-background tw-border-button-border ' +
55
+ 'hover:tw-bg-button-background-hover ' +
56
+ 'active:tw-bg-button-background-pressed',
57
+ },
58
+ {
59
+ style: 'default',
60
+ emphasis: 'weak',
61
+ class:
62
+ 'tw-border-transparent ' +
63
+ 'hover:tw-bg-button-background-hover hover:tw-border-button-border ' +
64
+ 'active:tw-bg-button-background-pressed',
65
+ },
66
+ {
67
+ style: 'default',
68
+ emphasis: 'strong',
69
+ class:
70
+ 'tw-bg-button-strong-background tw-border-button-strong-border ' +
71
+ 'hover:tw-bg-button-strong-background-hover ' +
72
+ 'active:tw-bg-button-strong-background-pressed',
73
+ },
74
+ {
75
+ style: 'positive',
76
+ emphasis: 'default',
77
+ class:
78
+ 'tw-bg-button-positive-background tw-border-button-positive-border ' +
79
+ 'hover:tw-bg-button-positive-background-hover ' +
80
+ 'active:tw-bg-button-positive-background-pressed',
81
+ },
82
+ {
83
+ style: 'positive',
84
+ emphasis: 'weak',
85
+ class:
86
+ 'tw-border-transparent ' +
87
+ 'hover:tw-bg-button-positive-background-hover hover:tw-border-button-positive-border ' +
88
+ 'active:tw-bg-button-positive-background-pressed',
89
+ },
90
+ {
91
+ style: 'positive',
92
+ emphasis: 'strong',
93
+ class:
94
+ 'tw-bg-button-strong-positive-background tw-border-button-strong-positive-border ' +
95
+ 'hover:tw-bg-button-strong-positive-background-hover ' +
96
+ 'active:tw-bg-button-strong-positive-background-pressed',
97
+ },
98
+ {
99
+ style: 'negative',
100
+ emphasis: 'default',
101
+ class:
102
+ 'tw-bg-button-negative-background tw-border-button-negative-border ' +
103
+ 'hover:tw-bg-button-negative-background-hover ' +
104
+ 'active:tw-bg-button-negative-background-pressed',
105
+ },
106
+ {
107
+ style: 'negative',
108
+ emphasis: 'weak',
109
+ class:
110
+ 'tw-border-transparent ' +
111
+ 'hover:tw-bg-button-negative-background-hover hover:tw-border-button-negative-border ' +
112
+ 'active:tw-bg-button-negative-background-pressed',
113
+ },
114
+ {
115
+ style: 'negative',
116
+ emphasis: 'strong',
117
+ class:
118
+ 'tw-bg-button-strong-negative-background tw-border-button-strong-negative-border ' +
119
+ 'hover:tw-bg-button-strong-negative-background-hover ' +
120
+ 'active:tw-bg-button-strong-negative-background-pressed',
121
+ },
122
+ {
123
+ style: 'danger',
124
+ emphasis: 'default',
125
+ class:
126
+ 'tw-bg-button-background tw-border-button-border ' +
127
+ 'hover:tw-bg-button-background-hover ' +
128
+ 'active:tw-bg-button-background-pressed',
129
+ },
130
+ {
131
+ style: 'danger',
132
+ emphasis: 'weak',
133
+ class:
134
+ 'tw-border-transparent ' +
135
+ 'hover:tw-bg-button-background-hover ' +
136
+ 'active:tw-bg-button-background-pressed',
137
+ },
138
+ {
139
+ style: 'danger',
140
+ emphasis: 'strong',
141
+ class:
142
+ 'tw-bg-button-danger-background tw-border-button-danger-border ' +
143
+ 'hover:tw-bg-button-danger-background-hover ' +
144
+ 'active:tw-bg-button-danger-background-pressed',
145
+ },
146
+ {
147
+ style: 'loud',
148
+ emphasis: 'default',
149
+ class:
150
+ 'tw-bg-box-selected tw-border-button-border ' +
151
+ 'hover:tw-bg-box-selected-hover ' +
152
+ 'active:tw-bg-box-selected-pressed ',
153
+ },
154
+ {
155
+ style: 'loud',
156
+ emphasis: 'weak',
157
+ class: 'tw-border-transparent hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed',
158
+ },
159
+ {
160
+ style: 'loud',
161
+ emphasis: 'strong',
162
+ class:
163
+ 'tw-bg-box-selected-strong tw-border-box-selected-strong ' +
164
+ 'hover:tw-bg-box-selected-strong-hover ' +
165
+ 'active:tw-bg-box-selected-strong-pressed ',
166
+ },
167
+ ],
168
+ defaultVariants: {
169
+ style: 'default',
170
+ emphasis: 'strong',
171
+ size: 'medium',
172
+ rounding: 'medium',
173
+ hugWidth: true,
174
+ },
175
+ });
@@ -0,0 +1,152 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { sv } from '#/utilities/styleUtilities';
4
+
5
+ export const iconStyles = sv({
6
+ variants: {
7
+ iconSpacing: {
8
+ none: '',
9
+ small: 'tw--ml-0.5 tw-mr-1',
10
+ medium: 'tw--ml-1 tw-mr-1.5',
11
+ large: 'tw--ml-1 tw-mr-2',
12
+ },
13
+ emphasis: {
14
+ default: '',
15
+ weak: '',
16
+ strong: '',
17
+ },
18
+ style: {
19
+ default: '',
20
+ positive: '',
21
+ negative: '',
22
+ danger: '',
23
+ loud: '',
24
+ },
25
+ },
26
+ compoundVariants: [
27
+ {
28
+ style: 'default',
29
+ emphasis: 'default',
30
+ class:
31
+ 'tw-text-button-icon ' +
32
+ 'group-hover:tw-text-button-icon-hover ' +
33
+ 'group-active:tw-text-button-icon-pressed tw-leading-none',
34
+ },
35
+ {
36
+ style: 'default',
37
+ emphasis: 'weak',
38
+ class:
39
+ 'tw-text-button-icon ' +
40
+ 'group-hover:tw-text-button-icon-hover ' +
41
+ 'group-active:tw-text-button-icon-pressed tw-leading-none',
42
+ },
43
+ {
44
+ style: 'default',
45
+ emphasis: 'strong',
46
+ class:
47
+ 'tw-text-button-strong-icon ' +
48
+ 'group-hover:tw-text-button-strong-icon-hover ' +
49
+ 'group-active:tw-text-button-strong-icon-pressed tw-leading-none',
50
+ },
51
+ {
52
+ style: 'positive',
53
+ emphasis: 'default',
54
+ class:
55
+ 'tw-text-button-positive-icon ' +
56
+ 'group-hover:tw-text-button-positive-icon-hover ' +
57
+ 'group-active:tw-text-button-positive-icon-pressed tw-leading-none',
58
+ },
59
+ {
60
+ style: 'positive',
61
+ emphasis: 'weak',
62
+ class:
63
+ 'tw-text-button-strong-positive-icon ' +
64
+ 'group-hover:tw-text-button-strong-positive-icon-hover' +
65
+ 'group-active:tw-text-button-strong-positive-icon-pressed tw-leading-none',
66
+ },
67
+ {
68
+ style: 'positive',
69
+ emphasis: 'strong',
70
+ class:
71
+ 'tw-text-button-strong-positive-icon ' +
72
+ 'group-hover:tw-text-button-strong-positive-icon-hover ' +
73
+ 'group-active:tw-text-button-strong-positive-icon-pressed tw-leading-none',
74
+ },
75
+ {
76
+ style: 'negative',
77
+ emphasis: 'default',
78
+ class:
79
+ 'tw-text-button-negative-icon ' +
80
+ 'group-hover:tw-text-button-negative-icon-hover' +
81
+ 'group-active:tw-text-button-negative-icon-pressed tw-leading-none',
82
+ },
83
+ {
84
+ style: 'negative',
85
+ emphasis: 'weak',
86
+ class:
87
+ 'tw-text-button-negative-icon ' +
88
+ 'group-hover:tw-text-button-negative-icon-hover' +
89
+ 'group-active:tw-text-button-negative-icon-pressed tw-leading-none',
90
+ },
91
+ {
92
+ style: 'negative',
93
+ emphasis: 'strong',
94
+ class:
95
+ 'tw-text-button-strong-negative-icon ' +
96
+ 'group-hover:tw-text-button-strong-negative-icon-hover' +
97
+ 'group-active:tw-text-button-strong-negative-icon-pressed tw-leading-none',
98
+ },
99
+ {
100
+ style: 'danger',
101
+ emphasis: 'default',
102
+ class:
103
+ 'tw-text-button-negative-icon ' +
104
+ 'group-hover:tw-text-button-negative-icon-hover' +
105
+ 'group-active:tw-text-button-negative-icon-pressed tw-leading-none',
106
+ },
107
+ {
108
+ style: 'danger',
109
+ emphasis: 'weak',
110
+ class:
111
+ 'tw-text-button-negative-icon ' +
112
+ 'group-hover:tw-text-button-negative-icon-hover' +
113
+ 'group-active:tw-text-button-negative-icon-pressed tw-leading-none',
114
+ },
115
+ {
116
+ style: 'danger',
117
+ emphasis: 'strong',
118
+ class:
119
+ 'tw-text-button-danger-icon ' +
120
+ 'group-hover:tw-text-button-danger-icon-hover' +
121
+ 'group-active:tw-text-button-danger-icon-pressed tw-leading-none',
122
+ },
123
+ {
124
+ style: 'loud',
125
+ emphasis: 'default',
126
+ class:
127
+ 'tw-text-box-selected-inverse ' +
128
+ 'group-hover:tw-text-box-selected-inverse-hover' +
129
+ 'group-active:tw-text-box-selected-inverse-pressed tw-leading-none',
130
+ },
131
+ {
132
+ style: 'loud',
133
+ emphasis: 'weak',
134
+ class:
135
+ 'tw-text-box-selected-inverse ' +
136
+ 'group-hover:tw-text-box-selected-inverse-hover' +
137
+ 'group-active:tw-text-box-selected-inverse-pressed tw-leading-none',
138
+ },
139
+ {
140
+ style: 'loud',
141
+ emphasis: 'strong',
142
+ class:
143
+ 'tw-text-box-selected-strong-inverse ' +
144
+ 'group-hover:tw-text-box-selected-strong-inverse' +
145
+ 'group-active:tw-text-box-selected-strong-inverse tw-leading-none',
146
+ },
147
+ ],
148
+ defaultVariants: {
149
+ emphasis: 'strong',
150
+ style: 'default',
151
+ },
152
+ });
@@ -0,0 +1,149 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { sv } from '#/utilities/styleUtilities';
4
+
5
+ export const textStyles = sv({
6
+ variants: {
7
+ hideLabel: {
8
+ true: 'tw-sr-only',
9
+ },
10
+ emphasis: {
11
+ default: '',
12
+ weak: '',
13
+ strong: '',
14
+ },
15
+ style: {
16
+ default: '',
17
+ positive: '',
18
+ negative: '',
19
+ danger: '',
20
+ loud: '',
21
+ },
22
+ },
23
+ compoundVariants: [
24
+ {
25
+ style: 'default',
26
+ emphasis: 'default',
27
+ class:
28
+ 'tw-text-button-text ' +
29
+ 'group-hover:tw-text-button-text-hover ' +
30
+ 'group-active:tw-text-button-text-pressed',
31
+ },
32
+ {
33
+ style: 'default',
34
+ emphasis: 'weak',
35
+ class:
36
+ 'tw-text-button-text ' +
37
+ 'group-hover:tw-text-button-text-hover ' +
38
+ 'group-active:tw-text-button-text-pressed',
39
+ },
40
+ {
41
+ style: 'default',
42
+ emphasis: 'strong',
43
+ class:
44
+ 'tw-text-button-strong-icon ' +
45
+ 'group-hover:tw-text-button-strong-icon-hover ' +
46
+ 'group-active:tw-text-button-strong-text-pressed',
47
+ },
48
+ {
49
+ style: 'positive',
50
+ emphasis: 'default',
51
+ class:
52
+ 'tw-text-button-positive-text ' +
53
+ 'group-hover:tw-text-button-positive-text-hover ' +
54
+ 'group-active:tw-text-button-positive-text-pressed',
55
+ },
56
+ {
57
+ style: 'positive',
58
+ emphasis: 'weak',
59
+ class:
60
+ 'tw-text-button-positive-text ' +
61
+ 'group-hover:tw-text-button-positive-text-hover ' +
62
+ 'group-active:tw-text-button-positive-text-pressed',
63
+ },
64
+ {
65
+ style: 'positive',
66
+ emphasis: 'strong',
67
+ class:
68
+ 'tw-text-button-strong-positive-text ' +
69
+ 'group-hover:tw-text-button-strong-positive-text-hover ' +
70
+ 'group-active:tw-text-button-strong-positive-text-pressed',
71
+ },
72
+ {
73
+ style: 'negative',
74
+ emphasis: 'default',
75
+ class:
76
+ 'tw-text-button-negative-text ' +
77
+ 'group-hover:tw-text-button-negative-text-hover' +
78
+ 'group-active:tw-text-button-negative-text-pressed',
79
+ },
80
+ {
81
+ style: 'negative',
82
+ emphasis: 'weak',
83
+ class:
84
+ 'tw-text-button-negative-text ' +
85
+ 'group-hover:tw-text-button-negative-text-hover' +
86
+ 'group-active:tw-text-button-negative-text-pressed',
87
+ },
88
+ {
89
+ style: 'negative',
90
+ emphasis: 'strong',
91
+ class:
92
+ 'tw-text-button-strong-negative-text ' +
93
+ 'group-hover:tw-text-button-strong-negative-text-hover' +
94
+ 'group-active:tw-text-button-strong-negative-text-pressed',
95
+ },
96
+ {
97
+ style: 'danger',
98
+ emphasis: 'default',
99
+ class:
100
+ 'tw-text-button-negative-icon ' +
101
+ 'group-hover:tw-text-button-negative-icon-hover' +
102
+ 'group-active:tw-text-button-negative-icon-pressed',
103
+ },
104
+ {
105
+ style: 'danger',
106
+ emphasis: 'weak',
107
+ class:
108
+ 'tw-text-button-negative-icon ' +
109
+ 'group-hover:tw-text-button-negative-icon-hover' +
110
+ 'group-active:tw-text-button-negative-icon-pressed',
111
+ },
112
+ {
113
+ style: 'danger',
114
+ emphasis: 'strong',
115
+ class:
116
+ 'tw-text-button-danger-text ' +
117
+ 'group-hover:tw-text-button-danger-text-hover' +
118
+ 'group-active:tw-text-button-danger-text-pressed',
119
+ },
120
+ {
121
+ style: 'loud',
122
+ emphasis: 'default',
123
+ class:
124
+ 'tw-text-box-selected-inverse ' +
125
+ 'group-hover:tw-text-box-selected-inverse-hover' +
126
+ 'group-active:tw-text-box-selected-inverse-pressed',
127
+ },
128
+ {
129
+ style: 'loud',
130
+ emphasis: 'weak',
131
+ class:
132
+ 'tw-text-box-selected-inverse ' +
133
+ 'group-hover:tw-text-box-selected-inverse-hover' +
134
+ 'group-active:tw-text-box-selected-inverse-pressed',
135
+ },
136
+ {
137
+ style: 'loud',
138
+ emphasis: 'strong',
139
+ class:
140
+ 'tw-text-box-selected-strong-inverse ' +
141
+ 'group-hover:tw-text-box-selected-strong-inverse' +
142
+ 'group-active:tw-text-box-selected-strong-inverse',
143
+ },
144
+ ],
145
+ defaultVariants: {
146
+ emphasis: 'strong',
147
+ style: 'default',
148
+ },
149
+ });
@@ -0,0 +1,61 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { IconIcon } from '@frontify/fondue-icons';
4
+ import { expect, test } from '@playwright/experimental-ct-react';
5
+
6
+ import { Button } from '../Button';
7
+
8
+ const BUTTON_TEXT = 'Frontify';
9
+
10
+ test('should render without error', async ({ mount }) => {
11
+ const component = await mount(<Button>{BUTTON_TEXT}</Button>);
12
+ await expect(component).toContainText(BUTTON_TEXT);
13
+ });
14
+
15
+ test('should render in positive medium and with only text.', async ({ mount }) => {
16
+ const component = await mount(
17
+ <Button style="positive" size="medium">
18
+ {BUTTON_TEXT}
19
+ </Button>,
20
+ );
21
+ await expect(component).toBeVisible();
22
+ await expect(component).toContainText(BUTTON_TEXT);
23
+ });
24
+
25
+ test('should react on Click', async ({ mount }) => {
26
+ const component = await mount(
27
+ <Button style="positive" size="medium">
28
+ {BUTTON_TEXT}
29
+ </Button>,
30
+ );
31
+ await expect(component).toBeVisible();
32
+ await expect(component).toContainText(BUTTON_TEXT);
33
+ });
34
+
35
+ test('should render in positive medium and with only icon.', async ({ mount }) => {
36
+ const component = await mount(
37
+ <Button style="positive" size="medium" icon={<IconIcon data-test-id="fondue-icon-icon" />} />,
38
+ );
39
+ await expect(component).toBeVisible();
40
+ await expect(component.locator('data-test-id=fondue-icon-icon')).toBeVisible();
41
+ });
42
+
43
+ test('should render in positive medium and with only only an icon and fully rounded.', async ({ mount }) => {
44
+ const component = await mount(
45
+ <Button style="positive" size="medium" icon={<IconIcon data-test-id="fondue-icon-icon" />} rounding="full" />,
46
+ );
47
+ await expect(component).toBeVisible();
48
+ await expect(component).toHaveClass(/tw-rounded-full/);
49
+ await expect(component.locator('data-test-id=fondue-icon-icon')).toBeVisible();
50
+ });
51
+
52
+ test('should render in positive medium with an icon and text.', async ({ mount }) => {
53
+ const component = await mount(
54
+ <Button style="positive" size="medium" icon={<IconIcon data-test-id="fondue-icon-icon" />}>
55
+ {BUTTON_TEXT}
56
+ </Button>,
57
+ );
58
+ await expect(component).toBeVisible();
59
+ await expect(component).toHaveText(BUTTON_TEXT);
60
+ await expect(component.locator('data-test-id=fondue-icon-icon')).toBeVisible();
61
+ });
@@ -0,0 +1,34 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { render } from '@testing-library/react';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+
6
+ import { Button } from '../Button';
7
+
8
+ const BUTTON_TEXT = 'Frontify';
9
+ const BUTTON_TEST_ID = 'fondue-button';
10
+
11
+ describe('Button component', () => {
12
+ it('reacts on click', () => {
13
+ const clickListener = vi.fn();
14
+ const { getByTestId } = render(<Button onClick={clickListener}>{BUTTON_TEXT}</Button>);
15
+ const button = getByTestId(BUTTON_TEST_ID);
16
+ expect(clickListener).not.toHaveBeenCalled();
17
+ button.click();
18
+ expect(clickListener).toHaveBeenCalledOnce();
19
+ });
20
+
21
+ it('does not react on click when disabled', () => {
22
+ const clickListener = vi.fn();
23
+ const { getByTestId } = render(
24
+ <Button onClick={clickListener} disabled>
25
+ {BUTTON_TEXT}
26
+ </Button>,
27
+ );
28
+ const button = getByTestId(BUTTON_TEST_ID);
29
+ expect(clickListener).not.toHaveBeenCalled();
30
+ expect(button).toHaveAttribute('disabled');
31
+ button.click();
32
+ expect(clickListener).not.toHaveBeenCalled();
33
+ });
34
+ });