@transferwise/components 46.115.1 → 46.116.1
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/alert/Alert.js +2 -1
- package/build/alert/Alert.js.map +1 -1
- package/build/alert/Alert.mjs +2 -1
- package/build/alert/Alert.mjs.map +1 -1
- package/build/criticalBanner/CriticalCommsBanner.js +1 -0
- package/build/criticalBanner/CriticalCommsBanner.js.map +1 -1
- package/build/criticalBanner/CriticalCommsBanner.mjs +1 -0
- package/build/criticalBanner/CriticalCommsBanner.mjs.map +1 -1
- package/build/main.css +428 -44
- package/build/mocks.js +7 -0
- package/build/mocks.js.map +1 -1
- package/build/mocks.mjs +7 -1
- package/build/mocks.mjs.map +1 -1
- package/build/sentimentSurface/SentimentSurface.js +43 -0
- package/build/sentimentSurface/SentimentSurface.js.map +1 -0
- package/build/sentimentSurface/SentimentSurface.mjs +39 -0
- package/build/sentimentSurface/SentimentSurface.mjs.map +1 -0
- package/build/sentimentSurface/classMap.js +17 -0
- package/build/sentimentSurface/classMap.js.map +1 -0
- package/build/sentimentSurface/classMap.mjs +14 -0
- package/build/sentimentSurface/classMap.mjs.map +1 -0
- package/build/statusIcon/StatusIcon.js +10 -1
- package/build/statusIcon/StatusIcon.js.map +1 -1
- package/build/statusIcon/StatusIcon.mjs +10 -1
- package/build/statusIcon/StatusIcon.mjs.map +1 -1
- package/build/styles/inputs/Input.css +2 -4
- package/build/styles/inputs/TextArea.css +2 -4
- package/build/styles/main.css +428 -44
- package/build/styles/popover/Popover.css +2 -4
- package/build/styles/sentimentSurface/SentimentSurface.css +420 -0
- package/build/styles/statusIcon/StatusIcon.css +4 -36
- package/build/types/alert/Alert.d.ts.map +1 -1
- package/build/types/criticalBanner/CriticalCommsBanner.d.ts +2 -1
- package/build/types/criticalBanner/CriticalCommsBanner.d.ts.map +1 -1
- package/build/types/mocks.d.ts +1 -0
- package/build/types/mocks.d.ts.map +1 -1
- package/build/types/sentimentSurface/SentimentSurface.d.ts +30 -0
- package/build/types/sentimentSurface/SentimentSurface.d.ts.map +1 -0
- package/build/types/sentimentSurface/SentimentSurface.types.d.ts +80 -0
- package/build/types/sentimentSurface/SentimentSurface.types.d.ts.map +1 -0
- package/build/types/sentimentSurface/classMap.d.ts +4 -0
- package/build/types/sentimentSurface/classMap.d.ts.map +1 -0
- package/build/types/sentimentSurface/index.d.ts +3 -0
- package/build/types/sentimentSurface/index.d.ts.map +1 -0
- package/build/types/statusIcon/StatusIcon.d.ts.map +1 -1
- package/build/types/test-utils/window-mock.d.ts +1 -0
- package/build/types/test-utils/window-mock.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/alert/Alert.tsx +3 -1
- package/src/criticalBanner/CriticalCommsBanner.tsx +3 -2
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.spec.tsx +229 -0
- package/src/expressiveMoneyInput/amountInput/AmountInput.spec.tsx +282 -0
- package/src/expressiveMoneyInput/currencySelector/CurrencySelector.spec.tsx +160 -0
- package/src/inputs/Input.css +2 -4
- package/src/inputs/SelectInput.spec.tsx +7 -1
- package/src/inputs/TextArea.css +2 -4
- package/src/main.css +428 -44
- package/src/main.less +2 -0
- package/src/mocks.ts +7 -0
- package/src/moneyInput/MoneyInput.spec.tsx +9 -1
- package/src/popover/Popover.css +2 -4
- package/src/provider/theme/ThemeProvider.story.tsx +78 -11
- package/src/sentimentSurface/SentimentSurface.css +420 -0
- package/src/sentimentSurface/SentimentSurface.docs.mdx +549 -0
- package/src/sentimentSurface/SentimentSurface.less +293 -0
- package/src/sentimentSurface/SentimentSurface.spec.tsx +140 -0
- package/src/sentimentSurface/SentimentSurface.story.tsx +303 -0
- package/src/sentimentSurface/SentimentSurface.tests.story.tsx +72 -0
- package/src/sentimentSurface/SentimentSurface.tsx +72 -0
- package/src/sentimentSurface/SentimentSurface.types.ts +104 -0
- package/src/sentimentSurface/classMap.ts +15 -0
- package/src/sentimentSurface/index.ts +8 -0
- package/src/statusIcon/StatusIcon.css +4 -36
- package/src/statusIcon/StatusIcon.less +3 -41
- package/src/statusIcon/StatusIcon.tsx +14 -1
- package/src/test-utils/jest.setup.ts +0 -5
- package/src/test-utils/window-mock.ts +5 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
import { Meta, Source, ArgTypes } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as SentimentSurfaceStories from './SentimentSurface.story';
|
|
3
|
+
|
|
4
|
+
<Meta title="Content/SentimentSurface/Developer Guide" />
|
|
5
|
+
|
|
6
|
+
# SentimentSurface Developer Guide
|
|
7
|
+
|
|
8
|
+
`SentimentSurface` is a polymorphic container component that establishes a semantic colour context by setting CSS custom properties (tokens) based on sentiment types. It does not apply any default background or text styling - instead, it provides access to sentiment-aware tokens that child components can use to style themselves appropriately.
|
|
9
|
+
|
|
10
|
+
## Basic Usage
|
|
11
|
+
|
|
12
|
+
Import and use the component with a required `sentiment` prop:
|
|
13
|
+
|
|
14
|
+
<Source dark code={`
|
|
15
|
+
import { SentimentSurface } from '@transferwise/components';
|
|
16
|
+
|
|
17
|
+
<SentimentSurface sentiment="negative">Your payment has failed</SentimentSurface>
|
|
18
|
+
`} />
|
|
19
|
+
|
|
20
|
+
### Props
|
|
21
|
+
|
|
22
|
+
<ArgTypes of={SentimentSurfaceStories} />
|
|
23
|
+
|
|
24
|
+
## Sentiment Types
|
|
25
|
+
|
|
26
|
+
The component supports five sentiment types (`negative`, `warning`, `neutral`, `proposition` and `success`), each communicating different types of information:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<SentimentSurface sentiment="negative">
|
|
30
|
+
Your payment has failed. Please try again.
|
|
31
|
+
</SentimentSurface>
|
|
32
|
+
|
|
33
|
+
<SentimentSurface sentiment="warning">
|
|
34
|
+
Action required: Please verify your email address.
|
|
35
|
+
</SentimentSurface>
|
|
36
|
+
|
|
37
|
+
<SentimentSurface sentiment="neutral">
|
|
38
|
+
Your account is up to date.
|
|
39
|
+
</SentimentSurface>
|
|
40
|
+
|
|
41
|
+
<SentimentSurface sentiment="proposition">
|
|
42
|
+
Try our new feature and save time on transfers.
|
|
43
|
+
</SentimentSurface>
|
|
44
|
+
|
|
45
|
+
<SentimentSurface sentiment="success">
|
|
46
|
+
Your payment was successful!
|
|
47
|
+
</SentimentSurface>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Emphasis Levels
|
|
53
|
+
|
|
54
|
+
Each sentiment type supports two emphasis levels that provide different sets of token values (`base`, `elevated`):
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<SentimentSurface sentiment="success" emphasis="base">
|
|
58
|
+
Base emphasis - provides tokens suited for subtle contexts
|
|
59
|
+
</SentimentSurface>
|
|
60
|
+
|
|
61
|
+
<SentimentSurface sentiment="success" emphasis="elevated">
|
|
62
|
+
Elevated emphasis - provides tokens suited for prominent contexts
|
|
63
|
+
</SentimentSurface>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**When to use:**
|
|
67
|
+
|
|
68
|
+
- **Base**: For inline notifications, subtle callouts, or when sentiment needs to be communicated without drawing too much attention
|
|
69
|
+
- **Elevated**: For prominent banners, critical alerts, or when the sentiment should be immediately noticeable
|
|
70
|
+
|
|
71
|
+
Note: The component does not apply background or text colours by default. Use the provided tokens in your styles to achieve the desired visual effect.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Polymorphic Rendering
|
|
76
|
+
|
|
77
|
+
The component is fully polymorphic, meaning it can render as any HTML element using the `as` prop while maintaining full type safety.
|
|
78
|
+
|
|
79
|
+
### Basic Examples
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// Render as div (default)
|
|
83
|
+
<SentimentSurface sentiment="neutral">
|
|
84
|
+
Default div element
|
|
85
|
+
</SentimentSurface>
|
|
86
|
+
|
|
87
|
+
// Render as section
|
|
88
|
+
<SentimentSurface sentiment="negative" as="section">
|
|
89
|
+
Semantic section element
|
|
90
|
+
</SentimentSurface>
|
|
91
|
+
|
|
92
|
+
// Render as article
|
|
93
|
+
<SentimentSurface sentiment="success" as="article">
|
|
94
|
+
Article element for standalone content
|
|
95
|
+
</SentimentSurface>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### With HTML Attributes
|
|
99
|
+
|
|
100
|
+
The component accepts all valid HTML attributes for the rendered element:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
// Section with ARIA attributes
|
|
104
|
+
<SentimentSurface
|
|
105
|
+
sentiment="negative"
|
|
106
|
+
as="section"
|
|
107
|
+
role="alert"
|
|
108
|
+
aria-live="polite"
|
|
109
|
+
aria-atomic="true"
|
|
110
|
+
>
|
|
111
|
+
Critical error message
|
|
112
|
+
</SentimentSurface>
|
|
113
|
+
|
|
114
|
+
// Article with data attributes
|
|
115
|
+
<SentimentSurface
|
|
116
|
+
sentiment="proposition"
|
|
117
|
+
as="article"
|
|
118
|
+
data-tracking-id="promo-banner"
|
|
119
|
+
data-position="top"
|
|
120
|
+
>
|
|
121
|
+
Promotional content
|
|
122
|
+
</SentimentSurface>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Type Safety
|
|
126
|
+
|
|
127
|
+
TypeScript provides full type checking for HTML attributes based on the `as` prop:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
// ✅ Valid - section supports these attributes
|
|
131
|
+
<SentimentSurface as="section" role="region" aria-labelledby="heading">
|
|
132
|
+
Content
|
|
133
|
+
</SentimentSurface>
|
|
134
|
+
|
|
135
|
+
// ❌ TypeScript error - 'href' is not valid for 'div'
|
|
136
|
+
<SentimentSurface as="div" href="/link">
|
|
137
|
+
Content
|
|
138
|
+
</SentimentSurface>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Nesting Sentiment Surfaces
|
|
144
|
+
|
|
145
|
+
Sentiment surfaces can be nested to create layered contexts. Each nested surface establishes its own colour context through CSS custom properties.
|
|
146
|
+
|
|
147
|
+
### Basic Nesting
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
<SentimentSurface sentiment="negative" emphasis="base">
|
|
151
|
+
<Title size="large">Payment Failed</Title>
|
|
152
|
+
<Body>There was an issue processing your payment.</Body>
|
|
153
|
+
|
|
154
|
+
<SentimentSurface sentiment="neutral" emphasis="elevated">
|
|
155
|
+
<Title size="small">What happened?</Title>
|
|
156
|
+
<Body>Your card was declined by your bank.</Body>
|
|
157
|
+
</SentimentSurface>
|
|
158
|
+
</SentimentSurface>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Multi-Level Nesting
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<SentimentSurface sentiment="success" emphasis="base">
|
|
165
|
+
Outer: Payment successful
|
|
166
|
+
<SentimentSurface sentiment="neutral" emphasis="elevated">
|
|
167
|
+
Inner: Transaction details
|
|
168
|
+
<SentimentSurface sentiment="warning" emphasis="base">
|
|
169
|
+
Deepest: Additional fees may apply
|
|
170
|
+
</SentimentSurface>
|
|
171
|
+
</SentimentSurface>
|
|
172
|
+
</SentimentSurface>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Nesting with Different Elements
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
<SentimentSurface sentiment="negative" as="section">
|
|
179
|
+
<Title size="large">Error Section</Title>
|
|
180
|
+
|
|
181
|
+
<SentimentSurface sentiment="neutral" as="article">
|
|
182
|
+
<Title size="small">Details</Title>
|
|
183
|
+
<Body>More information about the error.</Body>
|
|
184
|
+
</SentimentSurface>
|
|
185
|
+
|
|
186
|
+
<SentimentSurface sentiment="proposition" as="aside">
|
|
187
|
+
<Body>Need help? Contact support.</Body>
|
|
188
|
+
</SentimentSurface>
|
|
189
|
+
</SentimentSurface>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## CSS Custom Properties (Tokens)
|
|
195
|
+
|
|
196
|
+
The component sets CSS custom properties (CSS variables) that child components can use to style themselves according to the sentiment context. The component itself does not apply any visual styling - it simply makes these tokens available for use in your own styles or by sentiment-aware child components.
|
|
197
|
+
|
|
198
|
+
### Available Tokens
|
|
199
|
+
|
|
200
|
+
Each `SentimentSurface` sets tokens for content, interactive elements, and background surfaces. See the [Tokens story](?path=/story/content-sentimentsurface--tokens) for a visual demonstration of all tokens across sentiments and emphasis levels:
|
|
201
|
+
|
|
202
|
+
#### Content Tokens
|
|
203
|
+
|
|
204
|
+
```css
|
|
205
|
+
--color-sentiment-content-primary
|
|
206
|
+
--color-sentiment-content-primary-hover
|
|
207
|
+
--color-sentiment-content-primary-active
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### Interactive Primary Tokens
|
|
211
|
+
|
|
212
|
+
```css
|
|
213
|
+
--color-sentiment-interactive-primary
|
|
214
|
+
--color-sentiment-interactive-primary-hover
|
|
215
|
+
--color-sentiment-interactive-primary-active
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Interactive Secondary Tokens
|
|
219
|
+
|
|
220
|
+
```css
|
|
221
|
+
--color-sentiment-interactive-secondary
|
|
222
|
+
--color-sentiment-interactive-secondary-hover
|
|
223
|
+
--color-sentiment-interactive-secondary-active
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Interactive Secondary Neutral Tokens
|
|
227
|
+
|
|
228
|
+
```css
|
|
229
|
+
--color-sentiment-interactive-secondary-neutral
|
|
230
|
+
--color-sentiment-interactive-secondary-neutral-hover
|
|
231
|
+
--color-sentiment-interactive-secondary-neutral-active
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
#### Interactive Control Tokens
|
|
235
|
+
|
|
236
|
+
```css
|
|
237
|
+
--color-sentiment-interactive-control
|
|
238
|
+
--color-sentiment-interactive-control-hover
|
|
239
|
+
--color-sentiment-interactive-control-active
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Background Surface Tokens
|
|
243
|
+
|
|
244
|
+
```css
|
|
245
|
+
--color-sentiment-background-surface
|
|
246
|
+
--color-sentiment-background-surface-hover
|
|
247
|
+
--color-sentiment-background-surface-active
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Using Tokens in Component Styles
|
|
251
|
+
|
|
252
|
+
Components can reference these tokens with fallbacks to maintain functionality outside of a `SentimentSurface`:
|
|
253
|
+
|
|
254
|
+
```css
|
|
255
|
+
.wds-Button {
|
|
256
|
+
/* Primary button uses interactive primary tokens */
|
|
257
|
+
--Button-background: var(--color-sentiment-interactive-primary, var(--color-interactive-accent));
|
|
258
|
+
--Button-background-hover: var(
|
|
259
|
+
--color-sentiment-interactive-primary-hover,
|
|
260
|
+
var(--color-interactive-accent-hover)
|
|
261
|
+
);
|
|
262
|
+
--Button-background-active: var(
|
|
263
|
+
--color-sentiment-interactive-primary-active,
|
|
264
|
+
var(--color-interactive-accent-active)
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
/* Button text color uses control tokens */
|
|
268
|
+
--Button-color: var(--color-sentiment-interactive-control, var(--color-interactive-control));
|
|
269
|
+
--Button-color-hover: var(
|
|
270
|
+
--color-sentiment-interactive-control-hover,
|
|
271
|
+
var(--color-interactive-control-hover)
|
|
272
|
+
);
|
|
273
|
+
--Button-color-active: var(
|
|
274
|
+
--color-sentiment-interactive-control-active,
|
|
275
|
+
var(--color-interactive-control-active)
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.wds-Button--secondary {
|
|
280
|
+
/* Secondary button uses secondary tokens */
|
|
281
|
+
--Button-background: var(
|
|
282
|
+
--color-sentiment-interactive-secondary,
|
|
283
|
+
var(--color-interactive-neutral)
|
|
284
|
+
);
|
|
285
|
+
--Button-background-hover: var(
|
|
286
|
+
--color-sentiment-interactive-secondary-hover,
|
|
287
|
+
var(--color-interactive-neutral-hover)
|
|
288
|
+
);
|
|
289
|
+
--Button-color: var(--color-sentiment-interactive-primary, var(--color-interactive-primary));
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Example: Button in Sentiment Context
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import { Button, Body } from '@transferwise/components';
|
|
297
|
+
|
|
298
|
+
// Button automatically adapts to the sentiment context
|
|
299
|
+
<SentimentSurface sentiment="success">
|
|
300
|
+
<Body>Your payment was successful!</Body>
|
|
301
|
+
<Button v2 priority="primary">View Receipt</Button>
|
|
302
|
+
<Button v2 priority="secondary">Send Another</Button>
|
|
303
|
+
</SentimentSurface>
|
|
304
|
+
|
|
305
|
+
// Same buttons in different sentiment context
|
|
306
|
+
<SentimentSurface sentiment="negative">
|
|
307
|
+
<Body>Payment failed</Body>
|
|
308
|
+
<Button v2 priority="primary">Try Again</Button>
|
|
309
|
+
<Button v2 priority="secondary">Cancel</Button>
|
|
310
|
+
</SentimentSurface>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The buttons will automatically use appropriate colours based on the sentiment context.
|
|
314
|
+
|
|
315
|
+
### Applying Sentiment Tokens
|
|
316
|
+
|
|
317
|
+
To visually style content within a SentimentSurface, use the provided tokens in your styles:
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
// Apply tokens via inline styles
|
|
321
|
+
<SentimentSurface sentiment="warning">
|
|
322
|
+
<div
|
|
323
|
+
style={{
|
|
324
|
+
padding: '24px',
|
|
325
|
+
borderRadius: '16px',
|
|
326
|
+
backgroundColor: 'var(--color-sentiment-background-surface)',
|
|
327
|
+
color: 'var(--color-sentiment-content-primary)',
|
|
328
|
+
}}
|
|
329
|
+
>
|
|
330
|
+
This content uses the sentiment tokens for styling
|
|
331
|
+
</div>
|
|
332
|
+
</SentimentSurface>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Creating Custom Components with Sentiment Tokens
|
|
336
|
+
|
|
337
|
+
You can create your own components that respect sentiment context:
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
// CustomCard.css
|
|
341
|
+
.custom-card {
|
|
342
|
+
background-color: var(
|
|
343
|
+
--color-sentiment-background-surface,
|
|
344
|
+
var(--color-background-surface)
|
|
345
|
+
);
|
|
346
|
+
color: var(
|
|
347
|
+
--color-sentiment-content-primary,
|
|
348
|
+
var(--color-content-primary)
|
|
349
|
+
);
|
|
350
|
+
border: 1px solid var(
|
|
351
|
+
--color-sentiment-interactive-secondary,
|
|
352
|
+
var(--color-border-neutral)
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.custom-card:hover {
|
|
357
|
+
background-color: var(
|
|
358
|
+
--color-sentiment-background-surface-hover,
|
|
359
|
+
var(--color-background-surface-hover)
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.custom-card-link {
|
|
364
|
+
color: var(
|
|
365
|
+
--color-sentiment-interactive-primary,
|
|
366
|
+
var(--color-interactive-primary)
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.custom-card-link:hover {
|
|
371
|
+
color: var(
|
|
372
|
+
--color-sentiment-interactive-primary-hover,
|
|
373
|
+
var(--color-interactive-primary-hover)
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
// CustomCard.tsx
|
|
380
|
+
function CustomCard({ children }) {
|
|
381
|
+
return (
|
|
382
|
+
<div className="custom-card">
|
|
383
|
+
{children}
|
|
384
|
+
<a href="#" className="custom-card-link">
|
|
385
|
+
Learn more
|
|
386
|
+
</a>
|
|
387
|
+
</div>
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Usage
|
|
392
|
+
<SentimentSurface sentiment="warning">
|
|
393
|
+
<CustomCard>This card adapts to the warning sentiment</CustomCard>
|
|
394
|
+
</SentimentSurface>;
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Accessibility Considerations
|
|
400
|
+
|
|
401
|
+
### Semantic HTML
|
|
402
|
+
|
|
403
|
+
Use appropriate HTML elements via the `as` prop to ensure proper document structure:
|
|
404
|
+
|
|
405
|
+
```tsx
|
|
406
|
+
// ✅ Good - semantic HTML for alerts
|
|
407
|
+
<SentimentSurface
|
|
408
|
+
sentiment="negative"
|
|
409
|
+
as="section"
|
|
410
|
+
role="alert"
|
|
411
|
+
aria-live="assertive"
|
|
412
|
+
>
|
|
413
|
+
Critical error: Payment failed
|
|
414
|
+
</SentimentSurface>
|
|
415
|
+
|
|
416
|
+
// ✅ Good - article for standalone content
|
|
417
|
+
<SentimentSurface sentiment="proposition" as="article">
|
|
418
|
+
<Title size="large">New Feature Available</Title>
|
|
419
|
+
<Body>Try our new instant transfer feature...</Body>
|
|
420
|
+
</SentimentSurface>
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### ARIA Attributes
|
|
424
|
+
|
|
425
|
+
Add appropriate ARIA attributes for screen readers:
|
|
426
|
+
|
|
427
|
+
```tsx
|
|
428
|
+
// For errors or critical warnings
|
|
429
|
+
<SentimentSurface
|
|
430
|
+
sentiment="negative"
|
|
431
|
+
role="alert"
|
|
432
|
+
aria-live="assertive"
|
|
433
|
+
aria-atomic="true"
|
|
434
|
+
>
|
|
435
|
+
Error: Your session has expired
|
|
436
|
+
</SentimentSurface>
|
|
437
|
+
|
|
438
|
+
// For important but not critical information
|
|
439
|
+
<SentimentSurface
|
|
440
|
+
sentiment="warning"
|
|
441
|
+
role="status"
|
|
442
|
+
aria-live="polite"
|
|
443
|
+
>
|
|
444
|
+
Please verify your email address
|
|
445
|
+
</SentimentSurface>
|
|
446
|
+
|
|
447
|
+
// For regions with headings
|
|
448
|
+
<SentimentSurface
|
|
449
|
+
sentiment="success"
|
|
450
|
+
as="section"
|
|
451
|
+
role="region"
|
|
452
|
+
aria-labelledby="success-heading"
|
|
453
|
+
>
|
|
454
|
+
<Title id="success-heading" size="large">Payment Successful</Title>
|
|
455
|
+
<Body>Your payment has been processed.</Body>
|
|
456
|
+
</SentimentSurface>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Color Contrast
|
|
460
|
+
|
|
461
|
+
The tokens provided by the component are designed with WCAG AA contrast ratios in mind:
|
|
462
|
+
|
|
463
|
+
- **Base emphasis**: Tokens provide sufficient contrast for body text
|
|
464
|
+
- **Elevated emphasis**: Tokens provide higher contrast, often with inverted colours
|
|
465
|
+
|
|
466
|
+
Always test your content for contrast compliance, especially when:
|
|
467
|
+
|
|
468
|
+
- Applying tokens via `style` or `className`
|
|
469
|
+
- Using small text sizes
|
|
470
|
+
- Displaying important information
|
|
471
|
+
|
|
472
|
+
### Don't Rely on Color Alone
|
|
473
|
+
|
|
474
|
+
Sentiment should not be conveyed through colour alone. Always include:
|
|
475
|
+
|
|
476
|
+
```tsx
|
|
477
|
+
// ✅ Good - includes text and icons
|
|
478
|
+
<SentimentSurface sentiment="negative">
|
|
479
|
+
<ErrorIcon aria-hidden="true" />
|
|
480
|
+
<strong>Error:</strong> Payment failed
|
|
481
|
+
</SentimentSurface>
|
|
482
|
+
|
|
483
|
+
// ❌ Bad - relies only on colour
|
|
484
|
+
<SentimentSurface sentiment="negative">
|
|
485
|
+
Payment failed
|
|
486
|
+
</SentimentSurface>
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Focus Management
|
|
490
|
+
|
|
491
|
+
When using for alerts, consider focus management:
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
function ErrorBanner({ error }) {
|
|
495
|
+
const errorRef = useRef<HTMLElement>(null);
|
|
496
|
+
|
|
497
|
+
useEffect(() => {
|
|
498
|
+
if (error && errorRef.current) {
|
|
499
|
+
errorRef.current.focus();
|
|
500
|
+
}
|
|
501
|
+
}, [error]);
|
|
502
|
+
|
|
503
|
+
if (!error) return null;
|
|
504
|
+
|
|
505
|
+
return (
|
|
506
|
+
<SentimentSurface
|
|
507
|
+
ref={errorRef}
|
|
508
|
+
sentiment="negative"
|
|
509
|
+
as="section"
|
|
510
|
+
role="alert"
|
|
511
|
+
tabIndex={-1}
|
|
512
|
+
aria-live="assertive"
|
|
513
|
+
>
|
|
514
|
+
{error.message}
|
|
515
|
+
</SentimentSurface>
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## Best Practices
|
|
523
|
+
|
|
524
|
+
### Do's
|
|
525
|
+
|
|
526
|
+
✅ Use semantic HTML elements via the `as` prop
|
|
527
|
+
✅ Include ARIA attributes for screen readers
|
|
528
|
+
✅ Combine colour with icons and text for clarity
|
|
529
|
+
✅ Use appropriate sentiment types for the content
|
|
530
|
+
✅ Leverage CSS tokens for consistent theming
|
|
531
|
+
✅ Test contrast ratios for accessibility
|
|
532
|
+
✅ Provide focus management for critical alerts
|
|
533
|
+
|
|
534
|
+
### Don'ts
|
|
535
|
+
|
|
536
|
+
❌ Don't rely solely on colour to convey meaning
|
|
537
|
+
❌ Don't nest too many levels (3+ levels can be confusing)
|
|
538
|
+
❌ Don't override sentiment tokens without good reason
|
|
539
|
+
❌ Don't use `sentiment="negative"` for informational content
|
|
540
|
+
❌ Don't forget to test with screen readers
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
## Further Reading
|
|
545
|
+
|
|
546
|
+
- [Component Source Code](./SentimentSurface.tsx)
|
|
547
|
+
- [Storybook Examples](?path=/docs/content-sentimentsurface--docs)
|
|
548
|
+
- [WCAG Color Contrast Guidelines](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html)
|
|
549
|
+
- [ARIA Live Regions](https://www.w3.org/WAI/WCAG21/Understanding/status-messages.html)
|