@transferwise/components 46.160.7 → 46.161.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 (96) hide show
  1. package/build/Tag/Tag.js +45 -0
  2. package/build/Tag/Tag.js.map +1 -0
  3. package/build/Tag/Tag.mjs +41 -0
  4. package/build/Tag/Tag.mjs.map +1 -0
  5. package/build/index.js +2 -0
  6. package/build/index.js.map +1 -1
  7. package/build/index.mjs +1 -0
  8. package/build/index.mjs.map +1 -1
  9. package/build/main.css +853 -0
  10. package/build/styles/Inputs/Input/Input.css +88 -0
  11. package/build/styles/Inputs/TextArea/TextArea.css +88 -0
  12. package/build/styles/Popover/Popover.css +1 -0
  13. package/build/styles/Tag/Tag.css +30 -0
  14. package/build/styles/_deprecated/Select/Select.css +29 -0
  15. package/build/styles/css/accordion.css +30 -0
  16. package/build/styles/css/button-groups.css +29 -0
  17. package/build/styles/css/buttons.css +29 -0
  18. package/build/styles/css/decision.css +30 -0
  19. package/build/styles/css/dropdowns.css +59 -0
  20. package/build/styles/css/droppable.css +29 -0
  21. package/build/styles/css/footer.css +63 -0
  22. package/build/styles/css/input-groups.css +189 -0
  23. package/build/styles/css/list-group.css +1 -0
  24. package/build/styles/css/navbar.css +59 -0
  25. package/build/styles/css/neptune-addons.css +3 -0
  26. package/build/styles/css/neptune-core.css +185 -0
  27. package/build/styles/css/neptune.css +705 -0
  28. package/build/styles/css/popovers.css +59 -0
  29. package/build/styles/css/tooltip.css +29 -0
  30. package/build/styles/main.css +853 -0
  31. package/build/styles/styles/less/accordion.css +30 -0
  32. package/build/styles/styles/less/button-groups.css +29 -0
  33. package/build/styles/styles/less/buttons.css +29 -0
  34. package/build/styles/styles/less/decision.css +30 -0
  35. package/build/styles/styles/less/dropdowns.css +59 -0
  36. package/build/styles/styles/less/droppable.css +29 -0
  37. package/build/styles/styles/less/footer.css +63 -0
  38. package/build/styles/styles/less/forms/bootstrap-forms.css +116 -0
  39. package/build/styles/styles/less/input-groups.css +189 -0
  40. package/build/styles/styles/less/list-group.css +1 -0
  41. package/build/styles/styles/less/navbar.css +59 -0
  42. package/build/styles/styles/less/neptune-addons.css +3 -0
  43. package/build/styles/styles/less/neptune-core.css +185 -0
  44. package/build/styles/styles/less/neptune.css +705 -0
  45. package/build/styles/styles/less/popovers.css +59 -0
  46. package/build/styles/styles/less/tooltip.css +29 -0
  47. package/build/types/Tag/Tag.d.ts +24 -0
  48. package/build/types/Tag/Tag.d.ts.map +1 -0
  49. package/build/types/Tag/Tag.types.d.ts +39 -0
  50. package/build/types/Tag/Tag.types.d.ts.map +1 -0
  51. package/build/types/Tag/index.d.ts +3 -0
  52. package/build/types/Tag/index.d.ts.map +1 -0
  53. package/build/types/index.d.ts +2 -0
  54. package/build/types/index.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/src/Body/_stories/Body.test.story.tsx +81 -0
  57. package/src/Inputs/Input/Input.css +88 -0
  58. package/src/Inputs/TextArea/TextArea.css +88 -0
  59. package/src/Popover/Popover.css +1 -0
  60. package/src/Tag/Tag.css +30 -0
  61. package/src/Tag/Tag.less +31 -0
  62. package/src/Tag/Tag.test.tsx +70 -0
  63. package/src/Tag/Tag.tsx +71 -0
  64. package/src/Tag/Tag.types.ts +46 -0
  65. package/src/Tag/_stories/Tag.story.tsx +245 -0
  66. package/src/Tag/_stories/Tag.test.story.tsx +121 -0
  67. package/src/Tag/index.ts +2 -0
  68. package/src/_deprecated/Card/_stories/Card.test.story.tsx +1 -1
  69. package/src/_deprecated/CriticalBanner/_stories/CriticalCommsBanner.test.story.tsx +1 -1
  70. package/src/_deprecated/InlineAlert/_stories/InlineAlert.test.story.tsx +1 -1
  71. package/src/_deprecated/OverlayHeader/_stories/OverlayHeader.test.story.tsx +1 -1
  72. package/src/_deprecated/Select/Select.css +29 -0
  73. package/src/_deprecated/Select/_stories/Select.rtl.test.story.tsx +1 -1
  74. package/src/_deprecated/Select/_stories/Select.test.story.tsx +1 -1
  75. package/src/index.ts +2 -0
  76. package/src/main.css +853 -0
  77. package/src/main.less +1 -0
  78. package/src/styles/less/accordion.css +30 -0
  79. package/src/styles/less/addons/_spacing-utilities.less +2 -0
  80. package/src/styles/less/button-groups.css +29 -0
  81. package/src/styles/less/buttons.css +29 -0
  82. package/src/styles/less/core/_typography.less +12 -0
  83. package/src/styles/less/decision.css +30 -0
  84. package/src/styles/less/dropdowns.css +59 -0
  85. package/src/styles/less/droppable.css +29 -0
  86. package/src/styles/less/footer.css +63 -0
  87. package/src/styles/less/forms/bootstrap-forms.css +116 -0
  88. package/src/styles/less/input-groups.css +189 -0
  89. package/src/styles/less/list-group.css +1 -0
  90. package/src/styles/less/navbar.css +59 -0
  91. package/src/styles/less/neptune-addons.css +3 -0
  92. package/src/styles/less/neptune-core.css +185 -0
  93. package/src/styles/less/neptune.css +705 -0
  94. package/src/styles/less/popovers.css +59 -0
  95. package/src/styles/less/tooltip.css +29 -0
  96. package/src/test-utils/assets/card-payment-bakery.webp +0 -0
@@ -0,0 +1,31 @@
1
+ .wds-tag {
2
+ display: inline-block;
3
+ max-width: 240px;
4
+ min-width: 0;
5
+ overflow: hidden;
6
+ text-overflow: ellipsis;
7
+ vertical-align: middle;
8
+ white-space: nowrap;
9
+ width: fit-content;
10
+
11
+ &--small {
12
+ border-radius: 6px;
13
+ font-size: var(--font-size-12);
14
+ padding-block: 1px;
15
+ padding-inline: var(--size-4);
16
+ }
17
+
18
+ &--large {
19
+ border-radius: 8px;
20
+ padding-block: 1px;
21
+ padding-inline: 6px;
22
+ }
23
+
24
+ &.wds-tag--proposition {
25
+ color: var(--color-sentiment-interactive-primary);
26
+ }
27
+ }
28
+
29
+ .wds-tag-theme {
30
+ display: contents;
31
+ }
@@ -0,0 +1,70 @@
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 label as a span', () => {
8
+ render(<Tag label="Tag copy" data-testid="tag" />);
9
+ const tag = screen.getByTestId('tag');
10
+
11
+ expect(tag.tagName).toBe('SPAN');
12
+ expect(tag).toHaveTextContent('Tag copy');
13
+ });
14
+
15
+ it('defaults to a small, neutral tag', () => {
16
+ render(<Tag label="Tag copy" data-testid="tag" />);
17
+
18
+ expect(screen.getByTestId('tag')).toHaveClass('wds-tag', 'wds-tag--small', 'wds-tag--neutral');
19
+ });
20
+
21
+ it('renders the size as a class', () => {
22
+ render(<Tag label="Tag copy" size="large" data-testid="tag" />);
23
+
24
+ expect(screen.getByTestId('tag')).toHaveClass('wds-tag--large');
25
+ });
26
+
27
+ it('renders the sentiment as a class', () => {
28
+ render(<Tag label="Tag copy" sentiment="success" data-testid="tag" />);
29
+
30
+ expect(screen.getByTestId('tag')).toHaveClass('wds-tag--success');
31
+ });
32
+
33
+ it('follows the surrounding screen mode', () => {
34
+ render(
35
+ <ThemeProvider theme="personal" screenMode="dark">
36
+ <Tag label="Tag copy" data-testid="tag" />
37
+ </ThemeProvider>,
38
+ );
39
+
40
+ expect(screen.getByTestId('tag')).toHaveClass('wds-sentiment-neutral-dark-base');
41
+ });
42
+
43
+ it('uses the dark elevated surface when overMedia is set in a light screen mode', () => {
44
+ render(
45
+ <ThemeProvider theme="personal" screenMode="light">
46
+ <Tag label="Tag copy" data-testid="tag" overMedia />
47
+ </ThemeProvider>,
48
+ );
49
+
50
+ expect(screen.getByTestId('tag')).toHaveClass('wds-sentiment-neutral-dark-elevated');
51
+ });
52
+
53
+ it('keeps the surrounding brand theme when overMedia is set', () => {
54
+ render(
55
+ <ThemeProvider theme="business" screenMode="light">
56
+ <Tag label="Tag copy" data-testid="tag" overMedia />
57
+ </ThemeProvider>,
58
+ );
59
+
60
+ expect(screen.getByTestId('tag')).toHaveClass('np-theme-business');
61
+ });
62
+
63
+ it('applies a custom className and id', () => {
64
+ render(<Tag label="Tag copy" className="custom-class" id="custom-id" data-testid="tag" />);
65
+ const tag = screen.getByTestId('tag');
66
+
67
+ expect(tag).toHaveClass('custom-class');
68
+ expect(tag).toHaveAttribute('id', 'custom-id');
69
+ });
70
+ });
@@ -0,0 +1,71 @@
1
+ import { forwardRef } from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { ThemeProvider, useTheme } from '@wise/components-theming';
4
+
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} label - The text of the tag, kept to a word or two.
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" label="Verified" />
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
+ label,
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
+ const { theme, screenMode } = useTheme();
42
+
43
+ return (
44
+ <ThemeProvider
45
+ theme={theme}
46
+ screenMode={overMedia ? 'dark' : screenMode}
47
+ className="wds-tag-theme"
48
+ >
49
+ <SentimentSurface
50
+ // @ts-expect-error - SentimentSurface forwardRef types don't expose ref in props
51
+ ref={ref}
52
+ as="span"
53
+ sentiment={sentiment}
54
+ emphasis={overMedia ? 'elevated' : emphasis}
55
+ id={id}
56
+ data-testid={dataTestId}
57
+ className={clsx(
58
+ 'wds-tag',
59
+ `wds-tag--${size}`,
60
+ `wds-tag--${sentiment}`,
61
+ 'np-text-body-default-bold',
62
+ className,
63
+ )}
64
+ >
65
+ {label}
66
+ </SentimentSurface>
67
+ </ThemeProvider>
68
+ );
69
+ });
70
+
71
+ 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, kept to a word or two
11
+ */
12
+ label: 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
+ label: 'Tag copy',
56
+ },
57
+ argTypes: {
58
+ label: {
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 label="New" />
89
+ <Tag label="Verified" sentiment="success" emphasis="elevated" />
90
+ <Tag label="Action needed" sentiment="warning" size="large" />
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} label="A tag with very long text" />
238
+
239
+ <Tag {...args} label="A tag with very very very very very very long text" />
240
+ <div style={{ display: 'flex', width: '100px' }}>
241
+ <Tag {...args} label="A tag in a narrow container with long text" />
242
+ </div>
243
+ </>
244
+ ),
245
+ };
@@ -0,0 +1,121 @@
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'],
29
+ args: {
30
+ label: '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
+ label={`${size} ${sentiment}`}
50
+ size={size}
51
+ sentiment={sentiment}
52
+ emphasis={emphasis}
53
+ />
54
+ )),
55
+ ),
56
+ )}
57
+ </>
58
+ ),
59
+ decorators: [withMatrixGrid],
60
+ parameters: {
61
+ padding: '16px',
62
+ variants: ['default', 'dark', 'bright-green', 'forest-green'],
63
+ chromatic: {
64
+ dark: allModes.dark,
65
+ brightGreen: allModes.brightGreen,
66
+ forestGreen: allModes.forestGreen,
67
+ },
68
+ },
69
+ };
70
+
71
+ /**
72
+ * The tag's horizontal padding is asymmetric and long copy truncates, so both need to mirror.
73
+ */
74
+ export const RTLDiff: Story = {
75
+ render: () => (
76
+ <div
77
+ style={{
78
+ alignItems: 'flex-start',
79
+ display: 'flex',
80
+ flexDirection: 'column',
81
+ gap: '0.5rem',
82
+ }}
83
+ >
84
+ <Tag label="Tag copy" />
85
+ <Tag label="Tag copy" size="large" sentiment="success" emphasis="elevated" />
86
+ <Tag label="A tag with copy far too long to fit within its maximum width" />
87
+ </div>
88
+ ),
89
+ ...withRTLDiff(),
90
+ };
91
+
92
+ /**
93
+ * `overMedia` tags keep their dark screen mode colours in every theme.
94
+ */
95
+ export const OverMediaAcrossThemes: Story = {
96
+ render: () => (
97
+ <>
98
+ {(['small', 'large'] as const).map((size) =>
99
+ SENTIMENTS.map((sentiment) => (
100
+ <Tag
101
+ key={`${size}-${sentiment}`}
102
+ label={`${size} ${sentiment}`}
103
+ size={size}
104
+ sentiment={sentiment}
105
+ overMedia
106
+ />
107
+ )),
108
+ )}
109
+ </>
110
+ ),
111
+ decorators: [withMatrixGrid],
112
+ parameters: {
113
+ padding: '16px',
114
+ variants: ['default', 'dark', 'bright-green', 'forest-green'],
115
+ chromatic: {
116
+ dark: allModes.dark,
117
+ brightGreen: allModes.brightGreen,
118
+ forestGreen: allModes.forestGreen,
119
+ },
120
+ },
121
+ };
@@ -0,0 +1,2 @@
1
+ export { default } from './Tag';
2
+ export type { TagProps, TagSize } from './Tag.types';
@@ -7,7 +7,7 @@ import Card from '..';
7
7
  export default {
8
8
  component: Card,
9
9
  title: 'Layouts/Card/Tests',
10
- tags: ['!autodocs', '!manifest'],
10
+ tags: ['!autodocs', '!manifest', 'deprecated'],
11
11
  } satisfies Meta<typeof Card>;
12
12
 
13
13
  type Story = StoryObj<typeof Card>;
@@ -7,7 +7,7 @@ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator'
7
7
  export default {
8
8
  component: CriticalCommsBanner,
9
9
  title: 'Prompts/CriticalCommsBanner/Tests',
10
- tags: ['!autodocs', 'deprecated'],
10
+ tags: ['!autodocs', 'deprecated', 'deprecated'],
11
11
  } satisfies Meta<typeof CriticalCommsBanner>;
12
12
 
13
13
  type Story = StoryObj<typeof CriticalCommsBanner>;
@@ -6,7 +6,7 @@ import InlineAlert from '..';
6
6
  export default {
7
7
  component: InlineAlert,
8
8
  title: 'Prompts/InlineAlert/Tests',
9
- tags: ['!autodocs', '!manifest'],
9
+ tags: ['!autodocs', '!manifest', 'deprecated'],
10
10
  } satisfies Meta<typeof InlineAlert>;
11
11
 
12
12
  type Story = StoryObj<typeof InlineAlert>;
@@ -9,7 +9,7 @@ import OverlayHeader from '..';
9
9
  export default {
10
10
  component: OverlayHeader,
11
11
  title: 'Navigation/OverlayHeader/Tests',
12
- tags: ['!autodocs', '!manifest'],
12
+ tags: ['!autodocs', '!manifest', 'deprecated'],
13
13
  } satisfies Meta<typeof OverlayHeader>;
14
14
 
15
15
  type Story = StoryObj<typeof OverlayHeader>;
@@ -152,11 +152,40 @@
152
152
  letter-spacing: -0.006em;
153
153
  font-weight: 400;
154
154
  font-weight: var(--font-weight-regular);
155
+ word-wrap: break-word;
155
156
  }
156
157
  .np-theme-personal .np-dropdown-menu > li > a {
157
158
  border-radius: 10px;
158
159
  border-radius: var(--radius-small);
159
160
  }
161
+ @supports (hyphenate-limit-chars: 1) {
162
+ .np-dropdown-menu > li > a {
163
+ hyphens: auto;
164
+ hyphenate-limit-chars: 7 3;
165
+ }
166
+ @media (min-width: 840px) {
167
+ .np-dropdown-menu > li > a {
168
+ hyphenate-limit-chars: 8 3;
169
+ }
170
+ }
171
+ @media (min-width: 1160px) {
172
+ .np-dropdown-menu > li > a {
173
+ hyphenate-limit-chars: 10 4 3;
174
+ }
175
+ }
176
+ }
177
+ @supports (not (hyphenate-limit-chars: 1)) and (-webkit-hyphenate-limit-before: 1) {
178
+ .np-dropdown-menu > li > a {
179
+ hyphens: auto;
180
+ -webkit-hyphenate-limit-before: 3;
181
+ -webkit-hyphenate-limit-after: 3;
182
+ }
183
+ @media (min-width: 1160px) {
184
+ .np-dropdown-menu > li > a {
185
+ -webkit-hyphenate-limit-before: 4;
186
+ }
187
+ }
188
+ }
160
189
  .np-dropdown-menu > li:first-child > a {
161
190
  border-start-end-radius: 3px;
162
191
  border-start-start-radius: 3px;
@@ -8,7 +8,7 @@ import Select from '..';
8
8
  export default {
9
9
  component: Select,
10
10
  title: 'Forms/Select/Tests/RTL Diff',
11
- tags: ['!autodocs', '!manifest'],
11
+ tags: ['!autodocs', '!manifest', 'deprecated'],
12
12
  } satisfies Meta<typeof Select>;
13
13
 
14
14
  type Story = StoryObj<typeof Select>;
@@ -8,7 +8,7 @@ import Select, { SelectOptionItem } from '../Select';
8
8
  const meta = {
9
9
  title: 'Forms/Select/Tests',
10
10
  component: Select,
11
- tags: ['!autodocs', '!manifest'],
11
+ tags: ['!autodocs', '!manifest', 'deprecated'],
12
12
  } satisfies Meta<typeof Select>;
13
13
  export default meta;
14
14