@lynn123411/dsh-model-submenu 0.2.5 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,19 @@
1
1
  /*
2
- * The composer model seat's shape, values, and tokens follow the seat this
3
- * plugin takes over. The menu surface renders through the primitives'
4
- * MenuSurface, which owns the fill, the backdrop blur, the radius, and the
5
- * macOS backing — so nothing below paints the panel itself.
2
+ * The composer model seat and the picker it opens. The menu surface renders
3
+ * through the primitives' MenuSurface and the dialog through Modal, so neither
4
+ * this file paints a floating fill — it only places content on the surfaces
5
+ * those two own.
6
6
  */
7
+
7
8
  .root {
8
9
  min-width: 0;
9
10
  position: relative;
11
+ display: flex;
10
12
  }
11
13
 
14
+ /* The Models glyph replaces the text when the composer row cannot fit it; the
15
+ * row owns both variables, so this plugin follows the same compact contract as
16
+ * the built-in occupant. */
12
17
  .trigger {
13
18
  min-width: 0;
14
19
  max-width: min(360px, 45cqw);
@@ -46,31 +51,24 @@
46
51
  white-space: nowrap;
47
52
  min-width: 0;
48
53
  overflow: hidden;
54
+ display: var(--dsh-composer-model-text-display, block);
49
55
  }
50
56
 
57
+ /* The effort caption is the accent the reference UI uses to say "this is the
58
+ * thinking level in force"; it carries no extra meaning of its own. */
51
59
  .triggerEffort {
52
60
  text-overflow: ellipsis;
53
61
  white-space: nowrap;
54
62
  min-width: 0;
55
- color: var(--dsw-alias-label-caption);
63
+ color: var(--dsw-alias-state-business-primary);
56
64
  flex-shrink: 1000;
57
65
  overflow: hidden;
66
+ display: var(--dsh-composer-model-text-display, block);
58
67
  }
59
68
 
60
69
  .triggerIcon {
61
- flex: none;
62
- display: none;
63
- }
64
-
65
- @container (width <= 360px) {
66
- .triggerIcon {
67
- display: block;
68
- }
69
-
70
- .triggerLabel,
71
- .triggerEffort {
72
- display: none;
73
- }
70
+ flex: 0 0 auto;
71
+ display: var(--dsh-composer-model-icon-display, none);
74
72
  }
75
73
 
76
74
  .chevron {
@@ -86,10 +84,11 @@
86
84
  .menu {
87
85
  z-index: 1100;
88
86
  --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
89
- width: max-content;
90
- min-width: min(240px, 100vw - 32px);
91
- max-width: min(420px, 100vw - 32px);
92
- max-height: min(360px, 100vh - 96px);
87
+ /* A fixed width keeps the card independent of the trigger's text length, so
88
+ * opening the menu never reflows the composer. */
89
+ box-sizing: border-box;
90
+ width: min(252px, calc(100vw - 24px));
91
+ max-height: min(70vh, calc(100vh - 96px));
93
92
  box-shadow: var(--dsw-elevation-prominent);
94
93
  color: var(--dsw-alias-label-primary);
95
94
  --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
@@ -102,55 +101,46 @@
102
101
  overflow: hidden;
103
102
  }
104
103
 
105
- .status,
106
- .empty {
104
+ /* The provider name is a heading, not a control: it says which provider's
105
+ * models the list below belongs to. */
106
+ .providerName {
107
+ text-overflow: ellipsis;
108
+ white-space: nowrap;
109
+ min-height: 24px;
107
110
  color: var(--dsw-alias-label-tertiary);
108
- padding: 10px;
109
- font-size: 13px;
110
- line-height: 20px;
111
- }
112
-
113
- .error,
114
- .warning {
115
- background: var(--dsw-alias-interactive-bg-hover-danger);
116
- color: var(--dsw-alias-state-error-primary);
117
- border-radius: 8px;
118
- justify-content: space-between;
119
- align-items: flex-start;
120
- gap: 8px;
121
- margin-bottom: 4px;
122
- padding: 7px 8px;
111
+ align-items: center;
112
+ padding: 3px 8px;
123
113
  font-size: 12px;
114
+ font-weight: 500;
124
115
  line-height: 18px;
116
+ overflow: hidden;
125
117
  display: flex;
126
118
  }
127
119
 
128
- .warning {
129
- background: var(--dsw-alias-bg-module-platform);
130
- color: var(--dsw-alias-state-warn-label);
131
- }
132
-
133
- .retry {
134
- color: inherit;
135
- font: inherit;
136
- cursor: pointer;
137
- background: 0 0;
138
- border: none;
139
- flex: none;
140
- padding: 0;
141
- font-weight: 600;
142
- }
143
-
144
120
  .groups {
145
121
  min-height: 0;
146
122
  overflow-y: auto;
147
123
  }
148
124
 
149
- .option {
125
+ .row {
126
+ align-items: center;
127
+ gap: 2px;
128
+ display: flex;
129
+ }
130
+
131
+ .rowPick {
150
132
  box-sizing: border-box;
151
- width: auto;
152
- min-width: 100%;
153
- min-height: 38px;
133
+ /* A slightly tighter side padding buys the name a few more characters, which
134
+ * is what keeps a long provider suffix readable inside a narrow card. */
135
+ padding-inline: 6px;
136
+ /* The scroll list is a block container, so a flex item's `flex: 1` does
137
+ * nothing here: the row must claim the full width or a long model name pushes
138
+ * the favorite mark and the check past the card's edge, where overflow clips
139
+ * them. */
140
+ width: 100%;
141
+ flex: 1;
142
+ min-width: 0;
143
+ min-height: 34px;
154
144
  color: inherit;
155
145
  text-align: left;
156
146
  cursor: pointer;
@@ -159,88 +149,339 @@
159
149
  border-radius: 10px;
160
150
  outline: none;
161
151
  align-items: center;
162
- gap: 8px;
163
- padding: 6px 8px;
152
+ gap: 4px;
153
+ padding: 5px 7px;
164
154
  display: flex;
165
155
  }
166
156
 
167
- .option:hover:not(:disabled),
168
- .option:focus-visible {
157
+ .rowPick:hover:not(:disabled),
158
+ .rowPick:focus-visible {
169
159
  background: var(--dsw-alias-interactive-bg-hover);
170
160
  }
171
161
 
172
- .selected {
173
- background: 0 0;
174
- }
175
-
176
- .option:disabled {
162
+ .rowPick:disabled {
177
163
  color: var(--dsw-alias-label-dimmed);
178
164
  cursor: default;
179
165
  }
180
166
 
181
- .optionCopy {
167
+ .rowCopy {
182
168
  flex-direction: column;
183
169
  flex: 1;
184
170
  min-width: 0;
185
171
  display: flex;
186
172
  }
187
173
 
188
- .modelName {
174
+ .rowName {
189
175
  color: inherit;
190
176
  text-overflow: ellipsis;
191
177
  white-space: nowrap;
192
- font-size: 14px;
193
- font-weight: 500;
194
- line-height: 20px;
178
+ font-size: 11.5px;
179
+ font-weight: 400;
180
+ line-height: 17px;
181
+ overflow: hidden;
182
+ }
183
+
184
+ /* The menu's names carry the weight: at this size a regular face reads thin
185
+ * against the card. The picker's rows keep theirs regular — there the metadata
186
+ * line already separates the rows. */
187
+ .menu .rowName {
188
+ font-weight: 600;
189
+ }
190
+
191
+ .rowMeta {
192
+ color: var(--dsw-alias-label-tertiary);
193
+ text-overflow: ellipsis;
194
+ white-space: nowrap;
195
+ font-size: 12px;
196
+ line-height: 18px;
195
197
  overflow: hidden;
196
198
  }
197
199
 
198
200
  .check {
199
201
  color: var(--dsw-alias-label-primary);
200
- flex: 0 0 18px;
202
+ flex: 0 0 15px;
201
203
  place-items: center;
202
204
  display: grid;
203
205
  }
204
206
 
205
- .cell {
206
- box-sizing: border-box;
207
- width: auto;
208
- min-width: 100%;
209
- height: 40px;
207
+ /* The menu's favorite mark: it lives inside the row button, so hovering it
208
+ * highlights the row and clicking it picks the model — no separate hit area. */
209
+ .starStatic {
210
+ color: var(--dsw-alias-state-warn-primary);
211
+ flex: none;
212
+ place-items: center;
213
+ width: 14px;
214
+ display: grid;
215
+ }
216
+
217
+ /* The picker's star is a real control: outline until hover or focus, solid and
218
+ * gold once favorited, and visible without hover on touch screens. */
219
+ .starButton {
220
+ color: var(--dsw-alias-label-tertiary);
221
+ cursor: pointer;
222
+ background: 0 0;
223
+ border: none;
224
+ border-radius: 8px;
225
+ outline: none;
226
+ flex: none;
227
+ place-items: center;
228
+ width: 26px;
229
+ height: 26px;
230
+ display: grid;
231
+ opacity: 0;
232
+ }
233
+
234
+ .starButton:focus-visible {
235
+ outline: 2px solid var(--dsw-alias-border-l3);
236
+ }
237
+
238
+ .row:hover .starButton,
239
+ .row:focus-within .starButton {
240
+ opacity: 1;
241
+ }
242
+
243
+ .starButton[aria-pressed='true'] {
244
+ color: var(--dsw-alias-state-warn-primary);
245
+ opacity: 1;
246
+ }
247
+
248
+ @media (hover: none) {
249
+ .starButton {
250
+ opacity: 1;
251
+ }
252
+ }
253
+
254
+ .star {
255
+ flex: none;
256
+ }
257
+
258
+ .divider {
259
+ height: .5px;
260
+ background: var(--dsw-alias-border-l2);
261
+ flex: none;
262
+ margin: 3px 2px;
263
+ }
264
+
265
+ .effortRow {
266
+ align-items: center;
267
+ gap: 6px;
268
+ padding: 3px 6px;
269
+ display: flex;
270
+ }
271
+
272
+ .effortHeading {
210
273
  color: var(--dsw-alias-label-primary);
274
+ flex: none;
275
+ font-size: 12px;
276
+ line-height: 18px;
277
+ }
278
+
279
+ /* The segments scroll sideways rather than wrap, so the row keeps one height
280
+ * however many levels a model advertises. */
281
+ .effortTrack {
282
+ background: var(--dsw-alias-interactive-bg-hover);
283
+ border-radius: 999px;
284
+ align-items: center;
285
+ gap: 1px;
286
+ min-width: 0;
287
+ margin-left: auto;
288
+ padding: 2px;
289
+ display: flex;
290
+ overflow-x: auto;
291
+ scrollbar-width: none;
292
+ }
293
+
294
+ .effortTrack::-webkit-scrollbar {
295
+ display: none;
296
+ }
297
+
298
+ .effortSegment {
299
+ color: var(--dsw-alias-label-secondary);
300
+ cursor: pointer;
301
+ background: 0 0;
302
+ border: none;
303
+ border-radius: 999px;
304
+ outline: none;
305
+ flex: none;
306
+ padding: 2px 7px;
307
+ font-size: 11px;
308
+ line-height: 16px;
309
+ }
310
+
311
+ .effortSegment:hover:not(:disabled) {
312
+ color: var(--dsw-alias-label-primary);
313
+ }
314
+
315
+ .effortSegment[aria-checked='true'] {
316
+ color: var(--dsw-alias-label-primary);
317
+ background: var(--dsw-alias-bg-layer-1);
318
+ box-shadow: var(--dsw-elevation-soft);
319
+ font-weight: 600;
320
+ }
321
+
322
+ .effortSegment:disabled {
323
+ color: var(--dsw-alias-label-dimmed);
324
+ cursor: default;
325
+ }
326
+
327
+ .effortSegment:focus-visible {
328
+ outline: 2px solid var(--dsw-alias-border-l3);
329
+ outline-offset: -2px;
330
+ }
331
+
332
+ .hint {
333
+ color: var(--dsw-alias-label-tertiary);
334
+ margin: 0;
335
+ padding: 6px 8px;
336
+ font-size: 11px;
337
+ line-height: 16px;
338
+ }
339
+
340
+ .moreRow {
341
+ color: var(--dsw-alias-label-secondary);
211
342
  cursor: pointer;
212
- text-align: left;
213
343
  background: 0 0;
214
344
  border: none;
215
345
  border-radius: 10px;
346
+ outline: none;
216
347
  align-items: center;
217
- gap: 8px;
218
- padding: 0 10px;
219
- font-size: 14px;
220
- line-height: 22px;
348
+ gap: 6px;
349
+ min-height: 32px;
350
+ padding: 5px 8px;
351
+ font-size: 12px;
352
+ line-height: 18px;
221
353
  display: flex;
222
354
  }
223
355
 
224
- .cell:hover {
356
+ .moreRow:hover,
357
+ .moreRow:focus-visible {
358
+ color: var(--dsw-alias-label-primary);
225
359
  background: var(--dsw-alias-interactive-bg-hover);
226
360
  }
227
361
 
228
- .cellLabel {
229
- white-space: nowrap;
362
+ .moreIcon {
363
+ color: var(--dsw-alias-label-tertiary);
230
364
  flex: none;
231
365
  }
232
366
 
233
- .cellValue {
234
- text-overflow: ellipsis;
235
- white-space: nowrap;
236
- text-align: right;
237
- min-width: 0;
367
+ .notice {
238
368
  color: var(--dsw-alias-label-tertiary);
239
- flex: auto;
240
- overflow: hidden;
369
+ justify-content: space-between;
370
+ align-items: flex-start;
371
+ gap: 8px;
372
+ padding: 6px 10px;
373
+ font-size: 12px;
374
+ line-height: 18px;
375
+ display: flex;
241
376
  }
242
377
 
243
- .cellChevron {
244
- color: var(--dsw-alias-label-tertiary);
378
+ .retry {
379
+ color: inherit;
380
+ font: inherit;
381
+ cursor: pointer;
382
+ background: 0 0;
383
+ border: none;
245
384
  flex: none;
246
- }
385
+ padding: 0;
386
+ font-weight: 600;
387
+ text-decoration: underline;
388
+ }
389
+
390
+ /* ── the picker dialog ───────────────────────────────────────────────────── */
391
+
392
+ .pickerDialog {
393
+ width: min(680px, 100%);
394
+ height: min(640px, 80vh);
395
+ gap: 0;
396
+ padding: 0;
397
+ }
398
+
399
+ .pickerContent {
400
+ min-height: 0;
401
+ flex: 1;
402
+ display: flex;
403
+ flex-direction: column;
404
+ }
405
+
406
+ /* Modal wraps children in a body row of its own; that row — the content
407
+ * region's last child — is what has to carry the column and give the list its
408
+ * remaining height, so the footer stays put while the list scrolls. */
409
+ .pickerContent > :last-child {
410
+ min-height: 0;
411
+ flex: 1;
412
+ display: flex;
413
+ flex-direction: column;
414
+ }
415
+
416
+ .pickerSearch {
417
+ padding: 0 20px 12px;
418
+ }
419
+
420
+ .pickerSearchInput {
421
+ width: 100%;
422
+ }
423
+
424
+ .pickerTabs {
425
+ border-bottom: .5px solid var(--dsw-alias-border-l2);
426
+ gap: 2px;
427
+ padding: 0 16px;
428
+ display: flex;
429
+ flex-wrap: wrap;
430
+ }
431
+
432
+ .pickerTab {
433
+ color: var(--dsw-alias-label-secondary);
434
+ cursor: pointer;
435
+ background: 0 0;
436
+ border: none;
437
+ border-radius: 8px;
438
+ outline: none;
439
+ padding: 6px 10px;
440
+ font-size: 13px;
441
+ line-height: 18px;
442
+ white-space: nowrap;
443
+ }
444
+
445
+ .pickerTab:hover {
446
+ color: var(--dsw-alias-label-primary);
447
+ background: var(--dsw-alias-interactive-bg-hover);
448
+ }
449
+
450
+ .pickerTab[aria-selected='true'] {
451
+ color: var(--dsw-alias-label-primary);
452
+ background: var(--dsw-alias-interactive-bg-hover);
453
+ font-weight: 600;
454
+ }
455
+
456
+ .pickerTab:focus-visible {
457
+ outline: 2px solid var(--dsw-alias-border-l3);
458
+ }
459
+
460
+ .pickerList {
461
+ min-height: 0;
462
+ flex: 1;
463
+ padding: 8px 12px;
464
+ overflow-y: auto;
465
+ }
466
+
467
+ .pickerFooter {
468
+ border-top: .5px solid var(--dsw-alias-border-l2);
469
+ color: var(--dsw-alias-label-tertiary);
470
+ align-items: center;
471
+ gap: 6px;
472
+ padding: 10px 20px;
473
+ font-size: 12px;
474
+ line-height: 18px;
475
+ display: flex;
476
+ }
477
+
478
+ .footerHint {
479
+ align-items: center;
480
+ gap: 6px;
481
+ display: flex;
482
+ flex-wrap: wrap;
483
+ }
484
+
485
+ .footerDot {
486
+ color: var(--dsw-alias-label-dimmed);
487
+ }