@keenmate/web-multiselect 2.0.0-rc02 → 2.0.0-rc03

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.
@@ -54,6 +54,313 @@
54
54
  flex-direction: column;
55
55
  }
56
56
 
57
+ /* ------------------------------------------------------------------------------
58
+ FULLSCREEN OVERLAY — phone / touch presentation
59
+ Set by JS (setPresentation('fullscreen'), driven by the element's
60
+ environmentChanged hook) INSTEAD of anchoring the panel. The panel becomes a
61
+ fixed, full-viewport sheet with its own search + close header, so the input it
62
+ would otherwise float beneath is fully covered. `dvh` tracks the mobile URL bar.
63
+ ------------------------------------------------------------------------------ */
64
+ /* Phone-view scaling. Every size is calc(N × --ms-rem), but a custom property bakes
65
+ its var(--ms-rem) at its DECLARATION site — the semantic vars are declared at :host
66
+ (10px), so overriding --ms-rem on the panel alone does NOT re-scale them. So we both
67
+ (a) set the panel's --ms-rem to --ms-fullscreen-rem, and (b) RE-DECLARE the shared
68
+ option/checkbox/group vars here in the panel scope, with the same formulas as
69
+ variables.css, so their var(--ms-rem) now resolves to the enlarged value. Overlay-
70
+ only --ms-fullscreen-* vars already derive from --ms-fullscreen-rem at :host, and
71
+ JS-driven row heights (virtual/fixed) are scaled to match in code. */
72
+ .ms__dropdown--fullscreen,
73
+ .ms__selected-popover--fullscreen {
74
+ --ms-rem: var(--ms-fullscreen-rem);
75
+ --ms-option-padding: calc(0.8 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
76
+ --ms-option-gap: calc(0.8 * var(--ms-rem));
77
+ --ms-option-title-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
78
+ --ms-option-subtitle-font-size: calc(var(--base-font-size-xs, 1.2) * var(--ms-rem));
79
+ --ms-option-icon-font-size: calc(var(--base-font-size-base, 1.6) * var(--ms-rem));
80
+ --ms-checkbox-size: calc(1.6 * var(--ms-rem));
81
+ --ms-group-label-font-size: calc(var(--base-font-size-xs, 1.2) * var(--ms-rem));
82
+ --ms-group-label-padding: calc(0.4 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
83
+ /* Reclaim horizontal space for labels: tighter indent than the floating default
84
+ (--ms-tree-base-indent 0.75rem / --ms-tree-indent 1.25rem in tree.css). */
85
+ --ms-tree-base-indent: var(--ms-fullscreen-tree-base-indent);
86
+ --ms-tree-indent: var(--ms-fullscreen-tree-indent);
87
+ }
88
+
89
+ /* Bigger, dropdown-like selected-item rows in the phone overlay. The badge sizing
90
+ vars are declared at :host against the base --ms-rem (baked at 10px), so without
91
+ this they'd keep base-size text/padding inside the enlarged sheet and read as
92
+ cramped. Re-declaring them here — where --ms-rem is --ms-fullscreen-rem — scales
93
+ the pill height, text, padding and remove button up with the rest of the overlay.
94
+ The row height is also mirrored in JS (scaledBadgeHeight → --ms-badge-height-virtual)
95
+ for the virtual list, so both paths agree. */
96
+ .ms__selected-popover--fullscreen {
97
+ --ms-badge-gap: calc(0.8 * var(--ms-rem));
98
+ --ms-badge-height: calc(4.2 * var(--ms-rem));
99
+ --ms-badge-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
100
+ --ms-badge-text-padding: 0 calc(1.2 * var(--ms-rem));
101
+ --ms-badge-remove-width: calc(3.6 * var(--ms-rem));
102
+ --ms-badge-remove-icon-size: calc(1.2 * var(--ms-rem));
103
+ --ms-badge-remove-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
104
+ }
105
+
106
+ /* Action buttons (Select All / Clear All / custom) scale up in the overlay too — their
107
+ sizing vars are baked at :host against the base --ms-rem, so re-declare them here
108
+ (where --ms-rem is --ms-fullscreen-rem) for a comfortable touch target. Dropdown-only:
109
+ the selected-items popover has no actions row. */
110
+ .ms__dropdown--fullscreen {
111
+ --ms-actions-gap: calc(0.4 * var(--ms-rem));
112
+ --ms-actions-padding: calc(0.8 * var(--ms-rem));
113
+ --ms-action-btn-padding: calc(0.6 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
114
+ --ms-action-btn-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
115
+ }
116
+
117
+ .ms__dropdown--fullscreen {
118
+ position: fixed;
119
+ /* top/left only — NOT `inset: 0`. `inset` also sets `bottom: 0`, and a fixed box with
120
+ both `top` and `bottom` constrained ignores its `height`. observeKeyboardInset()
121
+ shrinks the sheet above the soft keyboard by writing `height` (+ `top`), so a pinned
122
+ `bottom` would silently defeat it — the list and bottom actions would stay behind the
123
+ keyboard. With only top/left pinned, height governs and the keyboard reflow works. */
124
+ top: 0;
125
+ inset-inline-start: 0;
126
+ width: 100vw;
127
+ max-width: 100vw;
128
+ height: 100dvh;
129
+ max-height: 100dvh;
130
+ border: none;
131
+ border-radius: 0;
132
+ background: var(--ms-fullscreen-bg);
133
+ color: var(--ms-fullscreen-text-color);
134
+ z-index: var(--ms-z-index-fullscreen);
135
+ }
136
+
137
+ .ms__dropdown--fullscreen .ms__dropdown-inner {
138
+ /* The panel is a full-height flex column; the list fills the space under the header. */
139
+ display: flex;
140
+ flex-direction: column;
141
+ flex: 1;
142
+ min-height: 0;
143
+ max-height: none;
144
+ /* The .ms__options child is the sole scroller in fullscreen (flex-fill + overflow-y
145
+ below). The base rule makes THIS element scroll too; two nested scrollers let the
146
+ last row get trapped in the outer one (partially visible, unreachable). Clip here so
147
+ scrolling happens in exactly one place. */
148
+ overflow: hidden;
149
+ }
150
+
151
+ /* The options list fills the sheet between the header and any actions row, scrolling
152
+ within the panel instead of at a fixed height — for BOTH the virtual list (its
153
+ inline maxHeight is dropped in fullscreen, see renderDropdownVirtual) and the plain
154
+ non-virtual list (small selections). Without flex-fill, a short non-virtual list
155
+ sits content-height at the top and a bottom actions row floats mid-sheet with empty
156
+ space beneath it. */
157
+ .ms__dropdown--fullscreen .ms__options {
158
+ flex: 1 1 0;
159
+ min-height: 0;
160
+ height: auto;
161
+ max-height: none;
162
+ overflow-y: auto;
163
+ /* Breathing room so the last row always clears the sheet's (or keyboard's) bottom edge
164
+ instead of sitting flush against it, half-cut. */
165
+ padding-bottom: var(--ms-option-gap);
166
+ }
167
+
168
+ /* Pin the action row (Select All / Clear / custom) so it never shrinks and stays docked
169
+ at the bottom of the sheet. Once observeKeyboardInset() shrinks the panel above the
170
+ soft keyboard, only .ms__options scrolls — the actions stay reachable above the keys. */
171
+ .ms__dropdown--fullscreen .ms__actions {
172
+ flex: 0 0 auto;
173
+ }
174
+
175
+ /* Shared fullscreen header bar — ONE treatment for both the dropdown (search
176
+ field) and the selected-items popover (title). Same padding, height, border, and
177
+ close button, so the two mobile overlays are visually identical. The popover's
178
+ header/close reuse their own class names but adopt these rules under
179
+ `--fullscreen`, and the selectors are listed together so there's one source of
180
+ truth (no drift between the two headers). */
181
+ .ms__fullscreen-header,
182
+ .ms__selected-popover--fullscreen .ms__selected-popover-header {
183
+ flex: 0 0 auto;
184
+ display: flex;
185
+ align-items: center;
186
+ /* Wrap lets the navigate-mode match navigator (flex-basis 100%) drop onto its own
187
+ row under the search box while search + close stay on the first row. */
188
+ flex-wrap: wrap;
189
+ gap: var(--ms-fullscreen-header-gap);
190
+ min-height: var(--ms-fullscreen-header-min-height);
191
+ padding: var(--ms-fullscreen-header-padding);
192
+ background: var(--ms-fullscreen-header-bg);
193
+ border-bottom: var(--ms-fullscreen-header-border);
194
+ }
195
+
196
+ /* Match navigator (navigate searchMode only): result count on the lead edge, round
197
+ prev/next buttons on the trailing edge, forced onto its own full-width row. Hidden
198
+ inline (display:none) by JS until there's a search term. */
199
+ .ms__fullscreen-nav {
200
+ flex: 0 0 100%;
201
+ display: flex;
202
+ align-items: center;
203
+ justify-content: space-between;
204
+ gap: var(--ms-fullscreen-nav-gap);
205
+ padding-top: var(--ms-fullscreen-nav-padding-top);
206
+ }
207
+
208
+ .ms__fullscreen-nav-count {
209
+ font-size: var(--ms-fullscreen-nav-count-font-size);
210
+ color: var(--ms-fullscreen-nav-count-color);
211
+ }
212
+
213
+ .ms__fullscreen-nav-controls {
214
+ display: flex;
215
+ align-items: center;
216
+ gap: var(--ms-fullscreen-nav-gap);
217
+ }
218
+
219
+ .ms__fullscreen-nav-btn {
220
+ flex: 0 0 auto;
221
+ display: inline-flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ width: var(--ms-fullscreen-nav-btn-size);
225
+ height: var(--ms-fullscreen-nav-btn-size);
226
+ padding: 0;
227
+ color: var(--ms-fullscreen-nav-btn-color);
228
+ background: var(--ms-fullscreen-nav-btn-bg);
229
+ border: none;
230
+ border-radius: 50%;
231
+ cursor: pointer;
232
+ }
233
+
234
+ .ms__fullscreen-nav-btn:hover:not(:disabled) {
235
+ background: var(--ms-fullscreen-nav-btn-bg-hover);
236
+ }
237
+
238
+ .ms__fullscreen-nav-btn:disabled {
239
+ opacity: 0.4;
240
+ cursor: default;
241
+ }
242
+
243
+ .ms__fullscreen-nav-btn::before {
244
+ content: "";
245
+ display: block;
246
+ width: var(--ms-fullscreen-nav-btn-icon-size);
247
+ height: var(--ms-fullscreen-nav-btn-icon-size);
248
+ background-color: currentColor;
249
+ -webkit-mask: var(--ms-icon-chevron) center / contain no-repeat;
250
+ mask: var(--ms-icon-chevron) center / contain no-repeat;
251
+ }
252
+
253
+ /* Chevron points up by default; the "next" (down) button flips it vertically. */
254
+ .ms__fullscreen-nav-btn--next::before {
255
+ transform: scaleY(-1);
256
+ }
257
+
258
+ /* The leading element (search field or title) fills the bar, pushing the close
259
+ button to the trailing edge in both overlays. */
260
+ .ms__fullscreen-header > .ms__fullscreen-search,
261
+ .ms__selected-popover--fullscreen .ms__selected-popover-header > span {
262
+ flex: 1 1 auto;
263
+ min-width: 0;
264
+ }
265
+
266
+ /* Popover title typography in fullscreen (matches a header title, not the small
267
+ floating-popover label). */
268
+ .ms__selected-popover--fullscreen .ms__selected-popover-header {
269
+ font-size: var(--ms-fullscreen-title-font-size);
270
+ font-weight: var(--ms-fullscreen-title-font-weight);
271
+ color: var(--ms-fullscreen-text-color);
272
+ }
273
+
274
+ .ms__fullscreen-search {
275
+ font-family: inherit;
276
+ font-size: var(--ms-fullscreen-search-font-size);
277
+ color: inherit;
278
+ background: transparent;
279
+ border: var(--ms-fullscreen-search-border);
280
+ border-radius: var(--ms-fullscreen-search-border-radius);
281
+ padding: var(--ms-fullscreen-search-padding);
282
+ }
283
+
284
+ .ms__fullscreen-search:focus {
285
+ outline: none;
286
+ border: var(--ms-input-border-focus);
287
+ }
288
+
289
+ /* Shared close button — identical big, round, mask-icon ✕ in both overlays. */
290
+ .ms__fullscreen-close,
291
+ .ms__selected-popover--fullscreen .ms__selected-popover-close {
292
+ flex: 0 0 auto;
293
+ display: inline-flex;
294
+ align-items: center;
295
+ justify-content: center;
296
+ width: var(--ms-fullscreen-close-size);
297
+ height: var(--ms-fullscreen-close-size);
298
+ padding: 0;
299
+ color: var(--ms-fullscreen-close-color);
300
+ background: transparent;
301
+ border: none;
302
+ border-radius: 50%;
303
+ cursor: pointer;
304
+ }
305
+
306
+ .ms__fullscreen-close:hover,
307
+ .ms__selected-popover--fullscreen .ms__selected-popover-close:hover {
308
+ background: var(--ms-fullscreen-close-bg-hover);
309
+ color: var(--ms-fullscreen-close-color);
310
+ }
311
+
312
+ .ms__fullscreen-close::before,
313
+ .ms__selected-popover--fullscreen .ms__selected-popover-close::before {
314
+ content: "";
315
+ display: block;
316
+ width: var(--ms-fullscreen-close-icon-size);
317
+ height: var(--ms-fullscreen-close-icon-size);
318
+ background-color: currentColor;
319
+ -webkit-mask: var(--ms-icon-remove) center / contain no-repeat;
320
+ mask: var(--ms-icon-remove) center / contain no-repeat;
321
+ }
322
+
323
+ /* Truncated-label reveal — a circled "i" at the trailing edge of a fullscreen row
324
+ whose label is clipped. Fullscreen-only markup (the renderer emits it only for the
325
+ overlay), and CSS keeps it hidden until JS tags the row .ms__option--truncated
326
+ (measured per render). Tapping it reveals the full label — the touch-friendly
327
+ substitute for the hover option tooltip, which never fires on touch. */
328
+ .ms__dropdown--fullscreen .ms__option-info {
329
+ flex: 0 0 auto;
330
+ display: none;
331
+ align-items: center;
332
+ justify-content: center;
333
+ width: var(--ms-fullscreen-info-size);
334
+ height: var(--ms-fullscreen-info-size);
335
+ margin-inline-start: var(--ms-option-gap);
336
+ padding: 0;
337
+ color: var(--ms-fullscreen-info-color);
338
+ background: transparent;
339
+ border: none;
340
+ border-radius: 50%;
341
+ cursor: pointer;
342
+ }
343
+
344
+ .ms__dropdown--fullscreen .ms__option--truncated .ms__option-info {
345
+ display: inline-flex;
346
+ }
347
+
348
+ @media (hover: hover) {
349
+ .ms__dropdown--fullscreen .ms__option-info:hover {
350
+ background: var(--ms-fullscreen-info-bg-hover);
351
+ }
352
+ }
353
+
354
+ .ms__dropdown--fullscreen .ms__option-info::before {
355
+ content: "";
356
+ display: block;
357
+ width: var(--ms-fullscreen-info-icon-size);
358
+ height: var(--ms-fullscreen-info-icon-size);
359
+ background-color: currentColor;
360
+ -webkit-mask: var(--ms-icon-info) center / contain no-repeat;
361
+ mask: var(--ms-icon-info) center / contain no-repeat;
362
+ }
363
+
57
364
  /* Inner scrolling container — clips scrollbar to rounded corners */
58
365
  .ms__dropdown-inner {
59
366
  flex: 1;
@@ -150,6 +457,64 @@
150
457
  visibility: visible;
151
458
  }
152
459
 
460
+ /* Truncated-label reveal fired from inside the fullscreen overlay — lift it above
461
+ the overlay (10001), which the plain option tooltip (10000) would sit behind. */
462
+ .ms__option-tooltip--fullscreen {
463
+ z-index: var(--ms-z-index-fullscreen-tooltip);
464
+ }
465
+
466
+ /* ==============================================================================
467
+ TRANSIENT MESSAGE / TOAST (showMessage)
468
+ ==============================================================================
469
+ Rendered above the panel so a veto reason (or any consumer feedback) is visible
470
+ in BOTH presentations: anchored under the control when floating (position set by
471
+ floating-ui), pinned to the bottom-centre of the viewport — above the sheet — when
472
+ fullscreen. One shows at a time; tap to dismiss. */
473
+ .ms__message {
474
+ position: fixed;
475
+ z-index: var(--ms-message-z-index);
476
+ box-sizing: border-box;
477
+ max-width: var(--ms-message-max-width);
478
+ padding: var(--ms-message-padding);
479
+ font-family: inherit;
480
+ font-size: var(--ms-message-font-size);
481
+ font-weight: var(--ms-message-font-weight);
482
+ line-height: var(--ms-line-height-normal);
483
+ color: var(--ms-message-color);
484
+ background: var(--ms-message-bg);
485
+ border: var(--ms-message-border);
486
+ border-radius: var(--ms-message-border-radius);
487
+ box-shadow: var(--ms-message-shadow);
488
+ cursor: pointer;
489
+ opacity: 0;
490
+ transition: opacity var(--ms-transition-normal) ease;
491
+ /* The one tap-highlight declaration NOT covered by :host (base.css): the message can
492
+ be reparented to document.body, outside the shadow subtree, so it sets its own. */
493
+ -webkit-tap-highlight-color: transparent;
494
+ }
495
+
496
+ .ms__message--visible {
497
+ opacity: 1;
498
+ }
499
+
500
+ .ms__message--info { background: var(--ms-message-info-bg); color: var(--ms-message-info-color); }
501
+ .ms__message--warning { background: var(--ms-message-warning-bg); color: var(--ms-message-warning-color); }
502
+ .ms__message--error { background: var(--ms-message-error-bg); color: var(--ms-message-error-color); }
503
+ .ms__message--success { background: var(--ms-message-success-bg); color: var(--ms-message-success-color); }
504
+
505
+ /* Fullscreen: bottom-centre of the viewport, above the overlay. Its sizing vars are
506
+ --ms-rem-based (baked at :host), so rescale the key ones here against
507
+ --ms-fullscreen-rem to match the enlarged phone view. */
508
+ .ms__message--fullscreen {
509
+ left: 50%;
510
+ right: auto;
511
+ bottom: var(--ms-message-fullscreen-offset);
512
+ transform: translateX(-50%);
513
+ max-width: min(var(--ms-message-max-width), calc(100vw - 4 * var(--ms-fullscreen-rem)));
514
+ padding: calc(1.0 * var(--ms-fullscreen-rem)) calc(1.4 * var(--ms-fullscreen-rem));
515
+ font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-fullscreen-rem));
516
+ }
517
+
153
518
  /* ==============================================================================
154
519
  SELECTED-ITEMS POPOVER
155
520
  ==============================================================================
@@ -182,6 +547,37 @@
182
547
  max-height: none;
183
548
  }
184
549
 
550
+ /* ------------------------------------------------------------------------------
551
+ FULLSCREEN OVERLAY — phone / touch presentation (mirrors the dropdown overlay).
552
+ Set by JS (setPresentation('fullscreen')) instead of anchoring. The popover
553
+ already renders its own header + close button, so it just becomes a fixed,
554
+ full-viewport sheet. Declared AFTER --virtual so its `display:flex` wins the
555
+ large-selection (virtual) case; the virtual body flexes to fill (its inline
556
+ height is dropped in fullscreen — see renderSelectedPopoverVirtual).
557
+ ------------------------------------------------------------------------------ */
558
+ .ms__selected-popover--fullscreen {
559
+ position: fixed;
560
+ inset: 0;
561
+ display: flex;
562
+ flex-direction: column;
563
+ width: 100vw;
564
+ max-width: 100vw;
565
+ height: 100dvh;
566
+ max-height: 100dvh;
567
+ border: none;
568
+ border-radius: 0;
569
+ overflow: hidden;
570
+ background: var(--ms-fullscreen-bg);
571
+ color: var(--ms-fullscreen-text-color);
572
+ z-index: var(--ms-z-index-fullscreen);
573
+ }
574
+
575
+ .ms__selected-popover--fullscreen .ms__selected-popover-body {
576
+ flex: 1 1 0;
577
+ min-height: 0;
578
+ max-height: none;
579
+ }
580
+
185
581
  .ms__selected-popover-header {
186
582
  display: flex;
187
583
  align-items: center;
@@ -261,6 +657,10 @@
261
657
  width: 100%;
262
658
  min-height: fit-content; /* Allow badges to expand based on content */
263
659
  line-height: var(--ms-line-height-relaxed); /* Override line-height: 1 to allow multi-line content */
660
+ /* The body is a flex column; without this, badges shrink (flex-shrink defaults to 1)
661
+ toward their min-content height once the list overflows — so rows visibly get
662
+ shorter as you select more. Pin the height and let the body scroll instead. */
663
+ flex-shrink: 0;
264
664
  }
265
665
 
266
666
  .ms__selected-popover-body .ms__badge-text {
@@ -98,11 +98,19 @@
98
98
  not a text-selection one — stop the browser from highlighting the label. */
99
99
  user-select: none;
100
100
  -webkit-user-select: none;
101
+ /* Tap-highlight flash is suppressed once for the whole component on :host (base.css) —
102
+ an inherited property, so it reaches this row without a per-element declaration. */
101
103
  }
102
104
 
103
- .ms__option:hover {
104
- background: var(--ms-option-bg-hover);
105
- color: var(--ms-option-color-hover, inherit);
105
+ /* Hover states are gated to real pointing devices. On touch, `:hover` "sticks"
106
+ after a tap until the next tap elsewhere, so a tapped row (or a tap on its info
107
+ affordance) would stay highlighted as if selected. `@media (hover: hover)` keeps
108
+ hover on mouse/trackpad and drops it on touch (phones, the fullscreen overlay). */
109
+ @media (hover: hover) {
110
+ .ms__option:hover {
111
+ background: var(--ms-option-bg-hover);
112
+ color: var(--ms-option-color-hover, inherit);
113
+ }
106
114
  }
107
115
 
108
116
  .ms__option--focused {
@@ -115,15 +123,17 @@
115
123
  .ms__option--matched {
116
124
  background: var(--ms-option-bg-matched);
117
125
  color: var(--ms-option-color-matched, inherit);
118
- border-left: var(--ms-option-border-matched);
126
+ border-inline-start: var(--ms-option-border-matched); /* leading-edge accent bar; flips in RTL */
119
127
  }
120
128
 
121
129
  .ms__option--selected {
122
130
  background: var(--ms-option-bg-selected);
123
131
  }
124
132
 
125
- .ms__option--selected:hover {
126
- background: var(--ms-option-bg-selected-hover, var(--ms-option-bg-selected));
133
+ @media (hover: hover) {
134
+ .ms__option--selected:hover {
135
+ background: var(--ms-option-bg-selected-hover, var(--ms-option-bg-selected));
136
+ }
127
137
  }
128
138
 
129
139
  .ms__option--disabled {
@@ -137,9 +147,11 @@
137
147
  }
138
148
 
139
149
  /* Focused + Hover */
140
- .ms__option--focused:hover {
141
- background: var(--ms-option-bg-focused-hover);
142
- color: var(--ms-option-color-focused-hover, var(--ms-option-color-focused, var(--ms-option-text-color)));
150
+ @media (hover: hover) {
151
+ .ms__option--focused:hover {
152
+ background: var(--ms-option-bg-focused-hover);
153
+ color: var(--ms-option-color-focused-hover, var(--ms-option-color-focused, var(--ms-option-text-color)));
154
+ }
143
155
  }
144
156
 
145
157
  /* Matched + Hover */
@@ -158,7 +170,7 @@
158
170
  /* Selected + Matched */
159
171
  .ms__option--selected.ms__option--matched {
160
172
  background: var(--ms-option-bg-selected-matched);
161
- border-left: var(--ms-option-border-matched);
173
+ border-inline-start: var(--ms-option-border-matched); /* leading-edge accent bar; flips in RTL */
162
174
  }
163
175
 
164
176
  /* Disabled + Selected */
@@ -195,9 +207,9 @@
195
207
  flex-shrink: 0;
196
208
  position: relative;
197
209
  margin-top: var(--ms-checkbox-margin-top);
198
- margin-right: var(--ms-checkbox-margin-right);
210
+ margin-inline-end: var(--ms-checkbox-margin-right);
199
211
  margin-bottom: var(--ms-checkbox-margin-bottom);
200
- margin-left: var(--ms-checkbox-margin-left);
212
+ margin-inline-start: var(--ms-checkbox-margin-left);
201
213
  width: var(--ms-checkbox-size);
202
214
  height: var(--ms-checkbox-size);
203
215
  transform: scale(var(--ms-checkbox-scale));
@@ -346,16 +358,20 @@
346
358
  }
347
359
 
348
360
  /* Title color states (for solid background themes) */
349
- .ms__option:hover .ms__option-title {
350
- color: var(--ms-option-title-color-hover, var(--ms-option-title-color));
361
+ @media (hover: hover) {
362
+ .ms__option:hover .ms__option-title {
363
+ color: var(--ms-option-title-color-hover, var(--ms-option-title-color));
364
+ }
351
365
  }
352
366
 
353
367
  .ms__option--selected .ms__option-title {
354
368
  color: var(--ms-option-title-color-selected, var(--ms-option-title-color));
355
369
  }
356
370
 
357
- .ms__option--selected:hover .ms__option-title {
358
- color: var(--ms-option-title-color-selected-hover, var(--ms-option-title-color-selected, var(--ms-option-title-color)));
371
+ @media (hover: hover) {
372
+ .ms__option--selected:hover .ms__option-title {
373
+ color: var(--ms-option-title-color-selected-hover, var(--ms-option-title-color-selected, var(--ms-option-title-color)));
374
+ }
359
375
  }
360
376
 
361
377
  /* Highlight matched text */
@@ -374,16 +390,20 @@
374
390
  }
375
391
 
376
392
  /* Subtitle color states (for solid background themes) */
377
- .ms__option:hover .ms__option-subtitle {
378
- color: var(--ms-option-subtitle-color-hover, var(--ms-option-subtitle-color));
393
+ @media (hover: hover) {
394
+ .ms__option:hover .ms__option-subtitle {
395
+ color: var(--ms-option-subtitle-color-hover, var(--ms-option-subtitle-color));
396
+ }
379
397
  }
380
398
 
381
399
  .ms__option--selected .ms__option-subtitle {
382
400
  color: var(--ms-option-subtitle-color-selected, var(--ms-option-subtitle-color));
383
401
  }
384
402
 
385
- .ms__option--selected:hover .ms__option-subtitle {
386
- color: var(--ms-option-subtitle-color-selected-hover, var(--ms-option-subtitle-color-selected, var(--ms-option-subtitle-color)));
403
+ @media (hover: hover) {
404
+ .ms__option--selected:hover .ms__option-subtitle {
405
+ color: var(--ms-option-subtitle-color-selected-hover, var(--ms-option-subtitle-color-selected, var(--ms-option-subtitle-color)));
406
+ }
387
407
  }
388
408
 
389
409
  /* ==============================================================================