fix: comprehensive dark mode support across all pages
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 1m11s

- Fix body/html dark background to surface-950
- Add dark scrollbar styling
- Fix App.svelte wrapper to use Tailwind dark: classes instead of conditional strings
- Add dark:bg-surface-800 and dark:border-surface-700 to all cards in Dashboard, Docker, Files, Gitea
- Add dark text variants for headings, labels, and content text
- Add dark hover states for interactive elements
- Enable cross-category sidebar drag-and-drop
This commit is contained in:
Gan, Jimmy
2026-03-01 14:59:23 +08:00
parent a8debcfb4b
commit 62856c9343
8 changed files with 84 additions and 58 deletions
@@ -69,6 +69,7 @@
// Drag-and-drop state
let dragCategory = $state(null);
let dragIndex = $state(-1);
let dropCategory = $state(null);
let dropIndex = $state(-1);
function handleDragStart(category, index, e) {
@@ -79,26 +80,49 @@
}
function handleDragOver(category, index, e) {
if (category !== dragCategory) return;
e.preventDefault();
e.dataTransfer.dropEffect = "move";
dropCategory = category;
dropIndex = index;
}
function handleDragEnd() {
dragCategory = null;
dragIndex = -1;
dropCategory = null;
dropIndex = -1;
}
function handleDrop(category, index, e) {
e.preventDefault();
if (category !== dragCategory || dragIndex === index) { handleDragEnd(); return; }
if (dragCategory === null) { handleDragEnd(); return; }
if (dragCategory === category && dragIndex === index) { handleDragEnd(); return; }
const lists = { main: [...links], media: [...media], tools: [...tools] };
const list = lists[category];
const [moved] = list.splice(dragIndex, 1);
list.splice(index, 0, moved);
lists[category] = list;
const [moved] = lists[dragCategory].splice(dragIndex, 1);
lists[category].splice(index, 0, moved);
const newOrder = {
main: lists.main.map(itemKey),
media: lists.media.map(itemKey),
tools: lists.tools.map(itemKey),
};
onOrderChange(newOrder);
handleDragEnd();
}
// Allow dropping at end of a category (on the section divider/header area)
function handleCategoryDragOver(category, e) {
e.preventDefault();
e.dataTransfer.dropEffect = "move";
dropCategory = category;
dropIndex = -1;
}
function handleCategoryDrop(category, e) {
e.preventDefault();
if (dragCategory === null) { handleDragEnd(); return; }
const lists = { main: [...links], media: [...media], tools: [...tools] };
const [moved] = lists[dragCategory].splice(dragIndex, 1);
lists[category].push(moved);
const newOrder = {
main: lists.main.map(itemKey),
media: lists.media.map(itemKey),
@@ -124,9 +148,8 @@
}
function dragClasses(category, index) {
if (dragCategory !== category) return "";
if (index === dragIndex) return "opacity-30";
if (index === dropIndex) return "border-t-2 border-primary-500";
if (dragCategory === category && index === dragIndex) return "opacity-30";
if (dropCategory === category && index === dropIndex) return "border-t-2 border-primary-500";
return "";
}
</script>
@@ -150,7 +173,7 @@
<!-- Nav Links -->
<nav class="flex-1 px-3 mt-2 overflow-y-auto">
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2">Main</p>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2" ondragover={(e) => handleCategoryDragOver("main", e)} ondrop={(e) => handleCategoryDrop("main", e)}>Main</p>
{#each links as link, i}
{#if canAccess(link.id)}
<button
@@ -186,7 +209,7 @@
{/each}
<div class="my-4 border-t border-surface-200 {dark ? 'border-surface-700' : ''}"></div>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2">Media</p>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2" ondragover={(e) => handleCategoryDragOver("media", e)} ondrop={(e) => handleCategoryDrop("media", e)}>Media</p>
{#each media as svc, i}
<a
href={extHref(svc)}
@@ -217,7 +240,7 @@
{/each}
<div class="my-4 border-t border-surface-200 {dark ? 'border-surface-700' : ''}"></div>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2">Tools</p>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2" ondragover={(e) => handleCategoryDragOver("tools", e)} ondrop={(e) => handleCategoryDrop("tools", e)}>Tools</p>
{#each tools as item, i}
{#if canAccess(item.id)}
{#if item.external || item.port}