@x1a0f3n9/dsh-client-ui-primitives 0.1.5-rc.3

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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +164 -0
  4. package/README.zh.md +164 -0
  5. package/lib/Button.module.css +79 -0
  6. package/lib/ConnectionIndicator.module.css +107 -0
  7. package/lib/DiffBlock.module.css +101 -0
  8. package/lib/DisclosureRow.module.css +84 -0
  9. package/lib/FileTypeIcon.module.css +50 -0
  10. package/lib/HoverCard.module.css +54 -0
  11. package/lib/Input.module.css +38 -0
  12. package/lib/JsonTree.module.css +222 -0
  13. package/lib/Menu.module.css +248 -0
  14. package/lib/Modal.module.css +103 -0
  15. package/lib/OnboardingSurface.module.css +29 -0
  16. package/lib/Pill.module.css +27 -0
  17. package/lib/ReadBlock.module.css +111 -0
  18. package/lib/RiskConfirmation.module.css +73 -0
  19. package/lib/SearchBlock.module.css +112 -0
  20. package/lib/StateDot.module.css +73 -0
  21. package/lib/Switch.module.css +50 -0
  22. package/lib/Tag.module.css +57 -0
  23. package/lib/TerminalBlock.module.css +205 -0
  24. package/lib/Toast.module.css +72 -0
  25. package/lib/Tooltip.module.css +42 -0
  26. package/lib/WebBlock.module.css +141 -0
  27. package/lib/index.js +8030 -0
  28. package/lib/markdown/CodeBlock.module.css +130 -0
  29. package/lib/markdown/JsonBlock.module.css +32 -0
  30. package/lib/markdown/MarkdownText.module.css +321 -0
  31. package/lib/types/BrandWordmark.d.ts +15 -0
  32. package/lib/types/Button.d.ts +18 -0
  33. package/lib/types/CodeFileIcon.d.ts +12 -0
  34. package/lib/types/ConnectionIndicator.d.ts +25 -0
  35. package/lib/types/DiffBlock.d.ts +53 -0
  36. package/lib/types/DisclosureRow.d.ts +29 -0
  37. package/lib/types/FileTypeIcon.d.ts +43 -0
  38. package/lib/types/FishLogo.d.ts +16 -0
  39. package/lib/types/FoldToggle.d.ts +20 -0
  40. package/lib/types/HoverCard.d.ts +24 -0
  41. package/lib/types/Input.d.ts +11 -0
  42. package/lib/types/JsonTree.d.ts +48 -0
  43. package/lib/types/LinkIcon.d.ts +38 -0
  44. package/lib/types/Menu.d.ts +85 -0
  45. package/lib/types/Modal.d.ts +35 -0
  46. package/lib/types/OnboardingSurface.d.ts +11 -0
  47. package/lib/types/Pill.d.ts +13 -0
  48. package/lib/types/ReadBlock.d.ts +47 -0
  49. package/lib/types/ReferenceIcon.d.ts +16 -0
  50. package/lib/types/RiskConfirmation.d.ts +20 -0
  51. package/lib/types/SearchBlock.d.ts +72 -0
  52. package/lib/types/StateDot.d.ts +18 -0
  53. package/lib/types/Switch.d.ts +20 -0
  54. package/lib/types/Tag.d.ts +32 -0
  55. package/lib/types/TerminalBlock.d.ts +61 -0
  56. package/lib/types/Toast.d.ts +32 -0
  57. package/lib/types/Tooltip.d.ts +34 -0
  58. package/lib/types/WebBlock.d.ts +61 -0
  59. package/lib/types/ansi.d.ts +17 -0
  60. package/lib/types/clipboard.d.ts +9 -0
  61. package/lib/types/code-file-icon-artwork.d.ts +54 -0
  62. package/lib/types/code-file-types.d.ts +30 -0
  63. package/lib/types/file-size.d.ts +8 -0
  64. package/lib/types/head-tail-cap.d.ts +23 -0
  65. package/lib/types/icons/index.d.ts +194 -0
  66. package/lib/types/icons/props.d.ts +9 -0
  67. package/lib/types/index.d.ts +66 -0
  68. package/lib/types/markdown/CodeBlock.d.ts +28 -0
  69. package/lib/types/markdown/JsonBlock.d.ts +8 -0
  70. package/lib/types/markdown/MarkdownText.d.ts +42 -0
  71. package/lib/types/markdown/cjkFriendlyStrong.d.ts +9 -0
  72. package/lib/types/markdown/highlight.d.ts +142 -0
  73. package/lib/types/markdown/incremental.d.ts +80 -0
  74. package/lib/types/markdown/katex.d.ts +27 -0
  75. package/lib/types/markdown/mathCompatibility.d.ts +11 -0
  76. package/lib/types/markdown/parse.d.ts +25 -0
  77. package/lib/types/markdown/plain-text.d.ts +22 -0
  78. package/lib/types/markdown/render.d.ts +138 -0
  79. package/lib/types/markdown/useViewportHighlighting.d.ts +11 -0
  80. package/lib/types/pointer-grace.d.ts +22 -0
  81. package/lib/types/rank-by-name.d.ts +22 -0
  82. package/lib/types/relative-time.d.ts +23 -0
  83. package/lib/types/use-copy-feedback.d.ts +14 -0
  84. package/lib/types/useAnchoredMaxHeight.d.ts +11 -0
  85. package/lib/types/useAnchoredPosition.d.ts +34 -0
  86. package/lib/types/useDismissOnOutsidePointer.d.ts +11 -0
  87. package/lib/types/user-text.d.ts +39 -0
  88. package/lib/user-text.module.css +43 -0
  89. package/package.json +58 -0
@@ -0,0 +1,84 @@
1
+ /* Shared disclosure header: [16px leading] gap 6 [title 13/24] at the default
2
+ size. The Settings font-size preference moves the row through the
3
+ body-published axis: title size follows the secondary tier
4
+ (--dsh-content-font-size-secondary: one step under the body — setting −1 at
5
+ ≤14, setting −2 above), and the row height, leading box, and glyph edge
6
+ shift by the body px delta so the icon keeps its optical share of the
7
+ line. */
8
+
9
+ .root {
10
+ display: flex;
11
+ flex-direction: column;
12
+ width: 100%;
13
+ min-width: 0;
14
+ }
15
+
16
+ .row {
17
+ position: relative;
18
+ overflow: hidden;
19
+ display: flex;
20
+ align-items: center;
21
+ height: calc(24px + var(--dsh-content-font-delta, 0px));
22
+ min-width: 0;
23
+ }
24
+
25
+ .row[data-expandable] {
26
+ cursor: pointer;
27
+ }
28
+
29
+ .leading {
30
+ position: relative;
31
+ flex: none;
32
+ width: calc(16px + var(--dsh-content-font-delta, 0px));
33
+ height: calc(16px + var(--dsh-content-font-delta, 0px));
34
+ display: inline-flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ margin-right: 6px;
38
+ padding: 0;
39
+ border: none;
40
+ background: none;
41
+ color: var(--dsw-alias-label-tertiary);
42
+ }
43
+
44
+ /* Flow-row glyphs render at 14px inside the 16px box; the CSS edge overrides
45
+ each svg's own width/height attributes so every registered icon scales
46
+ without a per-callsite size prop. StateDot (its svg carries data-state)
47
+ stays at its fixed figma size — it is a status mark, not text furniture. */
48
+ .leading svg:not([data-state]) {
49
+ width: calc(14px + var(--dsh-content-font-delta, 0px));
50
+ height: calc(14px + var(--dsh-content-font-delta, 0px));
51
+ }
52
+
53
+ button.leading {
54
+ cursor: pointer;
55
+ }
56
+
57
+ .iconIdle {
58
+ display: inline-flex;
59
+ opacity: 1;
60
+ transition: opacity 100ms ease;
61
+ }
62
+
63
+ .chevronHover {
64
+ position: absolute;
65
+ inset: 0;
66
+ margin: auto;
67
+ opacity: 0;
68
+ transition: opacity 100ms ease;
69
+ }
70
+
71
+ .row:hover .iconIdle {
72
+ opacity: 0;
73
+ }
74
+
75
+ .row:hover .chevronHover {
76
+ opacity: 1;
77
+ }
78
+
79
+ .title {
80
+ flex: none;
81
+ font-size: var(--dsh-content-font-size-secondary, 13px);
82
+ line-height: calc(24px + var(--dsh-content-font-delta, 0px));
83
+ color: var(--dsw-alias-label-secondary);
84
+ }
@@ -0,0 +1,50 @@
1
+ .icon {
2
+ /* The design platform has no violet token matching the supplied image/video artwork. */
3
+ --dsh-file-type-violet: rgb(139, 118, 246);
4
+
5
+ color: var(--dsh-file-type-icon-color, var(--dsh-file-type-default-color));
6
+ }
7
+
8
+ .code {
9
+ --dsh-file-type-default-color: var(--dsw-static-deepseek-500);
10
+ }
11
+
12
+ .excel {
13
+ --dsh-file-type-default-color: var(--dsw-static-green-500);
14
+ }
15
+
16
+ .folder {
17
+ --dsh-file-type-default-color: var(--dsw-static-amber-400);
18
+ }
19
+
20
+ .html {
21
+ --dsh-file-type-default-color: var(--dsw-static-deepseek-500);
22
+ }
23
+
24
+ .image {
25
+ --dsh-file-type-default-color: var(--dsh-file-type-violet);
26
+ }
27
+
28
+ .markdown {
29
+ --dsh-file-type-default-color: var(--dsw-static-deepseek-500);
30
+ }
31
+
32
+ .other {
33
+ --dsh-file-type-default-color: var(--dsw-static-neutral-bluish-300);
34
+ }
35
+
36
+ .pdf {
37
+ --dsh-file-type-default-color: var(--dsw-static-red-600);
38
+ }
39
+
40
+ .ppt {
41
+ --dsh-file-type-default-color: var(--dsw-static-amber-500);
42
+ }
43
+
44
+ .video {
45
+ --dsh-file-type-default-color: var(--dsh-file-type-violet);
46
+ }
47
+
48
+ .word {
49
+ --dsh-file-type-default-color: var(--dsw-static-deepseek-450);
50
+ }
@@ -0,0 +1,54 @@
1
+ /* Block, not inline-flex: consumers wrap full-width list rows and an
2
+ * inline wrapper would shrink them; the card still measures this rect. */
3
+ .root {
4
+ position: relative;
5
+ display: block;
6
+ }
7
+
8
+ /* Preview card (figma session hover card): 244 wide, r12, pad 12/16, the
9
+ * menu card's elevation. Surface is #2C2C2E in both themes (figma value,
10
+ * light/dark identical), so a component-level variable, not a theme token.
11
+ * Hit-testable on purpose: resting the pointer on the card holds it open
12
+ * (HoverCard's grace close), which a `pointer-events: none` card cannot do. */
13
+ .card {
14
+ --dsw-hovercard-bg: #2C2C2E;
15
+ position: fixed;
16
+ z-index: 100;
17
+ box-sizing: border-box;
18
+ width: 244px;
19
+ padding: 12px 16px;
20
+ border-radius: 12px;
21
+ background: var(--dsw-hovercard-bg);
22
+ box-shadow: var(--dsw-shadow-lv3);
23
+ }
24
+
25
+ .copyable {
26
+ cursor: pointer;
27
+ }
28
+
29
+ .copyable:focus-visible {
30
+ outline: 2px solid var(--dsw-alias-state-business-primary);
31
+ outline-offset: 2px;
32
+ }
33
+
34
+ .feedback {
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ }
39
+
40
+ .copied {
41
+ color: #FFFFFF;
42
+ font-size: 14px;
43
+ line-height: 20px;
44
+ text-align: center;
45
+ }
46
+
47
+ .status {
48
+ position: absolute;
49
+ width: 1px;
50
+ height: 1px;
51
+ overflow: hidden;
52
+ clip: rect(0 0 0 0);
53
+ white-space: nowrap;
54
+ }
@@ -0,0 +1,38 @@
1
+ .wrap {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: 6px;
5
+ height: 32px;
6
+ padding: 0 8px;
7
+ border: 0.5px solid var(--dsw-alias-border-l4);
8
+ border-radius: 8px;
9
+ background: var(--dsw-alias-bg-layer-1);
10
+ }
11
+
12
+ .wrap:focus-within {
13
+ border-color: var(--dsw-alias-brand-primary);
14
+ }
15
+
16
+ .icon {
17
+ display: inline-flex;
18
+ width: 16px;
19
+ height: 16px;
20
+ align-items: center;
21
+ justify-content: center;
22
+ color: var(--dsw-alias-label-tertiary);
23
+ }
24
+
25
+ .input {
26
+ flex: 1;
27
+ min-width: 0;
28
+ border: none;
29
+ outline: none;
30
+ background: transparent;
31
+ font-size: 14px;
32
+ line-height: 22px;
33
+ color: var(--dsw-alias-label-primary);
34
+ }
35
+
36
+ .input::placeholder {
37
+ color: var(--dsw-alias-label-dimmed);
38
+ }
@@ -0,0 +1,222 @@
1
+ .root {
2
+ --json-tree-property: #881391;
3
+ --json-tree-string: #c41a16;
4
+ --json-tree-number: #1c00cf;
5
+ --json-tree-keyword: #1c00cf;
6
+ --json-tree-punctuation: #202124;
7
+ --json-tree-icon: #5f6368;
8
+ --json-tree-hover: rgb(60 64 67 / 4%);
9
+
10
+ min-width: 0;
11
+ overflow: auto;
12
+ position: relative;
13
+ color: var(--dsw-alias-label-primary);
14
+ background: var(--dsw-alias-bg-layer-1);
15
+ font: 12px/16px var(--ds-font-family-code);
16
+ overscroll-behavior-x: contain;
17
+ overscroll-behavior-y: auto;
18
+ }
19
+
20
+ :global(body[data-ds-dark-theme]) .root {
21
+ --json-tree-property: #5db0d7;
22
+ --json-tree-string: #f28b82;
23
+ --json-tree-number: #99c8ff;
24
+ --json-tree-keyword: #99c8ff;
25
+ --json-tree-punctuation: #e8eaed;
26
+ --json-tree-icon: #9aa0a6;
27
+ --json-tree-hover: rgb(232 234 237 / 5%);
28
+ }
29
+
30
+ .container {
31
+ box-sizing: border-box;
32
+ width: max-content;
33
+ min-width: 100%;
34
+ margin: 0;
35
+ padding: 6px 8px 8px;
36
+ white-space: pre;
37
+ }
38
+
39
+ .expandedTopLevel {
40
+ box-sizing: border-box;
41
+ width: max-content;
42
+ min-width: 100%;
43
+ padding: 6px 8px 8px 14px;
44
+ }
45
+
46
+ .expandedTopLevel:has(> .topLevelBracket[data-json-root-row]:hover),
47
+ .expandedTopLevel:has(> .topLevelBracket[data-json-root-row][data-json-copy-active]) {
48
+ background: var(--json-tree-hover);
49
+ }
50
+
51
+ .expandedTopLevelContainer {
52
+ padding: 0;
53
+ }
54
+
55
+ .row.topLevelBracket {
56
+ margin-left: 0;
57
+ padding-left: 0;
58
+ }
59
+
60
+ .children {
61
+ margin: 0;
62
+ padding: 0;
63
+ list-style: none;
64
+ }
65
+
66
+ .row {
67
+ position: relative;
68
+ box-sizing: border-box;
69
+ min-width: 100%;
70
+ min-height: 16px;
71
+ margin: 0;
72
+ padding: 0 0 0 10px;
73
+ list-style: none;
74
+ }
75
+
76
+ .row:not(.topLevelBracket):hover:not(:has(.row:hover))::after,
77
+ .row:not(.topLevelBracket)[data-json-copy-active]::after,
78
+ .row:has(> .expander:focus-visible)::after {
79
+ position: absolute;
80
+ z-index: 0;
81
+ top: 0;
82
+ right: 0;
83
+ left: 0;
84
+ height: 16px;
85
+ background: var(--json-tree-hover);
86
+ content: '';
87
+ pointer-events: none;
88
+ }
89
+
90
+ .row > span:not(.expander) {
91
+ position: relative;
92
+ z-index: 1;
93
+ }
94
+
95
+ .label {
96
+ margin-right: 3px;
97
+ color: var(--json-tree-property);
98
+ font-weight: 400;
99
+ }
100
+
101
+ .clickableLabel {
102
+ cursor: pointer;
103
+ }
104
+
105
+ .stringValue {
106
+ color: var(--json-tree-string);
107
+ }
108
+
109
+ .numberValue {
110
+ color: var(--json-tree-number);
111
+ }
112
+
113
+ .keywordValue {
114
+ color: var(--json-tree-keyword);
115
+ }
116
+
117
+ .otherValue {
118
+ color: var(--dsw-alias-label-secondary);
119
+ }
120
+
121
+ .punctuation {
122
+ color: var(--json-tree-punctuation);
123
+ }
124
+
125
+ .preview {
126
+ color: var(--json-tree-punctuation);
127
+ }
128
+
129
+ .previewProperty {
130
+ color: var(--json-tree-punctuation);
131
+ }
132
+
133
+ .previewEllipsis {
134
+ color: var(--dsw-alias-label-tertiary);
135
+ }
136
+
137
+ .copyAnchor {
138
+ position: fixed;
139
+ z-index: 3;
140
+ display: inline-flex;
141
+ }
142
+
143
+ .copyButton {
144
+ box-sizing: border-box;
145
+ display: inline-flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ width: 20px;
149
+ height: 16px;
150
+ margin: 0;
151
+ padding: 0;
152
+ border: 0;
153
+ border-radius: 3px;
154
+ color: var(--dsw-alias-label-secondary);
155
+ background: var(--dsw-alias-bg-layer-1);
156
+ box-shadow: -5px 0 5px var(--dsw-alias-bg-layer-1);
157
+ cursor: pointer;
158
+ }
159
+
160
+ .copyButton:hover {
161
+ color: var(--dsw-alias-label-primary);
162
+ background: var(--dsw-alias-interactive-bg-hover);
163
+ }
164
+
165
+ .copyButton:focus-visible {
166
+ outline: 1px solid var(--dsw-alias-state-business-primary);
167
+ outline-offset: -1px;
168
+ }
169
+
170
+ .copyButton[data-state='failed'] {
171
+ color: var(--dsw-alias-state-error-primary);
172
+ }
173
+
174
+ .expander {
175
+ position: absolute;
176
+ z-index: 2;
177
+ top: 0;
178
+ left: 0;
179
+ display: inline-flex;
180
+ align-items: center;
181
+ justify-content: flex-start;
182
+ box-sizing: border-box;
183
+ width: 8px;
184
+ height: 16px;
185
+ margin: 0;
186
+ color: var(--json-tree-icon);
187
+ cursor: pointer;
188
+ user-select: none;
189
+ }
190
+
191
+ .expander::before {
192
+ width: 0;
193
+ height: 0;
194
+ border-top: 4px solid transparent;
195
+ border-bottom: 4px solid transparent;
196
+ border-left: 6px solid currentColor;
197
+ content: '';
198
+ transform: scale(0.75);
199
+ transform-origin: 33.333% center;
200
+ }
201
+
202
+ .collapseIcon::before {
203
+ transform: rotate(90deg) scale(0.75);
204
+ }
205
+
206
+ .expander:hover {
207
+ color: var(--dsw-alias-label-primary);
208
+ }
209
+
210
+ .expander:focus-visible {
211
+ outline: none;
212
+ }
213
+
214
+ .collapsedContent {
215
+ margin: 0 1px;
216
+ color: var(--json-tree-punctuation);
217
+ cursor: pointer;
218
+ }
219
+
220
+ .collapsedContent::after {
221
+ content: '…';
222
+ }
@@ -0,0 +1,248 @@
1
+ .root {
2
+ position: relative;
3
+ display: inline-flex;
4
+ }
5
+
6
+ /* Dropdown card (figma MenuDropdown 122:9481 / 419:16920): menu surface,
7
+ * r12, elevation-prominent (hairline stroke in shadow), 4px inset padding. */
8
+ .list,
9
+ .submenu {
10
+ /* min-widths below are the design's outer card widths — include the pad. */
11
+ box-sizing: border-box;
12
+ padding: 4px;
13
+ display: flex;
14
+ flex-direction: column;
15
+ gap: 0;
16
+ border: 0;
17
+ border-radius: 20px;
18
+ background: var(--dsw-specific-menu);
19
+ --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
20
+ box-shadow: var(--dsw-elevation-prominent);
21
+ /* Elevated surface: the scrollbar thumb takes the l2 elevation tokens. The
22
+ declaration sits on the card rather than on `.scrollable .viewport`
23
+ because the elevation is a property of this surface, and the custom
24
+ properties inherit down to whichever descendant actually scrolls (see
25
+ ui-theme styles/scrollbar.css for the rebinding contract). */
26
+ --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
27
+ --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
28
+ }
29
+
30
+ /* Primary card is 218 wide in the design across both hosts. */
31
+ .list {
32
+ position: absolute;
33
+ top: calc(100% + 4px);
34
+ left: 0;
35
+ z-index: 100;
36
+ min-width: 218px;
37
+ max-width: 360px;
38
+ }
39
+
40
+ /* Portal mode: fixed in the viewport, coordinates supplied inline from the
41
+ * anchor rect (side/align resolved in JS, the in-place offset rules above
42
+ * don't apply). Portaled lists must layer above modal overlays (z 1000) —
43
+ * an anchor inside a dialog still expects its menu on top. */
44
+ .portal {
45
+ position: fixed;
46
+ top: auto;
47
+ left: auto;
48
+ z-index: 1100;
49
+ }
50
+
51
+ /* Open above the anchor (empty-state workspace chip: figma 122:9481). */
52
+ .sideTop {
53
+ top: auto;
54
+ bottom: calc(100% + 4px);
55
+ }
56
+
57
+ .alignEnd {
58
+ left: auto;
59
+ right: 0;
60
+ }
61
+
62
+ /* Viewport fit: the card stops 12px short of the viewport's top/bottom edges
63
+ * (24 = 2 × the portal MARGIN in Menu.tsx) and taller content scrolls inside
64
+ * .viewport, so a pinned .footer stays visible. Menus with submenu rows skip
65
+ * this class — the overflow clip would crop the side card, so they rely on
66
+ * staying short. */
67
+ .scrollable {
68
+ max-height: calc(100vh - 24px);
69
+ }
70
+
71
+ .viewport {
72
+ display: flex;
73
+ flex-direction: column;
74
+ min-height: 0;
75
+ }
76
+
77
+ .scrollable .viewport {
78
+ overflow-y: auto;
79
+ }
80
+
81
+ /* Pinned rows below the scroll region; l2 hairline (l1 is near-invisible on
82
+ * the menu surface) mirrors the .separator spacing. */
83
+ .footer {
84
+ flex: none;
85
+ display: flex;
86
+ flex-direction: column;
87
+ margin-top: 4px;
88
+ padding-top: 4px;
89
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
90
+ }
91
+
92
+ .itemWrap {
93
+ position: relative;
94
+ }
95
+
96
+ /* Menu cell (figma .Menu_cell): min-h 40, r10, pad 10/8, 14/22 primary,
97
+ * gap 8 between leading icon / label / trailing check. */
98
+ .item {
99
+ display: flex;
100
+ align-items: center;
101
+ gap: 8px;
102
+ width: 100%;
103
+ min-height: 40px;
104
+ padding: 8px 10px;
105
+ border: none;
106
+ border-radius: 10px;
107
+ background: transparent;
108
+ cursor: pointer;
109
+ font-size: 14px;
110
+ line-height: 22px;
111
+ color: var(--dsw-alias-label-primary);
112
+ text-align: left;
113
+ }
114
+
115
+ .item:hover:not(:disabled) {
116
+ background: var(--dsw-alias-interactive-bg-hover);
117
+ }
118
+
119
+ .denseList .item {
120
+ min-height: 34px;
121
+ padding-block: 5px;
122
+ }
123
+
124
+ .denseList .label {
125
+ padding-block: 4px;
126
+ }
127
+
128
+ .list.compactList,
129
+ .submenu.compactList {
130
+ min-width: 164px;
131
+ padding: 2px;
132
+ border-radius: 7px;
133
+ }
134
+
135
+ .compactList .item {
136
+ min-height: 26px;
137
+ gap: 6px;
138
+ padding: 3px 7px;
139
+ border-radius: 5px;
140
+ font-size: 12px;
141
+ line-height: 18px;
142
+ }
143
+
144
+ .compactList .itemIcon {
145
+ width: 14px;
146
+ height: 14px;
147
+ }
148
+
149
+ .compactList .separator {
150
+ margin: 2px;
151
+ }
152
+
153
+ .compactList .label {
154
+ padding: 4px 7px;
155
+ font-size: 11px;
156
+ line-height: 16px;
157
+ }
158
+
159
+ .item:disabled {
160
+ opacity: 0.4;
161
+ cursor: not-allowed;
162
+ }
163
+
164
+ .itemIcon {
165
+ display: inline-flex;
166
+ flex: none;
167
+ width: 16px;
168
+ height: 16px;
169
+ align-items: center;
170
+ justify-content: center;
171
+ color: var(--dsw-alias-label-tertiary);
172
+ }
173
+
174
+ .itemLabel {
175
+ flex: 1;
176
+ min-width: 0;
177
+ overflow: hidden;
178
+ text-overflow: ellipsis;
179
+ white-space: nowrap;
180
+ }
181
+
182
+ .check {
183
+ flex: none;
184
+ color: var(--dsw-alias-label-primary);
185
+ }
186
+
187
+ /* Selected cell keeps the plain fill (marker is the trailing check); the
188
+ * class remains as a hook for owner-side emphasis. */
189
+ .selected {
190
+ background: transparent;
191
+ }
192
+
193
+ /* Fill-mode selection: the row holds the hover fill instead of a check. */
194
+ .selectedFill {
195
+ background: var(--dsw-alias-interactive-bg-hover);
196
+ }
197
+
198
+ /* Destructive row: error text/icon, danger hover fill. */
199
+ .danger {
200
+ color: var(--dsw-alias-state-error-primary);
201
+ }
202
+
203
+ .danger .itemIcon {
204
+ color: var(--dsw-alias-state-error-primary);
205
+ }
206
+
207
+ .danger:hover:not(:disabled) {
208
+ background: var(--dsw-alias-interactive-bg-hover-danger);
209
+ }
210
+
211
+ /* Heading row: non-interactive small grey text, padding aligned with items. */
212
+ .label {
213
+ padding: 8px 10px;
214
+ font-size: 12px;
215
+ line-height: 16px;
216
+ color: var(--dsw-alias-label-tertiary);
217
+ }
218
+
219
+ /* Separator cell (figma 122:9481): py 4 / px 2 around the hairline. */
220
+ .separator {
221
+ height: 0.5px;
222
+ margin: 4px 2px;
223
+ background: var(--dsw-alias-border-l1);
224
+ }
225
+
226
+ /* Nested card to the right of the parent row (figma 419:16920).
227
+ * Bottom-aligned with the parent menu card (grows upward): itemWrap sits in
228
+ * .list's 4px pad, so bottom: -4px matches the list's outer bottom edge.
229
+ * Horizontal: list pad (4px) + 6px card gap = 10px past itemWrap — plain
230
+ * `100% + 6px` collapses to ~2px between outer card edges.
231
+ * ::before bridges the full gap so the pointer can cross without mouseLeave. */
232
+ .submenu {
233
+ position: absolute;
234
+ top: auto;
235
+ bottom: -4px;
236
+ left: calc(100% + 10px);
237
+ z-index: 101;
238
+ min-width: 163px;
239
+ }
240
+
241
+ .submenu::before {
242
+ content: '';
243
+ position: absolute;
244
+ top: 0;
245
+ bottom: 0;
246
+ left: -10px;
247
+ width: 10px;
248
+ }