@hyphen/hyphen-components 7.9.0 → 8.0.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 (41) hide show
  1. package/dist/css/fonts.css +1 -1
  2. package/dist/css/index.css +292 -150
  3. package/dist/css/reset.css +1 -1
  4. package/dist/css/utilities.css +480 -38
  5. package/dist/css/variables.css +170 -25
  6. package/dist/hyphen-components.cjs.development.js +244 -311
  7. package/dist/hyphen-components.cjs.development.js.map +1 -1
  8. package/dist/hyphen-components.cjs.production.min.js +2 -2
  9. package/dist/hyphen-components.cjs.production.min.js.map +1 -1
  10. package/dist/hyphen-components.esm.js +198 -265
  11. package/dist/hyphen-components.esm.js.map +1 -1
  12. package/dist/index.d.ts +25 -60
  13. package/package.json +3 -3
  14. package/src/components/Alert/Alert.mdx +1 -1
  15. package/src/components/Alert/Alert.module.scss +29 -34
  16. package/src/components/Alert/Alert.stories.tsx +11 -3
  17. package/src/components/Alert/Alert.test.tsx +17 -11
  18. package/src/components/Alert/Alert.tsx +9 -16
  19. package/src/components/Badge/Badge.mdx +46 -4
  20. package/src/components/Badge/Badge.module.scss +235 -185
  21. package/src/components/Badge/Badge.stories.tsx +126 -36
  22. package/src/components/Badge/Badge.test.tsx +180 -21
  23. package/src/components/Badge/Badge.tsx +56 -21
  24. package/src/components/Drawer/Drawer.mdx +14 -16
  25. package/src/components/Formik/Formik.stories.tsx +3 -5
  26. package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +34 -67
  27. package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +0 -2
  28. package/src/components/Table/Table.stories.tsx +4 -4
  29. package/src/components/TimePicker/TimePicker.mdx +3 -11
  30. package/src/components/TimePicker/TimePicker.stories.tsx +61 -60
  31. package/src/components/TimePicker/TimePicker.test.tsx +76 -7
  32. package/src/components/TimePicker/TimePicker.tsx +37 -7
  33. package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
  34. package/src/docs/Colors.mdx +13 -0
  35. package/src/index.ts +0 -2
  36. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +0 -175
  37. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +0 -38
  38. package/src/components/TimePickerNative/TimePickerNative.mdx +0 -67
  39. package/src/components/TimePickerNative/TimePickerNative.stories.tsx +0 -150
  40. package/src/components/TimePickerNative/TimePickerNative.test.tsx +0 -117
  41. package/src/components/TimePickerNative/TimePickerNative.tsx +0 -93
@@ -1,185 +1,235 @@
1
- @import '@hyphen/hyphen-design-tokens/build/scss/variables';
2
-
3
- @mixin size-sm {
4
- font-size: var(--size-font-size-xs);
5
- padding: var(--size-spacing-2xs) var(--size-spacing-sm);
6
- border-radius: var(--size-border-radius-lg);
7
- }
8
-
9
- %size-sm {
10
- @include size-sm;
11
- }
12
- .size-sm {
13
- @extend %size-sm;
14
- }
15
-
16
- @mixin size-md {
17
- font-size: var(--size-font-size-sm);
18
- padding: var(--size-spacing-xs) var(--size-spacing-md);
19
- border-radius: var(--size-border-radius-xl);
20
- }
21
-
22
- %size-md {
23
- @include size-md;
24
- }
25
- .size-md {
26
- @extend %size-md;
27
- }
28
-
29
- @mixin size-lg {
30
- font-size: var(--size-font-size-md);
31
- padding: var(--size-spacing-sm) var(--size-spacing-lg);
32
- border-radius: var(--size-border-radius-2xl);
33
- }
34
-
35
- %size-lg {
36
- @include size-lg;
37
- }
38
- .size-lg {
39
- @extend %size-lg;
40
- }
41
-
42
- .badge {
43
- border-style: solid;
44
- border-width: var(--size-border-width-sm);
45
- font-weight: var(--size-font-weight-medium);
46
- line-height: var(--size-line-height-base);
47
-
48
- &.inverse {
49
- background-color: var(--color-background-inverse);
50
- border-color: var(--color-background-inverse);
51
- color: var(--color-font-inverse);
52
- }
53
-
54
- &.default {
55
- background-color: var(--color-background-badge-default);
56
- border-color: var(--color-border-badge-default);
57
- color: var(--color-font-badge-default);
58
- }
59
-
60
- &.secondary {
61
- background-color: var(--color-background-badge-secondary);
62
- border-color: var(--color-border-badge-secondary);
63
- color: var(--color-font-badge-secondary);
64
- }
65
-
66
- &.danger {
67
- background-color: var(--color-background-badge-danger);
68
- border-color: var(--color-border-badge-danger);
69
- color: var(--color-font-badge-danger);
70
- }
71
-
72
- &.outline {
73
- background-color: var(--color-background-badge-outline);
74
- border-color: var(--color-border-badge-outline);
75
- color: var(--color-font-badge-outline);
76
- }
77
-
78
- &.purple {
79
- background-color: var(--color-base-purple-500);
80
- border-color: var(--color-base-purple-600);
81
- color: var(--color-base-white);
82
- }
83
-
84
- &.green {
85
- background-color: var(--color-base-green-500);
86
- border-color: var(--color-base-green-600);
87
- color: var(--color-base-white);
88
- }
89
-
90
- &.red {
91
- background-color: var(--color-base-red-500);
92
- border-color: var(--color-base-red-600);
93
- color: var(--color-base-white);
94
- }
95
-
96
- &.blue {
97
- background-color: var(--color-base-blue-500);
98
- border-color: var(--color-base-blue-600);
99
- color: var(--color-base-white);
100
- }
101
-
102
- &.yellow {
103
- background-color: var(--color-base-yellow-400);
104
- border-color: var(--color-base-yellow-500);
105
- color: var(--color-base-black);
106
- }
107
-
108
- &.light-grey {
109
- background-color: var(--color-base-grey-200);
110
- border-color: var(--color-base-grey-200);
111
- color: var(--color-base-grey-600);
112
- }
113
-
114
- &.dark-grey {
115
- background-color: var(--color-base-grey-400);
116
- border-color: var(--color-base-grey-400);
117
- color: var(--color-base-white);
118
- }
119
-
120
- &.orange {
121
- background: var(--color-background-brand-orange);
122
- border-color: var(--color-border-brand-orange);
123
- color: var(--color-base-white);
124
- }
125
-
126
- &.hyphen {
127
- background: var(--color-background-brand-gradient);
128
- border-color: var(--color-base-yellow-500);
129
- color: var(--color-base-white);
130
- }
131
-
132
- &.size-sm {
133
- @extend %size-sm;
134
- }
135
-
136
- &.size-md {
137
- @extend %size-md;
138
- }
139
-
140
- &.size-lg {
141
- @extend %size-lg;
142
- }
143
-
144
- @media (min-width: $size-breakpoint-tablet) {
145
- &.size-sm-tablet {
146
- @include size-sm;
147
- }
148
-
149
- &.size-md-tablet {
150
- @include size-md;
151
- }
152
-
153
- &.size-lg-tablet {
154
- @include size-lg;
155
- }
156
- }
157
-
158
- @media (min-width: $size-breakpoint-desktop) {
159
- &.size-sm-desktop {
160
- @include size-sm;
161
- }
162
-
163
- &.size-md-desktop {
164
- @include size-md;
165
- }
166
-
167
- &.size-lg-desktop {
168
- @include size-lg;
169
- }
170
- }
171
-
172
- @media (min-width: $size-breakpoint-hd) {
173
- &.size-sm-hd {
174
- @include size-sm;
175
- }
176
-
177
- &.size-md-hd {
178
- @include size-md;
179
- }
180
-
181
- &.size-lg-hd {
182
- @include size-lg;
183
- }
184
- }
185
- }
1
+ @import '@hyphen/hyphen-design-tokens/build/scss/variables';
2
+
3
+ /*
4
+ * Trims the padding on whichever side carries a graphic rather than a text label,
5
+ * so a nested icon does not sit as far from the edge as text would.
6
+ *
7
+ * Block comments are deliberate throughout this file: postcss-loader runs before
8
+ * sass-loader (webpack applies loaders right to left), so PostCSS parses this file
9
+ * as plain CSS, where `//` is not a comment. A `;` or an apostrophe inside a `//`
10
+ * comment breaks the production build while Storybook, which compiles Sass first,
11
+ * keeps working.
12
+ */
13
+ @mixin graphic-padding($value) {
14
+ &:has(> :first-child:not(.label)) {
15
+ padding-left: $value;
16
+ }
17
+
18
+ &:has(> :last-child:not(.label)) {
19
+ padding-right: $value;
20
+ }
21
+ }
22
+
23
+ @mixin size-sm {
24
+ font-size: var(--size-font-size-xs);
25
+ padding: var(--size-spacing-2xs) var(--size-spacing-sm);
26
+ gap: var(--size-spacing-xs);
27
+
28
+ @include graphic-padding(var(--size-spacing-xs));
29
+ }
30
+
31
+ %size-sm {
32
+ @include size-sm;
33
+ }
34
+ .size-sm {
35
+ @extend %size-sm;
36
+ }
37
+
38
+ @mixin size-md {
39
+ font-size: var(--size-font-size-sm);
40
+ padding: var(--size-spacing-xs) var(--size-spacing-md);
41
+ gap: var(--size-spacing-xs);
42
+
43
+ @include graphic-padding(var(--size-spacing-sm));
44
+ }
45
+
46
+ %size-md {
47
+ @include size-md;
48
+ }
49
+ .size-md {
50
+ @extend %size-md;
51
+ }
52
+
53
+ @mixin size-lg {
54
+ font-size: var(--size-font-size-md);
55
+ padding: var(--size-spacing-sm) var(--size-spacing-lg);
56
+ gap: var(--size-spacing-sm);
57
+
58
+ @include graphic-padding(var(--size-spacing-md));
59
+ }
60
+
61
+ %size-lg {
62
+ @include size-lg;
63
+ }
64
+ .size-lg {
65
+ @extend %size-lg;
66
+ }
67
+
68
+ /*
69
+ * Each color class declares the six semantic values that the variants below consume,
70
+ * so styles stay at 8 colors + 4 variants instead of all 32 combinations.
71
+ */
72
+ @mixin badge-color($color) {
73
+ --badge-solid-background: var(--color-background-badge-solid-#{$color});
74
+ --badge-solid-border: var(--color-border-badge-solid-#{$color});
75
+ --badge-solid-font: var(--color-font-badge-solid-#{$color});
76
+ --badge-soft-background: var(--color-background-badge-soft-#{$color});
77
+ --badge-soft-font: var(--color-font-badge-soft-#{$color});
78
+ --badge-surface-background: var(--color-background-badge-surface-#{$color});
79
+ --badge-surface-border: var(--color-border-badge-surface-#{$color});
80
+ --badge-outline-border: var(--color-border-badge-outline-#{$color});
81
+ }
82
+
83
+ .badge {
84
+ border-style: solid;
85
+ border-width: var(--size-border-width-sm);
86
+ font-weight: var(--size-font-weight-medium);
87
+ line-height: var(--size-line-height-base);
88
+
89
+ /*
90
+ * Scale any nested graphic to the current text size. Icons are already sized in `em`,
91
+ * so this is what makes a Spinner (fixed pixel dimensions) track the badge instead.
92
+ */
93
+ svg {
94
+ width: 1em;
95
+ height: 1em;
96
+ flex-shrink: 0;
97
+ }
98
+
99
+ /* Spinner renders its svg inside a span. Keep that wrapper from adding line-box height. */
100
+ > span:not(.label) {
101
+ display: inline-flex;
102
+ align-items: center;
103
+ }
104
+
105
+ &.color-grey {
106
+ @include badge-color('grey');
107
+ }
108
+
109
+ &.color-blue {
110
+ @include badge-color('blue');
111
+ }
112
+
113
+ &.color-green {
114
+ @include badge-color('green');
115
+ }
116
+
117
+ &.color-yellow {
118
+ @include badge-color('yellow');
119
+ }
120
+
121
+ &.color-red {
122
+ @include badge-color('red');
123
+ }
124
+
125
+ &.color-purple {
126
+ @include badge-color('purple');
127
+ }
128
+
129
+ &.color-orange {
130
+ @include badge-color('orange');
131
+ }
132
+
133
+ &.color-brand {
134
+ @include badge-color('brand');
135
+ }
136
+
137
+ /* `background` rather than `background-color` so the brand gradient renders under `solid`. */
138
+ &.solid {
139
+ background: var(--badge-solid-background);
140
+ border-color: var(--badge-solid-border);
141
+ color: var(--badge-solid-font);
142
+ }
143
+
144
+ &.soft {
145
+ background: var(--badge-soft-background);
146
+ border-color: transparent;
147
+ color: var(--badge-soft-font);
148
+ }
149
+
150
+ &.surface {
151
+ background: var(--badge-surface-background);
152
+ border-color: var(--badge-surface-border);
153
+ color: var(--badge-soft-font);
154
+ }
155
+
156
+ &.outline {
157
+ background: transparent;
158
+ border-color: var(--badge-outline-border);
159
+ color: var(--badge-soft-font);
160
+ }
161
+
162
+ &.radius-none {
163
+ border-radius: var(--size-border-radius-0);
164
+ }
165
+
166
+ &.radius-sm {
167
+ border-radius: var(--size-border-radius-sm);
168
+ }
169
+
170
+ &.radius-md {
171
+ border-radius: var(--size-border-radius-md);
172
+ }
173
+
174
+ &.radius-lg {
175
+ border-radius: var(--size-border-radius-lg);
176
+ }
177
+
178
+ &.radius-full {
179
+ border-radius: var(--size-border-radius-full);
180
+ }
181
+
182
+ &.size-sm {
183
+ @extend %size-sm;
184
+ }
185
+
186
+ &.size-md {
187
+ @extend %size-md;
188
+ }
189
+
190
+ &.size-lg {
191
+ @extend %size-lg;
192
+ }
193
+
194
+ @media (min-width: $size-breakpoint-tablet) {
195
+ &.size-sm-tablet {
196
+ @include size-sm;
197
+ }
198
+
199
+ &.size-md-tablet {
200
+ @include size-md;
201
+ }
202
+
203
+ &.size-lg-tablet {
204
+ @include size-lg;
205
+ }
206
+ }
207
+
208
+ @media (min-width: $size-breakpoint-desktop) {
209
+ &.size-sm-desktop {
210
+ @include size-sm;
211
+ }
212
+
213
+ &.size-md-desktop {
214
+ @include size-md;
215
+ }
216
+
217
+ &.size-lg-desktop {
218
+ @include size-lg;
219
+ }
220
+ }
221
+
222
+ @media (min-width: $size-breakpoint-hd) {
223
+ &.size-sm-hd {
224
+ @include size-sm;
225
+ }
226
+
227
+ &.size-md-hd {
228
+ @include size-md;
229
+ }
230
+
231
+ &.size-lg-hd {
232
+ @include size-lg;
233
+ }
234
+ }
235
+ }
@@ -1,34 +1,40 @@
1
- import { Badge, BadgeVariant } from './Badge';
1
+ import {
2
+ Badge,
3
+ BadgeHue,
4
+ BadgeRadius,
5
+ BadgeSemanticColor,
6
+ BadgeSize,
7
+ BadgeVariant,
8
+ } from './Badge';
2
9
  import React from 'react';
3
10
  import { Box } from '../Box/Box';
11
+ import { Icon } from '../Icon/Icon';
12
+ import { Spinner } from '../Spinner/Spinner';
4
13
  import type { Meta, StoryObj } from '@storybook/react-vite';
5
14
  import { allModes } from '../../modes';
6
15
 
7
- const SEMANTIC_BADGE_VARIANTS: BadgeVariant[] = [
8
- 'default',
9
- 'secondary',
10
- 'danger',
11
- 'outline',
12
- ];
16
+ const BADGE_VARIANTS: BadgeVariant[] = ['solid', 'soft', 'surface', 'outline'];
13
17
 
14
- const FIXED_COLOR_BADGE_VARIANTS: BadgeVariant[] = [
15
- 'light-grey',
16
- 'dark-grey',
17
- 'inverse',
18
- 'purple',
18
+ const BADGE_HUES: BadgeHue[] = [
19
+ 'grey',
19
20
  'blue',
20
21
  'green',
21
22
  'yellow',
22
23
  'red',
24
+ 'purple',
23
25
  'orange',
24
- 'hyphen',
26
+ 'brand',
25
27
  ];
26
28
 
27
- const BADGE_VARIANTS: BadgeVariant[] = [
28
- ...SEMANTIC_BADGE_VARIANTS,
29
- ...FIXED_COLOR_BADGE_VARIANTS,
29
+ const BADGE_SEMANTIC_COLORS: BadgeSemanticColor[] = [
30
+ 'danger',
31
+ 'success',
32
+ 'warning',
33
+ 'info',
30
34
  ];
31
35
 
36
+ const BADGE_RADII: BadgeRadius[] = ['none', 'sm', 'md', 'lg', 'full'];
37
+
32
38
  const BADGE_SIZES = ['sm', 'md', 'lg'];
33
39
 
34
40
  const meta: Meta<typeof Badge> = {
@@ -38,31 +44,38 @@ const meta: Meta<typeof Badge> = {
38
44
  variant: {
39
45
  control: 'select',
40
46
  options: BADGE_VARIANTS,
41
- description: 'The type/color of the badge to show',
47
+ description: 'The visual style of the badge',
48
+ },
49
+ color: {
50
+ control: 'select',
51
+ options: [...BADGE_HUES, ...BADGE_SEMANTIC_COLORS],
52
+ description:
53
+ 'The color of the badge. Semantic names map onto a hue: danger, success, warning, info',
54
+ },
55
+ radius: {
56
+ control: 'select',
57
+ options: BADGE_RADII,
58
+ description: "The roundness of the badge's corners",
42
59
  },
43
60
  size: {
44
61
  control: 'select',
45
62
  options: BADGE_SIZES,
46
63
  description: 'The size of the badge',
47
64
  },
48
- message: {
49
- control: 'text',
50
- description:
51
- 'The text message to be rendered in the badge (deprecated, use children instead)',
52
- },
53
65
  className: {
54
66
  control: 'text',
55
67
  description: 'Custom class to apply to the badge',
56
68
  },
57
69
  children: {
58
70
  control: 'text',
59
- description: 'Badge content (preferred over message)',
71
+ description: 'Badge content',
60
72
  },
61
73
  },
62
74
  args: {
63
- variant: 'default',
75
+ variant: 'soft',
76
+ color: 'grey',
77
+ radius: 'full',
64
78
  size: 'md',
65
- message: '',
66
79
  className: '',
67
80
  children: undefined,
68
81
  },
@@ -82,15 +95,15 @@ type Story = StoryObj<typeof Badge>;
82
95
 
83
96
  export const Overview: Story = {
84
97
  args: {
85
- message: 'Hello world!',
98
+ children: 'Hello world!',
86
99
  },
87
100
  };
88
101
 
89
102
  export const Variants: Story = {
90
103
  render: () => (
91
104
  <Box direction="row" gap="sm">
92
- {SEMANTIC_BADGE_VARIANTS.map((variant) => (
93
- <Badge variant={variant} key={variant}>
105
+ {BADGE_VARIANTS.map((variant) => (
106
+ <Badge variant={variant} color="blue" key={variant}>
94
107
  {variant}
95
108
  </Badge>
96
109
  ))}
@@ -101,13 +114,90 @@ export const Variants: Story = {
101
114
  },
102
115
  };
103
116
 
104
- export const FixedColorVariants: Story = {
117
+ export const Colors: Story = {
105
118
  render: () => (
106
- <Box direction="row" gap="sm" flexWrap="wrap">
107
- {FIXED_COLOR_BADGE_VARIANTS.map((variant) => (
108
- <Badge variant={variant} key={variant}>
109
- {variant}
119
+ <Box direction="column" gap="sm">
120
+ {BADGE_VARIANTS.map((variant) => (
121
+ <Box direction="row" gap="sm" wrap key={variant}>
122
+ {BADGE_HUES.map((color) => (
123
+ <Badge variant={variant} color={color} key={color}>
124
+ {color}
125
+ </Badge>
126
+ ))}
127
+ </Box>
128
+ ))}
129
+ </Box>
130
+ ),
131
+ parameters: {
132
+ controls: { disable: true },
133
+ },
134
+ };
135
+
136
+ export const SemanticColors: Story = {
137
+ render: () => (
138
+ <Box direction="row" gap="sm" wrap>
139
+ {BADGE_SEMANTIC_COLORS.map((color) => (
140
+ <Badge color={color} key={color}>
141
+ {color}
142
+ </Badge>
143
+ ))}
144
+ </Box>
145
+ ),
146
+ parameters: {
147
+ controls: { disable: true },
148
+ },
149
+ };
150
+
151
+ export const Radii: Story = {
152
+ render: () => (
153
+ <Box direction="row" gap="sm" wrap>
154
+ {BADGE_RADII.map((radius) => (
155
+ <Badge radius={radius} variant="surface" color="blue" key={radius}>
156
+ {radius}
157
+ </Badge>
158
+ ))}
159
+ </Box>
160
+ ),
161
+ parameters: {
162
+ controls: { disable: true },
163
+ },
164
+ };
165
+
166
+ export const WithIcons: Story = {
167
+ render: () => (
168
+ <Box direction="column" alignItems="flex-start" gap="md">
169
+ <Box direction="row" gap="sm" alignItems="center" wrap>
170
+ <Badge variant="solid" color="green">
171
+ <Icon name="check" />
172
+ Verified
173
+ </Badge>
174
+ <Badge variant="outline" color="yellow">
175
+ Favorite
176
+ <Icon name="star" />
177
+ </Badge>
178
+ <Badge variant="soft" color="danger">
179
+ <Spinner />
180
+ Deleting
181
+ </Badge>
182
+ <Badge variant="surface" color="blue">
183
+ <Icon name="settings" />
110
184
  </Badge>
185
+ </Box>
186
+ {BADGE_SIZES.map((size) => (
187
+ <Box direction="row" gap="sm" alignItems="center" key={size}>
188
+ <Badge size={size as BadgeSize} variant="solid" color="green">
189
+ <Icon name="check" />
190
+ {size}
191
+ </Badge>
192
+ <Badge size={size as BadgeSize} variant="outline">
193
+ {size}
194
+ <Icon name="star" />
195
+ </Badge>
196
+ <Badge size={size as BadgeSize} variant="soft" color="danger">
197
+ <Spinner />
198
+ {size}
199
+ </Badge>
200
+ </Box>
111
201
  ))}
112
202
  </Box>
113
203
  ),
@@ -119,9 +209,9 @@ export const FixedColorVariants: Story = {
119
209
  export const Sizes: Story = {
120
210
  render: () => (
121
211
  <Box direction="column" alignItems="flex-start" gap="md">
122
- <Badge size="sm" message="Small" />
123
- <Badge size="md" message="Medium" />
124
- <Badge size="lg" message="Large" />
212
+ <Badge size="sm">Small</Badge>
213
+ <Badge size="md">Medium</Badge>
214
+ <Badge size="lg">Large</Badge>
125
215
  <Badge
126
216
  size={{
127
217
  base: 'sm',