@smwb/ui-styles 1.5.1 → 2.0.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.
Files changed (54) hide show
  1. package/README.md +210 -12
  2. package/less/components/appBar/appBar.less +108 -0
  3. package/less/components/avatar/avatar.less +22 -0
  4. package/less/components/button/button.less +7 -1
  5. package/less/components/card/card.less +15 -4
  6. package/less/components/chart/chart.less +16 -15
  7. package/less/components/checkbox/checkbox.less +55 -4
  8. package/less/components/chip/chip.less +48 -3
  9. package/less/components/commandPalette/commandPalette.entry.less +2 -0
  10. package/less/components/commandPalette/commandPalette.less +233 -0
  11. package/less/components/composer/composer.entry.less +2 -0
  12. package/less/components/composer/composer.less +294 -0
  13. package/less/components/composer/composer.variables.less +10 -0
  14. package/less/components/dagView/dagView.entry.less +2 -0
  15. package/less/components/dagView/dagView.less +280 -0
  16. package/less/components/descriptionList/descriptionList.less +7 -1
  17. package/less/components/diffStat/diffStat.entry.less +2 -0
  18. package/less/components/diffStat/diffStat.less +76 -0
  19. package/less/components/kbd/kbd.entry.less +2 -0
  20. package/less/components/kbd/kbd.less +55 -0
  21. package/less/components/list/list.less +39 -0
  22. package/less/components/menu/menu.less +25 -1
  23. package/less/components/personChip/personChip.less +4 -2
  24. package/less/components/qrCode/qrCode.entry.less +2 -0
  25. package/less/components/qrCode/qrCode.less +35 -0
  26. package/less/components/radioButton/radioButton.less +46 -1
  27. package/less/components/rating/rating.less +15 -2
  28. package/less/components/selectField/selectField.less +87 -5
  29. package/less/components/sidebar/sidebar.less +26 -0
  30. package/less/components/statusDot/statusDot.entry.less +2 -0
  31. package/less/components/statusDot/statusDot.less +118 -0
  32. package/less/components/swimlanes/swimlanes.entry.less +2 -0
  33. package/less/components/swimlanes/swimlanes.less +126 -0
  34. package/less/components/tabGroups/tabGroups.entry.less +2 -0
  35. package/less/components/tabGroups/tabGroups.less +219 -0
  36. package/less/components/table/table.less +12 -0
  37. package/less/components/tabs/tab/tab.less +128 -0
  38. package/less/components/tabs/tabPanel/tabPanel.entry.less +2 -0
  39. package/less/components/tabs/tabPanel/tabPanel.less +8 -0
  40. package/less/components/tabs/tabs.less +26 -0
  41. package/less/components/textField/textField.less +34 -9
  42. package/less/components/thumbCard/thumbCard.less +12 -2
  43. package/less/components/toggle/toggle.less +42 -2
  44. package/less/components/treeView/treeView.less +40 -2
  45. package/less/components/typography/typography.less +13 -6
  46. package/less/components.less +10 -0
  47. package/less/connects/rt/table.less +7 -0
  48. package/less/default/globals/default.variables.less +152 -1
  49. package/less/foundation/sizing.less +41 -5
  50. package/less/foundation/typography.less +21 -0
  51. package/less/themes/material/variables.less +1 -0
  52. package/less/themes/summer/variables.less +1 -0
  53. package/less/variables.less +5 -0
  54. 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,6 +120,86 @@
113
120
  cursor: default;
114
121
  }
115
122
 
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
+
116
203
  // Compact tabs (Tabs dense): labels as written — no capitals, no letter spacing —
117
204
  // and less padding, so more tabs fit in a row.
118
205
  .smwb-tabs--dense .smwb-tab {
@@ -121,3 +208,44 @@
121
208
  letter-spacing: normal;
122
209
  text-transform: none;
123
210
  }
211
+
212
+ // The close button shows when it is reachable: the item is hovered (item not disabled),
213
+ // the item is the active tab, or focus is inside the item. The disabled button stays
214
+ // hidden; the reveal restores what the hidden defaults below took away. Hidden means
215
+ // opacity/pointer-events only — never `visibility`, so the button stays in the
216
+ // accessibility tree (its accessible name is computed, a screen reader reaches it) — and
217
+ // never size, so the row does not jump. Scoped under .smwb-tabs so the rules only ever
218
+ // match inside a tabs row (dense included); a standalone closable Tab outside a row
219
+ // renders its close button visible and clickable.
220
+ .smwb-tabs {
221
+ .smwb-tab__close {
222
+ opacity: 0;
223
+ pointer-events: none;
224
+ transition: opacity 0.15s linear;
225
+ }
226
+
227
+ .smwb-tab-item:hover:not(.smwb-tab-item--disabled) .smwb-tab__close:not(:disabled),
228
+ .smwb-tab-item--active .smwb-tab__close:not(:disabled),
229
+ .smwb-tab-item:focus-within .smwb-tab__close:not(:disabled) {
230
+ opacity: 1;
231
+ pointer-events: auto;
232
+ }
233
+
234
+ // Drag-to-reorder states (Tabs `onReorder`): the dragged item dims, the drop target
235
+ // is marked with a 2px indicator line on its leading edge. The line rides above the
236
+ // item's hover layer and never takes pointer events.
237
+ .smwb-tab-item--dragging {
238
+ opacity: 0.6;
239
+ }
240
+
241
+ .smwb-tab-item--drop-target:after {
242
+ content: "";
243
+ position: absolute;
244
+ top: 0;
245
+ bottom: 0;
246
+ left: 0;
247
+ width: @tabsDragIndicatorSize;
248
+ background-color: var(--smui-primaryColor);
249
+ pointer-events: none;
250
+ }
251
+ }
@@ -0,0 +1,2 @@
1
+ @import (reference) "../../../_prelude.less";
2
+ @import "./tabPanel.less";
@@ -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: color 200ms cubic-bezier(0, 0, 0.2, 1) 0ms, transform 200ms cubic-bezier(0, 0, 0.2, 1) 0ms,
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
- // 8 + 23 + 9 = 40px, the md control height: the extra pixel at the bottom is the
365
- // same as the medium size's 16/17.
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: @smui-space-sm;
368
- padding-bottom: (@smui-space-sm + 1px);
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-space-sm);
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: @smui-space-lg;
377
- padding-bottom: @smui-space-lg;
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
+ }
@@ -1,10 +1,12 @@
1
+ // The root is a box around the content (the image and the caption: the card's
2
+ // button when it is selectable) and the corner slots, laid over the image
3
+ // beside that button, not inside it.
1
4
  .smwb-thumb-card {
2
5
  position: relative;
3
6
  display: flex;
4
7
  flex-direction: column;
5
8
  border-radius: 8px;
6
9
  overflow: visible;
7
- outline: none;
8
10
 
9
11
  &--interactive {
10
12
  cursor: pointer;
@@ -15,6 +17,13 @@
15
17
  pointer-events: none;
16
18
  }
17
19
 
20
+ // Takes focus; the ring is drawn on the image instead.
21
+ &__content {
22
+ display: flex;
23
+ flex-direction: column;
24
+ outline: none;
25
+ }
26
+
18
27
  &__media {
19
28
  position: relative;
20
29
  width: 100%;
@@ -29,11 +38,12 @@
29
38
  outline-offset: 1px;
30
39
  }
31
40
 
32
- &--interactive:focus-visible &__media {
41
+ &__content:focus-visible &__media {
33
42
  outline: 2px solid var(--smui-primaryColor);
34
43
  outline-offset: 1px;
35
44
  }
36
45
 
46
+ // Positioned against the root, whose top-left corner is the image's.
37
47
  &__slot {
38
48
  position: absolute;
39
49
  top: 4px;
@@ -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: 0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%);
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;
@@ -70,7 +97,20 @@
70
97
  }
71
98
 
72
99
  &__checkbox {
73
- display: none;
100
+ // Visually hidden but rendered: with display: none the input would be out of
101
+ // the tab order and the accessibility tree. It fills the switch, under the
102
+ // track and thumb, which take the pointer and pass clicks on through the label.
103
+ position: absolute;
104
+ top: 0;
105
+ left: 0;
106
+ width: 100%;
107
+ height: 100%;
108
+ margin: 0;
109
+ opacity: 0;
110
+ &:focus-visible ~ .smwb-toggle__track {
111
+ outline: 2px solid var(--smui-primaryColor);
112
+ outline-offset: 2px;
113
+ }
74
114
  &:checked {
75
115
  & ~ .smwb-toggle__track {
76
116
  background-color: var(--smui-toggleTrackActiveColor);
@@ -46,20 +46,58 @@
46
46
  }
47
47
  }
48
48
 
49
- &__content {
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-tree__node__content {
100
+ .smwb-tree__node_selected > .smwb-tree__node__row {
63
101
  background-color: var(--smui-onSurfaceHover);
64
102
  border-radius: 4px;
65
103
  }
@@ -7,10 +7,23 @@
7
7
  @s: ~"smui-font-@{v}-size";
8
8
  @w: ~"smui-font-@{v}-weight";
9
9
  @l: ~"smui-font-@{v}-lh";
10
+ @t: ~"smui-font-@{v}-transform";
11
+ @ls: ~"smui-font-@{v}-letter-spacing";
10
12
  &_@{v} {
11
13
  font-size: @@s;
12
14
  font-weight: @@w;
13
15
  line-height: @@l;
16
+ // `auto` (the default) declares nothing, so consumer rules on the element keep winning.
17
+ // A set value is emitted behind a runtime token: override --smui-font-<variant>-transform
18
+ // / -letter-spacing in CSS, or leave the compiled value.
19
+ & when not (@@t = auto) {
20
+ @tv: @@t;
21
+ text-transform: ~"var(--@{t}, @{tv})";
22
+ }
23
+ & when not (@@ls = auto) {
24
+ @lsv: @@ls;
25
+ letter-spacing: ~"var(--@{ls}, @{lsv})";
26
+ }
14
27
  }
15
28
  }
16
29
  .smui-type(h1);
@@ -27,12 +40,6 @@
27
40
  .smui-type(overline);
28
41
  .smui-type(button);
29
42
 
30
- &_overline,
31
- &_button {
32
- text-transform: uppercase;
33
- letter-spacing: 0.06em;
34
- }
35
-
36
43
  &_color-primary {
37
44
  color: var(--smui-primaryColor);
38
45
  }
@@ -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";
@@ -64,6 +71,9 @@
64
71
  @import "./components/rating/rating.less";
65
72
  @import "./components/skeleton/skeleton.less";
66
73
  @import "./components/chart/chart.less";
74
+ @import "./components/dagView/dagView.less";
75
+ @import "./components/swimlanes/swimlanes.less";
76
+ @import "./components/composer/composer.less";
67
77
  @import "./components/stepper/stepper.less";
68
78
  @import "./components/typography/typography.less";
69
79
  @import "./components/stack/stack.less";
@@ -15,11 +15,18 @@
15
15
  opacity: 1;
16
16
  }
17
17
 
18
+ // The resizer is one of the head cell's actions. It sits on the cell's edge, out
19
+ // of the flow, so alone it takes no room there: no gap after the sort control.
20
+ .smwb-head-cell .smwb-head-cell__actions:has(> .smwb-rt-table--resizer:only-child) {
21
+ margin-inline-start: 0;
22
+ }
23
+
18
24
  @media (hover: hover) {
19
25
  .smwb-rt-table--resizer {
20
26
  opacity: 0.5;
21
27
  }
22
28
 
29
+ .smwb-head-cell:hover .smwb-rt-table--resizer,
23
30
  *:hover > .smwb-rt-table--resizer {
24
31
  opacity: 1;
25
32
  }