@transferwise/components 0.0.0-experimental-b6c01fd → 0.0.0-experimental-75915af
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/build/main.css +42 -4
- package/build/statusIcon/StatusIcon.js +1 -12
- package/build/statusIcon/StatusIcon.js.map +1 -1
- package/build/statusIcon/StatusIcon.mjs +1 -12
- package/build/statusIcon/StatusIcon.mjs.map +1 -1
- package/build/styles/main.css +42 -4
- package/build/styles/statusIcon/StatusIcon.css +35 -4
- package/build/types/statusIcon/StatusIcon.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/main.css +42 -4
- package/src/statusIcon/StatusIcon.css +35 -4
- package/src/statusIcon/StatusIcon.less +35 -4
- package/src/statusIcon/StatusIcon.story.tsx +119 -79
- package/src/statusIcon/StatusIcon.test.story.tsx +132 -0
- package/src/statusIcon/StatusIcon.test.tsx +17 -24
- package/src/statusIcon/StatusIcon.tsx +2 -16
package/build/main.css
CHANGED
|
@@ -32413,12 +32413,50 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
32413
32413
|
}
|
|
32414
32414
|
}
|
|
32415
32415
|
|
|
32416
|
-
.
|
|
32417
|
-
|
|
32416
|
+
.status-circle.negative,
|
|
32417
|
+
.status-circle.error {
|
|
32418
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-negative));
|
|
32418
32419
|
}
|
|
32419
32420
|
|
|
32420
|
-
.
|
|
32421
|
-
|
|
32421
|
+
.status-circle.negative .status-icon,
|
|
32422
|
+
.status-circle.error .status-icon {
|
|
32423
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-negative-secondary));
|
|
32424
|
+
}
|
|
32425
|
+
|
|
32426
|
+
.status-circle.positive,
|
|
32427
|
+
.status-circle.success {
|
|
32428
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-positive));
|
|
32429
|
+
}
|
|
32430
|
+
|
|
32431
|
+
.status-circle.positive .status-icon,
|
|
32432
|
+
.status-circle.success .status-icon {
|
|
32433
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-positive-secondary));
|
|
32434
|
+
}
|
|
32435
|
+
|
|
32436
|
+
.status-circle.warning,
|
|
32437
|
+
.status-circle.pending {
|
|
32438
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-warning));
|
|
32439
|
+
}
|
|
32440
|
+
|
|
32441
|
+
.status-circle.warning .status-icon,
|
|
32442
|
+
.status-circle.pending .status-icon {
|
|
32443
|
+
color: var(--color-sentiment-interactive-control, var(--color-dark));
|
|
32444
|
+
}
|
|
32445
|
+
|
|
32446
|
+
.status-circle.neutral,
|
|
32447
|
+
.status-circle.info {
|
|
32448
|
+
background-color: #5d7079;
|
|
32449
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-content-secondary));
|
|
32450
|
+
}
|
|
32451
|
+
|
|
32452
|
+
.status-circle.neutral .status-icon,
|
|
32453
|
+
.status-circle.info .status-icon {
|
|
32454
|
+
color: var(--color-sentiment-interactive-control, var(--color-contrast-overlay));
|
|
32455
|
+
}
|
|
32456
|
+
|
|
32457
|
+
.np-theme-personal--bright-green .status-circle.neutral .status-icon,
|
|
32458
|
+
.np-theme-personal--bright-green .status-circle.info .status-icon {
|
|
32459
|
+
color: var(--color-sentiment-interactive-control, var(--color-white));
|
|
32422
32460
|
}
|
|
32423
32461
|
|
|
32424
32462
|
.tw-stepper {
|
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var icons = require('@transferwise/icons');
|
|
6
6
|
var clsx = require('clsx');
|
|
7
7
|
var reactIntl = require('react-intl');
|
|
8
|
-
var SentimentSurface = require('../sentimentSurface/SentimentSurface.js');
|
|
9
8
|
require('../common/theme.js');
|
|
10
9
|
require('../common/direction.js');
|
|
11
10
|
require('../common/propsValues/control.js');
|
|
@@ -83,25 +82,15 @@ const StatusIcon = ({
|
|
|
83
82
|
Icon,
|
|
84
83
|
defaultIconLabel
|
|
85
84
|
} = iconMetaBySentiment[sentiment$1];
|
|
86
|
-
const iconColor = sentiment$1 === 'warning' || sentiment$1 === 'pending' ? 'dark' : 'light';
|
|
87
85
|
const isTinyViewport = useMedia.useMedia(`(max-width: ${breakpoint.Breakpoint.ZOOM_400}px)`);
|
|
88
86
|
const size = mapLegacySize[sizeProp] ?? sizeProp;
|
|
89
|
-
// eslint-disable-next-line react/no-unstable-nested-components
|
|
90
|
-
const SentimentSurfaceSetting = props => /*#__PURE__*/jsxRuntime.jsx(SentimentSurface.default, {
|
|
91
|
-
as: "span"
|
|
92
|
-
// @ts-expect-error sentiment and SentimentSurface types mismatch
|
|
93
|
-
,
|
|
94
|
-
sentiment: sentiment$1 === 'positive' ? 'success' : sentiment$1 === 'pending' ? 'warning' : sentiment$1,
|
|
95
|
-
...props
|
|
96
|
-
});
|
|
97
87
|
return /*#__PURE__*/jsxRuntime.jsx(Circle.default, {
|
|
98
|
-
as: SentimentSurfaceSetting,
|
|
99
88
|
size: isTinyViewport && size < 40 ? 32 : size,
|
|
100
89
|
"data-testid": "status-icon",
|
|
101
90
|
className: clsx.clsx('status-circle', sentiment$1),
|
|
102
91
|
id: id,
|
|
103
92
|
children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
|
|
104
|
-
className:
|
|
93
|
+
className: "status-icon",
|
|
105
94
|
title: iconLabel === null ? undefined : iconLabel || defaultIconLabel
|
|
106
95
|
})
|
|
107
96
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusIcon.js","sources":["../../src/statusIcon/StatusIcon.tsx"],"sourcesContent":["import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { useIntl } from 'react-intl';\
|
|
1
|
+
{"version":3,"file":"StatusIcon.js","sources":["../../src/statusIcon/StatusIcon.tsx"],"sourcesContent":["import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { useIntl } from 'react-intl';\n\nimport { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size, Breakpoint, Status } from '../common';\nimport Circle, { CircleProps } from '../common/circle';\nimport { useMedia } from '../common/hooks/useMedia';\n\nimport messages from './StatusIcon.messages';\n\n/**\n * @deprecated Use `16 | 24 | 32 | 40 | 48 | 56 | 72` instead.\n */\ntype LegacySizes = SizeSmall | SizeMedium | SizeLarge;\n\nexport type StatusIconSentiment = Sentiment | Status.PENDING;\n\nexport type StatusIconProps = {\n id?: string;\n /** @default 'neutral' */\n sentiment?: `${StatusIconSentiment}`;\n /** @default 40 */\n size?: LegacySizes | 16 | 24 | 32 | 40 | 48 | 56 | 72;\n /**\n * Override for the sentiment's-derived, default, accessible\n * name announced by the screen readers. <br />\n * Using `null` will render the icon purely presentational.\n * */\n iconLabel?: string | null;\n};\n\nconst mapLegacySize = {\n [String(Size.SMALL)]: 16,\n [String(Size.MEDIUM)]: 40,\n [String(Size.LARGE)]: 48,\n} satisfies Record<string, CircleProps['size']>;\n\nconst StatusIcon = ({\n id,\n sentiment = 'neutral',\n size: sizeProp = 40,\n iconLabel,\n}: StatusIconProps) => {\n const intl = useIntl();\n\n const iconMetaBySentiment: Record<\n `${Sentiment}` | Status.PENDING,\n {\n Icon: React.ElementType;\n defaultIconLabel: string;\n }\n > = {\n [Sentiment.NEGATIVE]: {\n Icon: Cross,\n defaultIconLabel: intl.formatMessage(messages.errorLabel),\n },\n [Sentiment.POSITIVE]: {\n Icon: Check,\n defaultIconLabel: intl.formatMessage(messages.successLabel),\n },\n [Sentiment.WARNING]: {\n Icon: Alert,\n defaultIconLabel: intl.formatMessage(messages.warningLabel),\n },\n [Status.PENDING]: {\n Icon: ClockBorderless,\n defaultIconLabel: intl.formatMessage(messages.pendingLabel),\n },\n [Sentiment.NEUTRAL]: {\n Icon: Info,\n defaultIconLabel: intl.formatMessage(messages.informationLabel),\n },\n // deprecated\n [Sentiment.ERROR]: {\n Icon: Cross,\n defaultIconLabel: intl.formatMessage(messages.errorLabel),\n },\n [Sentiment.INFO]: {\n Icon: Info,\n defaultIconLabel: intl.formatMessage(messages.informationLabel),\n },\n [Sentiment.SUCCESS]: {\n Icon: Check,\n defaultIconLabel: intl.formatMessage(messages.successLabel),\n },\n };\n const { Icon, defaultIconLabel } = iconMetaBySentiment[sentiment];\n\n const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);\n const size = mapLegacySize[sizeProp] ?? sizeProp;\n\n return (\n <Circle\n size={isTinyViewport && size < 40 ? 32 : size}\n data-testid=\"status-icon\"\n className={clsx('status-circle', sentiment)}\n id={id}\n >\n <Icon\n className=\"status-icon\"\n title={iconLabel === null ? undefined : iconLabel || defaultIconLabel}\n />\n </Circle>\n );\n};\n\nexport default StatusIcon;\n"],"names":["mapLegacySize","String","Size","SMALL","MEDIUM","LARGE","StatusIcon","id","sentiment","size","sizeProp","iconLabel","intl","useIntl","iconMetaBySentiment","Sentiment","NEGATIVE","Icon","Cross","defaultIconLabel","formatMessage","messages","errorLabel","POSITIVE","Check","successLabel","WARNING","Alert","warningLabel","Status","PENDING","ClockBorderless","pendingLabel","NEUTRAL","Info","informationLabel","ERROR","INFO","SUCCESS","isTinyViewport","useMedia","Breakpoint","ZOOM_400","_jsx","Circle","className","clsx","children","title","undefined"],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Check, Info, Cross, ClockBorderless, Alert } from '@transferwise/icons';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
|
-
import SentimentSurface from '../sentimentSurface/SentimentSurface.mjs';
|
|
5
4
|
import '../common/theme.mjs';
|
|
6
5
|
import '../common/direction.mjs';
|
|
7
6
|
import '../common/propsValues/control.mjs';
|
|
@@ -79,25 +78,15 @@ const StatusIcon = ({
|
|
|
79
78
|
Icon,
|
|
80
79
|
defaultIconLabel
|
|
81
80
|
} = iconMetaBySentiment[sentiment];
|
|
82
|
-
const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
|
|
83
81
|
const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);
|
|
84
82
|
const size = mapLegacySize[sizeProp] ?? sizeProp;
|
|
85
|
-
// eslint-disable-next-line react/no-unstable-nested-components
|
|
86
|
-
const SentimentSurfaceSetting = props => /*#__PURE__*/jsx(SentimentSurface, {
|
|
87
|
-
as: "span"
|
|
88
|
-
// @ts-expect-error sentiment and SentimentSurface types mismatch
|
|
89
|
-
,
|
|
90
|
-
sentiment: sentiment === 'positive' ? 'success' : sentiment === 'pending' ? 'warning' : sentiment,
|
|
91
|
-
...props
|
|
92
|
-
});
|
|
93
83
|
return /*#__PURE__*/jsx(Circle, {
|
|
94
|
-
as: SentimentSurfaceSetting,
|
|
95
84
|
size: isTinyViewport && size < 40 ? 32 : size,
|
|
96
85
|
"data-testid": "status-icon",
|
|
97
86
|
className: clsx('status-circle', sentiment),
|
|
98
87
|
id: id,
|
|
99
88
|
children: /*#__PURE__*/jsx(Icon, {
|
|
100
|
-
className:
|
|
89
|
+
className: "status-icon",
|
|
101
90
|
title: iconLabel === null ? undefined : iconLabel || defaultIconLabel
|
|
102
91
|
})
|
|
103
92
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusIcon.mjs","sources":["../../src/statusIcon/StatusIcon.tsx"],"sourcesContent":["import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { useIntl } from 'react-intl';\
|
|
1
|
+
{"version":3,"file":"StatusIcon.mjs","sources":["../../src/statusIcon/StatusIcon.tsx"],"sourcesContent":["import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { useIntl } from 'react-intl';\n\nimport { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size, Breakpoint, Status } from '../common';\nimport Circle, { CircleProps } from '../common/circle';\nimport { useMedia } from '../common/hooks/useMedia';\n\nimport messages from './StatusIcon.messages';\n\n/**\n * @deprecated Use `16 | 24 | 32 | 40 | 48 | 56 | 72` instead.\n */\ntype LegacySizes = SizeSmall | SizeMedium | SizeLarge;\n\nexport type StatusIconSentiment = Sentiment | Status.PENDING;\n\nexport type StatusIconProps = {\n id?: string;\n /** @default 'neutral' */\n sentiment?: `${StatusIconSentiment}`;\n /** @default 40 */\n size?: LegacySizes | 16 | 24 | 32 | 40 | 48 | 56 | 72;\n /**\n * Override for the sentiment's-derived, default, accessible\n * name announced by the screen readers. <br />\n * Using `null` will render the icon purely presentational.\n * */\n iconLabel?: string | null;\n};\n\nconst mapLegacySize = {\n [String(Size.SMALL)]: 16,\n [String(Size.MEDIUM)]: 40,\n [String(Size.LARGE)]: 48,\n} satisfies Record<string, CircleProps['size']>;\n\nconst StatusIcon = ({\n id,\n sentiment = 'neutral',\n size: sizeProp = 40,\n iconLabel,\n}: StatusIconProps) => {\n const intl = useIntl();\n\n const iconMetaBySentiment: Record<\n `${Sentiment}` | Status.PENDING,\n {\n Icon: React.ElementType;\n defaultIconLabel: string;\n }\n > = {\n [Sentiment.NEGATIVE]: {\n Icon: Cross,\n defaultIconLabel: intl.formatMessage(messages.errorLabel),\n },\n [Sentiment.POSITIVE]: {\n Icon: Check,\n defaultIconLabel: intl.formatMessage(messages.successLabel),\n },\n [Sentiment.WARNING]: {\n Icon: Alert,\n defaultIconLabel: intl.formatMessage(messages.warningLabel),\n },\n [Status.PENDING]: {\n Icon: ClockBorderless,\n defaultIconLabel: intl.formatMessage(messages.pendingLabel),\n },\n [Sentiment.NEUTRAL]: {\n Icon: Info,\n defaultIconLabel: intl.formatMessage(messages.informationLabel),\n },\n // deprecated\n [Sentiment.ERROR]: {\n Icon: Cross,\n defaultIconLabel: intl.formatMessage(messages.errorLabel),\n },\n [Sentiment.INFO]: {\n Icon: Info,\n defaultIconLabel: intl.formatMessage(messages.informationLabel),\n },\n [Sentiment.SUCCESS]: {\n Icon: Check,\n defaultIconLabel: intl.formatMessage(messages.successLabel),\n },\n };\n const { Icon, defaultIconLabel } = iconMetaBySentiment[sentiment];\n\n const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);\n const size = mapLegacySize[sizeProp] ?? sizeProp;\n\n return (\n <Circle\n size={isTinyViewport && size < 40 ? 32 : size}\n data-testid=\"status-icon\"\n className={clsx('status-circle', sentiment)}\n id={id}\n >\n <Icon\n className=\"status-icon\"\n title={iconLabel === null ? undefined : iconLabel || defaultIconLabel}\n />\n </Circle>\n );\n};\n\nexport default StatusIcon;\n"],"names":["mapLegacySize","String","Size","SMALL","MEDIUM","LARGE","StatusIcon","id","sentiment","size","sizeProp","iconLabel","intl","useIntl","iconMetaBySentiment","Sentiment","NEGATIVE","Icon","Cross","defaultIconLabel","formatMessage","messages","errorLabel","POSITIVE","Check","successLabel","WARNING","Alert","warningLabel","Status","PENDING","ClockBorderless","pendingLabel","NEUTRAL","Info","informationLabel","ERROR","INFO","SUCCESS","isTinyViewport","useMedia","Breakpoint","ZOOM_400","_jsx","Circle","className","clsx","children","title","undefined"],"mappings":"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"}
|
package/build/styles/main.css
CHANGED
|
@@ -32413,12 +32413,50 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
32413
32413
|
}
|
|
32414
32414
|
}
|
|
32415
32415
|
|
|
32416
|
-
.
|
|
32417
|
-
|
|
32416
|
+
.status-circle.negative,
|
|
32417
|
+
.status-circle.error {
|
|
32418
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-negative));
|
|
32418
32419
|
}
|
|
32419
32420
|
|
|
32420
|
-
.
|
|
32421
|
-
|
|
32421
|
+
.status-circle.negative .status-icon,
|
|
32422
|
+
.status-circle.error .status-icon {
|
|
32423
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-negative-secondary));
|
|
32424
|
+
}
|
|
32425
|
+
|
|
32426
|
+
.status-circle.positive,
|
|
32427
|
+
.status-circle.success {
|
|
32428
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-positive));
|
|
32429
|
+
}
|
|
32430
|
+
|
|
32431
|
+
.status-circle.positive .status-icon,
|
|
32432
|
+
.status-circle.success .status-icon {
|
|
32433
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-positive-secondary));
|
|
32434
|
+
}
|
|
32435
|
+
|
|
32436
|
+
.status-circle.warning,
|
|
32437
|
+
.status-circle.pending {
|
|
32438
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-warning));
|
|
32439
|
+
}
|
|
32440
|
+
|
|
32441
|
+
.status-circle.warning .status-icon,
|
|
32442
|
+
.status-circle.pending .status-icon {
|
|
32443
|
+
color: var(--color-sentiment-interactive-control, var(--color-dark));
|
|
32444
|
+
}
|
|
32445
|
+
|
|
32446
|
+
.status-circle.neutral,
|
|
32447
|
+
.status-circle.info {
|
|
32448
|
+
background-color: #5d7079;
|
|
32449
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-content-secondary));
|
|
32450
|
+
}
|
|
32451
|
+
|
|
32452
|
+
.status-circle.neutral .status-icon,
|
|
32453
|
+
.status-circle.info .status-icon {
|
|
32454
|
+
color: var(--color-sentiment-interactive-control, var(--color-contrast-overlay));
|
|
32455
|
+
}
|
|
32456
|
+
|
|
32457
|
+
.np-theme-personal--bright-green .status-circle.neutral .status-icon,
|
|
32458
|
+
.np-theme-personal--bright-green .status-circle.info .status-icon {
|
|
32459
|
+
color: var(--color-sentiment-interactive-control, var(--color-white));
|
|
32422
32460
|
}
|
|
32423
32461
|
|
|
32424
32462
|
.tw-stepper {
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
.
|
|
2
|
-
|
|
1
|
+
.status-circle.negative,
|
|
2
|
+
.status-circle.error {
|
|
3
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-negative));
|
|
3
4
|
}
|
|
4
|
-
.
|
|
5
|
-
|
|
5
|
+
.status-circle.negative .status-icon,
|
|
6
|
+
.status-circle.error .status-icon {
|
|
7
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-negative-secondary));
|
|
8
|
+
}
|
|
9
|
+
.status-circle.positive,
|
|
10
|
+
.status-circle.success {
|
|
11
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-positive));
|
|
12
|
+
}
|
|
13
|
+
.status-circle.positive .status-icon,
|
|
14
|
+
.status-circle.success .status-icon {
|
|
15
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-positive-secondary));
|
|
16
|
+
}
|
|
17
|
+
.status-circle.warning,
|
|
18
|
+
.status-circle.pending {
|
|
19
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-warning));
|
|
20
|
+
}
|
|
21
|
+
.status-circle.warning .status-icon,
|
|
22
|
+
.status-circle.pending .status-icon {
|
|
23
|
+
color: var(--color-sentiment-interactive-control, var(--color-dark));
|
|
24
|
+
}
|
|
25
|
+
.status-circle.neutral,
|
|
26
|
+
.status-circle.info {
|
|
27
|
+
background-color: #5d7079;
|
|
28
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-content-secondary));
|
|
29
|
+
}
|
|
30
|
+
.status-circle.neutral .status-icon,
|
|
31
|
+
.status-circle.info .status-icon {
|
|
32
|
+
color: var(--color-sentiment-interactive-control, var(--color-contrast-overlay));
|
|
33
|
+
}
|
|
34
|
+
.np-theme-personal--bright-green .status-circle.neutral .status-icon,
|
|
35
|
+
.np-theme-personal--bright-green .status-circle.info .status-icon {
|
|
36
|
+
color: var(--color-sentiment-interactive-control, var(--color-white));
|
|
6
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusIcon.d.ts","sourceRoot":"","sources":["../../../src/statusIcon/StatusIcon.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StatusIcon.d.ts","sourceRoot":"","sources":["../../../src/statusIcon/StatusIcon.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAoB,MAAM,EAAE,MAAM,WAAW,CAAC;AAMlG;;GAEG;AACH,KAAK,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,SAAS,CAAC,EAAE,GAAG,mBAAmB,EAAE,CAAC;IACrC,kBAAkB;IAClB,IAAI,CAAC,EAAE,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACtD;;;;SAIK;IACL,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAQF,QAAA,MAAM,UAAU,GAAI,+CAKjB,eAAe,gCA8DjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
package/package.json
CHANGED
package/src/main.css
CHANGED
|
@@ -32413,12 +32413,50 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
32413
32413
|
}
|
|
32414
32414
|
}
|
|
32415
32415
|
|
|
32416
|
-
.
|
|
32417
|
-
|
|
32416
|
+
.status-circle.negative,
|
|
32417
|
+
.status-circle.error {
|
|
32418
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-negative));
|
|
32418
32419
|
}
|
|
32419
32420
|
|
|
32420
|
-
.
|
|
32421
|
-
|
|
32421
|
+
.status-circle.negative .status-icon,
|
|
32422
|
+
.status-circle.error .status-icon {
|
|
32423
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-negative-secondary));
|
|
32424
|
+
}
|
|
32425
|
+
|
|
32426
|
+
.status-circle.positive,
|
|
32427
|
+
.status-circle.success {
|
|
32428
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-positive));
|
|
32429
|
+
}
|
|
32430
|
+
|
|
32431
|
+
.status-circle.positive .status-icon,
|
|
32432
|
+
.status-circle.success .status-icon {
|
|
32433
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-positive-secondary));
|
|
32434
|
+
}
|
|
32435
|
+
|
|
32436
|
+
.status-circle.warning,
|
|
32437
|
+
.status-circle.pending {
|
|
32438
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-warning));
|
|
32439
|
+
}
|
|
32440
|
+
|
|
32441
|
+
.status-circle.warning .status-icon,
|
|
32442
|
+
.status-circle.pending .status-icon {
|
|
32443
|
+
color: var(--color-sentiment-interactive-control, var(--color-dark));
|
|
32444
|
+
}
|
|
32445
|
+
|
|
32446
|
+
.status-circle.neutral,
|
|
32447
|
+
.status-circle.info {
|
|
32448
|
+
background-color: #5d7079;
|
|
32449
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-content-secondary));
|
|
32450
|
+
}
|
|
32451
|
+
|
|
32452
|
+
.status-circle.neutral .status-icon,
|
|
32453
|
+
.status-circle.info .status-icon {
|
|
32454
|
+
color: var(--color-sentiment-interactive-control, var(--color-contrast-overlay));
|
|
32455
|
+
}
|
|
32456
|
+
|
|
32457
|
+
.np-theme-personal--bright-green .status-circle.neutral .status-icon,
|
|
32458
|
+
.np-theme-personal--bright-green .status-circle.info .status-icon {
|
|
32459
|
+
color: var(--color-sentiment-interactive-control, var(--color-white));
|
|
32422
32460
|
}
|
|
32423
32461
|
|
|
32424
32462
|
.tw-stepper {
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
.
|
|
2
|
-
|
|
1
|
+
.status-circle.negative,
|
|
2
|
+
.status-circle.error {
|
|
3
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-negative));
|
|
3
4
|
}
|
|
4
|
-
.
|
|
5
|
-
|
|
5
|
+
.status-circle.negative .status-icon,
|
|
6
|
+
.status-circle.error .status-icon {
|
|
7
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-negative-secondary));
|
|
8
|
+
}
|
|
9
|
+
.status-circle.positive,
|
|
10
|
+
.status-circle.success {
|
|
11
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-positive));
|
|
12
|
+
}
|
|
13
|
+
.status-circle.positive .status-icon,
|
|
14
|
+
.status-circle.success .status-icon {
|
|
15
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-positive-secondary));
|
|
16
|
+
}
|
|
17
|
+
.status-circle.warning,
|
|
18
|
+
.status-circle.pending {
|
|
19
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-warning));
|
|
20
|
+
}
|
|
21
|
+
.status-circle.warning .status-icon,
|
|
22
|
+
.status-circle.pending .status-icon {
|
|
23
|
+
color: var(--color-sentiment-interactive-control, var(--color-dark));
|
|
24
|
+
}
|
|
25
|
+
.status-circle.neutral,
|
|
26
|
+
.status-circle.info {
|
|
27
|
+
background-color: #5d7079;
|
|
28
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-content-secondary));
|
|
29
|
+
}
|
|
30
|
+
.status-circle.neutral .status-icon,
|
|
31
|
+
.status-circle.info .status-icon {
|
|
32
|
+
color: var(--color-sentiment-interactive-control, var(--color-contrast-overlay));
|
|
33
|
+
}
|
|
34
|
+
.np-theme-personal--bright-green .status-circle.neutral .status-icon,
|
|
35
|
+
.np-theme-personal--bright-green .status-circle.info .status-icon {
|
|
36
|
+
color: var(--color-sentiment-interactive-control, var(--color-white));
|
|
6
37
|
}
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
color: var(--color-sentiment-interactive-
|
|
1
|
+
.status-circle {
|
|
2
|
+
&.negative,
|
|
3
|
+
&.error {
|
|
4
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-negative));
|
|
5
|
+
.status-icon {
|
|
6
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-negative-secondary));
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&.positive,
|
|
11
|
+
&.success {
|
|
12
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-positive));
|
|
13
|
+
.status-icon {
|
|
14
|
+
color: var(--color-sentiment-interactive-control, var(--color-sentiment-positive-secondary));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&.warning,
|
|
19
|
+
&.pending {
|
|
20
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-sentiment-warning));
|
|
21
|
+
.status-icon {
|
|
22
|
+
color: var(--color-sentiment-interactive-control, var(--color-dark));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.neutral,
|
|
27
|
+
&.info {
|
|
28
|
+
background-color: var(--color-sentiment-interactive-primary, var(--color-content-secondary));
|
|
29
|
+
.status-icon {
|
|
30
|
+
color: var(--color-sentiment-interactive-control, var(--color-contrast-overlay));
|
|
31
|
+
|
|
32
|
+
.np-theme-personal--bright-green & {
|
|
33
|
+
color: var(--color-sentiment-interactive-control, var(--color-white));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
5
36
|
}
|
|
6
37
|
}
|
|
@@ -1,102 +1,142 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
2
|
|
|
3
|
-
import { Sentiment
|
|
3
|
+
import { Sentiment } from '../common';
|
|
4
|
+
import SentimentSurface from '../sentimentSurface';
|
|
4
5
|
|
|
5
6
|
import StatusIcon, { StatusIconSentiment } from './StatusIcon';
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
const sentiments = [
|
|
9
|
+
Sentiment.POSITIVE,
|
|
10
|
+
Sentiment.NEGATIVE,
|
|
11
|
+
Sentiment.WARNING,
|
|
12
|
+
Sentiment.NEUTRAL,
|
|
13
|
+
Sentiment.PENDING,
|
|
14
|
+
] as const;
|
|
15
|
+
|
|
16
|
+
const sizes = [16, 24, 32, 40, 48, 56, 72] as const;
|
|
17
|
+
|
|
18
|
+
const label: Record<string, string> = {
|
|
19
|
+
positive: 'Positive',
|
|
20
|
+
negative: 'Negative',
|
|
21
|
+
warning: 'Warning',
|
|
22
|
+
neutral: 'Neutral',
|
|
23
|
+
pending: 'Pending',
|
|
24
|
+
};
|
|
7
25
|
|
|
8
26
|
export default {
|
|
9
27
|
component: StatusIcon,
|
|
10
28
|
title: 'Other/StatusIcon',
|
|
11
|
-
|
|
12
|
-
argTypes: {
|
|
13
|
-
iconLabel: {
|
|
14
|
-
control: 'text',
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
29
|
} satisfies Meta<typeof StatusIcon>;
|
|
18
30
|
|
|
19
31
|
type Story = StoryObj<typeof StatusIcon>;
|
|
20
32
|
|
|
21
|
-
export const
|
|
33
|
+
export const Playground: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
size: 40,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
22
38
|
|
|
23
39
|
/**
|
|
24
|
-
*
|
|
40
|
+
* All available sentiments at the selected size.
|
|
25
41
|
*/
|
|
26
|
-
export const
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
export const Sentiments: Story = {
|
|
43
|
+
argTypes: {
|
|
44
|
+
sentiment: { table: { disable: true } },
|
|
29
45
|
},
|
|
46
|
+
render: ({ size }) => (
|
|
47
|
+
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
|
|
48
|
+
{sentiments.map((sentiment) => (
|
|
49
|
+
<div
|
|
50
|
+
key={sentiment}
|
|
51
|
+
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '4px' }}
|
|
52
|
+
>
|
|
53
|
+
<StatusIcon sentiment={sentiment as StatusIconSentiment} size={size} />
|
|
54
|
+
<span style={{ fontSize: '11px' }}>{label[sentiment]}</span>
|
|
55
|
+
</div>
|
|
56
|
+
))}
|
|
57
|
+
</div>
|
|
58
|
+
),
|
|
30
59
|
};
|
|
31
60
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
style={{
|
|
52
|
-
display: 'flex',
|
|
53
|
-
justifyContent: 'space-between',
|
|
54
|
-
flexDirection: 'column',
|
|
55
|
-
minHeight: '150px',
|
|
56
|
-
alignItems: 'center',
|
|
57
|
-
}}
|
|
58
|
-
>
|
|
59
|
-
{([16, 24, 32, 40, 48, 56, 72] as const).map((size) => {
|
|
60
|
-
return (
|
|
61
|
-
<StatusIcon key={size} size={size} sentiment={sentiment as StatusIconSentiment} />
|
|
62
|
-
);
|
|
63
|
-
})}
|
|
64
|
-
</span>
|
|
65
|
-
);
|
|
66
|
-
})}
|
|
67
|
-
</span>
|
|
61
|
+
/**
|
|
62
|
+
* All available sizes at the selected sentiment.
|
|
63
|
+
*/
|
|
64
|
+
export const Sizes: Story = {
|
|
65
|
+
argTypes: {
|
|
66
|
+
size: { table: { disable: true } },
|
|
67
|
+
},
|
|
68
|
+
render: ({ sentiment }) => (
|
|
69
|
+
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
|
|
70
|
+
{sizes.map((size) => (
|
|
71
|
+
<div
|
|
72
|
+
key={size}
|
|
73
|
+
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '4px' }}
|
|
74
|
+
>
|
|
75
|
+
<StatusIcon sentiment={sentiment} size={size} />
|
|
76
|
+
<span style={{ fontSize: '11px' }}>{size}</span>
|
|
77
|
+
</div>
|
|
78
|
+
))}
|
|
79
|
+
</div>
|
|
68
80
|
),
|
|
69
81
|
};
|
|
70
82
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}}
|
|
83
|
+
/**
|
|
84
|
+
* `StatusIcon` is sentiment-aware and will automatically adjust its colours when placed inside
|
|
85
|
+
* a [SentimentSurface](?path=/docs/foundations-sentimentsurface--docs) component — no extra
|
|
86
|
+
* props needed. Each row below is a `SentimentSurface` at either `base` or `elevated` emphasis (and a last row with no sentiment for refernce).
|
|
87
|
+
*/
|
|
88
|
+
export const SentimentAwareness: Story = {
|
|
89
|
+
argTypes: {
|
|
90
|
+
sentiment: { table: { disable: true } },
|
|
91
|
+
},
|
|
92
|
+
render: ({ size }) => {
|
|
93
|
+
const surfaceSentiments = ['success', 'warning', 'negative', 'neutral'] as const;
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
97
|
+
{surfaceSentiments.flatMap((sentiment) => [
|
|
98
|
+
<SentimentSurface
|
|
99
|
+
key={`${sentiment}-base`}
|
|
100
|
+
sentiment={sentiment}
|
|
101
|
+
emphasis="base"
|
|
102
|
+
style={{ display: 'flex', alignItems: 'center', padding: '8px', gap: '8px' }}
|
|
91
103
|
>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
<div
|
|
105
|
+
style={{ width: '120px', fontSize: '11px', fontWeight: 'bold', paddingLeft: '8px' }}
|
|
106
|
+
>
|
|
107
|
+
{sentiment} (base)
|
|
108
|
+
</div>
|
|
109
|
+
<StatusIcon sentiment={sentiment as StatusIconSentiment} size={size} />
|
|
110
|
+
</SentimentSurface>,
|
|
111
|
+
<SentimentSurface
|
|
112
|
+
key={`${sentiment}-elevated`}
|
|
113
|
+
sentiment={sentiment}
|
|
114
|
+
emphasis="elevated"
|
|
115
|
+
style={{ display: 'flex', alignItems: 'center', padding: '8px', gap: '8px' }}
|
|
116
|
+
>
|
|
117
|
+
<div
|
|
118
|
+
style={{ width: '120px', fontSize: '11px', fontWeight: 'bold', paddingLeft: '8px' }}
|
|
119
|
+
>
|
|
120
|
+
{sentiment} (elevated)
|
|
121
|
+
</div>
|
|
122
|
+
<StatusIcon sentiment={sentiment as StatusIconSentiment} size={size} />
|
|
123
|
+
</SentimentSurface>,
|
|
124
|
+
])}
|
|
125
|
+
|
|
126
|
+
{/* Row without a SentimentSurface wrapper */}
|
|
127
|
+
<div style={{ display: 'flex', alignItems: 'center', padding: '8px', gap: '8px' }}>
|
|
128
|
+
<div style={{ width: '120px', fontSize: '11px', fontWeight: 'bold', paddingLeft: '8px' }}>
|
|
129
|
+
none
|
|
130
|
+
</div>
|
|
131
|
+
<StatusIcon sentiment="pending" size={size} />
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
},
|
|
136
|
+
parameters: {
|
|
137
|
+
docs: {
|
|
138
|
+
source: { type: 'dynamic' },
|
|
139
|
+
canvas: { sourceState: 'hidden' },
|
|
140
|
+
},
|
|
141
|
+
},
|
|
102
142
|
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
+
|
|
3
|
+
import { Sentiment, Size } from '../common';
|
|
4
|
+
import SentimentSurface from '../sentimentSurface';
|
|
5
|
+
import { withVariantConfig } from '../../.storybook/helpers';
|
|
6
|
+
import { allModes } from '../../.storybook/modes';
|
|
7
|
+
|
|
8
|
+
import StatusIcon, { StatusIconSentiment } from './StatusIcon';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
title: 'Other/StatusIcon/Tests',
|
|
12
|
+
component: StatusIcon,
|
|
13
|
+
tags: ['!autodocs', '!manifest'],
|
|
14
|
+
} satisfies Meta<typeof StatusIcon>;
|
|
15
|
+
|
|
16
|
+
type Story = StoryObj<typeof StatusIcon>;
|
|
17
|
+
|
|
18
|
+
const sizes = [16, 24, 32, 40, 48, 56, 72] as const;
|
|
19
|
+
|
|
20
|
+
const surfaceSentiments = ['success', 'warning', 'negative', 'neutral'] as const;
|
|
21
|
+
|
|
22
|
+
// Cycle through different sentiments per size so each row shows varied icons
|
|
23
|
+
const iconSentiments: StatusIconSentiment[] = [
|
|
24
|
+
Sentiment.POSITIVE,
|
|
25
|
+
Sentiment.NEGATIVE,
|
|
26
|
+
Sentiment.WARNING,
|
|
27
|
+
Sentiment.NEUTRAL,
|
|
28
|
+
Sentiment.PENDING,
|
|
29
|
+
Sentiment.POSITIVE,
|
|
30
|
+
Sentiment.NEGATIVE,
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const rowStyle = {
|
|
34
|
+
display: 'flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
padding: '8px',
|
|
37
|
+
gap: '8px',
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
const labelStyle = {
|
|
41
|
+
width: '120px',
|
|
42
|
+
fontSize: '11px',
|
|
43
|
+
fontWeight: 'bold',
|
|
44
|
+
paddingLeft: '8px',
|
|
45
|
+
flexShrink: 0,
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* All sentiments, emphasis levels, and sizes across all themes for visual regression testing.
|
|
50
|
+
*/
|
|
51
|
+
export const Variants: Story = {
|
|
52
|
+
render: () => (
|
|
53
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
54
|
+
{surfaceSentiments.flatMap((sentiment) => [
|
|
55
|
+
<SentimentSurface
|
|
56
|
+
key={`${sentiment}-base`}
|
|
57
|
+
sentiment={sentiment}
|
|
58
|
+
emphasis="base"
|
|
59
|
+
style={rowStyle}
|
|
60
|
+
>
|
|
61
|
+
<div style={labelStyle}>{sentiment} (base)</div>
|
|
62
|
+
{sizes.map((size, i) => (
|
|
63
|
+
<StatusIcon key={size} sentiment={iconSentiments[i]} size={size} />
|
|
64
|
+
))}
|
|
65
|
+
</SentimentSurface>,
|
|
66
|
+
<SentimentSurface
|
|
67
|
+
key={`${sentiment}-elevated`}
|
|
68
|
+
sentiment={sentiment}
|
|
69
|
+
emphasis="elevated"
|
|
70
|
+
style={rowStyle}
|
|
71
|
+
>
|
|
72
|
+
<div style={labelStyle}>{sentiment} (elevated)</div>
|
|
73
|
+
{sizes.map((size, i) => (
|
|
74
|
+
<StatusIcon key={size} sentiment={iconSentiments[i]} size={size} />
|
|
75
|
+
))}
|
|
76
|
+
</SentimentSurface>,
|
|
77
|
+
])}
|
|
78
|
+
|
|
79
|
+
{/* Row without a SentimentSurface wrapper — standalone fallback colours */}
|
|
80
|
+
<div style={rowStyle}>
|
|
81
|
+
<div style={labelStyle}>none</div>
|
|
82
|
+
{sizes.map((size, i) => (
|
|
83
|
+
<StatusIcon key={size} sentiment={iconSentiments[i]} size={size} />
|
|
84
|
+
))}
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
),
|
|
88
|
+
parameters: {
|
|
89
|
+
padding: '16px',
|
|
90
|
+
variants: ['default', 'dark', 'bright-green', 'forest-green'],
|
|
91
|
+
chromatic: {
|
|
92
|
+
modes: {
|
|
93
|
+
dark: allModes.dark,
|
|
94
|
+
brightGreen: allModes.brightGreen,
|
|
95
|
+
forestGreen: allModes.forestGreen,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const RTL: Story = {
|
|
102
|
+
render: Variants.render,
|
|
103
|
+
...withVariantConfig(['rtl']),
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @deprecated Legacy `Size.SMALL | Size.MEDIUM | Size.LARGE` values still work but
|
|
108
|
+
* consumers should migrate to numeric sizes.
|
|
109
|
+
*/
|
|
110
|
+
export const LegacySizes: Story = {
|
|
111
|
+
render: () => {
|
|
112
|
+
const legacySizes = [
|
|
113
|
+
{ value: Size.SMALL, label: 'Size.SMALL' },
|
|
114
|
+
{ value: Size.MEDIUM, label: 'Size.MEDIUM' },
|
|
115
|
+
{ value: Size.LARGE, label: 'Size.LARGE' },
|
|
116
|
+
] as const;
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
|
|
120
|
+
{legacySizes.map(({ value, label }) => (
|
|
121
|
+
<div
|
|
122
|
+
key={label}
|
|
123
|
+
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '4px' }}
|
|
124
|
+
>
|
|
125
|
+
<StatusIcon size={value} />
|
|
126
|
+
<span style={{ fontSize: '11px' }}>{label}</span>
|
|
127
|
+
</div>
|
|
128
|
+
))}
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -43,31 +43,24 @@ describe('StatusIcon', () => {
|
|
|
43
43
|
},
|
|
44
44
|
);
|
|
45
45
|
|
|
46
|
-
it(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("'positive', 'negative', and 'neutral' sentiments generate 'light' colored icons", () => {
|
|
60
|
-
renderStatusIcon({ sentiment: Sentiment.POSITIVE });
|
|
61
|
-
expect(screen.getByTestId('check-icon')).toHaveClass('light');
|
|
62
|
-
cleanup();
|
|
63
|
-
|
|
64
|
-
renderStatusIcon({ sentiment: Sentiment.NEGATIVE });
|
|
65
|
-
expect(screen.getByTestId('cross-icon')).toHaveClass('light');
|
|
66
|
-
cleanup();
|
|
46
|
+
it.each([
|
|
47
|
+
[Sentiment.WARNING, 'alert-icon'],
|
|
48
|
+
[Sentiment.PENDING, 'clock-borderless-icon'],
|
|
49
|
+
[Status.PENDING, 'clock-borderless-icon'],
|
|
50
|
+
[Sentiment.POSITIVE, 'check-icon'],
|
|
51
|
+
[Sentiment.NEGATIVE, 'cross-icon'],
|
|
52
|
+
[Sentiment.NEUTRAL, 'info-icon'],
|
|
53
|
+
])(
|
|
54
|
+
"renders the correct icon for '%s' sentiment",
|
|
55
|
+
(sentiment: Sentiment | Status, expectedIconTestId: string) => {
|
|
56
|
+
renderStatusIcon({ sentiment: sentiment as StatusIconSentiment });
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
const icon = screen.getByTestId(expectedIconTestId);
|
|
59
|
+
expect(icon).toBeInTheDocument();
|
|
60
|
+
expect(icon).toHaveClass('status-icon');
|
|
61
|
+
cleanup();
|
|
62
|
+
},
|
|
63
|
+
);
|
|
71
64
|
|
|
72
65
|
describe('accessible name', () => {
|
|
73
66
|
it.each([
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
|
-
import { PropsWithChildren } from 'react';
|
|
5
4
|
|
|
6
|
-
import SentimentSurface from '../sentimentSurface';
|
|
7
5
|
import { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size, Breakpoint, Status } from '../common';
|
|
8
6
|
import Circle, { CircleProps } from '../common/circle';
|
|
9
7
|
import { useMedia } from '../common/hooks/useMedia';
|
|
@@ -88,30 +86,18 @@ const StatusIcon = ({
|
|
|
88
86
|
};
|
|
89
87
|
const { Icon, defaultIconLabel } = iconMetaBySentiment[sentiment];
|
|
90
88
|
|
|
91
|
-
const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
|
|
92
89
|
const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);
|
|
93
90
|
const size = mapLegacySize[sizeProp] ?? sizeProp;
|
|
94
|
-
|
|
95
|
-
const SentimentSurfaceSetting = (props: PropsWithChildren<Pick<CircleProps, 'className'>>) => (
|
|
96
|
-
<SentimentSurface
|
|
97
|
-
as="span"
|
|
98
|
-
// @ts-expect-error sentiment and SentimentSurface types mismatch
|
|
99
|
-
sentiment={
|
|
100
|
-
sentiment === 'positive' ? 'success' : sentiment === 'pending' ? 'warning' : sentiment
|
|
101
|
-
}
|
|
102
|
-
{...props}
|
|
103
|
-
/>
|
|
104
|
-
);
|
|
91
|
+
|
|
105
92
|
return (
|
|
106
93
|
<Circle
|
|
107
|
-
as={SentimentSurfaceSetting}
|
|
108
94
|
size={isTinyViewport && size < 40 ? 32 : size}
|
|
109
95
|
data-testid="status-icon"
|
|
110
96
|
className={clsx('status-circle', sentiment)}
|
|
111
97
|
id={id}
|
|
112
98
|
>
|
|
113
99
|
<Icon
|
|
114
|
-
className=
|
|
100
|
+
className="status-icon"
|
|
115
101
|
title={iconLabel === null ? undefined : iconLabel || defaultIconLabel}
|
|
116
102
|
/>
|
|
117
103
|
</Circle>
|