benivo-ui-library 1.9.76 → 1.10.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/README.md +22 -0
- package/accordion.less +6 -5
- package/activityFeed.less +394 -0
- package/asideSummaryCard.less +68 -5
- package/asideSummaryCardSection.less +95 -16
- package/avatar.less +6 -5
- package/benivo-ui-lib.less +30 -0
- package/button.less +43 -11
- package/buttonGroup.less +236 -0
- package/cardHeader.less +230 -0
- package/charts.less +182 -0
- package/checkbox.less +192 -41
- package/checkboxGroup.less +198 -0
- package/checklistCard.less +119 -0
- package/closeButton.less +70 -0
- package/contentDivider.less +68 -0
- package/currencyInput.less +6 -0
- package/dataGrid.less +690 -0
- package/datePicker.less +446 -96
- package/detailCard.less +80 -0
- package/emptyState.less +151 -0
- package/featuredIcon.less +13 -1
- package/fileCard.less +347 -0
- package/filePreview.less +380 -0
- package/fileTypeIcon.less +12 -0
- package/fileUpload.less +271 -0
- package/flagFeatureIcon.less +41 -0
- package/footer.less +123 -0
- package/forms.less +9 -4
- package/heroInput.less +20 -4
- package/illustration.less +62 -0
- package/index.js +1 -1
- package/input.less +17 -1
- package/menu.less +247 -0
- package/metric.less +241 -0
- package/miButton.less +149 -0
- package/modal.less +226 -0
- package/optionList.less +102 -0
- package/package.json +7 -3
- package/pageHeader.less +266 -0
- package/pageIndicator.less +127 -0
- package/pagination.less +227 -0
- package/phoneNumber.less +22 -0
- package/progressSteps.less +398 -0
- package/radiobutton.less +50 -7
- package/sectionHeader.less +244 -0
- package/select.less +76 -31
- package/slider.less +8 -1
- package/tabGroup.less +2 -1
- package/tabs.less +2 -1
- package/tag.less +70 -12
- package/tagsSelect.less +28 -0
- package/textarea.less +5 -1
- package/tileGeometry.less +12 -0
- package/variables.less +72 -12
- package/verificationCode.less +4 -1
- package/workspaceModal.less +607 -0
package/README.md
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
`benivo-ui-library` is a collection of react hooks and components for faster development.
|
|
6
6
|
|
|
7
|
+
Accessibility is tested automatically with jest-axe — run `npm run a11y:audit` and see
|
|
8
|
+
[docs/accessibility-testing.md](docs/accessibility-testing.md) for the enforcement model.
|
|
9
|
+
|
|
7
10
|
# Installation
|
|
8
11
|
|
|
9
12
|
```sh
|
|
@@ -36,3 +39,22 @@ function MyApp() {
|
|
|
36
39
|
);
|
|
37
40
|
}
|
|
38
41
|
```
|
|
42
|
+
|
|
43
|
+
# Publishing
|
|
44
|
+
|
|
45
|
+
Publishing auth comes from the `NPM_TOKEN` environment variable — never from a token
|
|
46
|
+
committed to this repo. Both `.npmrc` files reference it as `${NPM_TOKEN}`, which npm
|
|
47
|
+
expands at run time.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export NPM_TOKEN=<your granular npm publish token for benivo-ui-library>
|
|
51
|
+
npm run publish:lib
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`publish:lib` runs `check:npm-token` first and stops with a clear message if `NPM_TOKEN`
|
|
55
|
+
is unset, rather than failing part-way through a publish.
|
|
56
|
+
|
|
57
|
+
Use a **granular** npm access token scoped to the `benivo-ui-library` package only, with
|
|
58
|
+
publish rights and an expiry — not a classic automation token on the whole `benivo`
|
|
59
|
+
account. Keep it in your own environment or a CI secret. Do not add it to `.npmrc`,
|
|
60
|
+
`.storybook/.npmrc`, or any other tracked file.
|
package/accordion.less
CHANGED
|
@@ -64,12 +64,13 @@
|
|
|
64
64
|
text-align: left;
|
|
65
65
|
font-family: @font-family;
|
|
66
66
|
|
|
67
|
-
// Keyboard only, so clicking a row does not leave a ring behind.
|
|
68
|
-
//
|
|
69
|
-
//
|
|
67
|
+
// Keyboard only, so clicking a row does not leave a ring behind. This used to
|
|
68
|
+
// write the values out because the shared focus variables were not on main yet;
|
|
69
|
+
// BPO-14843 is the branch that comment was waiting for, so it is folded on now
|
|
70
|
+
// and a change to the indicator colour reaches this rule too.
|
|
70
71
|
&:focus-visible {
|
|
71
|
-
outline:
|
|
72
|
-
outline-offset:
|
|
72
|
+
outline: @focus-outline;
|
|
73
|
+
outline-offset: @focus-outline-offset;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Activity feed
|
|
3
|
+
//
|
|
4
|
+
// A timeline / message log built from FeedItems, matching the DS "Feed item base"
|
|
5
|
+
// and "Activity feed" (Figma page 253-14231). The container owns spacing and
|
|
6
|
+
// separators; the item owns its anatomy and the connector rail.
|
|
7
|
+
//
|
|
8
|
+
// Colours are tokens only (see scripts/check-tokens.sh): text on --black /
|
|
9
|
+
// --text-400 / --text-600, links and the "new" dot on --brand-700, rail and
|
|
10
|
+
// separators on --border-200, the date band on --bg-100.
|
|
11
|
+
//
|
|
12
|
+
|
|
13
|
+
@feed-bubble-shadow: 0 1px 1px rgba(16, 24, 40, 0.05);
|
|
14
|
+
@feed-gap: 32px; // spacing between items (Figma: 32px in every divider mode)
|
|
15
|
+
|
|
16
|
+
.bnv-feed {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
font-family: @font-family;
|
|
20
|
+
|
|
21
|
+
// ---- spacing per divider style ----
|
|
22
|
+
// none: 32px between items.
|
|
23
|
+
&--divider-none {
|
|
24
|
+
gap: @feed-gap;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// line: a full-width 1px separator sits in a 16px gap either side (~32px total).
|
|
28
|
+
&--divider-line {
|
|
29
|
+
gap: 16px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// connector: the rail is a flex segment inside the item, so the item carries
|
|
33
|
+
// its own bottom spacing (Figma: content pb 32). No container gap.
|
|
34
|
+
&--divider-connector {
|
|
35
|
+
gap: 0;
|
|
36
|
+
|
|
37
|
+
.bnv-feed-item:last-child .bnv-feed-item__body {
|
|
38
|
+
padding-bottom: 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// With a 32px container gap, the date's own 12px block margin would make the
|
|
43
|
+
// date↔item spacing 44px, which reads as disconnected. Drop it here so it is a
|
|
44
|
+
// clean 32px, uniform with the item spacing. (Line mode keeps the 12px → 28px.)
|
|
45
|
+
&--divider-none &__date,
|
|
46
|
+
&--divider-connector &__date {
|
|
47
|
+
margin: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ---- separators ----
|
|
51
|
+
&__separator {
|
|
52
|
+
height: 1px;
|
|
53
|
+
background-color: var(--border-200);
|
|
54
|
+
border: 0;
|
|
55
|
+
flex-shrink: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ---- day / date grouping header ----
|
|
59
|
+
// A pill (bg-100) with a calendar glyph and a bold date. The 12px block
|
|
60
|
+
// padding sits on top of the container gap, matching Figma's date frame.
|
|
61
|
+
&__date {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
gap: 10px;
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
width: 100%;
|
|
67
|
+
margin: 12px 0;
|
|
68
|
+
padding: 8px 12px;
|
|
69
|
+
background-color: var(--bg-100);
|
|
70
|
+
border-radius: 0.5rem;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&__date-icon {
|
|
74
|
+
flex-shrink: 0;
|
|
75
|
+
color: var(--text-600);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&__date-label {
|
|
79
|
+
font-size: @font-size; // 16px
|
|
80
|
+
line-height: 24px;
|
|
81
|
+
font-weight: @font-weight-semibold;
|
|
82
|
+
color: var(--black);
|
|
83
|
+
white-space: nowrap;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ------------------------------------------------------------------ FeedItem
|
|
88
|
+
.bnv-feed-item {
|
|
89
|
+
--fi-avatar: 48px;
|
|
90
|
+
position: relative;
|
|
91
|
+
display: flex;
|
|
92
|
+
gap: 12px;
|
|
93
|
+
align-items: flex-start;
|
|
94
|
+
box-sizing: border-box;
|
|
95
|
+
font-size: @font-size; // 16px
|
|
96
|
+
line-height: 24px;
|
|
97
|
+
color: var(--text-600);
|
|
98
|
+
|
|
99
|
+
&--sm {
|
|
100
|
+
--fi-avatar: 32px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------- leading column + rail ----------
|
|
104
|
+
&__leading {
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-direction: column;
|
|
107
|
+
align-items: center;
|
|
108
|
+
flex-shrink: 0;
|
|
109
|
+
width: var(--fi-avatar);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&--connector &__leading {
|
|
113
|
+
align-self: stretch;
|
|
114
|
+
gap: 4px;
|
|
115
|
+
padding-bottom: 4px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&__avatar {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
flex-shrink: 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Fallback marker when there is no avatar/icon.
|
|
124
|
+
&__marker {
|
|
125
|
+
width: 10px;
|
|
126
|
+
height: 10px;
|
|
127
|
+
margin-top: 7px;
|
|
128
|
+
border-radius: 50%;
|
|
129
|
+
background-color: var(--text-300);
|
|
130
|
+
flex-shrink: 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Decorative timeline rail — grows to fill the column below the avatar.
|
|
134
|
+
&__rail {
|
|
135
|
+
flex: 1 0 0;
|
|
136
|
+
width: 2px;
|
|
137
|
+
min-height: 8px;
|
|
138
|
+
border-radius: 2px;
|
|
139
|
+
background-color: var(--border-200);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ---------- body ----------
|
|
143
|
+
&__body {
|
|
144
|
+
flex: 1 1 0;
|
|
145
|
+
min-width: 0;
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-direction: column;
|
|
148
|
+
gap: 12px;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
&--connector &__body {
|
|
152
|
+
padding-bottom: @feed-gap;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Header + action line sit tight together; 12px separates them from supporting.
|
|
156
|
+
&__text-block {
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
&__heading {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
min-width: 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
&__meta {
|
|
168
|
+
display: flex;
|
|
169
|
+
align-items: baseline;
|
|
170
|
+
flex-wrap: wrap;
|
|
171
|
+
gap: 8px;
|
|
172
|
+
min-width: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
&__actor {
|
|
176
|
+
font-weight: @font-weight-semibold;
|
|
177
|
+
color: var(--black);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
&__timestamp {
|
|
181
|
+
font-weight: @font-weight-normal;
|
|
182
|
+
color: var(--text-400);
|
|
183
|
+
white-space: nowrap;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// @handle sub-line (messages).
|
|
187
|
+
&__handle {
|
|
188
|
+
font-size: @font-size-sm;
|
|
189
|
+
line-height: 20px;
|
|
190
|
+
color: var(--text-400);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Status pill sits below the action line, left-aligned.
|
|
194
|
+
&__status {
|
|
195
|
+
display: flex;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Edit/delete sit top-right, right of the name. Absolute + centred on the name
|
|
199
|
+
// row (24px) so taller buttons never push the description down.
|
|
200
|
+
&__trailing {
|
|
201
|
+
position: absolute;
|
|
202
|
+
top: 0;
|
|
203
|
+
right: 0;
|
|
204
|
+
height: 24px;
|
|
205
|
+
display: flex;
|
|
206
|
+
align-items: center;
|
|
207
|
+
gap: 8px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
&__actions {
|
|
211
|
+
display: flex;
|
|
212
|
+
align-items: center;
|
|
213
|
+
gap: 2px;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Row actions use the DS Button (icon-only). It carries its own styling — this
|
|
217
|
+
// class is only a hook for context tweaks if ever needed.
|
|
218
|
+
&__action-btn {
|
|
219
|
+
flex-shrink: 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Visually-hidden label (e.g. "Unread") — exposed to assistive tech only.
|
|
223
|
+
&__sr-only {
|
|
224
|
+
position: absolute;
|
|
225
|
+
width: 1px;
|
|
226
|
+
height: 1px;
|
|
227
|
+
margin: -1px;
|
|
228
|
+
padding: 0;
|
|
229
|
+
border: 0;
|
|
230
|
+
overflow: hidden;
|
|
231
|
+
clip: rect(0 0 0 0);
|
|
232
|
+
clip-path: inset(50%);
|
|
233
|
+
white-space: nowrap;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Unread indicator.
|
|
237
|
+
&__new-dot {
|
|
238
|
+
width: 10px;
|
|
239
|
+
height: 10px;
|
|
240
|
+
border-radius: 50%;
|
|
241
|
+
background-color: var(--brand-700);
|
|
242
|
+
flex-shrink: 0;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ---------- action line ----------
|
|
246
|
+
// Kept uniformly 16px/24px across every variant so the name→description gap is
|
|
247
|
+
// identical whether the item has a file, labels, text or nothing.
|
|
248
|
+
&__action {
|
|
249
|
+
color: var(--text-600);
|
|
250
|
+
|
|
251
|
+
a,
|
|
252
|
+
.bnv-feed-item__link {
|
|
253
|
+
color: var(--brand-700);
|
|
254
|
+
font-weight: @font-weight-medium;
|
|
255
|
+
text-decoration: none;
|
|
256
|
+
|
|
257
|
+
&:hover { text-decoration: underline; }
|
|
258
|
+
|
|
259
|
+
&:focus-visible {
|
|
260
|
+
outline: 2px solid var(--primary);
|
|
261
|
+
outline-offset: 2px;
|
|
262
|
+
border-radius: 0.125rem;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ---------- supporting: file ----------
|
|
268
|
+
// The file is its own hoverable target — download/delete belong to the document,
|
|
269
|
+
// so they sit on its right and reveal on hover/focus. A "card" outline is drawn
|
|
270
|
+
// just outside the content so nothing shifts when it appears.
|
|
271
|
+
&__file {
|
|
272
|
+
position: relative;
|
|
273
|
+
display: flex;
|
|
274
|
+
gap: 12px;
|
|
275
|
+
align-items: flex-start;
|
|
276
|
+
width: 100%;
|
|
277
|
+
min-width: 0;
|
|
278
|
+
|
|
279
|
+
&::before {
|
|
280
|
+
content: '';
|
|
281
|
+
position: absolute;
|
|
282
|
+
inset: -8px -12px;
|
|
283
|
+
border: 1px solid transparent;
|
|
284
|
+
border-radius: 0.5rem;
|
|
285
|
+
pointer-events: none;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
&:hover::before,
|
|
289
|
+
&:focus-within::before {
|
|
290
|
+
border-color: var(--border-200);
|
|
291
|
+
background-color: var(--white);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
> * { position: relative; } // keep content above the ::before card
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
&__file-icon {
|
|
298
|
+
flex-shrink: 0;
|
|
299
|
+
width: 32px;
|
|
300
|
+
height: 40px;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
&__file-text {
|
|
304
|
+
display: flex;
|
|
305
|
+
flex-direction: column;
|
|
306
|
+
flex: 1 1 auto;
|
|
307
|
+
min-width: 0;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
&__file-name {
|
|
311
|
+
color: var(--black);
|
|
312
|
+
overflow: hidden;
|
|
313
|
+
text-overflow: ellipsis;
|
|
314
|
+
white-space: nowrap;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
&__file-size {
|
|
318
|
+
font-size: @font-size-sm;
|
|
319
|
+
line-height: 20px;
|
|
320
|
+
color: var(--text-600);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Actions on the right of the file row — hidden until hover/focus.
|
|
324
|
+
&__file-actions {
|
|
325
|
+
display: flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
gap: 2px;
|
|
328
|
+
flex-shrink: 0;
|
|
329
|
+
align-self: center;
|
|
330
|
+
opacity: 0;
|
|
331
|
+
transition: opacity 0.12s ease;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
&__file:hover &__file-actions,
|
|
335
|
+
&__file:focus-within &__file-actions {
|
|
336
|
+
opacity: 1;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Touch devices have no hover — keep the actions visible there.
|
|
340
|
+
@media (hover: none) {
|
|
341
|
+
&__file-actions { opacity: 1; }
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ---------- supporting: labels ----------
|
|
345
|
+
&__labels {
|
|
346
|
+
display: flex;
|
|
347
|
+
flex-wrap: wrap;
|
|
348
|
+
gap: 4px;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// ---------- supporting: text (message bubble) ----------
|
|
352
|
+
&__bubble {
|
|
353
|
+
box-sizing: border-box;
|
|
354
|
+
width: 100%;
|
|
355
|
+
padding: 12px;
|
|
356
|
+
background-color: var(--white);
|
|
357
|
+
border: 1px solid var(--border-200);
|
|
358
|
+
// Speech-bubble: square top-left, rounded elsewhere.
|
|
359
|
+
border-radius: 0 8px 8px 8px;
|
|
360
|
+
box-shadow: @feed-bubble-shadow;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
&__text {
|
|
364
|
+
color: var(--black);
|
|
365
|
+
white-space: pre-wrap;
|
|
366
|
+
overflow-wrap: anywhere;
|
|
367
|
+
|
|
368
|
+
&.is-clamped {
|
|
369
|
+
display: -webkit-box;
|
|
370
|
+
-webkit-box-orient: vertical;
|
|
371
|
+
-webkit-line-clamp: 4; // overridden inline via clampLines
|
|
372
|
+
overflow: hidden;
|
|
373
|
+
position: relative;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Fade the last visible line while clamped and actually overflowing.
|
|
377
|
+
&.is-clamped.is-overflowing::after {
|
|
378
|
+
content: '';
|
|
379
|
+
position: absolute;
|
|
380
|
+
left: 0;
|
|
381
|
+
right: 0;
|
|
382
|
+
bottom: 0;
|
|
383
|
+
height: 1.4em;
|
|
384
|
+
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--white));
|
|
385
|
+
pointer-events: none;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// The toggle is the DS Button (text/link). Only position it below the text.
|
|
390
|
+
&__toggle {
|
|
391
|
+
align-self: flex-start;
|
|
392
|
+
margin-top: 8px;
|
|
393
|
+
}
|
|
394
|
+
}
|
package/asideSummaryCard.less
CHANGED
|
@@ -1,12 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AsideSummaryCard — new Figma "Summary card". BPO-15015. Node 10995:49133.
|
|
3
|
+
//
|
|
4
|
+
// Contract-preserving restyle: the card stays fluid (a sidebar sizes it, not the
|
|
5
|
+
// Figma fixed 376px) and keeps its `.summary-card*` classes. The card itself
|
|
6
|
+
// carries NO horizontal padding — each block (title, header, section) is inset
|
|
7
|
+
// 32px, so a section's divider can run full width while its text sits inset,
|
|
8
|
+
// exactly as Figma draws it. Blocks are spaced by a 20px column gap.
|
|
9
|
+
//
|
|
1
10
|
.summary-card {
|
|
2
11
|
background: var(--white);
|
|
3
|
-
padding: 24px;
|
|
4
12
|
border: 1px solid var(--border-200);
|
|
5
|
-
.border-radius(
|
|
13
|
+
.border-radius(16px);
|
|
14
|
+
padding: 26px 0;
|
|
15
|
+
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: 20px;
|
|
6
20
|
|
|
7
21
|
&__title {
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
width: 100%;
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
padding: 0 32px;
|
|
25
|
+
font-size: @font-size; // 16
|
|
26
|
+
line-height: 1.5rem; // 24
|
|
27
|
+
color: var(--black);
|
|
10
28
|
font-weight: @font-weight-semibold;
|
|
11
29
|
}
|
|
12
30
|
|
|
@@ -16,4 +34,49 @@
|
|
|
16
34
|
padding-left: 15px;
|
|
17
35
|
}
|
|
18
36
|
}
|
|
19
|
-
|
|
37
|
+
|
|
38
|
+
// ---- Opt-in: summary header (Figma "Summary header") -----------------
|
|
39
|
+
// Type=Assignment composes FlagFeatureIcon; Type=Feature icon composes
|
|
40
|
+
// FeaturedIcon; Type=Text passes no icon. The icon is a node either way.
|
|
41
|
+
&__header {
|
|
42
|
+
width: 100%;
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
padding: 0 32px;
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: 16px;
|
|
48
|
+
|
|
49
|
+
&-icon {
|
|
50
|
+
flex-shrink: 0;
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&-text {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
min-width: 0; // let long titles/meta ellipsis rather than push width
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&-title {
|
|
61
|
+
font-size: @h4-font-size; // 18 — DS has no dedicated 18px text token; h4 carries 18/28
|
|
62
|
+
line-height: @h4-line-height; // 28
|
|
63
|
+
color: var(--black);
|
|
64
|
+
font-weight: @font-weight-semibold;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&-meta {
|
|
68
|
+
font-size: @font-size; // 16
|
|
69
|
+
line-height: 1.5rem; // 24
|
|
70
|
+
color: var(--text-600);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---- Opt-in: empty state ---------------------------------------------
|
|
75
|
+
&__empty {
|
|
76
|
+
width: 100%;
|
|
77
|
+
box-sizing: border-box;
|
|
78
|
+
padding: 6px 32px;
|
|
79
|
+
display: flex;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -1,33 +1,66 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AsideSummaryCardSection — new Figma "Summary card" section + rows.
|
|
3
|
+
// BPO-15015. Nodes 10995:49049 (section) / 10995:49013 (input).
|
|
4
|
+
//
|
|
5
|
+
// Contract-preserving restyle: every `.summary-card-section*` class is kept, so
|
|
6
|
+
// consumers inherit the new look with no code change. Content is inset 32px; the
|
|
7
|
+
// section title's divider runs full width. Rows STACK (label 16/24 Text/600 over
|
|
8
|
+
// value 16/24 black, 4px apart) — the only layout. Blocks are spaced by a 20px
|
|
9
|
+
// column gap.
|
|
10
|
+
//
|
|
1
11
|
.summary-card-section {
|
|
2
|
-
|
|
3
|
-
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: 20px;
|
|
15
|
+
width: 100%;
|
|
16
|
+
font-size: @font-size; // 16
|
|
17
|
+
line-height: 1.5rem; // 24
|
|
4
18
|
|
|
5
19
|
&__title {
|
|
6
|
-
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
padding: 0 32px 12px;
|
|
7
22
|
border-bottom: 1px solid var(--border-200);
|
|
8
|
-
|
|
9
|
-
|
|
23
|
+
font-size: @font-size; // 16
|
|
24
|
+
line-height: 1.5rem; // 24
|
|
25
|
+
color: var(--black);
|
|
10
26
|
font-weight: @font-weight-semibold;
|
|
11
27
|
}
|
|
12
28
|
|
|
29
|
+
&__content {
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
padding: 0 32px;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 20px;
|
|
35
|
+
|
|
36
|
+
// Intro copy and step lists are supporting text — Text/600, not black.
|
|
37
|
+
p,
|
|
38
|
+
ol,
|
|
39
|
+
ul {
|
|
40
|
+
color: var(--text-600);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Full-width "View more" toggle (DS Button carries no fullWidth prop).
|
|
45
|
+
&__more {
|
|
46
|
+
width: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Stacked rows — the new default. Label above value, 4px apart.
|
|
50
|
+
// `!important` intentionally overrides the legacy inline `display` some
|
|
51
|
+
// consumers set on hand-written `__detail` rows, so the new stacked layout
|
|
52
|
+
// wins without touching their markup.
|
|
13
53
|
&__detail {
|
|
14
54
|
display: flex !important;
|
|
15
|
-
|
|
16
|
-
|
|
55
|
+
flex-direction: column;
|
|
56
|
+
gap: 4px;
|
|
17
57
|
|
|
18
58
|
&__label {
|
|
19
|
-
display: inline-block;
|
|
20
59
|
color: var(--text-600);
|
|
21
|
-
flex-basis: 50%;
|
|
22
|
-
padding-right: 10px;
|
|
23
60
|
}
|
|
24
61
|
|
|
25
62
|
&__value {
|
|
26
|
-
|
|
27
|
-
text-align: right;
|
|
28
|
-
overflow: hidden;
|
|
29
|
-
text-overflow: ellipsis;
|
|
30
|
-
white-space: nowrap;
|
|
63
|
+
color: var(--black);
|
|
31
64
|
|
|
32
65
|
i {
|
|
33
66
|
font-size: @font-size-xs;
|
|
@@ -35,4 +68,50 @@
|
|
|
35
68
|
}
|
|
36
69
|
}
|
|
37
70
|
}
|
|
38
|
-
|
|
71
|
+
|
|
72
|
+
// ---- Opt-in: avatar / user row (Figma "Summary input" Type=User) -----
|
|
73
|
+
&__user {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: 8px;
|
|
77
|
+
|
|
78
|
+
&-label {
|
|
79
|
+
color: var(--text-600);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&-row {
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
gap: 10px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&-info {
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
min-width: 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&-name {
|
|
95
|
+
font-size: @font-size-sm; // 14
|
|
96
|
+
line-height: 1.25rem; // 20
|
|
97
|
+
color: var(--black);
|
|
98
|
+
font-weight: @font-weight-semibold;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
&-email {
|
|
102
|
+
font-size: @font-size-sm; // 14
|
|
103
|
+
line-height: 1.25rem; // 20
|
|
104
|
+
color: var(--text-600);
|
|
105
|
+
overflow: hidden;
|
|
106
|
+
text-overflow: ellipsis;
|
|
107
|
+
white-space: nowrap;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ---- Opt-in: tag chips (Figma "Summary tags") ------------------------
|
|
112
|
+
&__tags {
|
|
113
|
+
display: flex;
|
|
114
|
+
flex-wrap: wrap;
|
|
115
|
+
gap: 8px;
|
|
116
|
+
}
|
|
117
|
+
}
|
package/avatar.less
CHANGED
|
@@ -144,11 +144,12 @@
|
|
|
144
144
|
}
|
|
145
145
|
&:focus-visible {
|
|
146
146
|
// Figma spec used a faint grey ring (rgba(152,162,179,0.14)) that fails
|
|
147
|
-
// WCAG 1.4.11/2.4.7 (~1.1:1) and diverges from DS focus rule.
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
outline
|
|
147
|
+
// WCAG 1.4.11/2.4.7 (~1.1:1) and diverges from DS focus rule. The DS halo
|
|
148
|
+
// is no better on its own at 1.37:1, so @focus-outline (--brand-500,
|
|
149
|
+
// 3.23:1) is the indicator; it also survives Windows High-Contrast /
|
|
150
|
+
// forced-colors mode, where the box-shadow is dropped.
|
|
151
|
+
outline: @focus-outline;
|
|
152
|
+
outline-offset: @focus-outline-offset;
|
|
152
153
|
box-shadow: @form-focus-box-shadow;
|
|
153
154
|
}
|
|
154
155
|
&:disabled {
|