@liberation-data/desk 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -1
- package/dist/core/desk.d.ts +13 -0
- package/dist/core/desk.d.ts.map +1 -1
- package/dist/core/desk.js +55 -1
- package/dist/core/desk.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/css/apps.css +57 -0
- package/dist/css/controls.css +975 -0
- package/dist/css/conversation.css +232 -0
- package/dist/css/dock.css +272 -0
- package/dist/css/menus.css +204 -0
- package/dist/css/overlays.css +237 -0
- package/dist/css/search.css +149 -0
- package/dist/css/setup.css +284 -0
- package/dist/css/tokens.css +90 -0
- package/dist/css/windows.css +321 -0
- package/dist/desk.css +1080 -1070
- package/dist/react/Desktop.d.ts.map +1 -1
- package/dist/react/Desktop.js +66 -17
- package/dist/react/Desktop.js.map +1 -1
- package/llms.txt +6 -0
- package/package.json +4 -3
- package/src/core/desk.ts +67 -1
- package/src/core/index.ts +1 -1
- package/src/css/apps.css +56 -0
- package/src/css/controls.css +974 -0
- package/src/css/conversation.css +231 -0
- package/src/css/dock.css +271 -0
- package/src/css/menus.css +203 -0
- package/src/css/overlays.css +236 -0
- package/src/css/search.css +148 -0
- package/src/css/setup.css +283 -0
- package/src/css/tokens.css +89 -0
- package/src/css/windows.css +320 -0
- package/src/react/Desktop.tsx +69 -20
- package/src/desk.css +0 -2820
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* @liberation-data/desk — tokens.css */
|
|
2
|
+
/*
|
|
3
|
+
* desk — the stage and its windows. Every value reads a --desk-* token, so an
|
|
4
|
+
* app restyles the desk by redefining tokens, never by overriding selectors.
|
|
5
|
+
*/
|
|
6
|
+
:root {
|
|
7
|
+
--desk-ground: #eef0f4;
|
|
8
|
+
--desk-surface: #ffffff;
|
|
9
|
+
--desk-titlebar: #f6f7f9;
|
|
10
|
+
--desk-ink: #1b1f27;
|
|
11
|
+
--desk-muted: #667085;
|
|
12
|
+
--desk-rule: #dde1e8;
|
|
13
|
+
--desk-accent: #5b57f5;
|
|
14
|
+
--desk-close: #ef6b63;
|
|
15
|
+
--desk-mode: #34c47a;
|
|
16
|
+
--desk-info: #34c47a;
|
|
17
|
+
--desk-radius: 12px;
|
|
18
|
+
--desk-gap: 12px;
|
|
19
|
+
--desk-padding: 12px;
|
|
20
|
+
--desk-shadow: 0 1px 2px rgb(16 24 40 / 6%), 0 12px 32px rgb(16 24 40 / 10%);
|
|
21
|
+
--desk-shadow-floating: 0 2px 4px rgb(16 24 40 / 8%), 0 24px 60px rgb(16 24 40 / 22%);
|
|
22
|
+
--desk-font: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
23
|
+
--desk-font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
|
|
24
|
+
|
|
25
|
+
/* The spacing scale (HIG.md §2). Nothing between these values. */
|
|
26
|
+
--desk-space-1: 4px;
|
|
27
|
+
--desk-space-2: 8px;
|
|
28
|
+
--desk-space-3: 12px;
|
|
29
|
+
--desk-space-4: 16px;
|
|
30
|
+
--desk-space-5: 24px;
|
|
31
|
+
--desk-space-6: 32px;
|
|
32
|
+
--desk-space-7: 48px;
|
|
33
|
+
|
|
34
|
+
/* State, kept apart from the accent. */
|
|
35
|
+
--desk-ok: #2f9e68;
|
|
36
|
+
--desk-warn: #b7791f;
|
|
37
|
+
--desk-bad: #c6483f;
|
|
38
|
+
|
|
39
|
+
--desk-control-height: 28px;
|
|
40
|
+
--desk-control-height-small: 22px;
|
|
41
|
+
--desk-control-radius: 7px;
|
|
42
|
+
--desk-field-bg: #ffffff;
|
|
43
|
+
--desk-on-accent: #ffffff;
|
|
44
|
+
--desk-ease: cubic-bezier(.32, .72, 0, 1);
|
|
45
|
+
--desk-dock-size: 48px;
|
|
46
|
+
--desk-dock-glass: rgb(255 255 255 / 72%);
|
|
47
|
+
--desk-dock-icon: linear-gradient(160deg, #ffffff, #eceff5);
|
|
48
|
+
--desk-badge: #ef4444;
|
|
49
|
+
--desk-badge-ink: #ffffff;
|
|
50
|
+
/* Room the stage leaves at the bottom for an overlay dock. */
|
|
51
|
+
--desk-inset-bottom: 0px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@media (prefers-color-scheme: dark) {
|
|
55
|
+
:root:not([data-theme="light"]) {
|
|
56
|
+
--desk-ground: #07090f;
|
|
57
|
+
--desk-surface: #101828;
|
|
58
|
+
--desk-titlebar: #0b111d;
|
|
59
|
+
--desk-ink: #e6e6e6;
|
|
60
|
+
--desk-muted: #99a1af;
|
|
61
|
+
--desk-rule: #1e2939;
|
|
62
|
+
--desk-shadow: 0 12px 32px rgb(0 0 0 / 45%);
|
|
63
|
+
--desk-shadow-floating: 0 30px 80px rgb(0 0 0 / 70%);
|
|
64
|
+
--desk-dock-glass: rgb(11 18 32 / 62%);
|
|
65
|
+
--desk-dock-icon: linear-gradient(160deg, #1a2338, #0e1526);
|
|
66
|
+
--desk-ok: #3ecf8e;
|
|
67
|
+
--desk-info: #3ecf8e;
|
|
68
|
+
--desk-warn: #fbbf24;
|
|
69
|
+
--desk-bad: #f87171;
|
|
70
|
+
--desk-field-bg: rgb(0 0 0 / 35%);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
:root[data-theme="dark"] {
|
|
75
|
+
--desk-ground: #07090f;
|
|
76
|
+
--desk-surface: #101828;
|
|
77
|
+
--desk-titlebar: #0b111d;
|
|
78
|
+
--desk-ink: #e6e6e6;
|
|
79
|
+
--desk-muted: #99a1af;
|
|
80
|
+
--desk-rule: #1e2939;
|
|
81
|
+
--desk-shadow: 0 12px 32px rgb(0 0 0 / 45%);
|
|
82
|
+
--desk-shadow-floating: 0 30px 80px rgb(0 0 0 / 70%);
|
|
83
|
+
--desk-dock-glass: rgb(11 18 32 / 62%);
|
|
84
|
+
--desk-dock-icon: linear-gradient(160deg, #1a2338, #0e1526);
|
|
85
|
+
--desk-ok: #3ecf8e;
|
|
86
|
+
--desk-info: #3ecf8e;
|
|
87
|
+
--desk-warn: #fbbf24;
|
|
88
|
+
--desk-bad: #f87171;
|
|
89
|
+
--desk-field-bg: rgb(0 0 0 / 35%);
|
|
90
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/* @liberation-data/desk — windows.css */
|
|
2
|
+
.desk-stage {
|
|
3
|
+
position: relative;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
height: 100%;
|
|
6
|
+
min-height: 0;
|
|
7
|
+
padding: var(--desk-padding);
|
|
8
|
+
padding-bottom: calc(var(--desk-padding) + var(--desk-inset-bottom));
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template: minmax(0, 1fr) / minmax(0, 1fr);
|
|
11
|
+
gap: var(--desk-gap);
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
background: var(--desk-ground);
|
|
14
|
+
color: var(--desk-ink);
|
|
15
|
+
font-family: var(--desk-font);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.desk-window {
|
|
19
|
+
/* Filled windows fill the stage inside its padding, layered in the order they were used. */
|
|
20
|
+
position: absolute;
|
|
21
|
+
top: var(--desk-padding);
|
|
22
|
+
right: var(--desk-padding);
|
|
23
|
+
bottom: calc(var(--desk-padding) + var(--desk-inset-bottom));
|
|
24
|
+
left: var(--desk-padding);
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
min-width: 0;
|
|
27
|
+
min-height: 0;
|
|
28
|
+
display: flex;
|
|
29
|
+
flex-direction: column;
|
|
30
|
+
background: var(--desk-surface);
|
|
31
|
+
border: 1px solid var(--desk-rule);
|
|
32
|
+
border-radius: var(--desk-radius);
|
|
33
|
+
box-shadow: var(--desk-shadow);
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
transition: border-color .15s var(--desk-ease), box-shadow .15s var(--desk-ease);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.desk-window:focus {
|
|
39
|
+
/* The key window is already marked by its border; a ring on the whole window would be noise. */
|
|
40
|
+
outline: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.desk-window[data-focused] {
|
|
44
|
+
border-color: color-mix(in srgb, var(--desk-accent) 45%, var(--desk-rule));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.desk-window[data-hidden] {
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* One window at a time: it fills the stage, and the zoom control is not offered. */
|
|
52
|
+
.desk-stage[data-layout="fullscreen"] .desk-window {
|
|
53
|
+
position: static;
|
|
54
|
+
inset: auto;
|
|
55
|
+
grid-area: 1 / 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.desk-window[data-mode="floating"] {
|
|
59
|
+
right: auto;
|
|
60
|
+
bottom: auto;
|
|
61
|
+
box-shadow: var(--desk-shadow-floating);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.desk-window[data-dragging] {
|
|
65
|
+
transition: none;
|
|
66
|
+
user-select: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.desk-titlebar {
|
|
70
|
+
flex: none;
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
gap: 10px;
|
|
74
|
+
padding: 8px 12px;
|
|
75
|
+
background: var(--desk-titlebar);
|
|
76
|
+
border-bottom: 1px solid var(--desk-rule);
|
|
77
|
+
user-select: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.desk-titlebar[data-draggable] {
|
|
81
|
+
cursor: grab;
|
|
82
|
+
touch-action: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.desk-window[data-dragging] .desk-titlebar {
|
|
86
|
+
cursor: grabbing;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.desk-controls {
|
|
90
|
+
display: flex;
|
|
91
|
+
gap: 7px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.desk-control {
|
|
95
|
+
width: 12px;
|
|
96
|
+
height: 12px;
|
|
97
|
+
padding: 0;
|
|
98
|
+
border: 0;
|
|
99
|
+
border-radius: 50%;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
background: var(--desk-rule);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.desk-window[data-focused] .desk-control[data-control="close"],
|
|
105
|
+
.desk-control[data-control="close"]:hover {
|
|
106
|
+
background: var(--desk-close);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.desk-window[data-focused] .desk-control[data-control="mode"],
|
|
110
|
+
.desk-control[data-control="mode"]:hover {
|
|
111
|
+
background: var(--desk-mode);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.desk-control:focus-visible {
|
|
115
|
+
outline: 2px solid var(--desk-accent);
|
|
116
|
+
outline-offset: 2px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.desk-title {
|
|
120
|
+
margin: 0;
|
|
121
|
+
min-width: 0;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
text-overflow: ellipsis;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
font-size: 13px;
|
|
126
|
+
font-weight: 600;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.desk-window:not([data-focused]) .desk-title {
|
|
130
|
+
color: var(--desk-muted);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.desk-window-note {
|
|
134
|
+
margin: 0 0 0 auto;
|
|
135
|
+
min-width: 0;
|
|
136
|
+
/* The title is what the window IS; the note is what it is looking at. In a narrow window the note
|
|
137
|
+
gives up its room first, and is cut before the title is. */
|
|
138
|
+
flex: 0 999 auto;
|
|
139
|
+
overflow: hidden;
|
|
140
|
+
text-overflow: ellipsis;
|
|
141
|
+
white-space: nowrap;
|
|
142
|
+
font-size: 11.5px;
|
|
143
|
+
color: var(--desk-muted);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* The note gives up the spare room; the (i) keeps its place at the end of the bar. */
|
|
147
|
+
.desk-window-note + .desk-window-info {
|
|
148
|
+
margin-left: var(--desk-space-2);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.desk-window-info {
|
|
152
|
+
margin-left: auto;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.desk-window-note ~ .desk-window-info {
|
|
156
|
+
margin-left: var(--desk-space-2);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.desk-window-info + .desk-window-actions,
|
|
160
|
+
.desk-window-note + .desk-window-actions {
|
|
161
|
+
margin-left: var(--desk-space-1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.desk-window-actions {
|
|
165
|
+
margin-left: auto;
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
gap: var(--desk-space-1);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.desk-body {
|
|
172
|
+
flex: 1;
|
|
173
|
+
min-height: 0;
|
|
174
|
+
overflow: auto;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.desk-window-status {
|
|
178
|
+
box-sizing: border-box;
|
|
179
|
+
height: 100%;
|
|
180
|
+
min-height: 120px;
|
|
181
|
+
display: flex;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
align-items: center;
|
|
184
|
+
justify-content: center;
|
|
185
|
+
gap: var(--desk-space-2);
|
|
186
|
+
padding: var(--desk-space-4);
|
|
187
|
+
text-align: center;
|
|
188
|
+
color: var(--desk-muted);
|
|
189
|
+
font-size: 13px;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.desk-window-status b {
|
|
193
|
+
color: var(--desk-ink);
|
|
194
|
+
font-weight: 600;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.desk-window-status-detail {
|
|
198
|
+
max-width: 40ch;
|
|
199
|
+
font-size: 12px;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Edges a window resizes from. Inside the window, so nothing clips them. */
|
|
203
|
+
.desk-edge {
|
|
204
|
+
position: absolute;
|
|
205
|
+
touch-action: none;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.desk-edge[data-edge="left"],
|
|
209
|
+
.desk-edge[data-edge="right"] {
|
|
210
|
+
top: 0;
|
|
211
|
+
bottom: 0;
|
|
212
|
+
width: 5px;
|
|
213
|
+
cursor: ew-resize;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.desk-edge[data-edge="left"] {
|
|
217
|
+
left: 0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.desk-edge[data-edge="right"] {
|
|
221
|
+
right: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.desk-edge[data-edge="bottom"] {
|
|
225
|
+
left: 0;
|
|
226
|
+
right: 0;
|
|
227
|
+
bottom: 0;
|
|
228
|
+
height: 5px;
|
|
229
|
+
cursor: ns-resize;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.desk-grip {
|
|
233
|
+
position: absolute;
|
|
234
|
+
right: 0;
|
|
235
|
+
bottom: 0;
|
|
236
|
+
width: 16px;
|
|
237
|
+
height: 16px;
|
|
238
|
+
cursor: nwse-resize;
|
|
239
|
+
touch-action: none;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* Where a dragged window would land if it were dropped now. */
|
|
243
|
+
.desk-stage[data-snap]::after {
|
|
244
|
+
content: "";
|
|
245
|
+
position: absolute;
|
|
246
|
+
top: var(--desk-padding);
|
|
247
|
+
bottom: calc(var(--desk-padding) + var(--desk-inset-bottom));
|
|
248
|
+
width: calc(50% - var(--desk-padding) - var(--desk-gap) / 2);
|
|
249
|
+
border: 2px solid var(--desk-accent);
|
|
250
|
+
border-radius: var(--desk-radius);
|
|
251
|
+
background: color-mix(in srgb, var(--desk-accent) 14%, transparent);
|
|
252
|
+
pointer-events: none;
|
|
253
|
+
z-index: 5;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.desk-stage[data-snap="start"]::after {
|
|
257
|
+
left: var(--desk-padding);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.desk-stage[data-snap="end"]::after {
|
|
261
|
+
right: var(--desk-padding);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* ── The inside of a window: controls that stay, content that scrolls ── */
|
|
265
|
+
|
|
266
|
+
.desk-pane {
|
|
267
|
+
display: flex;
|
|
268
|
+
flex-direction: column;
|
|
269
|
+
height: 100%;
|
|
270
|
+
min-height: 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.desk-pane-header,
|
|
274
|
+
.desk-pane-footer {
|
|
275
|
+
flex: none;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* The only part that scrolls, so the toolbar never leaves with the content. */
|
|
279
|
+
.desk-pane-body {
|
|
280
|
+
flex: 1;
|
|
281
|
+
min-height: 0;
|
|
282
|
+
overflow: auto;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.desk-pane-body:focus-visible {
|
|
286
|
+
outline: 2px solid var(--desk-accent);
|
|
287
|
+
outline-offset: -2px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* A window whose whole content is a pane does not scroll itself: the pane's middle does. */
|
|
291
|
+
.desk-body:has(> .desk-pane) {
|
|
292
|
+
overflow: hidden;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.desk-toolbar {
|
|
296
|
+
display: flex;
|
|
297
|
+
align-items: center;
|
|
298
|
+
flex-wrap: wrap;
|
|
299
|
+
gap: var(--desk-space-2);
|
|
300
|
+
/* One centre line for everything in the row, whatever each control's own height is. */
|
|
301
|
+
min-height: calc(var(--desk-control-height) + var(--desk-space-2) * 2);
|
|
302
|
+
padding: var(--desk-space-2) var(--desk-space-3);
|
|
303
|
+
border-bottom: 1px solid var(--desk-rule);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.desk-toolbar > *,
|
|
307
|
+
.desk-toolbar-trailing > * {
|
|
308
|
+
flex: none;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.desk-toolbar .desk-grow {
|
|
312
|
+
flex: 1 1 140px;
|
|
313
|
+
min-width: 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.desk-toolbar-trailing {
|
|
317
|
+
margin-left: auto;
|
|
318
|
+
display: flex;
|
|
319
|
+
align-items: center;
|
|
320
|
+
gap: var(--desk-space-2);
|
|
321
|
+
}
|