@smwb/ui-styles 2.3.0 → 2.5.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.
@@ -13,7 +13,7 @@
13
13
  display: flex;
14
14
  align-items: stretch;
15
15
  width: 100%;
16
- min-height: 56px;
16
+ min-height: @bottomBarHeight;
17
17
  }
18
18
 
19
19
  &__item {
@@ -53,6 +53,13 @@
53
53
  &:hover {
54
54
  background-color: var(--smui-onSurfaceActive);
55
55
  }
56
+
57
+ // On a coarse pointer the "..." button is a square of the sm step (44px there): it is
58
+ // otherwise as tall as a line of text and as wide as its dots.
59
+ @media (pointer: coarse) {
60
+ min-width: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
61
+ min-height: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
62
+ }
56
63
  }
57
64
 
58
65
  // One line: the list never wraps, the crumbs shrink and cut their text with an
@@ -6,14 +6,14 @@
6
6
  box-sizing: border-box;
7
7
  margin: 0;
8
8
  border: 0;
9
- padding: @composerFieldPaddingY @composerFieldPaddingX;
9
+ padding: var(--smwb-composer-field-padding-y, @composerFieldPaddingY) @composerFieldPaddingX;
10
10
  font: inherit;
11
11
  letter-spacing: inherit;
12
12
  line-height: @composerLineHeight;
13
13
  overflow-wrap: anywhere;
14
14
  // The height of N rows of text, with the text's own padding.
15
- min-height: ~"calc(var(--smwb-composer-min-rows, 1) * @{composerLineHeight} + 2 * @{composerFieldPaddingY})";
16
- max-height: ~"calc(var(--smwb-composer-max-rows, 8) * @{composerLineHeight} + 2 * @{composerFieldPaddingY})";
15
+ min-height: ~"calc(var(--smwb-composer-min-rows, 1) * @{composerLineHeight} + 2 * var(--smwb-composer-field-padding-y, @{composerFieldPaddingY}))";
16
+ max-height: ~"calc(var(--smwb-composer-max-rows, 8) * @{composerLineHeight} + 2 * var(--smwb-composer-field-padding-y, @{composerFieldPaddingY}))";
17
17
  }
18
18
 
19
19
  // A task input: a growing textarea with an attach button, a toolbar slot, a
@@ -36,6 +36,15 @@
36
36
  background-color: @composerBg;
37
37
  color: @composerText;
38
38
 
39
+ // Touch density: the icon buttons are the sm step (44px there) at least, and the one-line
40
+ // field grows with them (24px of text + 2 * padding = the button), so the row stays level.
41
+ // @composerIconButtonSize is a literal that composer.variables.less declares again after the
42
+ // theme, so the step is the way to raise it: @smui-control-h-sm-coarse.
43
+ @media (pointer: coarse) {
44
+ --smwb-composer-icon-button-size: max(@composerIconButtonSize, var(--smui-control-h-sm, @smui-control-h-sm-coarse));
45
+ --smwb-composer-field-padding-y: calc((var(--smwb-composer-icon-button-size) - @composerLineHeight) / 2);
46
+ }
47
+
39
48
  &__attachments {
40
49
  grid-area: attachments;
41
50
  min-width: 0;
@@ -86,8 +95,8 @@
86
95
  justify-content: center;
87
96
  box-sizing: border-box;
88
97
  flex: none;
89
- width: @composerIconButtonSize;
90
- height: @composerIconButtonSize;
98
+ width: var(--smwb-composer-icon-button-size, @composerIconButtonSize);
99
+ height: var(--smwb-composer-icon-button-size, @composerIconButtonSize);
91
100
  margin: 0;
92
101
  padding: 0;
93
102
  border: 0;
@@ -244,7 +253,7 @@
244
253
  .smwb-composer__counter {
245
254
  // On the bottom row of text, level with the action.
246
255
  align-self: end;
247
- padding-bottom: ~"calc((@{composerIconButtonSize} - 1rem) / 2)";
256
+ padding-bottom: ~"calc((var(--smwb-composer-icon-button-size, @{composerIconButtonSize}) - 1rem) / 2)";
248
257
  }
249
258
 
250
259
  .smwb-composer__attach ~ .smwb-composer__toolbar {
@@ -267,6 +267,11 @@
267
267
  width: 32px;
268
268
  height: 32px;
269
269
  padding: 0;
270
+ // On a coarse pointer the buttons are the sm step (44px there) at least.
271
+ @media (pointer: coarse) {
272
+ width: max(32px, var(--smui-control-h-sm, @smui-control-h-sm-coarse));
273
+ height: max(32px, var(--smui-control-h-sm, @smui-control-h-sm-coarse));
274
+ }
270
275
  border: 1px solid var(--smui-dividerColor);
271
276
  border-radius: @smui-radius-md;
272
277
  background-color: var(--smui-surfaceBackground);
@@ -93,6 +93,19 @@
93
93
  padding: @datePickerYearPadding;
94
94
  }
95
95
 
96
+ // On a coarse pointer the TextField adornment button is a square of the sm step (44px there)
97
+ // at least, the icon in the middle; the 36px it was is padding around the 24px glyph. The
98
+ // popup's small month and year arrows keep their 34px.
99
+ @media (pointer: coarse) {
100
+ &:not(&--small) {
101
+ box-sizing: border-box;
102
+ align-items: center;
103
+ justify-content: center;
104
+ min-width: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
105
+ min-height: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
106
+ }
107
+ }
108
+
96
109
  &--edge-start {
97
110
  margin-left: -12px;
98
111
  }
@@ -99,6 +99,40 @@
99
99
  cursor: pointer;
100
100
  }
101
101
 
102
+ // Touch density: on a coarse pointer the clear button and the delete button of a value chip
103
+ // answer a press from a square of the sm step (44px there), not the small icon they draw.
104
+ // The clear button is that square itself, in the actions row: its neighbours, the dropdown
105
+ // arrow and the control, keep their own boxes, so a press on the arrow opens the menu and
106
+ // never clears it. The negative margin keeps the height the icon gave the field; the row
107
+ // grows wider by what the square adds. A chip's delete button is laid over a bigger box by
108
+ // a pseudo-element (a chip must not grow): the box starts at the icon, so it never reaches
109
+ // back over the label, whose press opens the menu, and extends to the right, into the
110
+ // chip's padding; the next chip is positioned later and paints over it.
111
+ @media (pointer: coarse) {
112
+ &__clear {
113
+ align-items: center;
114
+ justify-content: center;
115
+ box-sizing: border-box;
116
+ width: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
117
+ height: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
118
+ margin: calc((16px - var(--smui-control-h-sm, @smui-control-h-sm-coarse)) / 2) 0;
119
+ }
120
+
121
+ .smwb-chip__delete-icon {
122
+ position: relative;
123
+
124
+ &::after {
125
+ content: "";
126
+ position: absolute;
127
+ top: 50%;
128
+ left: 0;
129
+ width: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
130
+ height: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
131
+ transform: translateY(-50%);
132
+ }
133
+ }
134
+ }
135
+
102
136
  &__values {
103
137
  white-space: nowrap;
104
138
  font: inherit;
@@ -3,6 +3,10 @@
3
3
  // sets it from its `offsetTop` prop and `AppLayout` publishes its sticky header's height as the
4
4
  // page default, so a panel starts below the header; with neither it is 0 and nothing moves.
5
5
  @sheetOffsetTop: var(--smui-sheet-offset-top, 0px);
6
+ // Gap between the bottom edge of the window and the bottom of the sheet and of its modal scrim. `BottomBar`
7
+ // publishes its height (with the safe-area inset) as the page default, so a panel stops above the bar; with the
8
+ // bar absent it is 0 and nothing moves.
9
+ @sheetOffsetBottom: var(--smui-bottom-bar-offset, 0px);
6
10
 
7
11
  background-color: var(--smui-surfaceBackground);
8
12
  position: fixed;
@@ -20,6 +24,11 @@
20
24
  display: flex;
21
25
  max-width: 100vw;
22
26
 
27
+ // A finger is dragging the panel (swipe to dismiss): it follows without easing.
28
+ &[data-smwb-swiping] {
29
+ transition: none;
30
+ }
31
+
23
32
  &__header {
24
33
  display: flex;
25
34
  justify-content: space-between;
@@ -30,6 +39,12 @@
30
39
 
31
40
  .smwb-button {
32
41
  min-width: 0;
42
+
43
+ // On a coarse pointer the close and size buttons are as wide as they are tall (the sm
44
+ // step, 44px there); their padding made them 42px wide.
45
+ @media (pointer: coarse) {
46
+ min-width: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
47
+ }
33
48
  }
34
49
  }
35
50
 
@@ -121,10 +136,12 @@
121
136
 
122
137
  &.smwb-bottom {
123
138
  border-radius: @sheetBorderRadius @sheetBorderRadius 0 0;
124
- bottom: 0;
139
+ bottom: @sheetOffsetBottom;
125
140
  left: 0;
126
141
  width: 100%;
127
142
  height: var(--sizeProp);
143
+ // A tall panel stops at the top of the window (below any offset) instead of running past it by the bar's height.
144
+ max-height: calc(100% - @sheetOffsetTop - @sheetOffsetBottom);
128
145
  transform: translateY(100%);
129
146
  flex-direction: column;
130
147
  .smwb-sheet__header {
@@ -139,7 +156,7 @@
139
156
  width: 100%;
140
157
  height: var(--sizeProp);
141
158
  // A tall panel stops at the bottom of the window instead of running past it by the offset.
142
- max-height: calc(100% - @sheetOffsetTop);
159
+ max-height: calc(100% - @sheetOffsetTop - @sheetOffsetBottom);
143
160
  transform: translateY(-100%);
144
161
  flex-direction: column;
145
162
  .smwb-sheet__header {
@@ -151,7 +168,7 @@
151
168
  border-radius: 0 @sheetBorderRadius @sheetBorderRadius 0;
152
169
  top: @sheetOffsetTop;
153
170
  left: 0;
154
- height: calc(100% - @sheetOffsetTop);
171
+ height: calc(100% - @sheetOffsetTop - @sheetOffsetBottom);
155
172
  width: var(--sizeProp);
156
173
  transform: translateX(-100%);
157
174
  flex-direction: row-reverse;
@@ -166,7 +183,7 @@
166
183
  border-radius: @sheetBorderRadius 0 0 @sheetBorderRadius;
167
184
  top: @sheetOffsetTop;
168
185
  right: 0;
169
- height: calc(100% - @sheetOffsetTop);
186
+ height: calc(100% - @sheetOffsetTop - @sheetOffsetBottom);
170
187
  width: var(--sizeProp);
171
188
  transform: translateX(100%);
172
189
  .smwb-sheet__header {
@@ -180,7 +197,7 @@
180
197
  top: @sheetOffsetTop;
181
198
  left: 0;
182
199
  width: 100%;
183
- height: calc(100% - @sheetOffsetTop);
200
+ height: calc(100% - @sheetOffsetTop - @sheetOffsetBottom);
184
201
  display: flex;
185
202
  flex-direction: column;
186
203
  z-index: 100;
@@ -203,7 +220,7 @@
203
220
  .smwb-sheet {
204
221
  opacity: 1;
205
222
  &.smwb-bottom {
206
- transform: translateY(0);
223
+ transform: translateY(var(--smwb-sheet-swipe, 0px));
207
224
  &.smwb-expanded {
208
225
  height: 90%;
209
226
  }
@@ -221,7 +238,7 @@
221
238
  }
222
239
  }
223
240
  &.smwb-left {
224
- transform: translateX(0);
241
+ transform: translateX(var(--smwb-sheet-swipe, 0px));
225
242
  &.smwb-expanded {
226
243
  width: 90%;
227
244
  }
@@ -230,7 +247,7 @@
230
247
  }
231
248
  }
232
249
  &.smwb-right {
233
- transform: translateX(0);
250
+ transform: translateX(var(--smwb-sheet-swipe, 0px));
234
251
  &.smwb-expanded {
235
252
  width: 90%;
236
253
  }
@@ -292,3 +292,29 @@
292
292
  white-space: nowrap;
293
293
  opacity: 0.7;
294
294
  }
295
+
296
+ // Touch density: on a coarse pointer the zone that takes a press on the rail, the padding around
297
+ // it, is the sm step (44px there) across, 30px otherwise, and so is the thumb's own zone. A mouse
298
+ // keeps all of it. The mark labels hang from the marks, which are centred on the rail, so they follow it.
299
+ @sliderTouchHit: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
300
+ @media (pointer: coarse) {
301
+ .smwb-slider {
302
+ padding-top: max(@sliderPaddingY, calc((@sliderTouchHit - 4px) / 2));
303
+ padding-bottom: max(@sliderPaddingY, calc((@sliderTouchHit - 4px) / 2));
304
+ }
305
+ .smwb-slider_size-small {
306
+ padding-top: max(@sliderPaddingY, calc((@sliderTouchHit - 2px) / 2));
307
+ padding-bottom: max(@sliderPaddingY, calc((@sliderTouchHit - 2px) / 2));
308
+ }
309
+ .smwb-slider_size-large {
310
+ padding-top: max(@sliderPaddingY, calc((@sliderTouchHit - 6px) / 2));
311
+ padding-bottom: max(@sliderPaddingY, calc((@sliderTouchHit - 6px) / 2));
312
+ }
313
+ .smwb-slider--vertical {
314
+ padding: 0 max(@sliderPaddingY, calc((@sliderTouchHit - 4px) / 2));
315
+ }
316
+ .smwb-slider__thumb:after {
317
+ width: max(42px, @sliderTouchHit);
318
+ height: max(42px, @sliderTouchHit);
319
+ }
320
+ }
@@ -4,6 +4,9 @@
4
4
  gap: @snackbarGap;
5
5
  position: fixed;
6
6
  z-index: 777;
7
+ // Gap above the window's bottom edge for a stack drawn at the bottom: `BottomBar` publishes its height as
8
+ // --smui-bottom-bar-offset, so the snackbars sit above the bar. With the variable unset it is 0 and nothing moves.
9
+ @snackbarsBottomOffset: var(--smui-bottom-bar-offset, 0px);
7
10
  &.smwb-top {
8
11
  top: 1rem;
9
12
  left: 50%;
@@ -18,17 +21,17 @@
18
21
  top: 1rem;
19
22
  }
20
23
  &.smwb-bottom {
21
- bottom: 1rem;
24
+ bottom: calc(1rem + @snackbarsBottomOffset);
22
25
  left: 50%;
23
26
  transform: translateX(-50%);
24
27
  }
25
28
  &.smwb-bottom-right {
26
29
  right: 1rem;
27
- bottom: 1rem;
30
+ bottom: calc(1rem + @snackbarsBottomOffset);
28
31
  }
29
32
  &.smwb-bottom-left {
30
33
  left: 1rem;
31
- bottom: 1rem;
34
+ bottom: calc(1rem + @snackbarsBottomOffset);
32
35
  }
33
36
  }
34
37
 
@@ -1,7 +1,34 @@
1
+ @stackDirections: row, row-reverse, column, column-reverse;
2
+
3
+ // `direction` given per breakpoint: one class per breakpoint and direction, base first and then
4
+ // the breakpoints in ascending order, so a wider one wins at the same specificity.
5
+ .stack-direction(@bp) {
6
+ each(@stackDirections, {
7
+ &--direction-@{bp}-@{value} {
8
+ flex-direction: @value;
9
+ }
10
+ });
11
+ }
12
+
1
13
  .smwb-stack {
2
14
  // layout is driven by inline flex props; this hook is for overrides
3
15
  min-width: 0;
4
16
 
17
+ .stack-direction(base);
18
+
19
+ .smui-media-up(sm; {
20
+ .stack-direction(sm);
21
+ });
22
+ .smui-media-up(md; {
23
+ .stack-direction(md);
24
+ });
25
+ .smui-media-up(lg; {
26
+ .stack-direction(lg);
27
+ });
28
+ .smui-media-up(xl; {
29
+ .stack-direction(xl);
30
+ });
31
+
5
32
  &__divider {
6
33
  display: flex;
7
34
  align-items: center;
@@ -182,6 +182,14 @@
182
182
  outline: 2px solid var(--smui-primaryColor);
183
183
  outline-offset: 2px;
184
184
  }
185
+ // On a coarse pointer the sort control is the sm step (44px there) at least, a line of text
186
+ // tall otherwise. The header cell (56px) already has the room.
187
+ @media (pointer: coarse) {
188
+ .smwb-head-cell_sortable .smwb-head-cell__content {
189
+ min-width: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
190
+ min-height: var(--smui-control-h-sm, @smui-control-h-sm-coarse);
191
+ }
192
+ }
185
193
 
186
194
  .smwb-table__row_selected {
187
195
  background-color: var(--smui-onSurfaceHover);
@@ -142,6 +142,10 @@
142
142
  // this one carries dark ink instead of @onWarningColor. 5.5:1 on @warningColor.
143
143
  @badgeWarningColor: #1c1b1f;
144
144
 
145
+ // Height of the `BottomBar` row, without the safe-area inset it adds below; the bar publishes the sum as
146
+ // --smui-bottom-bar-offset.
147
+ @bottomBarHeight: 56px;
148
+
145
149
  @buttonGap: @smui-space-sm;
146
150
  @buttonPaddingSmall: @smui-space-xs 10px; // 10 off-grid
147
151
  @buttonPaddingMedium: 6px 14px; // off-grid
@@ -50,7 +50,10 @@
50
50
  // an `@media (pointer: coarse)` block, which is why most components need no
51
51
  // rule of their own; only what sits off the scale has one (small clickable
52
52
  // or link Chip, Tabs dense and its scroll buttons, TabGroups dense actions button,
53
- // Menu dense items, List dense rows). A mouse keeps the sizes above.
53
+ // Menu dense items, List dense rows, and the targets the controls above do not
54
+ // cover: Composer icon buttons, Breadcrumbs "..." button, DagView zoom buttons,
55
+ // Slider rail and thumb zones, SelectField clear button and chip delete zones, Sheet
56
+ // header buttons, Table sort control, DatePicker adornment button). A mouse keeps the sizes above.
54
57
  // Still exempt on touch: the --filled and --inline fields, the compact Toggle
55
58
  // (capped at @toggleCompactMaxHeight) and a small Chip that is neither a button
56
59
  // nor a link.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smwb/ui-styles",
3
- "version": "2.3.0",
3
+ "version": "2.5.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": [