@smwb/ui-styles 1.6.0 → 2.1.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/README.md +157 -22
- package/less/components/appBar/appBar.less +108 -0
- package/less/components/badge/badge.less +8 -0
- package/less/components/button/button.less +7 -1
- package/less/components/checkbox/checkbox.less +37 -3
- package/less/components/chip/chip.less +15 -3
- package/less/components/commandPalette/commandPalette.entry.less +2 -0
- package/less/components/commandPalette/commandPalette.less +233 -0
- package/less/components/composer/composer.entry.less +2 -0
- package/less/components/composer/composer.less +294 -0
- package/less/components/composer/composer.variables.less +10 -0
- package/less/components/diffStat/diffStat.entry.less +2 -0
- package/less/components/diffStat/diffStat.less +76 -0
- package/less/components/kbd/kbd.entry.less +2 -0
- package/less/components/kbd/kbd.less +55 -0
- package/less/components/list/list.less +39 -0
- package/less/components/qrCode/qrCode.entry.less +2 -0
- package/less/components/qrCode/qrCode.less +35 -0
- package/less/components/radioButton/radioButton.less +32 -0
- package/less/components/selectField/selectField.less +21 -4
- package/less/components/sidebar/sidebar.less +26 -0
- package/less/components/statusDot/statusDot.entry.less +2 -0
- package/less/components/statusDot/statusDot.less +118 -0
- package/less/components/swimlanes/swimlanes.entry.less +2 -0
- package/less/components/swimlanes/swimlanes.less +126 -0
- package/less/components/tabGroups/tabGroups.entry.less +2 -0
- package/less/components/tabGroups/tabGroups.less +219 -0
- package/less/components/tabs/tab/tab.less +134 -2
- package/less/components/tabs/tabPanel/tabPanel.entry.less +2 -0
- package/less/components/tabs/tabPanel/tabPanel.less +8 -0
- package/less/components/tabs/tabs.less +26 -0
- package/less/components/textField/textField.less +34 -9
- package/less/components/toggle/toggle.less +28 -1
- package/less/components/treeView/treeView.less +40 -2
- package/less/components.less +9 -0
- package/less/default/globals/default.variables.less +84 -0
- package/less/foundation/sizing.less +41 -5
- package/less/variables.less +10 -0
- package/package.json +5 -2
|
@@ -50,6 +50,13 @@
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// normalize.css removes the outline, and the state layer above is no ring: a tab
|
|
54
|
+
// reached by the arrow keys shows one of its own.
|
|
55
|
+
&:focus-visible {
|
|
56
|
+
outline: 2px solid var(--smui-primaryColor);
|
|
57
|
+
outline-offset: -2px;
|
|
58
|
+
}
|
|
59
|
+
|
|
53
60
|
&__content {
|
|
54
61
|
position: relative;
|
|
55
62
|
display: flex;
|
|
@@ -113,11 +120,136 @@
|
|
|
113
120
|
cursor: default;
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
//
|
|
117
|
-
//
|
|
123
|
+
// A tab with a close button or actions (Tab `closable`, `actions`) sits in an item with them:
|
|
124
|
+
// a control inside role="tab" would join the tab's name, so the controls are the tab's siblings.
|
|
125
|
+
// They stay in the tab list, which ARIA 1.2 lets own only tabs (see the README). The item is the
|
|
126
|
+
// row's flex child in the tab's place, and draws the hover layer over the whole of it, controls
|
|
127
|
+
// included.
|
|
128
|
+
.smwb-tab-item {
|
|
129
|
+
position: relative;
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
flex: 1 0 auto;
|
|
133
|
+
|
|
134
|
+
&:before {
|
|
135
|
+
position: absolute;
|
|
136
|
+
inset: 0;
|
|
137
|
+
opacity: 0;
|
|
138
|
+
content: "";
|
|
139
|
+
pointer-events: none;
|
|
140
|
+
transition: opacity 15ms linear;
|
|
141
|
+
background-color: @tabBgColor;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
&:hover:not(&--disabled):before {
|
|
145
|
+
opacity: @tabOpacityHover;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// The item's layer replaces the tab's own hover layer (focus keeps the tab's).
|
|
149
|
+
> .smwb-tab:hover:before {
|
|
150
|
+
opacity: 0;
|
|
151
|
+
}
|
|
152
|
+
> .smwb-tab:focus:before {
|
|
153
|
+
opacity: @tabOpacityFocus;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The controls take the room the tab's trailing padding was.
|
|
157
|
+
> .smwb-tab:not(:last-child) {
|
|
158
|
+
padding-right: @smui-space-sm;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.smwb-tab__close,
|
|
163
|
+
.smwb-tab__actions {
|
|
164
|
+
position: relative;
|
|
165
|
+
z-index: 1;
|
|
166
|
+
flex: 0 0 auto;
|
|
167
|
+
margin-right: @tabControlsGap;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.smwb-tab__actions {
|
|
171
|
+
display: inline-flex;
|
|
172
|
+
align-items: center;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.smwb-tab__close {
|
|
176
|
+
display: inline-flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
justify-content: center;
|
|
179
|
+
box-sizing: border-box;
|
|
180
|
+
width: @tabCloseSize;
|
|
181
|
+
height: @tabCloseSize;
|
|
182
|
+
padding: 0;
|
|
183
|
+
border: none;
|
|
184
|
+
border-radius: 50%;
|
|
185
|
+
background: none;
|
|
186
|
+
color: var(--smui-onSurfaceVariant);
|
|
187
|
+
cursor: pointer;
|
|
188
|
+
|
|
189
|
+
&:hover:not(:disabled) {
|
|
190
|
+
background-color: var(--smui-onSurfaceHover);
|
|
191
|
+
}
|
|
192
|
+
// normalize.css removes the outline: the close button is out of the Tab order but takes focus from a press or a screen reader.
|
|
193
|
+
&:focus-visible {
|
|
194
|
+
outline: 2px solid var(--smui-primaryColor);
|
|
195
|
+
outline-offset: -2px;
|
|
196
|
+
}
|
|
197
|
+
&:disabled {
|
|
198
|
+
opacity: 0.38;
|
|
199
|
+
cursor: default;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Compact tabs (Tabs dense): a shorter row, labels as written — no capitals, no letter spacing —
|
|
204
|
+
// and less padding, so more tabs fit in a row. The height is a token, not a literal, and min-height
|
|
205
|
+
// alone holds the row: the tab is a flex container and its label sets its own line box, so the plain
|
|
206
|
+
// tab's line-height already fits it. A dense row keeps its scroll buttons, its indicator and a
|
|
207
|
+
// closable tab's controls inside that height.
|
|
118
208
|
.smwb-tabs--dense .smwb-tab {
|
|
209
|
+
min-height: var(--smui-tabDenseHeight, @tabDenseHeight);
|
|
119
210
|
padding: 0 @tabDensePaddingX;
|
|
120
211
|
font-weight: 500;
|
|
121
212
|
letter-spacing: normal;
|
|
122
213
|
text-transform: none;
|
|
123
214
|
}
|
|
215
|
+
|
|
216
|
+
// The close button shows when it is reachable: the item is hovered (item not disabled),
|
|
217
|
+
// the item is the active tab, or focus is inside the item. The disabled button stays
|
|
218
|
+
// hidden; the reveal restores what the hidden defaults below took away. Hidden means
|
|
219
|
+
// opacity/pointer-events only — never `visibility`, so the button stays in the
|
|
220
|
+
// accessibility tree (its accessible name is computed, a screen reader reaches it) — and
|
|
221
|
+
// never size, so the row does not jump. Scoped under .smwb-tabs so the rules only ever
|
|
222
|
+
// match inside a tabs row (dense included); a standalone closable Tab outside a row
|
|
223
|
+
// renders its close button visible and clickable.
|
|
224
|
+
.smwb-tabs {
|
|
225
|
+
.smwb-tab__close {
|
|
226
|
+
opacity: 0;
|
|
227
|
+
pointer-events: none;
|
|
228
|
+
transition: opacity 0.15s linear;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.smwb-tab-item:hover:not(.smwb-tab-item--disabled) .smwb-tab__close:not(:disabled),
|
|
232
|
+
.smwb-tab-item--active .smwb-tab__close:not(:disabled),
|
|
233
|
+
.smwb-tab-item:focus-within .smwb-tab__close:not(:disabled) {
|
|
234
|
+
opacity: 1;
|
|
235
|
+
pointer-events: auto;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Drag-to-reorder states (Tabs `onReorder`): the dragged item dims, the drop target
|
|
239
|
+
// is marked with a 2px indicator line on its leading edge. The line rides above the
|
|
240
|
+
// item's hover layer and never takes pointer events.
|
|
241
|
+
.smwb-tab-item--dragging {
|
|
242
|
+
opacity: 0.6;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.smwb-tab-item--drop-target:after {
|
|
246
|
+
content: "";
|
|
247
|
+
position: absolute;
|
|
248
|
+
top: 0;
|
|
249
|
+
bottom: 0;
|
|
250
|
+
left: 0;
|
|
251
|
+
width: @tabsDragIndicatorSize;
|
|
252
|
+
background-color: var(--smui-primaryColor);
|
|
253
|
+
pointer-events: none;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// A tab panel is a tab stop of its own (Tab moves from the tab list into it), and
|
|
2
|
+
// normalize.css removes the focus outline, so it draws its own ring.
|
|
3
|
+
.smwb-tab-panel {
|
|
4
|
+
&:focus-visible {
|
|
5
|
+
outline: 2px solid var(--smui-primaryColor);
|
|
6
|
+
outline-offset: -2px;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -71,6 +71,32 @@
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// The overflow-menu trigger (Tabs `overflowMenu`) renders beside the scroller in the
|
|
75
|
+
// scroll buttons' spot: the same box, its own width token.
|
|
76
|
+
&__overflow-trigger {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
flex: 0 0 auto;
|
|
81
|
+
width: @tabsOverflowTriggerWidth;
|
|
82
|
+
padding: 0;
|
|
83
|
+
border: none;
|
|
84
|
+
background: none;
|
|
85
|
+
color: var(--smui-onSurfaceVariant);
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
&:hover:not(:disabled) {
|
|
88
|
+
background-color: var(--smui-onSurfaceHover);
|
|
89
|
+
}
|
|
90
|
+
&:focus-visible {
|
|
91
|
+
outline: 2px solid var(--smui-primaryColor);
|
|
92
|
+
outline-offset: -2px;
|
|
93
|
+
}
|
|
94
|
+
&:disabled {
|
|
95
|
+
opacity: 0.38;
|
|
96
|
+
cursor: default;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
74
100
|
&__indicator {
|
|
75
101
|
display: flex;
|
|
76
102
|
justify-content: center;
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
left: 0;
|
|
32
32
|
top: 0;
|
|
33
33
|
transform: translate(16px, 16px);
|
|
34
|
-
transition:
|
|
34
|
+
transition:
|
|
35
|
+
color 200ms cubic-bezier(0, 0, 0.2, 1) 0ms,
|
|
36
|
+
transform 200ms cubic-bezier(0, 0, 0.2, 1) 0ms,
|
|
35
37
|
max-width 200ms cubic-bezier(0, 0, 0.2, 1) 0ms;
|
|
36
38
|
user-select: none;
|
|
37
39
|
|
|
@@ -72,8 +74,14 @@
|
|
|
72
74
|
box-sizing: content-box;
|
|
73
75
|
width: 100%;
|
|
74
76
|
|
|
77
|
+
// The control height comes from min-height (see the size rules below), so the
|
|
78
|
+
// vertical padding is 0 and the text is centred in the border box.
|
|
75
79
|
&:not(&--inline) {
|
|
76
80
|
padding: @textFieldFilledInputPadding;
|
|
81
|
+
padding-top: 0;
|
|
82
|
+
padding-bottom: 0;
|
|
83
|
+
box-sizing: border-box;
|
|
84
|
+
min-height: var(--smui-control-h-md, @smui-control-h-md);
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
&::placeholder {
|
|
@@ -361,19 +369,36 @@
|
|
|
361
369
|
}
|
|
362
370
|
}
|
|
363
371
|
|
|
364
|
-
//
|
|
365
|
-
//
|
|
372
|
+
// The height of an outlined field is its @smui-control-h-* token (md is the base
|
|
373
|
+
// rule above): the input is border-box with no vertical padding, so min-height is
|
|
374
|
+
// the whole box. The resting label is centred by the same token: its 23px line box
|
|
375
|
+
// sits (height - 23) / 2 from the top, i.e. 4.5 / 8.5 / 12.5px for 32 / 40 / 48.
|
|
376
|
+
.smwb-text-field:not(.smwb-text-field--filled) .smwb-text-field__label:not(.smwb-text-field__label--shrink) {
|
|
377
|
+
transform: translate(16px, calc((var(--smui-control-h-md, @smui-control-h-md) - 23px) / 2));
|
|
378
|
+
}
|
|
366
379
|
.smwb-text-field_size-small .smwb-text-field__input:not(.smwb-text-field__input--inline) {
|
|
367
|
-
padding-top:
|
|
368
|
-
padding-bottom:
|
|
380
|
+
padding-top: 0;
|
|
381
|
+
padding-bottom: 0;
|
|
382
|
+
min-height: var(--smui-control-h-sm, @smui-control-h-sm);
|
|
369
383
|
font-size: @smui-control-font-sm;
|
|
370
384
|
}
|
|
371
|
-
// A resting label sits in the middle of the smaller field, not 16px down.
|
|
372
385
|
.smwb-text-field_size-small:not(.smwb-text-field--filled) .smwb-text-field__label:not(.smwb-text-field__label--shrink) {
|
|
373
|
-
transform: translate(16px, @smui-
|
|
386
|
+
transform: translate(16px, calc((var(--smui-control-h-sm, @smui-control-h-sm) - 23px) / 2));
|
|
374
387
|
}
|
|
375
388
|
.smwb-text-field_size-large .smwb-text-field__input:not(.smwb-text-field__input--inline) {
|
|
376
|
-
padding-top:
|
|
377
|
-
padding-bottom:
|
|
389
|
+
padding-top: 0;
|
|
390
|
+
padding-bottom: 0;
|
|
391
|
+
min-height: var(--smui-control-h-lg, @smui-control-h-lg);
|
|
378
392
|
font-size: @smui-control-font-lg;
|
|
379
393
|
}
|
|
394
|
+
.smwb-text-field_size-large:not(.smwb-text-field--filled) .smwb-text-field__label:not(.smwb-text-field__label--shrink) {
|
|
395
|
+
transform: translate(16px, calc((var(--smui-control-h-lg, @smui-control-h-lg) - 23px) / 2));
|
|
396
|
+
}
|
|
397
|
+
// A filled field keeps its own height: the shrunk label needs the 23px of top
|
|
398
|
+
// padding, so there min-height is not a floor and the box is the padding sum.
|
|
399
|
+
.smwb-text-field--filled .smwb-text-field__input:not(.smwb-text-field__input--inline) {
|
|
400
|
+
box-sizing: content-box;
|
|
401
|
+
min-height: 0;
|
|
402
|
+
padding-top: 23px;
|
|
403
|
+
padding-bottom: 10px;
|
|
404
|
+
}
|
|
@@ -17,6 +17,30 @@
|
|
|
17
17
|
align-items: center;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
// The size prop maps the row onto the control-height scale. :has() is what
|
|
22
|
+
// reaches it: the size class rides .smwb-toggle, the switch itself, while the row
|
|
23
|
+
// is its ancestor __wrapper — and putting min-height on the switch would stretch
|
|
24
|
+
// the 50x30 box, whose track fills its parent by height: 100%. So the switch
|
|
25
|
+
// keeps its geometry at every size (no @smui-selection-* edge applies to it: a
|
|
26
|
+
// track and a 15/20px thumb are not a selection box), and the 40px thumb halo
|
|
27
|
+
// (::before) stays unscaled with it — it already surrounds the largest switch.
|
|
28
|
+
// justify-content centers the switch inside the taller row in the default
|
|
29
|
+
// column layout; with a label above (top/unset placement) the wrapper is
|
|
30
|
+
// already 61px at every size, so the row min-height is inert there and
|
|
31
|
+
// nothing moves. In the row layouts (label left/right) it is a no-op.
|
|
32
|
+
&__wrapper:has(.smwb-toggle_size-small) {
|
|
33
|
+
min-height: var(--smui-control-h-sm, @smui-control-h-sm);
|
|
34
|
+
justify-content: center;
|
|
35
|
+
}
|
|
36
|
+
&__wrapper:has(.smwb-toggle_size-medium) {
|
|
37
|
+
min-height: var(--smui-control-h-md, @smui-control-h-md);
|
|
38
|
+
justify-content: center;
|
|
39
|
+
}
|
|
40
|
+
&__wrapper:has(.smwb-toggle_size-large) {
|
|
41
|
+
min-height: var(--smui-control-h-lg, @smui-control-h-lg);
|
|
42
|
+
justify-content: center;
|
|
43
|
+
}
|
|
20
44
|
&.smwb-disabled {
|
|
21
45
|
opacity: 0.35;
|
|
22
46
|
pointer-events: none;
|
|
@@ -46,7 +70,10 @@
|
|
|
46
70
|
transform: translateY(-50%);
|
|
47
71
|
top: 50%;
|
|
48
72
|
transition: all 0.2s ease-in-out;
|
|
49
|
-
box-shadow:
|
|
73
|
+
box-shadow:
|
|
74
|
+
0 3px 1px -2px rgb(0 0 0 / 20%),
|
|
75
|
+
0 2px 2px 0 rgb(0 0 0 / 14%),
|
|
76
|
+
0 1px 5px 0 rgb(0 0 0 / 12%);
|
|
50
77
|
&::before {
|
|
51
78
|
width: 40px;
|
|
52
79
|
height: 40px;
|
|
@@ -46,20 +46,58 @@
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
// Chevron, checkbox, the row's button and the actions are siblings: the button holds only the
|
|
50
|
+
// label, so a control beside it never sits inside a role="button".
|
|
51
|
+
&__row {
|
|
50
52
|
display: flex;
|
|
51
53
|
align-items: center;
|
|
52
54
|
gap: @treeViewItemGap;
|
|
53
55
|
// min-height, not height: a fixed row height let a wrapped two-line label
|
|
54
56
|
// overflow the node and overlap the next one.
|
|
55
57
|
min-height: 40px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&__toggle {
|
|
61
|
+
display: inline-flex;
|
|
62
|
+
flex: none;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
// Leaves keep the empty box so labels line up across levels.
|
|
66
|
+
width: 24px;
|
|
56
67
|
cursor: pointer;
|
|
57
68
|
user-select: none;
|
|
69
|
+
|
|
70
|
+
&:empty {
|
|
71
|
+
cursor: default;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&__content {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
flex: 1 1 auto;
|
|
79
|
+
min-width: 0;
|
|
80
|
+
align-self: stretch;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
user-select: none;
|
|
83
|
+
border-radius: 4px;
|
|
84
|
+
|
|
85
|
+
&:focus-visible {
|
|
86
|
+
outline: 2px solid var(--smui-primaryColor);
|
|
87
|
+
outline-offset: -2px;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&__actions {
|
|
92
|
+
display: inline-flex;
|
|
93
|
+
flex: none;
|
|
94
|
+
align-items: center;
|
|
95
|
+
gap: 4px;
|
|
58
96
|
}
|
|
59
97
|
}
|
|
60
98
|
}
|
|
61
99
|
|
|
62
|
-
.smwb-tree__node_selected > .smwb-
|
|
100
|
+
.smwb-tree__node_selected > .smwb-tree__node__row {
|
|
63
101
|
background-color: var(--smui-onSurfaceHover);
|
|
64
102
|
border-radius: 4px;
|
|
65
103
|
}
|
package/less/components.less
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
@import "./components/saveAssetDialog/saveAssetDialog.less";
|
|
14
14
|
@import "./components/progressIndicator/progressIndicator.less";
|
|
15
15
|
@import "./components/meter/meter.less";
|
|
16
|
+
@import "./components/diffStat/diffStat.less";
|
|
17
|
+
@import "./components/statusDot/statusDot.less";
|
|
18
|
+
@import "./components/qrCode/qrCode.less";
|
|
16
19
|
@import "./components/radioButton/radioButton.less";
|
|
17
20
|
@import "./components/sidebar/sidebar.less";
|
|
18
21
|
@import "./components/bottomBar/bottomBar.less";
|
|
@@ -23,6 +26,7 @@
|
|
|
23
26
|
@import "./components/overflowMenu/overflowMenu.less";
|
|
24
27
|
@import "./components/tabs/tabs.less";
|
|
25
28
|
@import "./components/tabs/tab/tab.less";
|
|
29
|
+
@import "./components/tabs/tabPanel/tabPanel.less";
|
|
26
30
|
@import "./components/slider/slider.less";
|
|
27
31
|
@import "./components/valueSlider/valueSlider.less";
|
|
28
32
|
@import "./components/selectField/selectField.less";
|
|
@@ -36,6 +40,8 @@
|
|
|
36
40
|
@import "./components/assetGrid/assetGrid.less";
|
|
37
41
|
@import "./components/grid/grid.less";
|
|
38
42
|
@import "./components/tooltip/tooltip.less";
|
|
43
|
+
@import "./components/kbd/kbd.less";
|
|
44
|
+
@import "./components/commandPalette/commandPalette.less";
|
|
39
45
|
@import "./components/sheet/sheet.less";
|
|
40
46
|
@import "./components/floatingWindow/floatingWindow.less";
|
|
41
47
|
@import "./components/badge/badge.less";
|
|
@@ -50,6 +56,7 @@
|
|
|
50
56
|
@import "./components/table/tablePagination/tablePagination.less";
|
|
51
57
|
@import "./components/icon/icon.less";
|
|
52
58
|
@import "./components/screenDivider/screenDivider.less";
|
|
59
|
+
@import "./components/tabGroups/tabGroups.less";
|
|
53
60
|
@import "./components/datePicker/dataPicker.less";
|
|
54
61
|
@import "./components/timePicker/timePicker.less";
|
|
55
62
|
@import "./components/treeView/treeView.less";
|
|
@@ -65,6 +72,8 @@
|
|
|
65
72
|
@import "./components/skeleton/skeleton.less";
|
|
66
73
|
@import "./components/chart/chart.less";
|
|
67
74
|
@import "./components/dagView/dagView.less";
|
|
75
|
+
@import "./components/swimlanes/swimlanes.less";
|
|
76
|
+
@import "./components/composer/composer.less";
|
|
68
77
|
@import "./components/stepper/stepper.less";
|
|
69
78
|
@import "./components/typography/typography.less";
|
|
70
79
|
@import "./components/stack/stack.less";
|
|
@@ -120,8 +120,17 @@
|
|
|
120
120
|
@appBarPaddingX: @smui-space-lg;
|
|
121
121
|
@appBarActionPadding: @smui-space-md;
|
|
122
122
|
@appBarActionsGap: 10px; // off-grid
|
|
123
|
+
// Width reserved for the OS window buttons in `AppBar variant="window"`: the macOS traffic lights of Electron's
|
|
124
|
+
// `hiddenInset` end around 70-78px, so with @appBarPaddingX the content starts at 80px; Windows/Linux draw three
|
|
125
|
+
// 46px caption buttons. Not theme tokens — an app overrides both sides with --smui-appBarWindowControlsWidth.
|
|
126
|
+
@appBarWindowControlsLeft: 64px;
|
|
127
|
+
@appBarWindowControlsRight: 138px;
|
|
123
128
|
|
|
124
129
|
@badgePaddingX: 6px; // off-grid
|
|
130
|
+
// The `warning` badge fills with the theme's amber, which is light: white text on
|
|
131
|
+
// it measures 3.1:1, under the 4.5:1 WCAG AA needs at the badge's 12px label, so
|
|
132
|
+
// this one carries dark ink instead of @onWarningColor. 5.5:1 on @warningColor.
|
|
133
|
+
@badgeWarningColor: #1c1b1f;
|
|
125
134
|
|
|
126
135
|
@buttonGap: @smui-space-sm;
|
|
127
136
|
@buttonPaddingSmall: @smui-space-xs 10px; // 10 off-grid
|
|
@@ -168,6 +177,33 @@
|
|
|
168
177
|
@progressDotMargin: @smui-space-xs;
|
|
169
178
|
@meterHeight: 6px;
|
|
170
179
|
@meterMinBarWidth: 3.5rem; // the bar keeps at least this much beside its text
|
|
180
|
+
@statusDotSizeSm: 8px; // @smui-space-2
|
|
181
|
+
@statusDotSizeMd: 12px; // @smui-space-3
|
|
182
|
+
@statusDotRing: 2px; // the unknown status is a ring this thick
|
|
183
|
+
|
|
184
|
+
// A QR code is always dark modules on a white square — never theme tokens, so no
|
|
185
|
+
// theme (or forced-colours mode, see the component's print/forced-color-adjust) can
|
|
186
|
+
// invert it.
|
|
187
|
+
@qrCodeDarkColor: rgb(0 0 0);
|
|
188
|
+
@qrCodeLightColor: rgb(255 255 255);
|
|
189
|
+
@qrCodeRadius: @smui-radius-sm;
|
|
190
|
+
|
|
191
|
+
@kbdGap: @smui-space-xxs;
|
|
192
|
+
@kbdKeyMinSize: 1.5em; // a key cap is square at one character
|
|
193
|
+
@kbdKeyPaddingX: 0.375em;
|
|
194
|
+
@kbdKeyRadius: @smui-radius-sm;
|
|
195
|
+
// ---- DiffStat ----
|
|
196
|
+
@diffStatFontSize: 0.875rem;
|
|
197
|
+
@diffStatCompactFontSize: 0.75rem; // a tab label
|
|
198
|
+
@diffStatGap: @smui-space-xs; // the figures to the bar
|
|
199
|
+
@diffStatSignGap: @smui-space-xxs; // "+N" to "−M"
|
|
200
|
+
@diffStatCellWidth: 5px;
|
|
201
|
+
@diffStatCellHeight: 10px;
|
|
202
|
+
@diffStatCompactCellHeight: 8px;
|
|
203
|
+
@diffStatCellGap: @smui-space-xxs;
|
|
204
|
+
@diffStatCellRadius: 2px;
|
|
205
|
+
@diffStatColorMix: 55%; // how much of the success/error token survives against the surface ink
|
|
206
|
+
@diffStatNeutralMix: 60%; // how much surface ink an unowned cell's outline keeps (3:1 or better against the page)
|
|
171
207
|
|
|
172
208
|
@screenDividerLabelMargin: 5px; // off-grid
|
|
173
209
|
|
|
@@ -224,8 +260,19 @@
|
|
|
224
260
|
@tabIconPaddingBottom: @smui-space-xs;
|
|
225
261
|
@tabLabelPaddingLeft: @smui-space-sm;
|
|
226
262
|
@tabDensePaddingX: @smui-space-md;
|
|
263
|
+
@tabDenseHeight: 36px; // off-grid; the row height of Tabs dense, the height of the compact onreel strips
|
|
264
|
+
@tabCloseSize: @smui-space-6; // the close button of a closable tab
|
|
265
|
+
@tabControlsGap: @smui-space-xs; // between a tab's close button, its actions and the row's next tab
|
|
227
266
|
@tabsFadeWidth: 2.5rem; // scrollable row: the fading edge beyond which tabs are hidden
|
|
228
267
|
@tabsScrollButtonWidth: 40px;
|
|
268
|
+
@tabsOverflowTriggerWidth: @tabsScrollButtonWidth; // the "more tabs" trigger beside the scroller (Tabs `overflowMenu`)
|
|
269
|
+
@tabsDragIndicatorSize: 2px; // off-grid; the drop-target line of a drag-to-reorder
|
|
270
|
+
|
|
271
|
+
// ---- TabGroups ----
|
|
272
|
+
@tabGroupsSeparatorSize: 4px; // off-grid; the grid track a separator between two groups sits in
|
|
273
|
+
@tabGroupsSeparatorHitArea: 8px; // off-grid; the invisible grip around that track
|
|
274
|
+
@tabGroupsDropTintOpacity: 0.16; // how much primary the zone a dragged tab would land in shows
|
|
275
|
+
@tabGroupsActiveLineWidth: 2px; // off-grid; the line over the header of the group in use
|
|
229
276
|
|
|
230
277
|
@tableCellPaddingX: @smui-space-lg;
|
|
231
278
|
@tableToolbarMarginBottom: 10px; // off-grid
|
|
@@ -498,6 +545,43 @@
|
|
|
498
545
|
// The graph's height when the app sets none (its `height` prop or `style`).
|
|
499
546
|
@dagViewHeight: 480px;
|
|
500
547
|
|
|
548
|
+
// ---- Swimlanes ----
|
|
549
|
+
// The fixed header column's width when the app sets none (its `headerWidth`
|
|
550
|
+
// prop writes --smwb-swimlanes-header-width, which these fallbacks read).
|
|
551
|
+
@swimlanesHeaderWidth: 240px;
|
|
552
|
+
// The grid's height when the app sets none (its `height` prop or `style`).
|
|
553
|
+
@swimlanesHeight: 480px;
|
|
554
|
+
|
|
555
|
+
// ---- CommandPalette ----
|
|
556
|
+
// Escaped: Less would otherwise try to compute the mixed-unit min()/calc().
|
|
557
|
+
@commandPaletteWidth: ~"min(640px, calc(100vw - 32px))";
|
|
558
|
+
// The palette hangs near the top of the overlay, not centred, so that its
|
|
559
|
+
// bottom edge - and the row the keys are on - does not move as results arrive.
|
|
560
|
+
@commandPaletteTopOffset: ~"min(12vh, 96px)";
|
|
561
|
+
@commandPaletteMaxHeight: ~"min(560px, calc(100vh - 2 * min(12vh, 96px)))";
|
|
562
|
+
@commandPaletteItemMinHeight: 44px; // a pointer target, WCAG 2.5.5
|
|
563
|
+
@commandPaletteItemRadius: @smui-radius-sm;
|
|
564
|
+
@commandPaletteIconSize: 20px;
|
|
565
|
+
@commandPaletteActiveLayerOpacity: 0.12; // focus state layer, as menu items
|
|
566
|
+
@commandPaletteHoverLayerOpacity: 0.08;
|
|
567
|
+
// ---- Composer ----
|
|
568
|
+
// The task input's colours, as theme variables. The defaults are the theme's
|
|
569
|
+
// runtime tokens, so the dark theme follows without extra settings.
|
|
570
|
+
@composerBg: ~"var(--smui-surfaceBackground)";
|
|
571
|
+
@composerBorder: ~"var(--smui-outlineColor)";
|
|
572
|
+
@composerBorderFocus: ~"var(--smui-primaryColor)";
|
|
573
|
+
@composerText: ~"var(--smui-onSurfaceColor)";
|
|
574
|
+
@composerPlaceholder: ~"var(--smui-onSurfaceVariant)";
|
|
575
|
+
@composerCounter: ~"var(--smui-onSurfaceVariant)";
|
|
576
|
+
@composerCounterError: ~"var(--smui-errorColor)";
|
|
577
|
+
// The send button, and the stop button while the agent is busy.
|
|
578
|
+
@composerActionBg: ~"var(--smui-primaryColor)";
|
|
579
|
+
@composerActionColor: ~"var(--smui-onPrimaryColor)";
|
|
580
|
+
@composerStopBg: ~"var(--smui-onSurfaceColor)";
|
|
581
|
+
@composerStopColor: ~"var(--smui-surfaceBackground)";
|
|
582
|
+
// The surface while files are dragged over it.
|
|
583
|
+
@composerDragBg: ~"var(--smui-primaryContainer)";
|
|
584
|
+
|
|
501
585
|
/*===================================================== DARK THEME =================================================*/
|
|
502
586
|
/*-------------------
|
|
503
587
|
Common
|
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
//=====================================================================
|
|
2
2
|
// Control sizing scale (small / medium / large)
|
|
3
3
|
//---------------------------------------------------------------------
|
|
4
|
-
//
|
|
5
|
-
// (
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// The height tokens @smui-control-h-sm/md/lg are consumed via
|
|
5
|
+
// min-height: var(--smui-control-h-*, @smui-control-h-*) by:
|
|
6
|
+
// - Button (sm/md/lg size classes)
|
|
7
|
+
// - TextField and SelectField (base = md, plus sm/lg size classes)
|
|
8
|
+
// - Chip (default box; its _size-small 24px step stays hardcoded)
|
|
9
|
+
// - Checkbox, RadioButton (_size-small/-medium/-large row classes) and
|
|
10
|
+
// Toggle (row min-height via .smwb-toggle__wrapper:has(.smwb-toggle_size-*))
|
|
11
|
+
// The runtime tokens --smui-control-h-* are declared in variables.less
|
|
12
|
+
// (light mixin only — the same :root block applies under data-theme="dark",
|
|
13
|
+
// so a dark re-declaration would reset a consumer's global density override),
|
|
14
|
+
// and a subtree can override the height at runtime.
|
|
15
|
+
//
|
|
16
|
+
// Variant exemptions: TextField/SelectField --filled and --inline keep their
|
|
17
|
+
// own padding (no token read), radio _size-medium keeps its hardcoded 20px
|
|
18
|
+
// box, and Chip _size-small keeps 24px hardcoded.
|
|
19
|
+
//
|
|
20
|
+
// @smui-control-font-sm/lg is consumed by TextField/SelectField only;
|
|
21
|
+
// @smui-control-font-md is defined but not yet consumed (reserved).
|
|
22
|
+
//
|
|
23
|
+
// Defined but not yet consumed (reserved): @smui-control-px-* and
|
|
24
|
+
// @smui-icon-*. @smui-selection-* is consumed only by the checkbox box
|
|
25
|
+
// edges and the radio sm/lg box edges (radio md is hardcoded 20px);
|
|
26
|
+
// beyond that it is reserved.
|
|
27
|
+
//
|
|
28
|
+
// Intentionally exempt (do not wire without a design decision):
|
|
29
|
+
// - FloatingButton: Material FAB spec diameters (56/48/40, extended
|
|
30
|
+
// 48/40/34) are their own scale, not the control scale
|
|
31
|
+
// - Avatar: identity badge (@avatarSizeSmall/Medium/Large 24/40/56),
|
|
32
|
+
// not an interactive control
|
|
33
|
+
// - Pagination: has its own item scale (@paginationItemSize 32 /
|
|
34
|
+
// @paginationItemSizeSmall 26)
|
|
35
|
+
// - ProgressIndicator: indicator diameter (28px), not a control box
|
|
36
|
+
// - StatusDot: decorative dot (@statusDotSizeSm/Md); also uses the
|
|
37
|
+
// _size-sm suffix, a different class convention
|
|
38
|
+
// - Slider: size scales track thickness and thumb diameter, not a
|
|
39
|
+
// control height
|
|
40
|
+
// - Modal: size selects dialog width, not control height
|
|
41
|
+
// - Rating: size is a pixel number, not a three-step variant
|
|
42
|
+
// - DatePicker / TimePicker / DateTimePicker: compose TextField +
|
|
43
|
+
// Button, so they inherit the tokens
|
|
8
44
|
//
|
|
9
45
|
// Override one step from theme.config, e.g. @smui-control-h-md: 44px;
|
|
10
46
|
//=====================================================================
|
|
@@ -24,7 +60,7 @@
|
|
|
24
60
|
@smui-control-font-md: 14px;
|
|
25
61
|
@smui-control-font-lg: 16px;
|
|
26
62
|
|
|
27
|
-
// Selection-control box (checkbox/radio/
|
|
63
|
+
// Selection-control box edges (checkbox sm/md/lg, radio sm/lg)
|
|
28
64
|
@smui-selection-sm: 16px;
|
|
29
65
|
@smui-selection-md: 18px;
|
|
30
66
|
@smui-selection-lg: 22px;
|
package/less/variables.less
CHANGED
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
|
|
58
58
|
--smui-dividerColor: @dividerColor;
|
|
59
59
|
|
|
60
|
+
// Mode-independent (the amber is the same in dark), so light-only, like --smui-control-h-*:
|
|
61
|
+
// a dark-mixin copy would reset a consumer's :root override in dark mode.
|
|
62
|
+
--smui-badgeWarningColor: @badgeWarningColor;
|
|
63
|
+
|
|
60
64
|
--smui-buttonOutlinedHoverBg: @buttonOutlinedHoverBg;
|
|
61
65
|
--smui-buttonOutlinedActiveBg: @buttonOutlinedActiveBg;
|
|
62
66
|
--smui-buttonOutlinedFocusBg: @buttonOutlinedFocusBg;
|
|
@@ -88,6 +92,7 @@
|
|
|
88
92
|
|
|
89
93
|
--smui-tabIconColor: @tabIconColor;
|
|
90
94
|
--smui-tabColorDefault: @tabColorDefault;
|
|
95
|
+
--smui-tabDenseHeight: @tabDenseHeight;
|
|
91
96
|
|
|
92
97
|
--smui-sliderColor: @sliderColor;
|
|
93
98
|
--smui-sliderDisabledColor: @sliderDisabledColor;
|
|
@@ -142,6 +147,11 @@
|
|
|
142
147
|
--smui-space-xxl: @smui-space-xxl;
|
|
143
148
|
--smui-space-xxxl: @smui-space-xxxl;
|
|
144
149
|
|
|
150
|
+
// Control heights (overridable at runtime by client apps, e.g. a density switch)
|
|
151
|
+
--smui-control-h-sm: @smui-control-h-sm;
|
|
152
|
+
--smui-control-h-md: @smui-control-h-md;
|
|
153
|
+
--smui-control-h-lg: @smui-control-h-lg;
|
|
154
|
+
|
|
145
155
|
/* Border-radius scale */
|
|
146
156
|
--smui-radius-xs: @smui-radius-xs;
|
|
147
157
|
--smui-radius-sm: @smui-radius-sm;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smwb/ui-styles",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Framework-agnostic LESS design tokens and component styles (smwb-*) shared by the @smwb UI libraries. Prebuilt aggregate CSS lives in @smwb/ui-css.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sideEffects": [
|
|
@@ -19,12 +19,15 @@
|
|
|
19
19
|
"./package.json": "./package.json"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
|
-
"lint": "node scripts/check-aggregate.mjs && node scripts/check-tokens.mjs && node scripts/check-typography-case.mjs && node scripts/check-chart-series.mjs"
|
|
22
|
+
"lint": "node scripts/check-aggregate.mjs && node scripts/check-tokens.mjs && node scripts/check-control-heights.mjs && node scripts/check-typography-case.mjs && node scripts/check-chart-series.mjs"
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://sourcecraft.dev/elfenmail/ui",
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|
|
27
27
|
"url": "git+https://git.sourcecraft.dev/elfenmail/ui.git",
|
|
28
28
|
"directory": "packages/styles"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"less": "^4.6.4"
|
|
29
32
|
}
|
|
30
33
|
}
|