@floegence/floe-webapp-core 0.86.58 → 0.86.62
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.
- package/dist/components/chat/blocks/BlockRenderer.js +1 -1
- package/dist/components/chat/blocks/CodeDiffBlock.js +56 -56
- package/dist/components/chat/blocks/ImageBlock.js +1 -1
- package/dist/components/chat/blocks/ToolCallBlock.js +57 -57
- package/dist/components/chat/status/ConnectionStatus.js +10 -10
- package/dist/components/deck/DeckCell.js +25 -25
- package/dist/components/deck/DeckContextMenu.js +20 -20
- package/dist/components/deck/DeckGrid.js +1 -1
- package/dist/components/deck/DeckTopBar.js +42 -42
- package/dist/components/deck/DropZonePreview.js +6 -6
- package/dist/components/deck/LayoutSelector.js +53 -53
- package/dist/components/deck/WidgetFrame.js +28 -28
- package/dist/components/deck/WidgetPalette.js +31 -31
- package/dist/components/deck/WidgetTypeSwitcher.js +31 -31
- package/dist/components/file-browser/Breadcrumb.js +27 -27
- package/dist/components/file-browser/DirectoryTree.js +15 -15
- package/dist/components/file-browser/DragPreview.js +58 -58
- package/dist/components/file-browser/FileBrowser.js +17 -17
- package/dist/components/file-browser/FileBrowserStatusBar.js +18 -18
- package/dist/components/file-browser/FileBrowserToolbar.js +27 -27
- package/dist/components/file-browser/FileContextMenu.js +47 -47
- package/dist/components/file-browser/FileGridView.js +53 -51
- package/dist/components/file-browser/FileItemDecorations.js +30 -27
- package/dist/components/file-browser/FileListView.js +114 -114
- package/dist/components/icons/index.js +1357 -1357
- package/dist/components/launchpad/Launchpad.js +14 -14
- package/dist/components/launchpad/LaunchpadGrid.js +7 -7
- package/dist/components/launchpad/LaunchpadItem.js +11 -11
- package/dist/components/launchpad/LaunchpadPagination.js +16 -16
- package/dist/components/launchpad/LaunchpadSearch.js +9 -9
- package/dist/components/layout/ActivityBar.js +52 -55
- package/dist/components/layout/BottomBar.js +17 -17
- package/dist/components/layout/MobileNavigationPanel.js +36 -36
- package/dist/components/layout/MobileTabBar.js +39 -39
- package/dist/components/layout/Panel.js +16 -16
- package/dist/components/layout/ResizeHandle.js +19 -19
- package/dist/components/layout/Shell.js +50 -50
- package/dist/components/layout/Sidebar.js +37 -36
- package/dist/components/layout/SidebarPane.js +19 -19
- package/dist/components/layout/TopBar.js +16 -16
- package/dist/components/layout/TopBarIconButton.js +15 -15
- package/dist/components/loading/LoadingOverlay.js +9 -9
- package/dist/components/loading/Skeleton.js +11 -11
- package/dist/components/ui/Button.js +36 -36
- package/dist/components/ui/Card.d.ts +11 -62
- package/dist/components/ui/Card.js +64 -237
- package/dist/components/ui/Checkbox.js +79 -79
- package/dist/components/ui/CommandPalette.js +56 -55
- package/dist/components/ui/Dialog.js +91 -93
- package/dist/components/ui/DirectoryInput.js +22 -22
- package/dist/components/ui/DirectoryPicker.js +8 -8
- package/dist/components/ui/Dropdown.js +89 -87
- package/dist/components/ui/FeedbackIndicator.js +57 -57
- package/dist/components/ui/FileOpenPicker.js +37 -37
- package/dist/components/ui/FileSavePicker.js +41 -41
- package/dist/components/ui/FloatingWindow.js +266 -261
- package/dist/components/ui/Form.js +76 -76
- package/dist/components/ui/HighlightBlock.js +14 -14
- package/dist/components/ui/Input.js +106 -109
- package/dist/components/ui/Pagination.js +86 -86
- package/dist/components/ui/Popover.d.ts +33 -0
- package/dist/components/ui/Popover.js +133 -0
- package/dist/components/ui/ProcessingIndicator.js +344 -345
- package/dist/components/ui/Progress.js +94 -97
- package/dist/components/ui/QuoteBlock.js +25 -25
- package/dist/components/ui/Radio.js +91 -91
- package/dist/components/ui/SegmentedControl.js +24 -24
- package/dist/components/ui/Stepper.js +68 -60
- package/dist/components/ui/Switch.js +25 -25
- package/dist/components/ui/Tabs.js +99 -87
- package/dist/components/ui/Tag.js +12 -9
- package/dist/components/ui/Tooltip.js +30 -30
- package/dist/components/ui/floatingPresence.d.ts +7 -0
- package/dist/components/ui/floatingPresence.js +80 -39
- package/dist/components/ui/index.d.ts +2 -1
- package/dist/components/ui/picker/DirectoryFavorites.js +27 -27
- package/dist/components/ui/picker/PickerBase.js +107 -107
- package/dist/context/NotificationContext.js +4 -4
- package/dist/context/ThemeContext.js +71 -70
- package/dist/floe.css +205 -43
- package/dist/full.js +650 -652
- package/dist/language.css +320 -0
- package/dist/primitives.css +23 -17
- package/dist/standalone.css +1 -0
- package/dist/styles/themes/classicSemanticTokens.d.ts +122 -122
- package/dist/styles/themes/classicSemanticTokens.js +140 -138
- package/dist/styles/themes/index.d.ts +3 -1
- package/dist/styles/themes/index.js +10 -10
- package/dist/styles/themes/presets.d.ts +2 -2
- package/dist/styles/themes/presets.js +34 -34
- package/dist/styles/tokens.d.ts +152 -68
- package/dist/styles/tokens.js +87 -49
- package/dist/styles.css +1 -1
- package/dist/surface.css +161 -116
- package/dist/themes/dark.css +64 -64
- package/dist/themes/light.css +64 -64
- package/dist/ui.css +171 -255
- package/dist/ui.js +176 -178
- package/dist/utils/hotInteraction.d.ts +7 -0
- package/dist/utils/hotInteraction.js +12 -12
- package/dist/widgets/TerminalWidget.js +28 -28
- package/dist/workbench-composition.css +15 -15
- package/package.json +1 -1
package/dist/surface.css
CHANGED
|
@@ -12,18 +12,22 @@
|
|
|
12
12
|
* propagate that private value through its editor/content descendants. */
|
|
13
13
|
/* Preblend quiet seams onto the carrying background. Opaque borders avoid an
|
|
14
14
|
* extra blending path when native editors repaint their text and caret. */
|
|
15
|
+
/* The language owns the seams. Surfaces no longer invent their own edge
|
|
16
|
+
* percentages or shadows: a seam is the language's hairline preblended onto the
|
|
17
|
+
* carrying canvas (opaque, so editors repaint text and caret without a second
|
|
18
|
+
* blend pass), and elevation comes from the language's three-step ladder. */
|
|
15
19
|
:root {
|
|
16
|
-
--floe-surface-edge: color-mix(in srgb, var(--foreground)
|
|
17
|
-
--floe-surface-divider: color-mix(in srgb, var(--foreground)
|
|
18
|
-
--floe-surface-highlight:
|
|
19
|
-
--floe-surface-shade:
|
|
20
|
+
--floe-surface-edge: color-mix(in srgb, var(--foreground) 9%, var(--background));
|
|
21
|
+
--floe-surface-divider: color-mix(in srgb, var(--foreground) 5.5%, var(--background));
|
|
22
|
+
--floe-surface-highlight: transparent;
|
|
23
|
+
--floe-surface-shade: color-mix(in srgb, #000 8%, transparent);
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
/* Keep dimensions and semantic palette tokens intact. Neutral boundaries become
|
|
23
27
|
* quiet seams; material and existing fills carry the grouping. High contrast
|
|
24
28
|
* retains the original boundaries. Explicit rich Card variants stay independent. */
|
|
25
29
|
@media (forced-colors: none) {
|
|
26
|
-
:where(:root
|
|
30
|
+
:where(:root:not([data-floe-shell-theme='hc-light']))
|
|
27
31
|
:is(
|
|
28
32
|
.border-border,
|
|
29
33
|
[class~='border-border/40'],
|
|
@@ -37,13 +41,24 @@
|
|
|
37
41
|
.border-input,
|
|
38
42
|
[data-floe-input-surface],
|
|
39
43
|
[data-floe-input-surface] *,
|
|
44
|
+
/* A form field draws its own boundary. The seam is a hairline preblended
|
|
45
|
+
* onto the page ground, which is right for a divider sitting on that
|
|
46
|
+
* ground and wrong for a well carved into a card: 9% over the page
|
|
47
|
+
* against a 4.5% fill lands within one step of the fill, so the edge
|
|
48
|
+
* vanishes instead of quietening. Fields carry `--floe-field-edge`,
|
|
49
|
+
* measured against the plane they actually sit on. */
|
|
50
|
+
input,
|
|
51
|
+
textarea,
|
|
52
|
+
select,
|
|
53
|
+
.floe-field,
|
|
54
|
+
[data-floe-control],
|
|
40
55
|
[data-floe-surface-part='tab'],
|
|
41
56
|
[data-floe-card-variant]:not([data-floe-card-variant='default'])
|
|
42
57
|
)
|
|
43
58
|
) {
|
|
44
59
|
border-color: var(--floe-surface-edge);
|
|
45
60
|
}
|
|
46
|
-
:where(:root
|
|
61
|
+
:where(:root:not([data-floe-shell-theme='hc-light']))
|
|
47
62
|
:is(
|
|
48
63
|
[data-floe-shell-slot],
|
|
49
64
|
.workbench-widget__header,
|
|
@@ -58,7 +73,7 @@
|
|
|
58
73
|
--terminal-panel-border: var(--floe-surface-divider);
|
|
59
74
|
border-color: var(--floe-surface-divider);
|
|
60
75
|
}
|
|
61
|
-
:where(:root
|
|
76
|
+
:where(:root:not([data-floe-shell-theme='hc-light']))
|
|
62
77
|
:is(
|
|
63
78
|
.bg-border,
|
|
64
79
|
.workbench-dock__divider,
|
|
@@ -69,41 +84,39 @@
|
|
|
69
84
|
) {
|
|
70
85
|
background-color: var(--floe-surface-divider);
|
|
71
86
|
}
|
|
72
|
-
:where(:root
|
|
87
|
+
:where(:root:not([data-floe-shell-theme='hc-light']))
|
|
73
88
|
.workbench-canvas__grid {
|
|
74
89
|
opacity: 0.35;
|
|
75
90
|
}
|
|
76
|
-
:root
|
|
91
|
+
:root:not([data-floe-shell-theme='hc-light'])
|
|
77
92
|
[data-floe-surface-divider] {
|
|
78
93
|
border-color: var(--floe-surface-divider);
|
|
79
94
|
}
|
|
80
|
-
:root
|
|
95
|
+
:root:not([data-floe-shell-theme='hc-light'])
|
|
81
96
|
.workbench-surface {
|
|
82
97
|
--wb-dock-material-border: var(--floe-surface-edge);
|
|
83
98
|
--wb-dock-material-border-top: var(--floe-surface-edge);
|
|
84
99
|
--wb-dock-material-shadow: var(
|
|
85
100
|
--floe-surface-shadow-raised,
|
|
86
|
-
0 2px 5px -2px var(--floe-surface-shade)
|
|
87
|
-
inset 0 1px 1px var(--floe-surface-highlight)
|
|
101
|
+
0 2px 5px -2px var(--floe-surface-shade)
|
|
88
102
|
);
|
|
89
103
|
}
|
|
90
104
|
}
|
|
91
105
|
:root.dark {
|
|
92
106
|
--floe-surface-highlight: transparent;
|
|
93
|
-
--floe-surface-shadow-raised:
|
|
107
|
+
--floe-surface-shadow-raised: var(--floe-elevation-raised);
|
|
94
108
|
--floe-surface-shadow-inset: 0 0 transparent;
|
|
95
|
-
--floe-surface-shade:
|
|
109
|
+
--floe-surface-shade: color-mix(in srgb, #000 34%, transparent);
|
|
96
110
|
}
|
|
97
111
|
|
|
98
|
-
[data-floe-surface
|
|
112
|
+
[data-floe-surface] {
|
|
99
113
|
--floe-surface-decoration: 0 0 transparent;
|
|
100
114
|
box-shadow: var(--floe-surface-decoration);
|
|
101
115
|
}
|
|
102
116
|
|
|
103
117
|
/* Material never owns movement. Keep the motion component's property list,
|
|
104
118
|
* duration and easing together instead of remapping its transition shorthand. */
|
|
105
|
-
[data-floe-surface
|
|
106
|
-
[data-floe-surface]:not(
|
|
119
|
+
[data-floe-surface]:not(
|
|
107
120
|
:where(
|
|
108
121
|
.floe-floating-presence,
|
|
109
122
|
[data-floe-surface-part='switch-thumb'],
|
|
@@ -114,24 +127,16 @@
|
|
|
114
127
|
transition-property: color, background-color, border-color, opacity;
|
|
115
128
|
}
|
|
116
129
|
|
|
117
|
-
[data-floe-surface
|
|
118
|
-
--floe-surface-decoration: var(
|
|
119
|
-
--floe-surface-shadow-raised,
|
|
120
|
-
0 1px 3px -2px var(--floe-surface-shade),
|
|
121
|
-
inset 0 1px 1px var(--floe-surface-highlight)
|
|
122
|
-
);
|
|
130
|
+
[data-floe-surface='raised'] {
|
|
131
|
+
--floe-surface-decoration: var(--floe-surface-shadow-raised, var(--floe-elevation-raised));
|
|
123
132
|
}
|
|
124
|
-
[data-floe-surface
|
|
125
|
-
--floe-surface-decoration: var(
|
|
126
|
-
--floe-surface-shadow-inset,
|
|
127
|
-
inset 0 1px 1px var(--floe-surface-shade),
|
|
128
|
-
inset 0 -1px 1px var(--floe-surface-highlight)
|
|
129
|
-
);
|
|
133
|
+
[data-floe-surface='inset'] {
|
|
134
|
+
--floe-surface-decoration: var(--floe-surface-shadow-inset, 0 0 transparent);
|
|
130
135
|
}
|
|
131
|
-
[data-floe-surface
|
|
136
|
+
[data-floe-surface='floating'] {
|
|
132
137
|
--floe-surface-decoration: var(
|
|
133
138
|
--floe-surface-shadow-floating,
|
|
134
|
-
var(--floe-
|
|
139
|
+
var(--floe-elevation-float)
|
|
135
140
|
);
|
|
136
141
|
background-color: var(--popover);
|
|
137
142
|
-webkit-backdrop-filter: none;
|
|
@@ -140,25 +145,24 @@
|
|
|
140
145
|
|
|
141
146
|
/* The geometry owner must not clip the moving panel's external shadow. Paint
|
|
142
147
|
* containment belongs on the existing panel that also owns content clipping. */
|
|
143
|
-
[data-floe-
|
|
148
|
+
[data-floe-geometry-surface='floating-window'] {
|
|
144
149
|
contain: layout style;
|
|
145
150
|
}
|
|
146
|
-
[data-floe-
|
|
151
|
+
[data-floe-floating-window-surface='true'] {
|
|
147
152
|
contain: paint;
|
|
148
153
|
}
|
|
149
|
-
[data-floe-
|
|
154
|
+
[data-floe-dialog-backdrop]:not(.floe-bottom-drawer-backdrop) {
|
|
150
155
|
background-color: rgb(0 0 0 / 16%);
|
|
151
156
|
-webkit-backdrop-filter: none;
|
|
152
157
|
backdrop-filter: none;
|
|
153
158
|
}
|
|
154
|
-
:root.dark[data-floe-
|
|
159
|
+
:root.dark[data-floe-dialog-backdrop]:not(.floe-bottom-drawer-backdrop) {
|
|
155
160
|
background-color: rgb(0 0 0 / 36%);
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
/* A new selection is visible in its first painted frame. Fading the two faces
|
|
159
164
|
* leaves the old choice visually active after the native state has changed. */
|
|
160
|
-
|
|
161
|
-
:is(
|
|
165
|
+
:is(
|
|
162
166
|
[data-floe-surface-part='choice'],
|
|
163
167
|
[data-floe-surface-part='indicator'],
|
|
164
168
|
[data-floe-surface-part='tab'],
|
|
@@ -169,18 +173,16 @@
|
|
|
169
173
|
|
|
170
174
|
/* A compound input has one decorative boundary, including host compositions
|
|
171
175
|
* that contain an Input component. Dense nested actions stay flat. */
|
|
172
|
-
[data-floe-
|
|
173
|
-
[data-floe-surface
|
|
174
|
-
[data-floe-surface='raised']
|
|
176
|
+
[data-floe-input-surface] [data-floe-surface],
|
|
177
|
+
[data-floe-surface='raised']
|
|
175
178
|
[data-floe-surface='raised']:not([data-floe-surface-part]),
|
|
176
|
-
[data-floe-surface
|
|
179
|
+
[data-floe-surface='flat'] {
|
|
177
180
|
--floe-surface-decoration: 0 0 transparent;
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
/* Decoration cannot replace independent keyboard indicators. Inputs, including
|
|
181
184
|
* button-based compound fields, continue to use input-focus.css exclusively. */
|
|
182
|
-
[data-floe-surface-
|
|
183
|
-
[data-floe-surface]:focus-visible:not(
|
|
185
|
+
[data-floe-surface]:focus-visible:not(
|
|
184
186
|
:where(input, textarea, select, [data-floe-input-surface], [data-floe-input-surface] *)
|
|
185
187
|
) {
|
|
186
188
|
box-shadow:
|
|
@@ -189,24 +191,23 @@
|
|
|
189
191
|
var(--floe-surface-decoration);
|
|
190
192
|
}
|
|
191
193
|
|
|
192
|
-
|
|
194
|
+
.workbench-widget[data-floe-surface] {
|
|
193
195
|
/* Some local palettes use translucent body tints. Composite onto an opaque
|
|
194
196
|
* card base instead of reintroducing glass or letting content bleed through. */
|
|
195
197
|
background: linear-gradient(var(--wb-widget-body), var(--wb-widget-body)), var(--card);
|
|
196
198
|
}
|
|
197
|
-
|
|
199
|
+
.workbench-widget.is-selected {
|
|
198
200
|
border-color: transparent;
|
|
199
201
|
}
|
|
200
|
-
|
|
201
|
-
.workbench-widget.is-selected
|
|
202
|
+
.workbench-widget.is-selected
|
|
202
203
|
.workbench-widget__header {
|
|
203
204
|
background: color-mix(in srgb, var(--wb-accent) 8%, var(--card));
|
|
204
205
|
color: var(--wb-accent);
|
|
205
206
|
}
|
|
206
|
-
[data-floe-surface-
|
|
207
|
+
[data-floe-surface-interacting='true'] {
|
|
207
208
|
--floe-surface-decoration: var(
|
|
208
209
|
--floe-surface-shadow-interacting,
|
|
209
|
-
|
|
210
|
+
var(--floe-elevation-raised)
|
|
210
211
|
);
|
|
211
212
|
transition: none;
|
|
212
213
|
}
|
|
@@ -215,13 +216,11 @@
|
|
|
215
216
|
* Tight static highlights carry material without large soft shadows per item.
|
|
216
217
|
* Functional transforms, progress widths, and SVG strokes retain their motion. */
|
|
217
218
|
@media (forced-colors: none) {
|
|
218
|
-
:root
|
|
219
|
-
--floe-surface-compact-raised:
|
|
220
|
-
|
|
221
|
-
--floe-surface-compact-inset:
|
|
222
|
-
inset 0 1px 1px var(--floe-surface-shade), inset 0 -1px 1px var(--floe-surface-highlight);
|
|
219
|
+
:root:not([data-floe-shell-theme='hc-light']) {
|
|
220
|
+
--floe-surface-compact-raised: var(--floe-elevation-raised);
|
|
221
|
+
--floe-surface-compact-inset: 0 0 transparent;
|
|
223
222
|
}
|
|
224
|
-
:where(:root
|
|
223
|
+
:where(:root:not([data-floe-shell-theme='hc-light'])) {
|
|
225
224
|
& [data-floe-surface-part][data-floe-surface='raised'] {
|
|
226
225
|
--floe-surface-decoration: var(
|
|
227
226
|
--floe-surface-shadow-raised,
|
|
@@ -234,12 +233,28 @@
|
|
|
234
233
|
var(--floe-surface-compact-inset)
|
|
235
234
|
);
|
|
236
235
|
}
|
|
236
|
+
/* Two tags, two gestures. An outline rides along with content; a wash
|
|
237
|
+
* wins the eye inside a list. The accent is the tone's own color, so one
|
|
238
|
+
* recipe covers every semantic variant in every preset. */
|
|
239
|
+
&
|
|
240
|
+
[data-floe-surface-part='badge'][data-floe-tone='soft']:not(
|
|
241
|
+
[data-floe-surface='flat']
|
|
242
|
+
) {
|
|
243
|
+
background-color: transparent;
|
|
244
|
+
border-color: var(--floe-line-strong);
|
|
245
|
+
}
|
|
246
|
+
&
|
|
247
|
+
[data-floe-surface-part='badge'][data-floe-tone='solid']:not(
|
|
248
|
+
[data-floe-surface='flat']
|
|
249
|
+
) {
|
|
250
|
+
background-color: color-mix(in srgb, var(--tag-accent) 15%, transparent);
|
|
251
|
+
border-color: color-mix(in srgb, var(--tag-accent) 26%, transparent);
|
|
252
|
+
}
|
|
237
253
|
& [data-floe-surface-part='badge'] {
|
|
238
254
|
/* These can repeat in dense lists. Keep lighting inside the painted box. */
|
|
239
255
|
--floe-surface-decoration: var(
|
|
240
256
|
--floe-surface-shadow-raised,
|
|
241
|
-
|
|
242
|
-
inset 0 -1px 1px var(--floe-surface-shade)
|
|
257
|
+
0 0 0 1px color-mix(in srgb, var(--foreground) 6%, transparent)
|
|
243
258
|
);
|
|
244
259
|
}
|
|
245
260
|
& [data-floe-surface-part='badge'][data-floe-surface='inset'],
|
|
@@ -259,10 +274,16 @@
|
|
|
259
274
|
--floe-surface-decoration: var(--floe-surface-shadow-raised, none);
|
|
260
275
|
}
|
|
261
276
|
& :is([data-floe-surface-part='rail'], [data-floe-surface-part='tab-rail']) {
|
|
262
|
-
background-color:
|
|
277
|
+
background-color: var(--floe-well);
|
|
263
278
|
}
|
|
264
279
|
/* Keep the existing box metrics, but let the carrying fill reach the edge.
|
|
265
280
|
* An opaque seam based on the page background becomes a dark frame here. */
|
|
281
|
+
/* A card is a filled plane on the canvas. Its separation is the fill step
|
|
282
|
+
* plus the canvas gutter, so it carries no contour and no resting shadow. */
|
|
283
|
+
& [data-floe-card-variant='default'][data-floe-surface] {
|
|
284
|
+
border-color: transparent;
|
|
285
|
+
--floe-surface-decoration: 0 0 transparent;
|
|
286
|
+
}
|
|
266
287
|
&
|
|
267
288
|
:is(
|
|
268
289
|
[data-floe-card-variant='default'],
|
|
@@ -282,26 +303,47 @@
|
|
|
282
303
|
[data-floe-surface-part='choice']:not([data-floe-selected='true']):hover:not(
|
|
283
304
|
:has(:disabled)
|
|
284
305
|
) {
|
|
285
|
-
background-color:
|
|
306
|
+
background-color: var(--floe-state-hover);
|
|
286
307
|
}
|
|
287
308
|
& [data-floe-surface-part='choice'][data-floe-selected='true'] {
|
|
288
|
-
background-color: var(--
|
|
289
|
-
}
|
|
290
|
-
/*
|
|
291
|
-
*
|
|
309
|
+
background-color: var(--floe-state-selected);
|
|
310
|
+
}
|
|
311
|
+
/* A committed compact choice is a filled control, because the fill is the
|
|
312
|
+
* state indicator and has to carry 3:1 against its rail by itself. A
|
|
313
|
+
* translucent wash with a 34% accent hairline measures about 1.1:1, which
|
|
314
|
+
* reads as the same surface turned slightly warmer, not as a selection.
|
|
315
|
+
* The semantic pair is the one opaque thing on the rail; relief would only
|
|
316
|
+
* restate the fill, so it stays off. */
|
|
292
317
|
& [data-floe-choice-variant='button'][data-floe-selected='true'],
|
|
293
318
|
& [data-floe-surface-part='segment'][aria-checked='true'] {
|
|
294
319
|
background-color: var(--primary);
|
|
295
320
|
color: var(--primary-foreground);
|
|
321
|
+
border-color: var(--primary);
|
|
296
322
|
--floe-surface-decoration: 0 0 transparent;
|
|
297
323
|
}
|
|
324
|
+
/* A selected tab is a surface sitting proud of its rail: solid fill, the
|
|
325
|
+
* language's hairline and the first elevation step. This is the one place a
|
|
326
|
+
* small control is allowed relief, because the rail sits directly behind it. */
|
|
327
|
+
& [data-floe-surface-part='tab']:not([aria-selected='true']):hover:not(:has(:disabled)) {
|
|
328
|
+
background-color: var(--floe-state-hover);
|
|
329
|
+
color: var(--foreground);
|
|
330
|
+
}
|
|
298
331
|
& [data-floe-surface-part='tab'][aria-selected='true'] {
|
|
299
|
-
background-color: var(--
|
|
332
|
+
background-color: var(--card);
|
|
300
333
|
color: var(--foreground);
|
|
334
|
+
border-color: var(--floe-line);
|
|
335
|
+
--floe-surface-decoration: var(--floe-elevation-raised);
|
|
301
336
|
}
|
|
302
337
|
& [data-floe-surface-part='segment'][aria-checked='false'] {
|
|
303
338
|
background-color: transparent;
|
|
304
339
|
}
|
|
340
|
+
&
|
|
341
|
+
[data-floe-surface-part='segment'][aria-checked='false']:hover:not(
|
|
342
|
+
:disabled
|
|
343
|
+
):not(:has(:disabled)) {
|
|
344
|
+
background-color: var(--floe-state-hover);
|
|
345
|
+
color: var(--foreground);
|
|
346
|
+
}
|
|
305
347
|
& [data-floe-surface-part='tab'].border-primary {
|
|
306
348
|
border-color: color-mix(in srgb, var(--primary) 24%, var(--card));
|
|
307
349
|
}
|
|
@@ -314,8 +356,8 @@
|
|
|
314
356
|
background-color: var(--card);
|
|
315
357
|
}
|
|
316
358
|
& [data-floe-surface-part='step'][data-floe-step-state='current'] {
|
|
317
|
-
background-color:
|
|
318
|
-
color: var(--
|
|
359
|
+
background-color: var(--floe-state-selected-strong);
|
|
360
|
+
color: var(--foreground);
|
|
319
361
|
}
|
|
320
362
|
& [data-floe-surface-part='indicator']:not([data-floe-selected='true']),
|
|
321
363
|
& [data-floe-surface-part='switch-track']:not([data-floe-selected='true']) {
|
|
@@ -332,13 +374,8 @@
|
|
|
332
374
|
[data-floe-surface-part='indicator'],
|
|
333
375
|
[data-floe-surface-part='switch-track']
|
|
334
376
|
)[data-floe-surface='inset'] {
|
|
335
|
-
/*
|
|
336
|
-
|
|
337
|
-
--floe-surface-decoration: var(
|
|
338
|
-
--floe-surface-shadow-inset,
|
|
339
|
-
inset 0 1px 1px var(--floe-surface-shade),
|
|
340
|
-
inset 0 -1px 0 var(--floe-surface-highlight)
|
|
341
|
-
);
|
|
377
|
+
/* Small indicators rely on their own fill contrast, not on relief. */
|
|
378
|
+
--floe-surface-decoration: var(--floe-surface-shadow-inset, 0 0 transparent);
|
|
342
379
|
}
|
|
343
380
|
& [data-floe-surface-part='switch-track'] {
|
|
344
381
|
transition-duration: 140ms;
|
|
@@ -348,7 +385,7 @@
|
|
|
348
385
|
/* A hollow hairline keeps an unchecked radio quieter than its selected dot.
|
|
349
386
|
* Border-box dimensions and hit targets stay fixed; there is no blurred well. */
|
|
350
387
|
border-width: 1px;
|
|
351
|
-
border-color: color-mix(in srgb, var(--muted-foreground)
|
|
388
|
+
border-color: color-mix(in srgb, var(--muted-foreground) 72%, var(--card));
|
|
352
389
|
background-color: transparent;
|
|
353
390
|
--floe-surface-decoration: var(--floe-surface-shadow-inset, none);
|
|
354
391
|
}
|
|
@@ -356,7 +393,7 @@
|
|
|
356
393
|
[data-floe-surface-part='indicator'][data-floe-selected='true']:has(
|
|
357
394
|
[data-floe-surface-part='radio-dot']
|
|
358
395
|
) {
|
|
359
|
-
background-color:
|
|
396
|
+
background-color: var(--floe-state-selected);
|
|
360
397
|
}
|
|
361
398
|
& [data-floe-surface-part='radio-dot'] {
|
|
362
399
|
background-color: var(--foreground);
|
|
@@ -366,10 +403,8 @@
|
|
|
366
403
|
transition-property: width, background-color;
|
|
367
404
|
}
|
|
368
405
|
& [data-floe-surface-part='action']:active:not(:disabled) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
var(--floe-surface-compact-inset)
|
|
372
|
-
);
|
|
406
|
+
/* Press settles the control instead of embossing it. */
|
|
407
|
+
--floe-surface-decoration: 0 0 transparent;
|
|
373
408
|
}
|
|
374
409
|
/* Hidden native inputs delegate their indicator to the visible existing
|
|
375
410
|
* face. A pointer selection does not receive this keyboard-only outline. */
|
|
@@ -382,34 +417,34 @@
|
|
|
382
417
|
box-shadow: var(--floe-surface-decoration);
|
|
383
418
|
}
|
|
384
419
|
}
|
|
385
|
-
:where(:root
|
|
420
|
+
:where(:root:not([data-floe-shell-theme='hc-light'])) {
|
|
386
421
|
& :is([data-floe-input-surface], input, textarea, select)[data-floe-surface='inset'] {
|
|
387
|
-
background-color:
|
|
422
|
+
background-color: var(--floe-well);
|
|
388
423
|
}
|
|
389
424
|
}
|
|
390
425
|
}
|
|
391
426
|
|
|
392
|
-
/* Text-labelled actions
|
|
393
|
-
*
|
|
427
|
+
/* Text-labelled actions and fields use one contour. Stacked inset and contact
|
|
428
|
+
* shadows turn a quiet toolbar into an embossed frame.
|
|
429
|
+
* A rail and a tab rail are wells, not planes: they recede behind their
|
|
430
|
+
* segments, and the relief belongs to the one selected item inside them. Giving
|
|
431
|
+
* the well the raised step made it cast a drop shadow in dark palettes while
|
|
432
|
+
* staying flat in light ones, so the same control had two different shapes.
|
|
394
433
|
* Small check/switch indicators retain their independent relief and contrast. */
|
|
395
|
-
|
|
396
|
-
:is(
|
|
434
|
+
:is(
|
|
397
435
|
[data-floe-surface-part='action'],
|
|
398
|
-
[data-floe-surface-part='rail'],
|
|
399
|
-
[data-floe-surface-part='tab-rail'],
|
|
400
436
|
[data-floe-surface-part='tab'],
|
|
401
437
|
[data-floe-surface-part='segment']
|
|
402
438
|
)[data-floe-surface] {
|
|
403
439
|
--floe-surface-decoration: var(--floe-surface-shadow-raised, 0 0 transparent);
|
|
404
440
|
}
|
|
405
|
-
[data-floe-surface-
|
|
406
|
-
:is([data-floe-input-surface], input, textarea, select)[data-floe-surface='inset'] {
|
|
441
|
+
:is([data-floe-input-surface], input, textarea, select)[data-floe-surface='inset'] {
|
|
407
442
|
--floe-surface-decoration: var(--floe-surface-shadow-inset, 0 0 transparent);
|
|
408
443
|
}
|
|
409
444
|
|
|
410
445
|
/* Explicit host opt-outs and compound input boundaries outrank compact states. */
|
|
411
|
-
:root[data-floe-surface
|
|
412
|
-
:root[data-floe-
|
|
446
|
+
:root[data-floe-surface='flat'],
|
|
447
|
+
:root[data-floe-input-surface] [data-floe-surface] {
|
|
413
448
|
--floe-surface-decoration: 0 0 transparent;
|
|
414
449
|
}
|
|
415
450
|
|
|
@@ -417,7 +452,7 @@
|
|
|
417
452
|
* distinct from ordinary Cards, Dialogs and menus. Only this visible panel owns
|
|
418
453
|
* material; the outer geometry owner and its input lifecycle stay unchanged. */
|
|
419
454
|
@media (forced-colors: none) {
|
|
420
|
-
:root
|
|
455
|
+
:root:not([data-floe-shell-theme='hc-light'])
|
|
421
456
|
[data-floe-floating-window-surface='true'][data-floe-surface='floating'] {
|
|
422
457
|
--floe-window-radius: var(--floe-radius-floating);
|
|
423
458
|
background: var(--floe-window-background);
|
|
@@ -462,36 +497,45 @@
|
|
|
462
497
|
}
|
|
463
498
|
}
|
|
464
499
|
|
|
465
|
-
/* Dark shell palettes use a restrained
|
|
466
|
-
*
|
|
467
|
-
:
|
|
500
|
+
/* Dark shell palettes use a restrained step for active chrome so the window
|
|
501
|
+
* remains discoverable without a bright outline or animated glow. The step is
|
|
502
|
+
* taken toward the foreground, not toward the page ground: an accent wash alone
|
|
503
|
+
* lands within three 8-bit units of a near-black window body (soft-black
|
|
504
|
+
* measured 19,20,21 on 16,17,19), so the titlebar stopped being identifiable in
|
|
505
|
+
* grayscale at all. Foreground is light in every dark preset, so mixing 8% of it
|
|
506
|
+
* guarantees an upward step from any accent while title text keeps 5.3:1 or
|
|
507
|
+
* better. Light presets take no such step: their background is already far from
|
|
508
|
+
* the accent wash, and darkening it there would eat title text contrast. */
|
|
509
|
+
:root.dark:not([data-floe-shell-theme='hc-light'])
|
|
468
510
|
[data-floe-floating-window-surface='true'][data-floe-floating-window-state='active']
|
|
469
511
|
> [data-floe-floating-window-titlebar='true'] {
|
|
470
|
-
background-color: color-mix(
|
|
512
|
+
background-color: color-mix(
|
|
513
|
+
in srgb,
|
|
514
|
+
var(--accent) 24%,
|
|
515
|
+
color-mix(in srgb, var(--foreground) 8%, var(--floe-window-titlebar-background))
|
|
516
|
+
);
|
|
471
517
|
}
|
|
472
518
|
|
|
473
519
|
/* FloatingWindow keeps rich text at scale 1 throughout its short presence
|
|
474
|
-
* motion
|
|
475
|
-
*
|
|
476
|
-
|
|
520
|
+
* motion: a window is a large reading surface, so a scale that suits a menu
|
|
521
|
+
* would blur its text mid-flight. The class lives on the panel, not on <html>,
|
|
522
|
+
* so the selector has to match the panel or the override never applies.
|
|
523
|
+
*
|
|
524
|
+
* Promotion belongs to the two transitioning states only; a settled window must
|
|
525
|
+
* not hold a compositor layer (see .floe-floating-presence in floe.css). */
|
|
526
|
+
.floe-floating-window-motion {
|
|
477
527
|
--floe-floating-enter-scale: 1;
|
|
478
528
|
--floe-floating-exit-scale: 1;
|
|
479
529
|
--floe-floating-enter-y: 3px;
|
|
480
530
|
--floe-floating-exit-y: 2px;
|
|
481
|
-
will-change: auto;
|
|
482
|
-
}
|
|
483
|
-
:root[data-floe-surface-style='soft-neumorphic'] .floe-floating-window-motion:is(
|
|
484
|
-
[data-floating-presence='entering'], [data-floating-presence='exiting']
|
|
485
|
-
) {
|
|
486
|
-
will-change: opacity, transform;
|
|
487
531
|
}
|
|
488
532
|
|
|
489
533
|
/* High contrast stays flat, with real boundaries and keyboard indicators. */
|
|
490
|
-
:root[data-floe-
|
|
534
|
+
:root[data-floe-shell-theme='hc-light']
|
|
491
535
|
[data-floe-surface] {
|
|
492
536
|
--floe-surface-decoration: 0 0 transparent;
|
|
493
537
|
}
|
|
494
|
-
:root[data-floe-
|
|
538
|
+
:root[data-floe-shell-theme='hc-light']
|
|
495
539
|
.workbench-widget.is-selected {
|
|
496
540
|
border-color: var(--wb-accent);
|
|
497
541
|
}
|
|
@@ -505,25 +549,28 @@
|
|
|
505
549
|
box-shadow: none;
|
|
506
550
|
transition: none;
|
|
507
551
|
}
|
|
508
|
-
[data-floe-surface
|
|
552
|
+
[data-floe-surface] {
|
|
509
553
|
--floe-surface-decoration: 0 0 transparent;
|
|
510
554
|
}
|
|
511
|
-
[data-floe-surface-style='soft-neumorphic']
|
|
512
555
|
[data-floe-surface]:focus-visible:not(
|
|
513
556
|
:where(input, textarea, select, [data-floe-input-surface], [data-floe-input-surface] *)
|
|
514
557
|
) {
|
|
515
558
|
outline: 2px solid Highlight;
|
|
516
559
|
outline-offset: 2px;
|
|
517
560
|
}
|
|
518
|
-
|
|
561
|
+
.workbench-widget.is-selected {
|
|
519
562
|
border-color: Highlight;
|
|
520
563
|
}
|
|
521
564
|
}
|
|
522
565
|
@media (prefers-reduced-motion: reduce) {
|
|
523
|
-
|
|
566
|
+
/* `:root` carries the specificity this reset needs: a surface part may pair
|
|
567
|
+
* two attribute selectors to own a transition of its own, and a bare
|
|
568
|
+
* `[data-floe-surface]` would lose to it. Reduced motion is a user setting,
|
|
569
|
+
* so it must win without `!important`. */
|
|
570
|
+
:root [data-floe-surface] {
|
|
524
571
|
transition: none;
|
|
525
572
|
}
|
|
526
|
-
|
|
573
|
+
:root [data-floe-surface-part='indicator'] > svg {
|
|
527
574
|
animation: none;
|
|
528
575
|
}
|
|
529
576
|
}
|
|
@@ -539,18 +586,16 @@
|
|
|
539
586
|
}
|
|
540
587
|
}
|
|
541
588
|
|
|
542
|
-
:root[data-floe-
|
|
589
|
+
:root[data-floe-shell-theme='hc-light']
|
|
543
590
|
[data-floe-surface-part='choice']:has([data-floe-choice-input]:focus-visible),
|
|
544
|
-
:root[data-floe-
|
|
591
|
+
:root[data-floe-shell-theme='hc-light']
|
|
545
592
|
[data-floe-choice-input]:focus-visible
|
|
546
593
|
+ :is([data-floe-surface-part='indicator'], [data-floe-surface-part='switch-track']) {
|
|
547
594
|
outline: 2px solid var(--ring);
|
|
548
595
|
outline-offset: 3px;
|
|
549
596
|
}
|
|
550
597
|
@media (forced-colors: active) {
|
|
551
|
-
[data-floe-surface-style='soft-neumorphic']
|
|
552
598
|
[data-floe-surface-part='choice']:has([data-floe-choice-input]:focus-visible),
|
|
553
|
-
[data-floe-surface-style='soft-neumorphic']
|
|
554
599
|
[data-floe-choice-input]:focus-visible
|
|
555
600
|
+ :is([data-floe-surface-part='indicator'], [data-floe-surface-part='switch-track']) {
|
|
556
601
|
outline: 2px solid Highlight;
|