@farming-labs/svelte-theme 0.0.3-beta.2 → 0.0.3-beta.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.
- package/package.json +3 -3
- package/src/components/DocsContent.svelte +288 -6
- package/src/components/DocsLayout.svelte +2 -6
- package/src/components/FloatingAIChat.svelte +2 -2
- package/src/components/SearchDialog.svelte +354 -55
- package/src/themes/colorful.js +1 -1
- package/styles/colorful.css +72 -0
- package/styles/darksharp.css +71 -0
- package/styles/docs.css +197 -11
- package/styles/greentree.css +50 -0
- package/styles/omni.css +362 -0
- package/styles/pixel-border.css +190 -1
|
@@ -1,91 +1,390 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Omni command palette — pixel-perfect default for SvelteKit, aligned with
|
|
4
|
+
* website/components/ui/omni-command-palette.tsx. Recents when empty,
|
|
5
|
+
* /api/docs search, keyboard nav, same copy and structure.
|
|
5
6
|
*/
|
|
6
|
-
import { onMount } from "svelte";
|
|
7
|
+
import { onMount, onDestroy, tick } from "svelte";
|
|
7
8
|
import { goto } from "$app/navigation";
|
|
8
9
|
|
|
10
|
+
const STORAGE_KEY = "fd:omni:recents";
|
|
11
|
+
const MAX_RECENTS = 8;
|
|
12
|
+
const DEBOUNCE_MS = 120;
|
|
13
|
+
const PLACEHOLDER = "Search documentation…";
|
|
14
|
+
|
|
9
15
|
let { onclose } = $props();
|
|
16
|
+
|
|
10
17
|
let query = $state("");
|
|
11
|
-
let
|
|
18
|
+
let currentResults = $state([]);
|
|
12
19
|
let loading = $state(false);
|
|
13
|
-
let
|
|
14
|
-
let
|
|
20
|
+
let activeId = $state(null);
|
|
21
|
+
let recentsList = $state([]);
|
|
22
|
+
let inputEl = $state(null);
|
|
23
|
+
let listRef = $state(null);
|
|
24
|
+
let debounceTimer = null;
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
let flatItems = $derived.by(() => {
|
|
27
|
+
const q = query.trim();
|
|
28
|
+
if (q && currentResults.length) {
|
|
29
|
+
return currentResults.map((r) => ({
|
|
30
|
+
id: r.url,
|
|
31
|
+
label: r.content,
|
|
32
|
+
url: r.url,
|
|
33
|
+
subtitle: r.description ?? "Page",
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
return recentsList.map((r) => ({
|
|
37
|
+
id: r.id,
|
|
38
|
+
label: r.label,
|
|
39
|
+
url: r.url,
|
|
40
|
+
subtitle: "Recently used",
|
|
41
|
+
}));
|
|
18
42
|
});
|
|
19
43
|
|
|
20
|
-
$
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
let showRecents = $derived(!query.trim());
|
|
45
|
+
let showDocs = $derived(!!query.trim() && currentResults.length > 0);
|
|
46
|
+
let showEmpty = $derived(
|
|
47
|
+
query.trim() ? currentResults.length === 0 && !loading : recentsList.length === 0
|
|
48
|
+
);
|
|
49
|
+
let emptyText = $derived(
|
|
50
|
+
query.trim()
|
|
51
|
+
? "No results found. Try a different query."
|
|
52
|
+
: "Type to search the docs, or browse recent items."
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
function getRecents() {
|
|
56
|
+
if (typeof document === "undefined" || typeof localStorage === "undefined") return [];
|
|
57
|
+
try {
|
|
58
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
59
|
+
return raw ? JSON.parse(raw) : [];
|
|
60
|
+
} catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function saveRecent(entry) {
|
|
66
|
+
if (typeof localStorage === "undefined") return;
|
|
67
|
+
try {
|
|
68
|
+
const recents = getRecents();
|
|
69
|
+
const next = [entry, ...recents.filter((r) => r.id !== entry.id)].slice(0, MAX_RECENTS);
|
|
70
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
|
|
71
|
+
} catch {}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function loadRecents() {
|
|
75
|
+
recentsList = getRecents();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function close() {
|
|
79
|
+
if (typeof document !== "undefined") document.body.style.overflow = "";
|
|
80
|
+
onclose?.();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function executeItem(item) {
|
|
84
|
+
saveRecent({ id: item.url, label: item.label ?? item.content ?? item.url, url: item.url });
|
|
85
|
+
if (item.url.startsWith("http")) {
|
|
86
|
+
if (typeof window !== "undefined") window.open(item.url, "_blank", "noopener,noreferrer");
|
|
87
|
+
} else {
|
|
88
|
+
goto(item.url);
|
|
25
89
|
}
|
|
26
|
-
|
|
90
|
+
close();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function moveActive(delta) {
|
|
94
|
+
if (!flatItems.length) return;
|
|
95
|
+
const idx = flatItems.findIndex((i) => i.id === activeId);
|
|
96
|
+
const nextIdx = idx < 0 ? 0 : (((idx + delta) % flatItems.length) + flatItems.length) % flatItems.length;
|
|
97
|
+
activeId = flatItems[nextIdx].id;
|
|
98
|
+
scrollActiveIntoView();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function executeActive() {
|
|
102
|
+
const idx = activeId != null ? flatItems.findIndex((i) => i.id === activeId) : 0;
|
|
103
|
+
const item = flatItems[idx ?? 0];
|
|
104
|
+
if (item) executeItem(item);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function scrollActiveIntoView() {
|
|
108
|
+
tick().then(() => {
|
|
109
|
+
if (typeof document === "undefined" || !listRef) return;
|
|
110
|
+
const node = listRef.querySelector(`[data-id="${activeId}"]`);
|
|
111
|
+
node?.scrollIntoView({ block: "nearest" });
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function onInput() {
|
|
116
|
+
loadRecents();
|
|
117
|
+
loading = false;
|
|
118
|
+
currentResults = [];
|
|
119
|
+
activeId = null;
|
|
120
|
+
const q = query.trim();
|
|
121
|
+
if (!q) return;
|
|
122
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
27
123
|
debounceTimer = setTimeout(async () => {
|
|
124
|
+
loading = true;
|
|
28
125
|
try {
|
|
29
|
-
const res = await fetch(`/api/docs?query=${encodeURIComponent(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
126
|
+
const res = await fetch(`/api/docs?query=${encodeURIComponent(q)}`);
|
|
127
|
+
const data = res.ok ? await res.json() : [];
|
|
128
|
+
currentResults = Array.isArray(data) ? data : [];
|
|
129
|
+
activeId = currentResults[0]?.url ?? null;
|
|
34
130
|
} catch {
|
|
35
|
-
|
|
131
|
+
currentResults = [];
|
|
36
132
|
} finally {
|
|
37
133
|
loading = false;
|
|
38
134
|
}
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
function navigate(url) {
|
|
43
|
-
onclose?.();
|
|
44
|
-
goto(url);
|
|
135
|
+
}, DEBOUNCE_MS);
|
|
45
136
|
}
|
|
46
137
|
|
|
138
|
+
$effect(() => {
|
|
139
|
+
void query;
|
|
140
|
+
onInput();
|
|
141
|
+
});
|
|
142
|
+
|
|
47
143
|
function handleKeydown(e) {
|
|
48
144
|
if (e.key === "Escape") {
|
|
49
|
-
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
close();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (e.key === "ArrowDown") {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
moveActive(1);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (e.key === "ArrowUp") {
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
moveActive(-1);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (e.key === "Enter") {
|
|
160
|
+
e.preventDefault();
|
|
161
|
+
executeActive();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function onOverlayClick() {
|
|
166
|
+
close();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function onContentClick(e) {
|
|
170
|
+
e.stopPropagation();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function onExternalClick(e, url) {
|
|
174
|
+
e.preventDefault();
|
|
175
|
+
e.stopPropagation();
|
|
176
|
+
try {
|
|
177
|
+
if (typeof window !== "undefined") window.open(url, "_blank", "noopener,noreferrer");
|
|
178
|
+
} catch {
|
|
179
|
+
if (typeof window !== "undefined") window.location.href = url;
|
|
50
180
|
}
|
|
51
181
|
}
|
|
182
|
+
|
|
183
|
+
const FileIcon = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg>`;
|
|
184
|
+
const ExternalIcon = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>`;
|
|
185
|
+
const ChevronIcon = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>`;
|
|
186
|
+
const EmptyIcon = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>`;
|
|
187
|
+
|
|
188
|
+
onMount(() => {
|
|
189
|
+
loadRecents();
|
|
190
|
+
if (typeof document !== "undefined") document.body.style.overflow = "hidden";
|
|
191
|
+
tick().then(() => inputEl?.focus());
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
onDestroy(() => {
|
|
195
|
+
if (typeof document !== "undefined") document.body.style.overflow = "";
|
|
196
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
197
|
+
});
|
|
52
198
|
</script>
|
|
53
199
|
|
|
200
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
54
201
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
55
|
-
<div
|
|
202
|
+
<div
|
|
203
|
+
class="omni-overlay"
|
|
204
|
+
aria-hidden="true"
|
|
205
|
+
role="presentation"
|
|
206
|
+
onclick={onOverlayClick}
|
|
207
|
+
onkeydown={handleKeydown}
|
|
208
|
+
>
|
|
56
209
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
57
210
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
58
|
-
<div
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class="
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
211
|
+
<div
|
|
212
|
+
class="omni-content"
|
|
213
|
+
role="dialog"
|
|
214
|
+
aria-label="Command palette"
|
|
215
|
+
tabindex="-1"
|
|
216
|
+
onclick={onContentClick}
|
|
217
|
+
>
|
|
218
|
+
<div class="omni-header">
|
|
219
|
+
<div class="omni-search-row">
|
|
220
|
+
<span class="omni-search-icon" aria-hidden="true">
|
|
221
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
222
|
+
<circle cx="11" cy="11" r="8" />
|
|
223
|
+
<path d="m21 21-4.3-4.3" />
|
|
224
|
+
</svg>
|
|
225
|
+
</span>
|
|
226
|
+
<input
|
|
227
|
+
bind:this={inputEl}
|
|
228
|
+
bind:value={query}
|
|
229
|
+
type="text"
|
|
230
|
+
class="omni-search-input"
|
|
231
|
+
role="combobox"
|
|
232
|
+
aria-expanded="true"
|
|
233
|
+
aria-controls="omni-listbox"
|
|
234
|
+
aria-activedescendant={activeId ? `omni-item-${activeId}` : undefined}
|
|
235
|
+
placeholder={PLACEHOLDER}
|
|
236
|
+
autocomplete="off"
|
|
237
|
+
onkeydown={handleKeydown}
|
|
238
|
+
/>
|
|
239
|
+
<kbd class="omni-kbd">⌘K</kbd>
|
|
240
|
+
<button type="button" aria-label="Close" class="omni-close-btn" onclick={close}>
|
|
241
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
242
|
+
<path d="M18 6 6 18" />
|
|
243
|
+
<path d="m6 6 12 12" />
|
|
244
|
+
</svg>
|
|
245
|
+
</button>
|
|
246
|
+
</div>
|
|
72
247
|
</div>
|
|
73
248
|
|
|
74
|
-
<div
|
|
249
|
+
<div
|
|
250
|
+
bind:this={listRef}
|
|
251
|
+
id="omni-listbox"
|
|
252
|
+
class="omni-body"
|
|
253
|
+
role="listbox"
|
|
254
|
+
aria-label="Command results"
|
|
255
|
+
>
|
|
75
256
|
{#if loading}
|
|
76
|
-
<div class="
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
257
|
+
<div class="omni-loading">
|
|
258
|
+
<svg class="omni-spin" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
259
|
+
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
|
260
|
+
</svg>
|
|
261
|
+
Fetching results…
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
{:else if showRecents && recentsList.length > 0}
|
|
265
|
+
<div class="omni-group">
|
|
266
|
+
<div class="omni-group-label">Recent</div>
|
|
267
|
+
<div class="omni-group-items">
|
|
268
|
+
{#each flatItems as item, i}
|
|
269
|
+
{@const active = item.id === activeId || (activeId == null && i === 0)}
|
|
270
|
+
<button
|
|
271
|
+
type="button"
|
|
272
|
+
id="omni-item-{item.id}"
|
|
273
|
+
data-id={item.id}
|
|
274
|
+
class="omni-item"
|
|
275
|
+
class:omni-item-active={active}
|
|
276
|
+
role="option"
|
|
277
|
+
aria-selected={active}
|
|
278
|
+
onmouseenter={() => (activeId = item.id)}
|
|
279
|
+
onclick={() => executeItem(item)}
|
|
280
|
+
>
|
|
281
|
+
<div class="omni-item-icon">
|
|
282
|
+
{@html FileIcon}
|
|
283
|
+
</div>
|
|
284
|
+
<div class="omni-item-text">
|
|
285
|
+
<div class="omni-item-label">{item.label}</div>
|
|
286
|
+
<div class="omni-item-subtitle">{item.subtitle}</div>
|
|
287
|
+
</div>
|
|
288
|
+
<a
|
|
289
|
+
href={item.url}
|
|
290
|
+
class="omni-item-badge"
|
|
291
|
+
title="Open in new tab"
|
|
292
|
+
target="_blank"
|
|
293
|
+
rel="noopener noreferrer"
|
|
294
|
+
aria-hidden="true"
|
|
295
|
+
onclick={(e) => onExternalClick(e, item.url)}
|
|
296
|
+
>
|
|
297
|
+
{@html ExternalIcon}
|
|
298
|
+
</a>
|
|
299
|
+
<span class="omni-item-chevron" aria-hidden="true">
|
|
300
|
+
{@html ChevronIcon}
|
|
301
|
+
</span>
|
|
302
|
+
</button>
|
|
303
|
+
{/each}
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
|
|
307
|
+
{:else if showDocs}
|
|
308
|
+
<div class="omni-group">
|
|
309
|
+
<div class="omni-group-label">Documentation</div>
|
|
310
|
+
<div class="omni-group-items">
|
|
311
|
+
{#each flatItems as item, i}
|
|
312
|
+
{@const active = item.id === activeId || (activeId == null && i === 0)}
|
|
313
|
+
<button
|
|
314
|
+
type="button"
|
|
315
|
+
id="omni-item-{item.id}"
|
|
316
|
+
data-id={item.id}
|
|
317
|
+
class="omni-item"
|
|
318
|
+
class:omni-item-active={active}
|
|
319
|
+
role="option"
|
|
320
|
+
aria-selected={active}
|
|
321
|
+
onmouseenter={() => (activeId = item.id)}
|
|
322
|
+
onclick={() => executeItem(item)}
|
|
323
|
+
>
|
|
324
|
+
<div class="omni-item-icon">
|
|
325
|
+
{@html FileIcon}
|
|
326
|
+
</div>
|
|
327
|
+
<div class="omni-item-text">
|
|
328
|
+
<div class="omni-item-label">{item.label}</div>
|
|
329
|
+
<div class="omni-item-subtitle">{item.subtitle}</div>
|
|
330
|
+
</div>
|
|
331
|
+
<a
|
|
332
|
+
href={item.url}
|
|
333
|
+
class="omni-item-badge"
|
|
334
|
+
title="Open in new tab"
|
|
335
|
+
target="_blank"
|
|
336
|
+
rel="noopener noreferrer"
|
|
337
|
+
aria-hidden="true"
|
|
338
|
+
onclick={(e) => onExternalClick(e, item.url)}
|
|
339
|
+
>
|
|
340
|
+
{@html ExternalIcon}
|
|
341
|
+
</a>
|
|
342
|
+
<span class="omni-item-chevron" aria-hidden="true">
|
|
343
|
+
{@html ChevronIcon}
|
|
344
|
+
</span>
|
|
345
|
+
</button>
|
|
346
|
+
{/each}
|
|
347
|
+
</div>
|
|
348
|
+
</div>
|
|
88
349
|
{/if}
|
|
350
|
+
|
|
351
|
+
{#if showEmpty}
|
|
352
|
+
<div class="omni-empty">
|
|
353
|
+
<div class="omni-empty-icon">
|
|
354
|
+
{@html EmptyIcon}
|
|
355
|
+
</div>
|
|
356
|
+
{emptyText}
|
|
357
|
+
</div>
|
|
358
|
+
{/if}
|
|
359
|
+
</div>
|
|
360
|
+
|
|
361
|
+
<div class="omni-footer">
|
|
362
|
+
<div class="omni-footer-inner">
|
|
363
|
+
<div class="omni-footer-hints">
|
|
364
|
+
<span class="omni-footer-hint">
|
|
365
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
366
|
+
<polyline points="9 18 15 12 9 6" />
|
|
367
|
+
</svg>
|
|
368
|
+
to select
|
|
369
|
+
</span>
|
|
370
|
+
<span class="omni-footer-hint">
|
|
371
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
372
|
+
<path d="M18 15l-6-6-6 6" />
|
|
373
|
+
</svg>
|
|
374
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
375
|
+
<path d="M6 9l6 6 6-6" />
|
|
376
|
+
</svg>
|
|
377
|
+
to navigate
|
|
378
|
+
</span>
|
|
379
|
+
<span class="omni-footer-hint omni-footer-hint-desktop">
|
|
380
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
381
|
+
<path d="M18 6 6 18" />
|
|
382
|
+
<path d="m6 6 12 12" />
|
|
383
|
+
</svg>
|
|
384
|
+
to close
|
|
385
|
+
</span>
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
89
388
|
</div>
|
|
90
389
|
</div>
|
|
91
390
|
</div>
|
package/src/themes/colorful.js
CHANGED
|
@@ -24,7 +24,7 @@ const ColorfulUIDefaults = {
|
|
|
24
24
|
layout: {
|
|
25
25
|
contentWidth: 768,
|
|
26
26
|
sidebarWidth: 260,
|
|
27
|
-
toc: { enabled: true, depth: 3, style: "
|
|
27
|
+
toc: { enabled: true, depth: 3, style: "default" },
|
|
28
28
|
header: { height: 56, sticky: true },
|
|
29
29
|
},
|
|
30
30
|
components: {
|
package/styles/colorful.css
CHANGED
|
@@ -84,6 +84,57 @@
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/* ─── Omni Command Palette — colorful theme ────────────────────────── */
|
|
88
|
+
|
|
89
|
+
.omni-content {
|
|
90
|
+
border-radius: 0.75rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.omni-item-active {
|
|
94
|
+
background: color-mix(in srgb, var(--color-fd-primary) 15%, transparent);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.omni-highlight {
|
|
98
|
+
background: color-mix(in srgb, var(--color-fd-primary) 30%, transparent);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.omni-search-input:focus {
|
|
102
|
+
caret-color: var(--color-fd-primary);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* ─── Page Actions — colorful theme ────────────────────────────────── */
|
|
106
|
+
|
|
107
|
+
.fd-page-action-btn {
|
|
108
|
+
border-radius: 0.375rem !important;
|
|
109
|
+
font-size: 0.8125rem !important;
|
|
110
|
+
letter-spacing: normal !important;
|
|
111
|
+
box-shadow: none !important;
|
|
112
|
+
text-transform: capitalize !important;
|
|
113
|
+
font-family: var(--fd-font-sans, ui-sans-serif, system-ui, sans-serif) !important;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.fd-page-action-dropdown {
|
|
117
|
+
position: relative !important;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.fd-page-action-menu {
|
|
121
|
+
border-radius: 0.5rem !important;
|
|
122
|
+
border: 1px solid var(--color-fd-border) !important;
|
|
123
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2) !important;
|
|
124
|
+
background: var(--color-fd-popover) !important;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.fd-page-action-menu-item {
|
|
128
|
+
border-radius: 0.25rem !important;
|
|
129
|
+
font-size: 0.8125rem !important;
|
|
130
|
+
color: var(--color-fd-foreground) !important;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.fd-page-action-menu-item:hover {
|
|
134
|
+
background: var(--color-fd-accent) !important;
|
|
135
|
+
color: var(--color-fd-accent-foreground) !important;
|
|
136
|
+
}
|
|
137
|
+
|
|
87
138
|
/* ─── Page nav cards ───────────────────────────────────────────────── */
|
|
88
139
|
|
|
89
140
|
.fd-page-nav-card {
|
|
@@ -148,3 +199,24 @@
|
|
|
148
199
|
.fd-docs-content hr {
|
|
149
200
|
border-color: var(--color-fd-border);
|
|
150
201
|
}
|
|
202
|
+
|
|
203
|
+
/* ─── Ask AI button (floating + custom trigger) — sync with Next.js ───── */
|
|
204
|
+
|
|
205
|
+
.fd-ai-floating-btn {
|
|
206
|
+
border-radius: 26px;
|
|
207
|
+
box-shadow: 0 8px 32px rgba(180, 140, 20, 0.3);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.fd-ai-floating-btn:hover {
|
|
211
|
+
box-shadow: 0 10px 40px rgba(180, 140, 20, 0.4);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.fd-ai-floating-trigger .ask-ai-trigger {
|
|
215
|
+
font-family: var(--fd-font-sans, inherit);
|
|
216
|
+
border-radius: 26px !important;
|
|
217
|
+
box-shadow: 0 8px 32px rgba(180, 140, 20, 0.3) !important;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.fd-ai-floating-trigger .ask-ai-trigger:hover {
|
|
221
|
+
box-shadow: 0 10px 40px rgba(180, 140, 20, 0.4);
|
|
222
|
+
}
|
package/styles/darksharp.css
CHANGED
|
@@ -204,3 +204,74 @@ code:not(pre code) {
|
|
|
204
204
|
.fd-ai-fm-trigger-btn:hover {
|
|
205
205
|
transform: none;
|
|
206
206
|
}
|
|
207
|
+
|
|
208
|
+
/* Custom Ask AI trigger — same as fd-ai-floating-btn for theme */
|
|
209
|
+
.fd-ai-floating-trigger .ask-ai-trigger {
|
|
210
|
+
font-family: var(--fd-font-sans, inherit);
|
|
211
|
+
border-radius: 2px !important;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.fd-ai-floating-trigger .ask-ai-trigger:hover {
|
|
215
|
+
box-shadow: 0 0 0 1px var(--color-fd-ring);
|
|
216
|
+
transform: none;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.fd-ai-fm-input-bar .fd-ai-floating-trigger .ask-ai-trigger {
|
|
220
|
+
border-radius: 2px !important;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.fd-ai-fm-input-bar .fd-ai-floating-trigger .ask-ai-trigger:hover {
|
|
224
|
+
transform: none;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* ─── Omni Command Palette — darksharp theme ────────────────────── */
|
|
228
|
+
|
|
229
|
+
.omni-content {
|
|
230
|
+
border-radius: 0.5rem !important;
|
|
231
|
+
border: 1px solid var(--color-fd-border) !important;
|
|
232
|
+
background: var(--color-fd-popover) !important;
|
|
233
|
+
box-shadow:
|
|
234
|
+
0 24px 60px -12px rgba(0, 0, 0, 0.7),
|
|
235
|
+
0 0 0 1px rgba(255, 255, 255, 0.06) !important;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.omni-item {
|
|
239
|
+
border-radius: 0.25rem !important;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.omni-highlight {
|
|
243
|
+
background: color-mix(in srgb, var(--color-fd-primary) 30%, transparent) !important;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* ─── Page Actions — darksharp theme ────────────────────────────── */
|
|
247
|
+
|
|
248
|
+
.fd-page-action-btn {
|
|
249
|
+
border-radius: 0.2rem !important;
|
|
250
|
+
font-size: 0.8125rem !important;
|
|
251
|
+
letter-spacing: normal !important;
|
|
252
|
+
box-shadow: none !important;
|
|
253
|
+
text-transform: capitalize !important;
|
|
254
|
+
font-family: var(--fd-font-sans, ui-sans-serif, system-ui, sans-serif) !important;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.fd-page-action-dropdown {
|
|
258
|
+
position: relative !important;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.fd-page-action-menu {
|
|
262
|
+
border-radius: 0.2rem !important;
|
|
263
|
+
border: 1px solid var(--color-fd-border) !important;
|
|
264
|
+
box-shadow: 0 4px 24px hsl(0 0% 0% / 0.4) !important;
|
|
265
|
+
background: var(--color-fd-popover) !important;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.fd-page-action-menu-item {
|
|
269
|
+
border-radius: 0.1rem !important;
|
|
270
|
+
font-size: 0.8125rem !important;
|
|
271
|
+
color: var(--color-fd-foreground) !important;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.fd-page-action-menu-item:hover {
|
|
275
|
+
background: var(--color-fd-accent) !important;
|
|
276
|
+
color: var(--color-fd-accent-foreground) !important;
|
|
277
|
+
}
|