@hyphen/hyphen-components 6.2.2 → 6.3.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.
- package/dist/components/Button/Button.d.ts +1 -1
- package/dist/components/Button/Button.stories.d.ts +1 -0
- package/dist/css/index.css +1 -1
- package/dist/hyphen-components.cjs.development.js +5 -4
- package/dist/hyphen-components.cjs.development.js.map +1 -1
- package/dist/hyphen-components.cjs.production.min.js +1 -1
- package/dist/hyphen-components.cjs.production.min.js.map +1 -1
- package/dist/hyphen-components.esm.js +5 -4
- package/dist/hyphen-components.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/Button.module.scss +32 -0
- package/src/components/Button/Button.stories.tsx +33 -11
- package/src/components/Button/Button.tsx +12 -4
- package/src/components/ResponsiveProvider/ResponsiveProvider.test.tsx +18 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.tsx +4 -1
package/package.json
CHANGED
|
@@ -245,6 +245,38 @@
|
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
&.link {
|
|
249
|
+
display: inline-flex;
|
|
250
|
+
background-color: transparent;
|
|
251
|
+
border: none;
|
|
252
|
+
color: inherit;
|
|
253
|
+
padding: 0;
|
|
254
|
+
text-decoration: none;
|
|
255
|
+
font-size: inherit;
|
|
256
|
+
height: auto;
|
|
257
|
+
|
|
258
|
+
&:not(:disabled):hover {
|
|
259
|
+
text-decoration: underline;
|
|
260
|
+
text-underline-offset: var(--size-spacing-xs);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
&:focus {
|
|
264
|
+
outline: 0;
|
|
265
|
+
box-shadow: var(--button-box-shadow-focus);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Show focus styles on keyboard focus.
|
|
269
|
+
&:focus-visible {
|
|
270
|
+
outline: 0;
|
|
271
|
+
box-shadow: var(--button-box-shadow-focus);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
&:focus:not(:focus-visible) {
|
|
275
|
+
outline: 0;
|
|
276
|
+
box-shadow: none;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
248
280
|
&.size-sm {
|
|
249
281
|
@extend %size-sm;
|
|
250
282
|
}
|
|
@@ -32,13 +32,18 @@ export const AsChild = () => (
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
export const Variants = () => (
|
|
35
|
-
<Box
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
<Box
|
|
36
|
+
gap="md"
|
|
37
|
+
background="primary"
|
|
38
|
+
direction="row"
|
|
39
|
+
alignItems="center"
|
|
40
|
+
fontSize="sm"
|
|
41
|
+
>
|
|
42
|
+
<Button variant="primary">Primary</Button>
|
|
43
|
+
<Button variant="secondary">Secondary</Button>
|
|
44
|
+
<Button variant="tertiary">Tertiary</Button>
|
|
45
|
+
<Button variant="danger">Danger</Button>
|
|
46
|
+
<Button variant="link">Link</Button>
|
|
42
47
|
</Box>
|
|
43
48
|
);
|
|
44
49
|
|
|
@@ -85,15 +90,16 @@ export const Icons = () => (
|
|
|
85
90
|
);
|
|
86
91
|
|
|
87
92
|
export const IconButton = () => (
|
|
88
|
-
|
|
93
|
+
<Box gap="lg" direction="row" alignItems="center">
|
|
89
94
|
<Button variant="tertiary" iconPrefix="add" aria-label="add" />
|
|
90
95
|
<Button variant="tertiary" iconPrefix="dots" aria-label="open menu" />
|
|
91
96
|
<Button variant="danger" iconPrefix="trash" aria-label="remove" />
|
|
92
|
-
|
|
97
|
+
<Button variant="link" iconPrefix="chat" aria-label="chat" />
|
|
98
|
+
</Box>
|
|
93
99
|
);
|
|
94
100
|
|
|
95
101
|
export const Loading = () => (
|
|
96
|
-
<Box direction="row" gap="md">
|
|
102
|
+
<Box direction="row" gap="md" fontSize="sm">
|
|
97
103
|
<Button isLoading aria-label="primary loading">
|
|
98
104
|
Primary Loading
|
|
99
105
|
</Button>
|
|
@@ -103,11 +109,14 @@ export const Loading = () => (
|
|
|
103
109
|
<Button variant="tertiary" isLoading aria-label="tertiary loading">
|
|
104
110
|
Tertiary Loading
|
|
105
111
|
</Button>
|
|
112
|
+
<Button variant="link" isLoading aria-label="link loading">
|
|
113
|
+
Link Loading
|
|
114
|
+
</Button>
|
|
106
115
|
</Box>
|
|
107
116
|
);
|
|
108
117
|
|
|
109
118
|
export const Disabled = () => (
|
|
110
|
-
<Box direction="row" gap="md">
|
|
119
|
+
<Box direction="row" gap="md" fontSize="sm">
|
|
111
120
|
<Button variant="primary" isDisabled>
|
|
112
121
|
Primary Disabled
|
|
113
122
|
</Button>
|
|
@@ -117,6 +126,9 @@ export const Disabled = () => (
|
|
|
117
126
|
<Button variant="tertiary" isDisabled>
|
|
118
127
|
Tertiary Disabled
|
|
119
128
|
</Button>
|
|
129
|
+
<Button variant="link" isDisabled>
|
|
130
|
+
Link Disabled
|
|
131
|
+
</Button>
|
|
120
132
|
</Box>
|
|
121
133
|
);
|
|
122
134
|
|
|
@@ -133,3 +145,13 @@ export const Shadow = () => (
|
|
|
133
145
|
</Button>
|
|
134
146
|
</Box>
|
|
135
147
|
);
|
|
148
|
+
|
|
149
|
+
export const InlineLink = () => (
|
|
150
|
+
<Box display="block" as="p" fontSize="sm" color="base" width="8xl">
|
|
151
|
+
This is an example of a button used as an inline link.{' '}
|
|
152
|
+
<Button variant="link" size="md">
|
|
153
|
+
Inline Link Button
|
|
154
|
+
</Button>
|
|
155
|
+
. It will wrap with text.
|
|
156
|
+
</Box>
|
|
157
|
+
);
|
|
@@ -8,7 +8,12 @@ import classNames from 'classnames';
|
|
|
8
8
|
import { generateResponsiveClasses } from '../../lib/generateResponsiveClasses';
|
|
9
9
|
import styles from './Button.module.scss';
|
|
10
10
|
|
|
11
|
-
export type ButtonVariant =
|
|
11
|
+
export type ButtonVariant =
|
|
12
|
+
| 'primary'
|
|
13
|
+
| 'secondary'
|
|
14
|
+
| 'tertiary'
|
|
15
|
+
| 'danger'
|
|
16
|
+
| 'link';
|
|
12
17
|
|
|
13
18
|
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
14
19
|
|
|
@@ -87,9 +92,12 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
87
92
|
) => {
|
|
88
93
|
const disabled = isLoading || isDisabled;
|
|
89
94
|
|
|
90
|
-
const responsiveClasses =
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
const responsiveClasses =
|
|
96
|
+
variant !== 'link'
|
|
97
|
+
? generateResponsiveClasses('size', size)
|
|
98
|
+
.map((c) => styles[c])
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
: [];
|
|
93
101
|
|
|
94
102
|
const buttonClasses = classNames(
|
|
95
103
|
'hyphen-components__variables__form-control',
|
|
@@ -68,3 +68,21 @@ describe('Responsive hooks', () => {
|
|
|
68
68
|
).toEqual(1);
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
|
+
|
|
72
|
+
describe('Cleanup', () => {
|
|
73
|
+
it('clears pending resize timeout on unmount', () => {
|
|
74
|
+
jest.useFakeTimers();
|
|
75
|
+
const clearSpy = jest.spyOn(window, 'clearTimeout');
|
|
76
|
+
const { unmount } = render(
|
|
77
|
+
<ResponsiveProvider throttle={100}>
|
|
78
|
+
<div />
|
|
79
|
+
</ResponsiveProvider>
|
|
80
|
+
);
|
|
81
|
+
window.dispatchEvent(new Event('resize'));
|
|
82
|
+
expect(clearSpy).toHaveBeenCalledTimes(1);
|
|
83
|
+
unmount();
|
|
84
|
+
expect(clearSpy).toHaveBeenCalledTimes(2);
|
|
85
|
+
clearSpy.mockRestore();
|
|
86
|
+
jest.useRealTimers();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -53,7 +53,10 @@ export const ResponsiveProvider: React.FC<ResponsiveProviderProps> = ({
|
|
|
53
53
|
|
|
54
54
|
window.addEventListener('resize', throttledResize);
|
|
55
55
|
|
|
56
|
-
return () =>
|
|
56
|
+
return () => {
|
|
57
|
+
window.removeEventListener('resize', throttledResize);
|
|
58
|
+
clearTimeout(timeoutId);
|
|
59
|
+
};
|
|
57
60
|
}
|
|
58
61
|
}, [throttle]);
|
|
59
62
|
|