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