@transferwise/components 0.0.0-experimental-feef95e → 0.0.0-experimental-1bb5459

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 (95) hide show
  1. package/build/SentimentSurface/SentimentSurface.js +2 -1
  2. package/build/SentimentSurface/SentimentSurface.js.map +1 -1
  3. package/build/SentimentSurface/SentimentSurface.mjs +2 -1
  4. package/build/SentimentSurface/SentimentSurface.mjs.map +1 -1
  5. package/build/Tag/Tag.js +42 -0
  6. package/build/Tag/Tag.js.map +1 -0
  7. package/build/Tag/Tag.mjs +38 -0
  8. package/build/Tag/Tag.mjs.map +1 -0
  9. package/build/index.js +2 -0
  10. package/build/index.js.map +1 -1
  11. package/build/index.mjs +1 -0
  12. package/build/index.mjs.map +1 -1
  13. package/build/main.css +57 -809
  14. package/build/styles/Inputs/Input/Input.css +0 -84
  15. package/build/styles/Inputs/TextArea/TextArea.css +0 -84
  16. package/build/styles/Tag/Tag.css +35 -0
  17. package/build/styles/_deprecated/Select/Select.css +0 -28
  18. package/build/styles/css/accordion.css +0 -28
  19. package/build/styles/css/button-groups.css +0 -28
  20. package/build/styles/css/buttons.css +0 -28
  21. package/build/styles/css/decision.css +0 -28
  22. package/build/styles/css/dropdowns.css +0 -56
  23. package/build/styles/css/droppable.css +0 -28
  24. package/build/styles/css/footer.css +0 -61
  25. package/build/styles/css/input-groups.css +0 -183
  26. package/build/styles/css/navbar.css +0 -56
  27. package/build/styles/css/neptune-core.css +0 -179
  28. package/build/styles/css/neptune.css +0 -675
  29. package/build/styles/css/popovers.css +0 -56
  30. package/build/styles/css/tooltip.css +0 -28
  31. package/build/styles/main.css +57 -809
  32. package/build/styles/styles/less/accordion.css +0 -28
  33. package/build/styles/styles/less/button-groups.css +0 -28
  34. package/build/styles/styles/less/buttons.css +0 -28
  35. package/build/styles/styles/less/decision.css +0 -28
  36. package/build/styles/styles/less/dropdowns.css +0 -56
  37. package/build/styles/styles/less/droppable.css +0 -28
  38. package/build/styles/styles/less/footer.css +0 -61
  39. package/build/styles/styles/less/forms/bootstrap-forms.css +0 -112
  40. package/build/styles/styles/less/input-groups.css +0 -183
  41. package/build/styles/styles/less/navbar.css +0 -56
  42. package/build/styles/styles/less/neptune-core.css +0 -179
  43. package/build/styles/styles/less/neptune.css +0 -675
  44. package/build/styles/styles/less/popovers.css +0 -56
  45. package/build/styles/styles/less/tooltip.css +0 -28
  46. package/build/types/SentimentSurface/SentimentSurface.d.ts +1 -0
  47. package/build/types/SentimentSurface/SentimentSurface.d.ts.map +1 -1
  48. package/build/types/SentimentSurface/SentimentSurface.types.d.ts +9 -0
  49. package/build/types/SentimentSurface/SentimentSurface.types.d.ts.map +1 -1
  50. package/build/types/SentimentSurface/index.d.ts +1 -1
  51. package/build/types/SentimentSurface/index.d.ts.map +1 -1
  52. package/build/types/Tag/Tag.d.ts +24 -0
  53. package/build/types/Tag/Tag.d.ts.map +1 -0
  54. package/build/types/Tag/Tag.types.d.ts +39 -0
  55. package/build/types/Tag/Tag.types.d.ts.map +1 -0
  56. package/build/types/Tag/index.d.ts +3 -0
  57. package/build/types/Tag/index.d.ts.map +1 -0
  58. package/build/types/index.d.ts +3 -1
  59. package/build/types/index.d.ts.map +1 -1
  60. package/package.json +1 -1
  61. package/src/Inputs/Input/Input.css +0 -84
  62. package/src/Inputs/TextArea/TextArea.css +0 -84
  63. package/src/SentimentSurface/SentimentSurface.test.tsx +24 -0
  64. package/src/SentimentSurface/SentimentSurface.tsx +3 -1
  65. package/src/SentimentSurface/SentimentSurface.types.ts +11 -0
  66. package/src/SentimentSurface/_stories/SentimentSurface.story.tsx +10 -0
  67. package/src/SentimentSurface/index.ts +1 -0
  68. package/src/Tag/Tag.css +35 -0
  69. package/src/Tag/Tag.less +35 -0
  70. package/src/Tag/Tag.test.tsx +72 -0
  71. package/src/Tag/Tag.tsx +60 -0
  72. package/src/Tag/Tag.types.ts +46 -0
  73. package/src/Tag/_stories/Tag.story.tsx +245 -0
  74. package/src/Tag/_stories/Tag.test.story.tsx +120 -0
  75. package/src/Tag/index.ts +2 -0
  76. package/src/_deprecated/Select/Select.css +0 -28
  77. package/src/index.ts +3 -0
  78. package/src/main.css +57 -809
  79. package/src/main.less +1 -0
  80. package/src/styles/less/accordion.css +0 -28
  81. package/src/styles/less/button-groups.css +0 -28
  82. package/src/styles/less/buttons.css +0 -28
  83. package/src/styles/less/core/_typography.less +0 -12
  84. package/src/styles/less/decision.css +0 -28
  85. package/src/styles/less/dropdowns.css +0 -56
  86. package/src/styles/less/droppable.css +0 -28
  87. package/src/styles/less/footer.css +0 -61
  88. package/src/styles/less/forms/bootstrap-forms.css +0 -112
  89. package/src/styles/less/input-groups.css +0 -183
  90. package/src/styles/less/navbar.css +0 -56
  91. package/src/styles/less/neptune-core.css +0 -179
  92. package/src/styles/less/neptune.css +0 -675
  93. package/src/styles/less/popovers.css +0 -56
  94. package/src/styles/less/tooltip.css +0 -28
  95. package/src/test-utils/assets/card-payment-bakery.webp +0 -0
@@ -0,0 +1,35 @@
1
+ .wds-tag {
2
+ align-items: center;
3
+ display: inline-flex;
4
+ gap: 1px;
5
+ max-inline-size: 240px;
6
+ min-inline-size: 0;
7
+ inline-size: -moz-fit-content;
8
+ inline-size: fit-content;
9
+ }
10
+ .wds-tag--small {
11
+ border-radius: 6px;
12
+ padding-block: 1px;
13
+ padding-inline: 3px 4px;
14
+ padding-inline: 3px var(--size-4);
15
+ }
16
+ .wds-tag--small .wds-tag__text {
17
+ font-size: 0.75rem;
18
+ font-size: var(--font-size-12);
19
+ }
20
+ .wds-tag--large {
21
+ border-radius: 8px;
22
+ border-radius: var(--size-8);
23
+ padding-block: 1px;
24
+ padding-inline: 5px 6px;
25
+ padding-inline: var(--size-5) 6px;
26
+ }
27
+ .wds-tag__text {
28
+ overflow: hidden;
29
+ padding-inline-start: 1px;
30
+ text-overflow: ellipsis;
31
+ white-space: nowrap;
32
+ }
33
+ .wds-tag.wds-tag--proposition {
34
+ color: var(--color-sentiment-interactive-primary);
35
+ }
@@ -0,0 +1,35 @@
1
+ .wds-tag {
2
+ align-items: center;
3
+ display: inline-flex;
4
+ gap: 1px;
5
+ max-width: 240px;
6
+ min-width: 0;
7
+ width: fit-content;
8
+
9
+ &--small {
10
+ border-radius: 6px;
11
+ padding-block: 1px;
12
+ padding-inline: 3px var(--size-4);
13
+
14
+ .wds-tag__text {
15
+ font-size: var(--font-size-12);
16
+ }
17
+ }
18
+
19
+ &--large {
20
+ border-radius: var(--size-8);
21
+ padding-block: 1px;
22
+ padding-inline: var(--size-5) 6px;
23
+ }
24
+
25
+ &__text {
26
+ overflow: hidden;
27
+ padding-inline-start: 1px;
28
+ text-overflow: ellipsis;
29
+ white-space: nowrap;
30
+ }
31
+
32
+ &.wds-tag--proposition {
33
+ color: var(--color-sentiment-interactive-primary);
34
+ }
35
+ }
@@ -0,0 +1,72 @@
1
+ import { ThemeProvider } from '@wise/components-theming';
2
+
3
+ import { render, screen } from '../test-utils';
4
+ import Tag from './Tag';
5
+
6
+ describe('Tag', () => {
7
+ it('renders the text as a span', () => {
8
+ render(<Tag data-testid="tag">Tag copy</Tag>);
9
+ const tag = screen.getByTestId('tag');
10
+
11
+ expect(tag.tagName).toBe('SPAN');
12
+ expect(tag).toHaveTextContent('Tag copy');
13
+ });
14
+
15
+ it('wraps the text in a truncating text wrapper', () => {
16
+ render(<Tag data-testid="tag">Tag copy</Tag>);
17
+ const text = screen.getByText('Tag copy');
18
+
19
+ expect(text).toHaveClass('wds-tag__text');
20
+ expect(text.parentElement).toHaveClass('wds-tag');
21
+ });
22
+
23
+ it('defaults to a small, neutral tag', () => {
24
+ render(<Tag data-testid="tag">Tag copy</Tag>);
25
+
26
+ expect(screen.getByTestId('tag')).toHaveClass('wds-tag', 'wds-tag--small', 'wds-tag--neutral');
27
+ });
28
+
29
+ it('renders the size as a class', () => {
30
+ render(
31
+ <Tag size="large" data-testid="tag">
32
+ Tag copy
33
+ </Tag>,
34
+ );
35
+
36
+ expect(screen.getByTestId('tag')).toHaveClass('wds-tag--large');
37
+ });
38
+
39
+ it('renders the sentiment as a class', () => {
40
+ render(
41
+ <Tag sentiment="success" data-testid="tag">
42
+ Tag copy
43
+ </Tag>,
44
+ );
45
+
46
+ expect(screen.getByTestId('tag')).toHaveClass('wds-tag--success');
47
+ });
48
+
49
+ it('uses the dark elevated surface when overMedia is set in a light screen mode', () => {
50
+ render(
51
+ <ThemeProvider theme="personal" screenMode="light">
52
+ <Tag data-testid="tag" overMedia>
53
+ Tag copy
54
+ </Tag>
55
+ </ThemeProvider>,
56
+ );
57
+
58
+ expect(screen.getByTestId('tag')).toHaveClass('wds-sentiment-neutral-dark-elevated');
59
+ });
60
+
61
+ it('applies a custom className and id', () => {
62
+ render(
63
+ <Tag className="custom-class" id="custom-id" data-testid="tag">
64
+ Tag copy
65
+ </Tag>,
66
+ );
67
+ const tag = screen.getByTestId('tag');
68
+
69
+ expect(tag).toHaveClass('custom-class');
70
+ expect(tag).toHaveAttribute('id', 'custom-id');
71
+ });
72
+ });
@@ -0,0 +1,60 @@
1
+ import { forwardRef } from 'react';
2
+ import { clsx } from 'clsx';
3
+
4
+ import Body from '../Body';
5
+ import SentimentSurface from '../SentimentSurface';
6
+ import { TagProps } from './Tag.types';
7
+
8
+ /**
9
+ * Tag is a small, non-interactive label that categorises or highlights a piece of content.
10
+ *
11
+ * @param {string} children - The text of the tag.
12
+ * @param {Sentiment} [sentiment='neutral'] - Optional prop to set the sentiment type (negative, warning, neutral, success, proposition).
13
+ * @param {TagSize} [size='small'] - Optional prop to set the size of the tag (small or large).
14
+ * @param {Emphasis} [emphasis='base'] - Optional prop to specify the emphasis level (base or elevated).
15
+ * @param {boolean} [overMedia=false] - If true, renders the tag for use over media, keeping the colours it uses in dark screen modes.
16
+ * @param {string} [className] - Additional CSS classes to apply.
17
+ * @param {string} [id] - Unique identifier for the component.
18
+ * @param {string} [data-testid] - A unique string that appears as data attribute `data-testid` in the rendered code.
19
+ *
20
+ * @component
21
+ * @example
22
+ * ```tsx
23
+ * <Tag sentiment="success">Verified</Tag>
24
+ * ```
25
+ *
26
+ * @see {@link https://storybook.wise.design/?path=/docs/tag--docs|Storybook Wise Design}
27
+ */
28
+ const Tag = forwardRef<HTMLSpanElement, TagProps>(function Tag(
29
+ {
30
+ children,
31
+ sentiment = 'neutral',
32
+ size = 'small',
33
+ emphasis = 'base',
34
+ overMedia = false,
35
+ className,
36
+ id,
37
+ 'data-testid': dataTestId,
38
+ },
39
+ ref,
40
+ ) {
41
+ return (
42
+ <SentimentSurface
43
+ // @ts-expect-error - SentimentSurface forwardRef types don't expose ref in props
44
+ ref={ref}
45
+ as="span"
46
+ sentiment={sentiment}
47
+ emphasis={overMedia ? 'elevated' : emphasis}
48
+ colourScheme={overMedia ? 'dark' : undefined}
49
+ id={id}
50
+ data-testid={dataTestId}
51
+ className={clsx('wds-tag', `wds-tag--${size}`, `wds-tag--${sentiment}`, className)}
52
+ >
53
+ <Body as="span" type="body-default-bold" className="wds-tag__text">
54
+ {children}
55
+ </Body>
56
+ </SentimentSurface>
57
+ );
58
+ });
59
+
60
+ export default Tag;
@@ -0,0 +1,46 @@
1
+ import type { Emphasis, Sentiment } from '../SentimentSurface';
2
+
3
+ /**
4
+ * Sizes for the Tag component
5
+ */
6
+ export type TagSize = 'small' | 'large';
7
+
8
+ export interface TagProps {
9
+ /**
10
+ * The text of the tag
11
+ */
12
+ children: string;
13
+
14
+ /**
15
+ * The sentiment type that determines the colour scheme
16
+ * @default 'neutral'
17
+ */
18
+ sentiment?: Sentiment;
19
+
20
+ /**
21
+ * The size of the tag
22
+ * @default 'small'
23
+ */
24
+ size?: TagSize;
25
+
26
+ /**
27
+ * The emphasis level affecting background and text contrast
28
+ * @default 'base'
29
+ */
30
+ emphasis?: Emphasis;
31
+
32
+ /**
33
+ * If true, renders the tag for use over media such as a photo or a video, keeping the colours
34
+ * it uses in dark screen modes so that it stays legible over unpredictable artwork
35
+ * @default false
36
+ */
37
+ overMedia?: boolean;
38
+
39
+ className?: string;
40
+ id?: string;
41
+
42
+ /**
43
+ * A unique string that appears as data attribute `data-testid` in the rendered code, serving as a hook for automated tests
44
+ */
45
+ 'data-testid'?: string;
46
+ }
@@ -0,0 +1,245 @@
1
+ import { Fragment } from 'react';
2
+ import type { ReactElement, ReactNode } from 'react';
3
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
4
+
5
+ import {
6
+ createSandboxStory,
7
+ globalScope,
8
+ } from '../../../.storybook/components/sandbox/SandboxEditor';
9
+ import Tag from '..';
10
+ import type { TagProps } from '..';
11
+
12
+ const withComponentGrid = (Story: () => ReactElement) => (
13
+ <div
14
+ style={{
15
+ display: 'flex',
16
+ flexWrap: 'wrap',
17
+ alignItems: 'center',
18
+ gap: '0.5rem',
19
+ }}
20
+ >
21
+ <Story />
22
+ </div>
23
+ );
24
+
25
+ const SENTIMENTS = ['neutral', 'negative', 'warning', 'success', 'proposition'] as const;
26
+ const SIZES = ['small', 'large'] as const;
27
+ const EMPHASES = ['base', 'elevated'] as const;
28
+ const PHOTO = '../card-payment-bakery.webp';
29
+
30
+ const Label = ({ children }: { children: ReactNode }) => (
31
+ <span
32
+ className="np-text-body-default"
33
+ style={{
34
+ color: 'var(--color-content-secondary)',
35
+ textTransform: 'capitalize',
36
+ whiteSpace: 'nowrap',
37
+ }}
38
+ >
39
+ {children}
40
+ </span>
41
+ );
42
+
43
+ /**
44
+ * Tag is a small, non-interactive label that categorises or highlights a piece of content,
45
+ * such as a status, a category, or a promotion.
46
+ *
47
+ * Tags are decorative labels, not controls — if the user needs to act on the tag, use `Chips`
48
+ * instead.
49
+ */
50
+ export default {
51
+ title: 'Prompts/Tag',
52
+ component: Tag,
53
+ tags: ['early-access'],
54
+ args: {
55
+ children: 'Tag copy',
56
+ },
57
+ argTypes: {
58
+ children: {
59
+ control: 'text',
60
+ table: {
61
+ type: { summary: 'string' },
62
+ },
63
+ },
64
+ sentiment: {
65
+ control: 'select',
66
+ options: SENTIMENTS,
67
+ },
68
+ size: {
69
+ control: 'inline-radio',
70
+ options: SIZES,
71
+ },
72
+ emphasis: {
73
+ control: 'inline-radio',
74
+ options: EMPHASES,
75
+ },
76
+ overMedia: {
77
+ control: 'boolean',
78
+ },
79
+ },
80
+ } satisfies Meta<TagProps>;
81
+
82
+ type Story = StoryObj<TagProps>;
83
+
84
+ export const Playground: Story = {};
85
+
86
+ export const Sandbox = createSandboxStory({
87
+ code: `<div className="d-flex align-items-center" style={{ gap: '8px' }}>
88
+ <Tag>New</Tag>
89
+ <Tag sentiment="success" emphasis="elevated">Verified</Tag>
90
+ <Tag sentiment="warning" size="large">Action needed</Tag>
91
+ </div>`,
92
+ scope: globalScope,
93
+ });
94
+
95
+ /**
96
+ * Every tag the component can render. Each cell sets its own `sentiment`, `emphasis` and
97
+ * `overMedia`; the `size` and text controls apply to the whole table.
98
+ */
99
+ export const Overview: Story = {
100
+ args: {
101
+ size: 'small',
102
+ },
103
+ render: (args) => (
104
+ <div
105
+ style={{
106
+ alignItems: 'center',
107
+ columnGap: '2rem',
108
+ display: 'grid',
109
+ gridTemplateColumns: 'repeat(4, max-content)',
110
+ justifyItems: 'start',
111
+ rowGap: '0.75rem',
112
+ }}
113
+ >
114
+ <span />
115
+ <Label>Base</Label>
116
+ <Label>Elevated</Label>
117
+ <Label>Over media</Label>
118
+
119
+ {SENTIMENTS.map((sentiment) => (
120
+ <Fragment key={sentiment}>
121
+ <Label>{sentiment}</Label>
122
+ <Tag {...args} sentiment={sentiment} />
123
+ <Tag {...args} sentiment={sentiment} emphasis="elevated" />
124
+ <Tag {...args} sentiment={sentiment} overMedia />
125
+ </Fragment>
126
+ ))}
127
+ </div>
128
+ ),
129
+ };
130
+
131
+ /**
132
+ * Tags come in two sizes. Use `small` alongside body text and `large` when the tag sits next to
133
+ * headings or other prominent content.
134
+ */
135
+ export const Sizes: Story = {
136
+ decorators: [withComponentGrid],
137
+ render: (args) => (
138
+ <>
139
+ <Tag {...args} size="small" />
140
+ <Tag {...args} size="large" />
141
+ </>
142
+ ),
143
+ };
144
+
145
+ /**
146
+ * The `sentiment` prop conveys the meaning of the tag:
147
+ *
148
+ * - `neutral` (default): general categorisation
149
+ * - `negative`: errors and failures
150
+ * - `warning`: something needs attention
151
+ * - `success`: completed or verified states
152
+ * - `proposition`: promotions and new features
153
+ */
154
+ export const Sentiments: Story = {
155
+ decorators: [withComponentGrid],
156
+ render: (args) => (
157
+ <>
158
+ {SENTIMENTS.map((sentiment) => (
159
+ <Tag key={sentiment} {...args} sentiment={sentiment} />
160
+ ))}
161
+ </>
162
+ ),
163
+ };
164
+
165
+ /**
166
+ * Set `emphasis` to `elevated` to make the tag stand out from the content around it. Use it
167
+ * sparingly — when every tag is emphasised, none of them are.
168
+ */
169
+ export const Emphasis: Story = {
170
+ decorators: [withComponentGrid],
171
+ render: (args) => (
172
+ <>
173
+ {SENTIMENTS.map((sentiment) => (
174
+ <Tag key={sentiment} {...args} sentiment={sentiment} emphasis="elevated" />
175
+ ))}
176
+ </>
177
+ ),
178
+ };
179
+
180
+ /**
181
+ * Set `overMedia` when the tag sits on top of a photo, a video or any other rich backdrop. The
182
+ * tag then keeps the colours it uses in dark screen modes, regardless of the current one, so that
183
+ * it stays legible over unpredictable artwork. Tags over media are always elevated.
184
+ */
185
+ export const OverMedia: Story = {
186
+ decorators: [
187
+ (Story: () => ReactElement) => (
188
+ <div
189
+ style={{
190
+ alignItems: 'flex-start',
191
+ backgroundImage: `url(${PHOTO})`,
192
+ backgroundPosition: 'center',
193
+ backgroundSize: 'cover',
194
+ borderRadius: 'var(--radius-medium)',
195
+ display: 'flex',
196
+ flexWrap: 'wrap',
197
+ gap: '0.5rem',
198
+ height: '160px',
199
+ padding: '1rem',
200
+ width: '100%',
201
+ }}
202
+ >
203
+ <Story />
204
+ </div>
205
+ ),
206
+ ],
207
+ render: (args) => (
208
+ <>
209
+ {SENTIMENTS.map((sentiment) => (
210
+ <Tag key={sentiment} {...args} sentiment={sentiment} overMedia />
211
+ ))}
212
+ </>
213
+ ),
214
+ };
215
+
216
+ /**
217
+ * Tag copy never wraps. It truncates with an ellipsis, either at the tag's own 240px maximum
218
+ * width or at the width of a narrower parent, so keep the copy to a word or two.
219
+ */
220
+ export const LongText: Story = {
221
+ decorators: [
222
+ (Story: () => ReactElement) => (
223
+ <div
224
+ style={{
225
+ alignItems: 'flex-start',
226
+ display: 'flex',
227
+ flexDirection: 'column',
228
+ gap: '0.5rem',
229
+ }}
230
+ >
231
+ <Story />
232
+ </div>
233
+ ),
234
+ ],
235
+ render: (args) => (
236
+ <>
237
+ <Tag {...args}>A tag with very long text</Tag>
238
+
239
+ <Tag {...args}>A tag with very very very very very very long text</Tag>
240
+ <div style={{ display: 'flex', width: '100px' }}>
241
+ <Tag {...args}>A tag in a narrow container with long text</Tag>
242
+ </div>
243
+ </>
244
+ ),
245
+ };
@@ -0,0 +1,120 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
3
+
4
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
5
+ import { allModes } from '../../../.storybook/modes';
6
+ import Tag from '..';
7
+ import type { TagProps } from '..';
8
+
9
+ const SENTIMENTS = ['neutral', 'negative', 'warning', 'success', 'proposition'] as const;
10
+
11
+ const withMatrixGrid = (Story: () => ReactElement) => (
12
+ <div
13
+ style={{
14
+ alignItems: 'center',
15
+ display: 'grid',
16
+ gap: '0.5rem',
17
+ gridTemplateColumns: 'repeat(5, max-content)',
18
+ justifyItems: 'start',
19
+ }}
20
+ >
21
+ <Story />
22
+ </div>
23
+ );
24
+
25
+ const meta = {
26
+ title: 'Prompts/Tag/Tests',
27
+ component: Tag,
28
+ tags: ['!autodocs', '!manifest', 'early-access'],
29
+ args: {
30
+ children: 'Tag copy',
31
+ },
32
+ } satisfies Meta<TagProps>;
33
+
34
+ export default meta;
35
+
36
+ type Story = StoryObj<TagProps>;
37
+
38
+ /**
39
+ * Every combination of size, emphasis and sentiment, across all themes.
40
+ */
41
+ export const AllThemesAndSentiments: Story = {
42
+ render: () => (
43
+ <>
44
+ {(['small', 'large'] as const).map((size) =>
45
+ (['base', 'elevated'] as const).map((emphasis) =>
46
+ SENTIMENTS.map((sentiment) => (
47
+ <Tag
48
+ key={`${size}-${emphasis}-${sentiment}`}
49
+ size={size}
50
+ sentiment={sentiment}
51
+ emphasis={emphasis}
52
+ >
53
+ {`${size} ${sentiment}`}
54
+ </Tag>
55
+ )),
56
+ ),
57
+ )}
58
+ </>
59
+ ),
60
+ decorators: [withMatrixGrid],
61
+ parameters: {
62
+ padding: '16px',
63
+ variants: ['default', 'dark', 'bright-green', 'forest-green'],
64
+ chromatic: {
65
+ dark: allModes.dark,
66
+ brightGreen: allModes.brightGreen,
67
+ forestGreen: allModes.forestGreen,
68
+ },
69
+ },
70
+ };
71
+
72
+ /**
73
+ * The tag's horizontal padding is asymmetric and long copy truncates, so both need to mirror.
74
+ */
75
+ export const RTLDiff: Story = {
76
+ render: () => (
77
+ <div
78
+ style={{
79
+ alignItems: 'flex-start',
80
+ display: 'flex',
81
+ flexDirection: 'column',
82
+ gap: '0.5rem',
83
+ }}
84
+ >
85
+ <Tag>Tag copy</Tag>
86
+ <Tag size="large" sentiment="success" emphasis="elevated">
87
+ Tag copy
88
+ </Tag>
89
+ <Tag>A tag with copy far too long to fit within its maximum width</Tag>
90
+ </div>
91
+ ),
92
+ ...withRTLDiff(),
93
+ };
94
+
95
+ /**
96
+ * `overMedia` tags keep their dark screen mode colours in every theme.
97
+ */
98
+ export const OverMediaAcrossThemes: Story = {
99
+ render: () => (
100
+ <>
101
+ {(['small', 'large'] as const).map((size) =>
102
+ SENTIMENTS.map((sentiment) => (
103
+ <Tag key={`${size}-${sentiment}`} size={size} sentiment={sentiment} overMedia>
104
+ {`${size} ${sentiment}`}
105
+ </Tag>
106
+ )),
107
+ )}
108
+ </>
109
+ ),
110
+ decorators: [withMatrixGrid],
111
+ parameters: {
112
+ padding: '16px',
113
+ variants: ['default', 'dark', 'bright-green', 'forest-green'],
114
+ chromatic: {
115
+ dark: allModes.dark,
116
+ brightGreen: allModes.brightGreen,
117
+ forestGreen: allModes.forestGreen,
118
+ },
119
+ },
120
+ };
@@ -0,0 +1,2 @@
1
+ export { default } from './Tag';
2
+ export type { TagProps, TagSize } from './Tag.types';
@@ -157,34 +157,6 @@
157
157
  border-radius: 10px;
158
158
  border-radius: var(--radius-small);
159
159
  }
160
- @supports (hyphenate-limit-chars: 1) {
161
- .np-dropdown-menu > li > a {
162
- hyphens: auto;
163
- hyphenate-limit-chars: 7 3;
164
- }
165
- @media (min-width: 840px) {
166
- .np-dropdown-menu > li > a {
167
- hyphenate-limit-chars: 8 3;
168
- }
169
- }
170
- @media (min-width: 1160px) {
171
- .np-dropdown-menu > li > a {
172
- hyphenate-limit-chars: 10 4 3;
173
- }
174
- }
175
- }
176
- @supports (not (hyphenate-limit-chars: 1)) and (-webkit-hyphenate-limit-before: 1) {
177
- .np-dropdown-menu > li > a {
178
- hyphens: auto;
179
- -webkit-hyphenate-limit-before: 3;
180
- -webkit-hyphenate-limit-after: 3;
181
- }
182
- @media (min-width: 1160px) {
183
- .np-dropdown-menu > li > a {
184
- -webkit-hyphenate-limit-before: 4;
185
- }
186
- }
187
- }
188
160
  .np-dropdown-menu > li:first-child > a {
189
161
  border-start-end-radius: 3px;
190
162
  border-start-start-radius: 3px;
package/src/index.ts CHANGED
@@ -144,10 +144,12 @@ export type {
144
144
  SentimentSurfaceProps,
145
145
  SentimentSurfaceComponent,
146
146
  Sentiment as SurfaceSentiment,
147
+ ColourScheme as SurfaceColourScheme,
147
148
  } from './SentimentSurface';
148
149
  export type { SwitchProps } from './Switch';
149
150
  export type { SwitchOptionProps } from './_deprecated/SwitchOption';
150
151
  export type { TabItem, TabsProps, TabProps, TabListProps, TabPanelProps } from './Tabs';
152
+ export type { TagProps, TagSize } from './Tag';
151
153
  export type { TextareaWithDisplayFormatProps } from './TextareaWithDisplayFormat';
152
154
  export type { TileProps } from './Tile';
153
155
  export type { TitleProps } from './Title';
@@ -291,6 +293,7 @@ export { default as Summary } from './_deprecated/Summary';
291
293
  export { default as Switch } from './Switch';
292
294
  export { default as SwitchOption } from './_deprecated/SwitchOption';
293
295
  export { default as Tabs } from './Tabs';
296
+ export { default as Tag } from './Tag';
294
297
  export { default as TextareaWithDisplayFormat } from './TextareaWithDisplayFormat';
295
298
  export { default as Title } from './Title';
296
299
  export { default as Tile } from './Tile';