fix(ui): apply corner style to remaining controls

This commit is contained in:
zipg authored and GitHub committed 2026-07-23 17:29:59 +08:00
1 parent b9c1feab82
commit 136ead2007
80 files changed
+487 -305

No files matched your search

+3
View File
@@ -22,10 +22,12 @@
(() => { (() => {
const root = document.documentElement; const root = document.documentElement;
let mode = null; let mode = null;
let cornerStyle = null;
// localStorage can throw when WebView storage is unavailable; keep the existing light fallback. // localStorage can throw when WebView storage is unavailable; keep the existing light fallback.
try { try {
mode = localStorage.getItem("dbx-theme"); mode = localStorage.getItem("dbx-theme");
cornerStyle = localStorage.getItem("dbx-corner-style");
} catch {} } catch {}
const followsSystem = mode === "system" || mode === "soft-system"; const followsSystem = mode === "system" || mode === "soft-system";
@@ -40,6 +42,7 @@
} }
root.classList.toggle("dark", dark); root.classList.toggle("dark", dark);
root.dataset.cornerStyle = cornerStyle === "none" || cornerStyle === "large" ? cornerStyle : "small";
root.style.colorScheme = dark ? "dark" : "light"; root.style.colorScheme = dark ? "dark" : "light";
})(); })();
</script> </script>
@@ -241,7 +241,7 @@ defineExpose({ expandAll, collapseAll, resetExpansion, refresh });
min-height: 24px; min-height: 24px;
align-items: flex-start; align-items: flex-start;
gap: 4px; gap: 4px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
} }
.json-tree-row:hover { .json-tree-row:hover {
@@ -1196,7 +1196,7 @@ watch(driverStoreTab, (tab) => {
<div v-if="driverStoreTab === 'agent' && !isWeb" class="flex items-center gap-1.5"> <div v-if="driverStoreTab === 'agent' && !isWeb" class="flex items-center gap-1.5">
<span class="text-xs text-muted-foreground">{{ t("settings.updateDownloadSource") }}</span> <span class="text-xs text-muted-foreground">{{ t("settings.updateDownloadSource") }}</span>
<Select :model-value="settingsStore.editorSettings.updateDownloadSource" :disabled="downloadSourceBusy" @update:model-value="setUpdateDownloadSource"> <Select :model-value="settingsStore.editorSettings.updateDownloadSource" :disabled="downloadSourceBusy" @update:model-value="setUpdateDownloadSource">
<SelectTrigger class="h-7 w-[160px] rounded-[6px] text-xs"> <SelectTrigger class="h-7 w-[160px] rounded-md text-xs">
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
@@ -1205,11 +1205,11 @@ watch(driverStoreTab, (tab) => {
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<Button variant="ghost" size="sm" class="h-7 rounded-[6px] text-xs gap-1 text-muted-foreground" :disabled="importingZip" @click="importOfflineZip"> <Button variant="ghost" size="sm" class="h-7 rounded-md text-xs gap-1 text-muted-foreground" :disabled="importingZip" @click="importOfflineZip">
<FileUp class="h-3.5 w-3.5" /> <FileUp class="h-3.5 w-3.5" />
{{ importingZip ? t("driverStore.importing") : t("driverStore.importOfflinePackage") }} {{ importingZip ? t("driverStore.importing") : t("driverStore.importOfflinePackage") }}
</Button> </Button>
<Button variant="ghost" size="sm" class="h-7 rounded-[6px] text-xs gap-1 text-muted-foreground" :disabled="refreshing" @click="forceRefresh"> <Button variant="ghost" size="sm" class="h-7 rounded-md text-xs gap-1 text-muted-foreground" :disabled="refreshing" @click="forceRefresh">
<RefreshCw class="h-3.5 w-3.5" :class="{ 'animate-spin': refreshing }" /> <RefreshCw class="h-3.5 w-3.5" :class="{ 'animate-spin': refreshing }" />
{{ t("driverStore.refresh") }} {{ t("driverStore.refresh") }}
</Button> </Button>
@@ -1219,7 +1219,7 @@ watch(driverStoreTab, (tab) => {
<!-- Agent Tab --> <!-- Agent Tab -->
<TabsContent value="agent" class="driver-store-tab driver-store-agent-tab mt-5 space-y-5"> <TabsContent value="agent" class="driver-store-tab driver-store-agent-tab mt-5 space-y-5">
<!-- Java Runtime --> <!-- Java Runtime -->
<div class="rounded-xl border bg-muted/20 p-4 space-y-3" data-driver-store-focus="jre" :class="{ 'driver-store-focus-highlight': highlightedFocusKey === 'jre' }"> <div class="rounded-lg border bg-muted/20 p-4 space-y-3" data-driver-store-focus="jre" :class="{ 'driver-store-focus-highlight': highlightedFocusKey === 'jre' }">
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<Label class="shrink-0">{{ t("driverStore.javaRuntime") }}</Label> <Label class="shrink-0">{{ t("driverStore.javaRuntime") }}</Label>
<Select :model-value="javaRuntimeConfig.mode" @update:model-value="setJavaRuntimeMode"> <Select :model-value="javaRuntimeConfig.mode" @update:model-value="setJavaRuntimeMode">
@@ -1236,11 +1236,11 @@ watch(driverStoreTab, (tab) => {
<span v-else class="min-w-0 flex-1 truncate text-xs text-muted-foreground"> <span v-else class="min-w-0 flex-1 truncate text-xs text-muted-foreground">
{{ javaRuntimeConfig.mode === "system" ? t("driverStore.systemJavaHint") : t("driverStore.jreRuntimeAutoDownloadHint") }} {{ javaRuntimeConfig.mode === "system" ? t("driverStore.systemJavaHint") : t("driverStore.jreRuntimeAutoDownloadHint") }}
</span> </span>
<Button v-if="javaRuntimeConfig.mode === 'custom'" variant="outline" class="h-8 shrink-0 rounded-[6px] text-xs" @click="chooseCustomJavaPath"> <Button v-if="javaRuntimeConfig.mode === 'custom'" variant="outline" class="h-8 shrink-0 rounded-md text-xs" @click="chooseCustomJavaPath">
<FolderOpen class="h-3.5 w-3.5" /> <FolderOpen class="h-3.5 w-3.5" />
{{ t("driverStore.choose") }} {{ t("driverStore.choose") }}
</Button> </Button>
<Button class="h-8 shrink-0 rounded-[6px] text-xs" :disabled="savingJavaRuntime || (javaRuntimeConfig.mode === 'custom' && !customJavaPath.trim())" @click="saveJavaRuntimeConfig"> <Button class="h-8 shrink-0 rounded-md text-xs" :disabled="savingJavaRuntime || (javaRuntimeConfig.mode === 'custom' && !customJavaPath.trim())" @click="saveJavaRuntimeConfig">
{{ savingJavaRuntime ? t("driverStore.saving") : t("settings.save") }} {{ savingJavaRuntime ? t("driverStore.saving") : t("settings.save") }}
</Button> </Button>
</div> </div>
@@ -1257,15 +1257,15 @@ watch(driverStoreTab, (tab) => {
<Check v-if="jre.installed" class="h-4 w-4 text-green-600" /> <Check v-if="jre.installed" class="h-4 w-4 text-green-600" />
<span v-else class="text-xs text-muted-foreground">{{ t("driverStore.notInstalled") }}</span> <span v-else class="text-xs text-muted-foreground">{{ t("driverStore.notInstalled") }}</span>
<DriverInstallProgressCircle v-if="reinstallingJre === jre.key" :percent="agentProgressNumber" :title="agentProgressTitle(jre.installed ? t('driverStore.reinstalling') : t('driverStore.installing'))" /> <DriverInstallProgressCircle v-if="reinstallingJre === jre.key" :percent="agentProgressNumber" :title="agentProgressTitle(jre.installed ? t('driverStore.reinstalling') : t('driverStore.installing'))" />
<Button v-else-if="!jre.installed" type="button" variant="default" size="sm" class="h-8 rounded-[6px] text-xs" :disabled="reinstallingJre !== null || installing !== null" @click="reinstallJre(jre.key)"> <Button v-else-if="!jre.installed" type="button" variant="default" size="sm" class="h-8 rounded-md text-xs" :disabled="reinstallingJre !== null || installing !== null" @click="reinstallJre(jre.key)">
<Download class="h-3.5 w-3.5 mr-1" /> <Download class="h-3.5 w-3.5 mr-1" />
{{ t("driverStore.install") }} {{ t("driverStore.install") }}
</Button> </Button>
<Button v-else-if="jre.installed" type="button" variant="outline" size="sm" class="h-8 rounded-[6px] text-xs" :disabled="reinstallingJre !== null || installing !== null" @click="reinstallJre(jre.key)"> <Button v-else-if="jre.installed" type="button" variant="outline" size="sm" class="h-8 rounded-md text-xs" :disabled="reinstallingJre !== null || installing !== null" @click="reinstallJre(jre.key)">
<RotateCcw class="h-3.5 w-3.5 mr-1" /> <RotateCcw class="h-3.5 w-3.5 mr-1" />
{{ t("driverStore.reinstall") }} {{ t("driverStore.reinstall") }}
</Button> </Button>
<Button v-if="jre.installed" type="button" variant="ghost" size="sm" class="h-8 rounded-[6px] text-xs text-muted-foreground hover:text-destructive" :disabled="reinstallingJre !== null || installing !== null" @click="uninstallJre(jre.key)"> <Button v-if="jre.installed" type="button" variant="ghost" size="sm" class="h-8 rounded-md text-xs text-muted-foreground hover:text-destructive" :disabled="reinstallingJre !== null || installing !== null" @click="uninstallJre(jre.key)">
{{ t("driverStore.uninstall") }} {{ t("driverStore.uninstall") }}
</Button> </Button>
</div> </div>
@@ -1284,14 +1284,14 @@ watch(driverStoreTab, (tab) => {
<div v-else-if="filteredAgentDrivers.length === 0" class="py-12 text-center text-sm text-muted-foreground"> <div v-else-if="filteredAgentDrivers.length === 0" class="py-12 text-center text-sm text-muted-foreground">
{{ t("driverStore.noMatchingDrivers") }} {{ t("driverStore.noMatchingDrivers") }}
</div> </div>
<div v-else class="driver-store-agent-list rounded-md border divide-y"> <div v-else class="driver-store-agent-list rounded-lg border divide-y">
<!-- Updates Available header --> <!-- Updates Available header -->
<div v-if="filteredUpdatableDrivers.length > 0" class="flex items-center justify-between px-4 py-2.5 bg-amber-500/10"> <div v-if="filteredUpdatableDrivers.length > 0" class="flex items-center justify-between px-4 py-2.5 bg-amber-500/10">
<div class="min-w-0"> <div class="min-w-0">
<div class="text-sm font-semibold">{{ t("driverStore.updatesAvailableTitle") }} ({{ filteredUpdatableCount }})</div> <div class="text-sm font-semibold">{{ t("driverStore.updatesAvailableTitle") }} ({{ filteredUpdatableCount }})</div>
<p class="text-xs text-muted-foreground">{{ t("driverStore.updatesAvailableDescription") }}</p> <p class="text-xs text-muted-foreground">{{ t("driverStore.updatesAvailableDescription") }}</p>
</div> </div>
<Button size="sm" class="h-7 rounded-[6px] text-xs shrink-0 ml-3" :disabled="installing !== null || upgradingAll" @click="upgradeAll"> <Button size="sm" class="h-7 rounded-md text-xs shrink-0 ml-3" :disabled="installing !== null || upgradingAll" @click="upgradeAll">
<Loader2 v-if="upgradingAll" class="h-3 w-3 animate-spin mr-1" /> <Loader2 v-if="upgradingAll" class="h-3 w-3 animate-spin mr-1" />
<Download v-else class="h-3 w-3 mr-1" /> <Download v-else class="h-3 w-3 mr-1" />
{{ upgradingAll ? t("driverStore.upgradingProgress", { current: upgradingIndex, total: upgradingTotal }) : t("driverStore.upgradeAll") }} {{ upgradingAll ? t("driverStore.upgradingProgress", { current: upgradingIndex, total: upgradingTotal }) : t("driverStore.upgradeAll") }}
@@ -1304,7 +1304,7 @@ watch(driverStoreTab, (tab) => {
class="driver-store-agent-row flex items-center gap-3 px-4 py-2 transition hover:bg-muted/30" class="driver-store-agent-row flex items-center gap-3 px-4 py-2 transition hover:bg-muted/30"
:class="{ 'driver-store-focus-highlight': highlightedFocusKey === `driver:${driver.db_type}` }" :class="{ 'driver-store-focus-highlight': highlightedFocusKey === `driver:${driver.db_type}` }"
> >
<span class="flex h-8 w-8 items-center justify-center rounded-lg bg-muted/60 shrink-0"> <span class="flex h-8 w-8 items-center justify-center rounded-md bg-muted/60 shrink-0">
<DatabaseIcon :db-type="driver.db_type" class="h-4 w-4" /> <DatabaseIcon :db-type="driver.db_type" class="h-4 w-4" />
</span> </span>
<div class="driver-store-agent-name min-w-0 flex-1"> <div class="driver-store-agent-name min-w-0 flex-1">
@@ -1318,12 +1318,12 @@ watch(driverStoreTab, (tab) => {
<span v-if="formatSize(driver.size)" class="rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground">{{ formatSize(driver.size) }}</span> <span v-if="formatSize(driver.size)" class="rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground">{{ formatSize(driver.size) }}</span>
</div> </div>
<div class="driver-store-agent-actions flex shrink-0 items-center gap-2"> <div class="driver-store-agent-actions flex shrink-0 items-center gap-2">
<Button v-if="!driver.installed && isDriverQueued(driver.db_type)" size="sm" variant="outline" class="h-7 rounded-[6px] border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15" :disabled="upgradingAll" @click="removeQueuedDriverInstall(driver.db_type)"> <Button v-if="!driver.installed && isDriverQueued(driver.db_type)" size="sm" variant="outline" class="h-7 rounded-md border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15" :disabled="upgradingAll" @click="removeQueuedDriverInstall(driver.db_type)">
<Clock3 class="h-3 w-3 mr-1" /> <Clock3 class="h-3 w-3 mr-1" />
{{ t("driverStore.queued") }} {{ t("driverStore.queued") }}
</Button> </Button>
<DriverInstallProgressCircle v-else-if="!driver.installed && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.installing'))" /> <DriverInstallProgressCircle v-else-if="!driver.installed && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.installing'))" />
<Button v-else-if="!driver.installed" size="sm" class="h-7 rounded-[6px] text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)"> <Button v-else-if="!driver.installed" size="sm" class="h-7 rounded-md text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)">
<Download class="h-3 w-3 mr-1" /> <Download class="h-3 w-3 mr-1" />
{{ t("driverStore.install") }} {{ t("driverStore.install") }}
</Button> </Button>
@@ -1331,7 +1331,7 @@ watch(driverStoreTab, (tab) => {
v-if="!driver.installed && !isPrestoSqlBuiltinDriver(driver.db_type) && !isDriverProgressActive(driver.db_type) && !isDriverQueued(driver.db_type)" v-if="!driver.installed && !isPrestoSqlBuiltinDriver(driver.db_type) && !isDriverProgressActive(driver.db_type) && !isDriverQueued(driver.db_type)"
size="sm" size="sm"
variant="ghost" variant="ghost"
class="h-7 w-7 rounded-[6px] text-xs text-muted-foreground" class="h-7 w-7 rounded-md text-xs text-muted-foreground"
:title="t('driverStore.importLocalJar')" :title="t('driverStore.importLocalJar')"
:disabled="upgradingAll || installing !== null" :disabled="upgradingAll || installing !== null"
@click="importDriverFile(driver)" @click="importDriverFile(driver)"
@@ -1343,7 +1343,7 @@ watch(driverStoreTab, (tab) => {
v-if="driver.installed && driver.update_available && isDriverQueued(driver.db_type)" v-if="driver.installed && driver.update_available && isDriverQueued(driver.db_type)"
size="sm" size="sm"
variant="outline" variant="outline"
class="h-7 rounded-[6px] border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15" class="h-7 rounded-md border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15"
:disabled="upgradingAll" :disabled="upgradingAll"
@click="removeQueuedDriverInstall(driver.db_type)" @click="removeQueuedDriverInstall(driver.db_type)"
> >
@@ -1351,10 +1351,10 @@ watch(driverStoreTab, (tab) => {
{{ t("driverStore.queued") }} {{ t("driverStore.queued") }}
</Button> </Button>
<DriverInstallProgressCircle v-else-if="driver.installed && driver.update_available && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.updating'))" /> <DriverInstallProgressCircle v-else-if="driver.installed && driver.update_available && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.updating'))" />
<Button v-else-if="driver.installed && driver.update_available" size="sm" variant="outline" class="h-7 rounded-[6px] text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)"> <Button v-else-if="driver.installed && driver.update_available" size="sm" variant="outline" class="h-7 rounded-md text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)">
{{ t("driverStore.update") }} {{ t("driverStore.update") }}
</Button> </Button>
<Button v-if="driver.installed" variant="ghost" size="sm" class="h-7 rounded-[6px] text-xs text-muted-foreground hover:text-destructive" :disabled="installing !== null || upgradingAll || isDriverQueued(driver.db_type)" @click="uninstallDriver(driver.db_type)"> <Button v-if="driver.installed" variant="ghost" size="sm" class="h-7 rounded-md text-xs text-muted-foreground hover:text-destructive" :disabled="installing !== null || upgradingAll || isDriverQueued(driver.db_type)" @click="uninstallDriver(driver.db_type)">
{{ t("driverStore.uninstall") }} {{ t("driverStore.uninstall") }}
</Button> </Button>
</div> </div>
@@ -1370,7 +1370,7 @@ watch(driverStoreTab, (tab) => {
class="driver-store-agent-row flex items-center gap-3 px-4 py-2 transition hover:bg-muted/30" class="driver-store-agent-row flex items-center gap-3 px-4 py-2 transition hover:bg-muted/30"
:class="{ 'driver-store-focus-highlight': highlightedFocusKey === `driver:${driver.db_type}` }" :class="{ 'driver-store-focus-highlight': highlightedFocusKey === `driver:${driver.db_type}` }"
> >
<span class="flex h-8 w-8 items-center justify-center rounded-lg bg-muted/60 shrink-0"> <span class="flex h-8 w-8 items-center justify-center rounded-md bg-muted/60 shrink-0">
<DatabaseIcon :db-type="driver.db_type" class="h-4 w-4" /> <DatabaseIcon :db-type="driver.db_type" class="h-4 w-4" />
</span> </span>
<div class="driver-store-agent-name min-w-0 flex-1"> <div class="driver-store-agent-name min-w-0 flex-1">
@@ -1384,12 +1384,12 @@ watch(driverStoreTab, (tab) => {
<span v-if="formatSize(driver.size)" class="rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground">{{ formatSize(driver.size) }}</span> <span v-if="formatSize(driver.size)" class="rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground">{{ formatSize(driver.size) }}</span>
</div> </div>
<div class="driver-store-agent-actions flex shrink-0 items-center gap-2"> <div class="driver-store-agent-actions flex shrink-0 items-center gap-2">
<Button v-if="!driver.installed && isDriverQueued(driver.db_type)" size="sm" variant="outline" class="h-7 rounded-[6px] border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15" :disabled="upgradingAll" @click="removeQueuedDriverInstall(driver.db_type)"> <Button v-if="!driver.installed && isDriverQueued(driver.db_type)" size="sm" variant="outline" class="h-7 rounded-md border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15" :disabled="upgradingAll" @click="removeQueuedDriverInstall(driver.db_type)">
<Clock3 class="h-3 w-3 mr-1" /> <Clock3 class="h-3 w-3 mr-1" />
{{ t("driverStore.queued") }} {{ t("driverStore.queued") }}
</Button> </Button>
<DriverInstallProgressCircle v-else-if="!driver.installed && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.installing'))" /> <DriverInstallProgressCircle v-else-if="!driver.installed && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.installing'))" />
<Button v-else-if="!driver.installed" size="sm" class="h-7 rounded-[6px] text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)"> <Button v-else-if="!driver.installed" size="sm" class="h-7 rounded-md text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)">
<Download class="h-3 w-3 mr-1" /> <Download class="h-3 w-3 mr-1" />
{{ t("driverStore.install") }} {{ t("driverStore.install") }}
</Button> </Button>
@@ -1397,7 +1397,7 @@ watch(driverStoreTab, (tab) => {
v-if="!driver.installed && !isPrestoSqlBuiltinDriver(driver.db_type) && !isDriverProgressActive(driver.db_type) && !isDriverQueued(driver.db_type)" v-if="!driver.installed && !isPrestoSqlBuiltinDriver(driver.db_type) && !isDriverProgressActive(driver.db_type) && !isDriverQueued(driver.db_type)"
size="sm" size="sm"
variant="ghost" variant="ghost"
class="h-7 w-7 rounded-[6px] text-xs text-muted-foreground" class="h-7 w-7 rounded-md text-xs text-muted-foreground"
:title="t('driverStore.importLocalJar')" :title="t('driverStore.importLocalJar')"
:disabled="upgradingAll || installing !== null" :disabled="upgradingAll || installing !== null"
@click="importDriverFile(driver)" @click="importDriverFile(driver)"
@@ -1409,7 +1409,7 @@ watch(driverStoreTab, (tab) => {
v-if="driver.installed && driver.update_available && isDriverQueued(driver.db_type)" v-if="driver.installed && driver.update_available && isDriverQueued(driver.db_type)"
size="sm" size="sm"
variant="outline" variant="outline"
class="h-7 rounded-[6px] border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15" class="h-7 rounded-md border-green-500/30 bg-green-500/10 text-xs text-green-700 hover:bg-green-500/15"
:disabled="upgradingAll" :disabled="upgradingAll"
@click="removeQueuedDriverInstall(driver.db_type)" @click="removeQueuedDriverInstall(driver.db_type)"
> >
@@ -1417,10 +1417,10 @@ watch(driverStoreTab, (tab) => {
{{ t("driverStore.queued") }} {{ t("driverStore.queued") }}
</Button> </Button>
<DriverInstallProgressCircle v-else-if="driver.installed && driver.update_available && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.updating'))" /> <DriverInstallProgressCircle v-else-if="driver.installed && driver.update_available && isDriverProgressActive(driver.db_type)" :percent="agentProgressNumber" :title="agentProgressTitle(t('driverStore.updating'))" />
<Button v-else-if="driver.installed && driver.update_available" size="sm" variant="outline" class="h-7 rounded-[6px] text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)"> <Button v-else-if="driver.installed && driver.update_available" size="sm" variant="outline" class="h-7 rounded-md text-xs" :disabled="upgradingAll" @click="installDriver(driver.db_type)">
{{ t("driverStore.update") }} {{ t("driverStore.update") }}
</Button> </Button>
<Button v-if="driver.installed" variant="ghost" size="sm" class="h-7 rounded-[6px] text-xs text-muted-foreground hover:text-destructive" :disabled="installing !== null || upgradingAll || isDriverQueued(driver.db_type)" @click="uninstallDriver(driver.db_type)"> <Button v-if="driver.installed" variant="ghost" size="sm" class="h-7 rounded-md text-xs text-muted-foreground hover:text-destructive" :disabled="installing !== null || upgradingAll || isDriverQueued(driver.db_type)" @click="uninstallDriver(driver.db_type)">
{{ t("driverStore.uninstall") }} {{ t("driverStore.uninstall") }}
</Button> </Button>
</div> </div>
@@ -1431,7 +1431,7 @@ watch(driverStoreTab, (tab) => {
<!-- JDBC Tab --> <!-- JDBC Tab -->
<TabsContent value="jdbc" class="driver-store-tab driver-store-jdbc-tab mt-5 space-y-5"> <TabsContent value="jdbc" class="driver-store-tab driver-store-jdbc-tab mt-5 space-y-5">
<!-- JDBC Plugin --> <!-- JDBC Plugin -->
<div class="rounded-xl border bg-muted/20 p-4"> <div class="rounded-lg border bg-muted/20 p-4">
<div class="flex min-h-12 items-center justify-between gap-3"> <div class="flex min-h-12 items-center justify-between gap-3">
<div class="min-w-0 space-y-1"> <div class="min-w-0 space-y-1">
<Label>{{ t("settings.jdbcPlugin") }}</Label> <Label>{{ t("settings.jdbcPlugin") }}</Label>
@@ -1451,16 +1451,16 @@ watch(driverStoreTab, (tab) => {
}} }}
</span> </span>
<span v-if="jdbcPluginStatus?.installed && jdbcPluginStatus.update_available" class="rounded-full bg-amber-500/15 px-2 py-0.5 text-[11px] text-amber-600">→ v{{ jdbcPluginStatus.latest_version }}</span> <span v-if="jdbcPluginStatus?.installed && jdbcPluginStatus.update_available" class="rounded-full bg-amber-500/15 px-2 py-0.5 text-[11px] text-amber-600">→ v{{ jdbcPluginStatus.latest_version }}</span>
<Button v-if="jdbcPluginStatus?.installed && jdbcPluginStatus.update_available" type="button" variant="outline" class="rounded-[6px]" :disabled="isInstallingJdbcPlugin" @click="installJdbcPlugin"> <Button v-if="jdbcPluginStatus?.installed && jdbcPluginStatus.update_available" type="button" variant="outline" class="rounded-md" :disabled="isInstallingJdbcPlugin" @click="installJdbcPlugin">
{{ isInstallingJdbcPlugin ? t("common.loading") : t("settings.jdbcPluginUpdate") }} {{ isInstallingJdbcPlugin ? t("common.loading") : t("settings.jdbcPluginUpdate") }}
</Button> </Button>
<Button v-if="jdbcPluginStatus?.installed" type="button" variant="outline" class="rounded-[6px]" :disabled="isUninstallingJdbcPlugin" @click="uninstallJdbcPlugin"> <Button v-if="jdbcPluginStatus?.installed" type="button" variant="outline" class="rounded-md" :disabled="isUninstallingJdbcPlugin" @click="uninstallJdbcPlugin">
{{ isUninstallingJdbcPlugin ? t("common.loading") : t("settings.jdbcPluginUninstall") }} {{ isUninstallingJdbcPlugin ? t("common.loading") : t("settings.jdbcPluginUninstall") }}
</Button> </Button>
<Button v-else type="button" variant="default" class="rounded-[6px]" :disabled="isInstallingJdbcPlugin" @click="installJdbcPlugin"> <Button v-else type="button" variant="default" class="rounded-md" :disabled="isInstallingJdbcPlugin" @click="installJdbcPlugin">
{{ isInstallingJdbcPlugin ? t("common.loading") : t("settings.jdbcPluginInstall") }} {{ isInstallingJdbcPlugin ? t("common.loading") : t("settings.jdbcPluginInstall") }}
</Button> </Button>
<Button v-if="!jdbcPluginStatus?.installed" type="button" variant="outline" class="rounded-[6px]" :disabled="isInstallingJdbcPlugin" @click="installJdbcPluginLocal"> <Button v-if="!jdbcPluginStatus?.installed" type="button" variant="outline" class="rounded-md" :disabled="isInstallingJdbcPlugin" @click="installJdbcPluginLocal">
<FolderOpen class="h-3.5 w-3.5 mr-1" /> <FolderOpen class="h-3.5 w-3.5 mr-1" />
{{ t("driverStore.localInstall") }} {{ t("driverStore.localInstall") }}
</Button> </Button>
@@ -1479,10 +1479,10 @@ watch(driverStoreTab, (tab) => {
</div> </div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<Input v-model="jdbcDriverPathInput" class="flex-1" :placeholder="t('settings.jdbcDriverPathPlaceholder')" @keydown.enter.prevent="importJdbcDriverPathInput" /> <Input v-model="jdbcDriverPathInput" class="flex-1" :placeholder="t('settings.jdbcDriverPathPlaceholder')" @keydown.enter.prevent="importJdbcDriverPathInput" />
<Button variant="outline" class="rounded-[6px]" :disabled="!jdbcDriverPathInput.trim()" @click="importJdbcDriverPathInput"> <Button variant="outline" class="rounded-md" :disabled="!jdbcDriverPathInput.trim()" @click="importJdbcDriverPathInput">
{{ t("settings.jdbcImportPath") }} {{ t("settings.jdbcImportPath") }}
</Button> </Button>
<Button class="shrink-0 rounded-[6px]" @click="importJdbcDrivers"> <Button class="shrink-0 rounded-md" @click="importJdbcDrivers">
<FolderOpen class="h-4 w-4" /> <FolderOpen class="h-4 w-4" />
{{ t("settings.jdbcImport") }} {{ t("settings.jdbcImport") }}
</Button> </Button>
@@ -1499,7 +1499,7 @@ watch(driverStoreTab, (tab) => {
</SelectItem> </SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<Button class="h-8 shrink-0 rounded-[6px]" :disabled="!jdbcMavenCoordinateInput.trim() || isInstallingJdbcMavenDriver || (jdbcMavenRepository === 'custom' && !customJdbcMavenRepository.trim())" @click="installJdbcMavenDriver"> <Button class="h-8 shrink-0 rounded-md" :disabled="!jdbcMavenCoordinateInput.trim() || isInstallingJdbcMavenDriver || (jdbcMavenRepository === 'custom' && !customJdbcMavenRepository.trim())" @click="installJdbcMavenDriver">
<Loader2 v-if="isInstallingJdbcMavenDriver" class="h-4 w-4 animate-spin" /> <Loader2 v-if="isInstallingJdbcMavenDriver" class="h-4 w-4 animate-spin" />
<Download v-else class="h-4 w-4" /> <Download v-else class="h-4 w-4" />
{{ t("driverStore.jdbcMavenInstall") }} {{ t("driverStore.jdbcMavenInstall") }}
@@ -1508,7 +1508,7 @@ watch(driverStoreTab, (tab) => {
<Input v-if="jdbcMavenRepository === 'custom'" v-model="customJdbcMavenRepository" class="h-8 text-xs" placeholder="https://repo.example.com/repository/maven-public" @keydown.enter.prevent="installJdbcMavenDriver" /> <Input v-if="jdbcMavenRepository === 'custom'" v-model="customJdbcMavenRepository" class="h-8 text-xs" placeholder="https://repo.example.com/repository/maven-public" @keydown.enter.prevent="installJdbcMavenDriver" />
</div> </div>
<div class="driver-store-jdbc-list rounded-md border"> <div class="driver-store-jdbc-list rounded-lg border">
<div v-if="isLoadingJdbcDrivers" class="p-4 text-sm text-muted-foreground"> <div v-if="isLoadingJdbcDrivers" class="p-4 text-sm text-muted-foreground">
{{ t("common.loading") }} {{ t("common.loading") }}
</div> </div>
@@ -1530,7 +1530,7 @@ watch(driverStoreTab, (tab) => {
<div class="truncate text-xs text-muted-foreground">{{ item.subtitle }}</div> <div class="truncate text-xs text-muted-foreground">{{ item.subtitle }}</div>
</div> </div>
<div class="shrink-0 text-xs text-muted-foreground">{{ formatBytes(item.size) }}</div> <div class="shrink-0 text-xs text-muted-foreground">{{ formatBytes(item.size) }}</div>
<Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 rounded-[6px]" @click="item.kind === 'maven' ? deleteJdbcMavenBundle(item.bundle.id) : item.kind === 'local' ? deleteJdbcLocalBundle(item.bundle.id) : deleteJdbcDriver(item.driver.path)"> <Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 rounded-md" @click="item.kind === 'maven' ? deleteJdbcMavenBundle(item.bundle.id) : item.kind === 'local' ? deleteJdbcLocalBundle(item.bundle.id) : deleteJdbcDriver(item.driver.path)">
<Trash2 class="h-4 w-4" /> <Trash2 class="h-4 w-4" />
</Button> </Button>
</div> </div>
@@ -1541,14 +1541,14 @@ watch(driverStoreTab, (tab) => {
<!-- Runtime Tab --> <!-- Runtime Tab -->
<TabsContent value="storage" class="driver-store-tab driver-store-storage-tab mt-5 space-y-5"> <TabsContent value="storage" class="driver-store-tab driver-store-storage-tab mt-5 space-y-5">
<!-- Storage Usage --> <!-- Storage Usage -->
<div class="rounded-xl border bg-muted/20 p-4 space-y-3"> <div class="rounded-lg border bg-muted/20 p-4 space-y-3">
<div class="flex items-center justify-between gap-3"> <div class="flex items-center justify-between gap-3">
<div class="text-sm font-medium">{{ t("driverStore.usageTitle") }}</div> <div class="text-sm font-medium">{{ t("driverStore.usageTitle") }}</div>
<div class="flex shrink-0 items-center gap-2"> <div class="flex shrink-0 items-center gap-2">
<div class="text-xs text-muted-foreground"> <div class="text-xs text-muted-foreground">
{{ usageSummary.length ? t("driverStore.usageTotal", { size: formatBytes(usageSummary[0].bytes) }) : t("driverStore.calculating") }} {{ usageSummary.length ? t("driverStore.usageTotal", { size: formatBytes(usageSummary[0].bytes) }) : t("driverStore.calculating") }}
</div> </div>
<Button variant="outline" size="sm" class="h-7 gap-1.5 rounded-[6px] text-xs" :disabled="!canClearDownloadCache" @click="clearDownloadCache"> <Button variant="outline" size="sm" class="h-7 gap-1.5 rounded-md text-xs" :disabled="!canClearDownloadCache" @click="clearDownloadCache">
<Loader2 v-if="clearingDownloadCache" class="h-3.5 w-3.5 animate-spin" /> <Loader2 v-if="clearingDownloadCache" class="h-3.5 w-3.5 animate-spin" />
<Trash2 v-else class="h-3.5 w-3.5" /> <Trash2 v-else class="h-3.5 w-3.5" />
{{ clearingDownloadCache ? t("common.loading") : t("driverStore.clearDownloadCache") }} {{ clearingDownloadCache ? t("common.loading") : t("driverStore.clearDownloadCache") }}
@@ -1564,7 +1564,7 @@ watch(driverStoreTab, (tab) => {
</div> </div>
<!-- Driver Store Path --> <!-- Driver Store Path -->
<div v-if="!isWeb" class="rounded-xl border bg-muted/20 p-4 space-y-3"> <div v-if="!isWeb" class="rounded-lg border bg-muted/20 p-4 space-y-3">
<div class="text-sm font-medium">{{ t("driverStore.driverStoreDir") }}</div> <div class="text-sm font-medium">{{ t("driverStore.driverStoreDir") }}</div>
<p class="text-xs text-muted-foreground">{{ t("driverStore.driverStoreDirDescription") }}</p> <p class="text-xs text-muted-foreground">{{ t("driverStore.driverStoreDirDescription") }}</p>
<div class="space-y-2.5"> <div class="space-y-2.5">
@@ -1604,7 +1604,7 @@ watch(driverStoreTab, (tab) => {
</div> </div>
<!-- Offline Download --> <!-- Offline Download -->
<div class="rounded-xl border bg-muted/20 p-4"> <div class="rounded-lg border bg-muted/20 p-4">
<div class="flex items-center justify-between gap-3"> <div class="flex items-center justify-between gap-3">
<div class="min-w-0 text-xs text-muted-foreground"> <div class="min-w-0 text-xs text-muted-foreground">
{{ t("driverStore.offlineDownloadHint") }} {{ t("driverStore.offlineDownloadHint") }}
@@ -1617,7 +1617,7 @@ watch(driverStoreTab, (tab) => {
</div> </div>
<!-- Runtime Info --> <!-- Runtime Info -->
<div class="overflow-hidden rounded-md border bg-background"> <div class="overflow-hidden rounded-lg border bg-background">
<div class="flex flex-col gap-3 border-b px-4 py-3 lg:flex-row lg:items-center lg:justify-between"> <div class="flex flex-col gap-3 border-b px-4 py-3 lg:flex-row lg:items-center lg:justify-between">
<div class="flex min-w-0 items-center gap-2.5"> <div class="flex min-w-0 items-center gap-2.5">
<span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-muted"> <span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-muted">
@@ -1633,7 +1633,7 @@ watch(driverStoreTab, (tab) => {
</div> </div>
</div> </div>
</div> </div>
<Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 rounded-[6px] text-muted-foreground" :title="t('driverStore.refresh')" :disabled="runtimeLoading" @click="refreshDriverRuntime"> <Button variant="ghost" size="icon" class="h-8 w-8 shrink-0 rounded-md text-muted-foreground" :title="t('driverStore.refresh')" :disabled="runtimeLoading" @click="refreshDriverRuntime">
<RefreshCw class="h-4 w-4" :class="{ 'animate-spin': runtimeLoading }" /> <RefreshCw class="h-4 w-4" :class="{ 'animate-spin': runtimeLoading }" />
</Button> </Button>
</div> </div>
@@ -1705,10 +1705,10 @@ watch(driverStoreTab, (tab) => {
{{ formatRuntimeUptime(runtime.uptime_seconds) }} {{ formatRuntimeUptime(runtime.uptime_seconds) }}
</div> </div>
<div class="flex min-w-0 items-center gap-1.5 lg:justify-end"> <div class="flex min-w-0 items-center gap-1.5 lg:justify-end">
<Button v-if="runtime.can_stop" variant="ghost" size="icon" class="h-7 w-7 rounded-[6px] text-muted-foreground hover:text-destructive" :title="t('driverStore.runtimeStop')" :disabled="runtimeBusy === runtime.id" @click="stopRuntime(runtime)"> <Button v-if="runtime.can_stop" variant="ghost" size="icon" class="h-7 w-7 rounded-md text-muted-foreground hover:text-destructive" :title="t('driverStore.runtimeStop')" :disabled="runtimeBusy === runtime.id" @click="stopRuntime(runtime)">
<Square class="h-3.5 w-3.5" /> <Square class="h-3.5 w-3.5" />
</Button> </Button>
<Button v-if="runtime.can_restart" variant="ghost" size="icon" class="h-7 w-7 rounded-[6px] text-muted-foreground" :title="t('driverStore.runtimeRestart')" :disabled="runtimeBusy === runtime.id" @click="restartRuntime(runtime)"> <Button v-if="runtime.can_restart" variant="ghost" size="icon" class="h-7 w-7 rounded-md text-muted-foreground" :title="t('driverStore.runtimeRestart')" :disabled="runtimeBusy === runtime.id" @click="restartRuntime(runtime)">
<RotateCcw class="h-3.5 w-3.5" :class="{ 'animate-spin': runtimeBusy === runtime.id }" /> <RotateCcw class="h-3.5 w-3.5" :class="{ 'animate-spin': runtimeBusy === runtime.id }" />
</Button> </Button>
<span v-if="!runtime.can_stop && !runtime.can_restart" class="min-w-0 truncate text-[11px] text-muted-foreground lg:text-right" :title="runtimeControlUnavailableReasonLabel(runtime.control_unavailable_reason)"> <span v-if="!runtime.can_stop && !runtime.can_restart" class="min-w-0 truncate text-[11px] text-muted-foreground lg:text-right" :title="runtimeControlUnavailableReasonLabel(runtime.control_unavailable_reason)">
@@ -1734,7 +1734,7 @@ watch(driverStoreTab, (tab) => {
.driver-store-focus-highlight { .driver-store-focus-highlight {
background-color: hsl(var(--primary) / 0.08); background-color: hsl(var(--primary) / 0.08);
box-shadow: inset 0 0 0 1.5px hsl(var(--primary) / 0.45); box-shadow: inset 0 0 0 1.5px hsl(var(--primary) / 0.45);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
} }
.driver-store-view, .driver-store-view,
@@ -1491,7 +1491,7 @@ defineExpose({ focusSearch });
<span v-if="(dataGridRef?.hiddenColumnCount ?? 0) > 0" class="tabular-nums"> {{ dataGridRef?.visibleColumnCount }}/{{ dataGridRef?.displayableColumnCount }} </span> <span v-if="(dataGridRef?.hiddenColumnCount ?? 0) > 0" class="tabular-nums"> {{ dataGridRef?.visibleColumnCount }}/{{ dataGridRef?.displayableColumnCount }} </span>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="end" class="w-64 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="end" class="w-64 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-2 py-1.5"> <div class="border-b bg-muted/40 px-2 py-1.5">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
<div class="text-xs font-semibold">{{ t("grid.columnVisibility") }}</div> <div class="text-xs font-semibold">{{ t("grid.columnVisibility") }}</div>
@@ -1536,7 +1536,7 @@ defineExpose({ focusSearch });
<Wrench class="h-4 w-4" /> <Wrench class="h-4 w-4" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="end" class="w-max min-w-44 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="end" class="w-max min-w-44 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-3 py-2"> <div class="border-b bg-muted/40 px-3 py-2">
<div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div> <div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div>
</div> </div>
@@ -1984,7 +1984,7 @@ defineExpose({ focusSearch });
min-height: 0; min-height: 0;
resize: none; resize: none;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-4);
background: var(--background); background: var(--background);
color: var(--foreground); color: var(--foreground);
padding: 14px 16px; padding: 14px 16px;
@@ -200,7 +200,7 @@ function confirmRemoveChild() {
border: 1px solid var(--border); border: 1px solid var(--border);
border: 1px solid color-mix(in oklab, var(--border) 82%, transparent); border: 1px solid color-mix(in oklab, var(--border) 82%, transparent);
border-left-width: 3px; border-left-width: 3px;
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--muted); background: var(--muted);
background: color-mix(in oklab, var(--background) 76%, var(--muted)); background: color-mix(in oklab, var(--background) 76%, var(--muted));
} }
@@ -227,7 +227,7 @@ function confirmRemoveChild() {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
border: 0; border: 0;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: transparent; background: transparent;
color: inherit; color: inherit;
font: inherit; font: inherit;
@@ -264,7 +264,7 @@ function confirmRemoveChild() {
min-height: 42px; min-height: 42px;
resize: vertical; resize: vertical;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--background); background: var(--background);
padding: 5px 8px; padding: 5px 8px;
font: inherit; font: inherit;
@@ -431,7 +431,7 @@ watch(
</Button> </Button>
</div> </div>
</div> </div>
<div class="mt-3 overflow-hidden rounded-xl border border-border/70 bg-background/80 shadow-xs"> <div class="mt-3 overflow-hidden rounded-lg border border-border/70 bg-background/80 shadow-xs">
<div class="flex flex-col md:flex-row"> <div class="flex flex-col md:flex-row">
<div class="flex min-w-0 flex-1 items-center gap-1 px-2 py-1.5"> <div class="flex min-w-0 flex-1 items-center gap-1 px-2 py-1.5">
<Popover v-model:open="filterBuilderOpen"> <Popover v-model:open="filterBuilderOpen">
@@ -178,7 +178,7 @@ onMounted(() => {
</Button> </Button>
</div> </div>
</div> </div>
<div class="mt-3 overflow-hidden rounded-xl border border-border/70 bg-background/80 shadow-xs"> <div class="mt-3 overflow-hidden rounded-lg border border-border/70 bg-background/80 shadow-xs">
<div class="flex flex-col md:flex-row"> <div class="flex flex-col md:flex-row">
<div class="flex min-w-0 flex-1 items-center gap-1 px-2 py-1.5"> <div class="flex min-w-0 flex-1 items-center gap-1 px-2 py-1.5">
<Popover v-model:open="filterBuilderOpen"> <Popover v-model:open="filterBuilderOpen">
@@ -493,7 +493,7 @@ defineExpose({
.editor-search-panel--editor { .editor-search-panel--editor {
background: #f6f7f9; background: #f6f7f9;
border-color: #d8dce3; border-color: #d8dce3;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
box-shadow: box-shadow:
0 8px 22px rgb(15 23 42 / 0.14), 0 8px 22px rgb(15 23 42 / 0.14),
0 1px 0 rgb(255 255 255 / 0.78) inset; 0 1px 0 rgb(255 255 255 / 0.78) inset;
@@ -537,7 +537,7 @@ defineExpose({
.editor-search-panel--editor :deep(.border-input) { .editor-search-panel--editor :deep(.border-input) {
background: #ffffff; background: #ffffff;
border-color: #c7ccd5; border-color: #c7ccd5;
border-radius: 5px; border-radius: var(--dbx-radius-fixed-5);
box-shadow: 0 1px 0 rgb(15 23 42 / 0.03) inset; box-shadow: 0 1px 0 rgb(15 23 42 / 0.03) inset;
} }
@@ -112,7 +112,7 @@ import ChangelogPanel from "@/components/settings/ChangelogPanel.vue";
import McpConnectionScopePicker from "@/components/settings/McpConnectionScopePicker.vue"; import McpConnectionScopePicker from "@/components/settings/McpConnectionScopePicker.vue";
import ScheduledDatabaseBackupSettings from "@/components/backup/ScheduledDatabaseBackupSettings.vue"; import ScheduledDatabaseBackupSettings from "@/components/backup/ScheduledDatabaseBackupSettings.vue";
import SqlFormatterSettingsPanel from "./SqlFormatterSettingsPanel.vue"; import SqlFormatterSettingsPanel from "./SqlFormatterSettingsPanel.vue";
import { APP_THEME_PALETTES, type AppThemeAppearance, type AppThemeMode, type AppThemePalette } from "@/lib/app/appTheme"; import { APP_THEME_PALETTES, type AppCornerStyle, type AppThemeAppearance, type AppThemeMode, type AppThemePalette } from "@/lib/app/appTheme";
import { editorSettingsDraftChanged, editorSettingsDraftFromSettings, editorSettingsPatchFromDraft, normalizeTableOpenPageSizeDraft, type EditorSettingsDraft } from "@/lib/settings/editorSettingsDraft"; import { editorSettingsDraftChanged, editorSettingsDraftFromSettings, editorSettingsPatchFromDraft, normalizeTableOpenPageSizeDraft, type EditorSettingsDraft } from "@/lib/settings/editorSettingsDraft";
import { useConnectionStore } from "@/stores/connectionStore"; import { useConnectionStore } from "@/stores/connectionStore";
import { useSavedSqlStore } from "@/stores/savedSqlStore"; import { useSavedSqlStore } from "@/stores/savedSqlStore";
@@ -137,7 +137,7 @@ const connectionStore = useConnectionStore();
const savedSqlStore = useSavedSqlStore(); const savedSqlStore = useSavedSqlStore();
const promptTemplateStore = usePromptTemplateStore(); const promptTemplateStore = usePromptTemplateStore();
const tunnelProfileStore = useTunnelProfileStore(); const tunnelProfileStore = useTunnelProfileStore();
const { isDark, themeMode, themePalette, setThemeMode, setThemePalette } = useTheme(); const { isDark, themeMode, themePalette, cornerStyle, setThemeMode, setThemePalette, setCornerStyle } = useTheme();
const appThemePaletteOptions = computed( const appThemePaletteOptions = computed(
(): Array<{ value: AppThemePalette; label: string; previewColor: string }> => (): Array<{ value: AppThemePalette; label: string; previewColor: string }> =>
@@ -154,6 +154,11 @@ const appThemeModeOptions = computed(() => [
{ value: "dark" as AppThemeMode, label: t("toolbar.themeDark"), icon: Moon }, { value: "dark" as AppThemeMode, label: t("toolbar.themeDark"), icon: Moon },
{ value: "system" as AppThemeMode, label: t("toolbar.themeSystem"), icon: SunMoon }, { value: "system" as AppThemeMode, label: t("toolbar.themeSystem"), icon: SunMoon },
]); ]);
const appCornerStyleOptions = computed(() => [
{ value: "none" as AppCornerStyle, label: t("settings.cornerStyleNone"), previewRadius: "0px" },
{ value: "small" as AppCornerStyle, label: t("settings.cornerStyleSmall"), previewRadius: "4px" },
{ value: "large" as AppCornerStyle, label: t("settings.cornerStyleLarge"), previewRadius: "10px" },
]);
const props = defineProps<{ const props = defineProps<{
open?: boolean; open?: boolean;
@@ -3630,22 +3635,43 @@ onUnmounted(cleanupPreviewEditor);
</div> </div>
</div> </div>
<div class="settings-appearance-group"> <div class="settings-appearance-theme-grid">
<Label>{{ t("settings.theme") }}</Label> <div class="settings-appearance-group min-w-0">
<div class="settings-appearance-button-row flex flex-wrap gap-2"> <Label>{{ t("settings.theme") }}</Label>
<Button <div class="settings-appearance-button-row flex flex-wrap gap-2">
v-for="option in appThemeModeOptions" <Button
:key="option.value" v-for="option in appThemeModeOptions"
type="button" :key="option.value"
variant="outline" type="button"
size="sm" variant="outline"
class="settings-choice-button h-8 gap-1.5 rounded-[6px] px-3" size="sm"
:class="themeMode === option.value ? 'settings-choice-button--selected border-primary/40 bg-primary/10 text-primary ring-1 ring-primary/30' : 'text-foreground'" class="settings-choice-button h-8 gap-1.5 px-3"
@click="setThemeMode(option.value)" :class="themeMode === option.value ? 'settings-choice-button--selected border-primary/40 bg-primary/10 text-primary ring-1 ring-primary/30' : 'text-foreground'"
> @click="setThemeMode(option.value)"
<component :is="option.icon" class="h-3.5 w-3.5" /> >
{{ option.label }} <component :is="option.icon" class="h-3.5 w-3.5" />
</Button> {{ option.label }}
</Button>
</div>
</div>
<div class="settings-appearance-group min-w-0">
<Label>{{ t("settings.cornerStyle") }}</Label>
<div class="settings-appearance-button-row flex flex-wrap gap-2">
<Button
v-for="option in appCornerStyleOptions"
:key="option.value"
type="button"
variant="outline"
size="sm"
class="settings-choice-button h-8 px-3"
:class="cornerStyle === option.value ? 'settings-choice-button--selected border-primary/40 bg-primary/10 text-primary ring-1 ring-primary/30' : 'text-foreground'"
:style="{ borderRadius: option.previewRadius }"
@click="setCornerStyle(option.value)"
>
{{ option.label }}
</Button>
</div>
</div> </div>
</div> </div>
@@ -5855,12 +5881,19 @@ onUnmounted(cleanupPreviewEditor);
gap: 0.625rem; gap: 0.625rem;
} }
.settings-appearance-theme-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.75rem;
}
.settings-option-stack > * + * { .settings-option-stack > * + * {
margin-top: 0.625rem; margin-top: 0.625rem;
} }
@media (max-width: 760px) { @media (max-width: 760px) {
.settings-appearance-top-grid, .settings-appearance-top-grid,
.settings-appearance-theme-grid,
.settings-appearance-choice-grid { .settings-appearance-choice-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
@@ -4370,7 +4370,7 @@ defineExpose({
margin: 0; margin: 0;
padding: 0; padding: 0;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
vertical-align: middle; vertical-align: middle;
white-space: nowrap; white-space: nowrap;
transition: transition:
@@ -4417,7 +4417,7 @@ defineExpose({
margin: 0; margin: 0;
padding: 0; padding: 0;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: transparent; background: transparent;
color: transparent; color: transparent;
vertical-align: middle; vertical-align: middle;
@@ -0,0 +1,10 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
const editorSearchPanelSource = readFileSync(new URL("../EditorSearchPanel.vue", import.meta.url), "utf8");
describe("EditorSearchPanel corner style", () => {
it("uses the configurable five-pixel radius token for editor inputs", () => {
expect(editorSearchPanelSource).toContain("border-radius: var(--dbx-radius-fixed-5);");
});
});
@@ -4870,7 +4870,7 @@ const canvasDetailButtonStyle = computed(() => {
const edgeGap = 6; const edgeGap = 6;
return { return {
left: `${Math.max(DATA_GRID_ROW_NUM_WIDTH, cell.rect.left + cell.rect.width - actionWidth - edgeGap)}px`, left: `${Math.max(DATA_GRID_ROW_NUM_WIDTH, cell.rect.left + cell.rect.width - actionWidth - edgeGap)}px`,
top: `${cell.rect.top + 2}px`, top: `${cell.rect.top + cell.rect.height / 2}px`,
}; };
}); });
@@ -7851,7 +7851,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<span class="text-muted-foreground/70 italic">{{ draftCellPlaceholder(displayItems[cell.recordIndex], cell.valueIndex) }}</span> <span class="text-muted-foreground/70 italic">{{ draftCellPlaceholder(displayItems[cell.recordIndex], cell.valueIndex) }}</span>
</template> </template>
<template v-else>{{ firstLineCellDisplayValue(cell.display) }}</template> <template v-else>{{ firstLineCellDisplayValue(cell.display) }}</template>
<div v-if="cellDetailButtonVisible(cell.recordIndex, cell.valueIndex)" class="absolute right-2 top-0.5 flex items-center gap-1"> <div v-if="cellDetailButtonVisible(cell.recordIndex, cell.valueIndex)" class="absolute right-2 top-1/2 flex -translate-y-1/2 items-center gap-1">
<LightDropdownMenu <LightDropdownMenu
v-if="canQuickDownloadCellValue(cell.recordIndex, cell.valueIndex)" v-if="canQuickDownloadCellValue(cell.recordIndex, cell.valueIndex)"
:items="binaryCellDownloadMenuItems" :items="binaryCellDownloadMenuItems"
@@ -8002,7 +8002,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<Code2 class="h-3.5 w-3.5" /> <Code2 class="h-3.5 w-3.5" />
</button> </button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="start" side="bottom" class="w-[450px] max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="start" side="bottom" class="w-[450px] max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-3 py-2"> <div class="border-b bg-muted/40 px-3 py-2">
<div class="text-sm font-semibold"> <div class="text-sm font-semibold">
{{ t("grid.columnFormatterFor", { column: col.name }) }} {{ t("grid.columnFormatterFor", { column: col.name }) }}
@@ -8181,7 +8181,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<Filter class="h-3.5 w-3.5" /> <Filter class="h-3.5 w-3.5" />
</button> </button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="start" side="bottom" class="w-[300px] max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="start" side="bottom" class="w-[300px] max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-2 py-1.5 text-center text-xs font-semibold"> <div class="border-b bg-muted/40 px-2 py-1.5 text-center text-xs font-semibold">
{{ columnFilterPanelTitle(col.name) }} {{ columnFilterPanelTitle(col.name) }}
</div> </div>
@@ -8347,7 +8347,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
@paste.stop="onCellEditTextareaPaste" @paste.stop="onCellEditTextareaPaste"
/> />
</div> </div>
<div v-if="canvasDetailButtonCell" class="absolute pointer-events-auto z-20 flex items-center gap-1" :style="canvasDetailButtonStyle" @mouseenter="keepCanvasDetailHover" @mouseleave="clearCanvasDetailHover"> <div v-if="canvasDetailButtonCell" class="absolute pointer-events-auto z-20 flex -translate-y-1/2 items-center gap-1" :style="canvasDetailButtonStyle" @mouseenter="keepCanvasDetailHover" @mouseleave="clearCanvasDetailHover">
<LightDropdownMenu <LightDropdownMenu
v-if="canvasDetailButtonCell.canQuickDownload" v-if="canvasDetailButtonCell.canQuickDownload"
:items="binaryCellDownloadMenuItems" :items="binaryCellDownloadMenuItems"
@@ -8509,7 +8509,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<span class="text-muted-foreground/70 italic">{{ draftCellPlaceholder(item, col.actualColIdx) }}</span> <span class="text-muted-foreground/70 italic">{{ draftCellPlaceholder(item, col.actualColIdx) }}</span>
</template> </template>
<template v-else>{{ firstLineCellDisplayValue(formatCellCached(item.data[col.actualColIdx], col.actualColIdx)) }}</template> <template v-else>{{ firstLineCellDisplayValue(formatCellCached(item.data[col.actualColIdx], col.actualColIdx)) }}</template>
<div v-if="cellDetailButtonVisible(item.displayIndex, col.actualColIdx)" class="absolute right-2 top-0.5 flex items-center gap-1"> <div v-if="cellDetailButtonVisible(item.displayIndex, col.actualColIdx)" class="absolute right-2 top-1/2 flex -translate-y-1/2 items-center gap-1">
<LightDropdownMenu <LightDropdownMenu
v-if="canQuickDownloadCellValue(item.displayIndex, col.actualColIdx)" v-if="canQuickDownloadCellValue(item.displayIndex, col.actualColIdx)"
:items="binaryCellDownloadMenuItems" :items="binaryCellDownloadMenuItems"
@@ -8553,7 +8553,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<div ref="gridVerticalScrollbarThumbRef" class="data-grid-vertical-scrollbar__thumb" /> <div ref="gridVerticalScrollbarThumbRef" class="data-grid-vertical-scrollbar__thumb" />
</div> </div>
<div v-if="loading" class="absolute inset-0 z-20 bg-background/50 flex items-center justify-center"> <div v-if="loading" class="absolute inset-0 z-20 bg-background/50 flex items-center justify-center">
<div class="flex items-center gap-2 px-3 py-1.5 rounded-md bg-background border shadow-sm text-xs text-muted-foreground"> <div class="flex items-center gap-2 rounded-md border bg-background px-3 py-1.5 text-xs text-muted-foreground shadow-sm">
<Loader2 class="w-3.5 h-3.5 animate-spin" /> <Loader2 class="w-3.5 h-3.5 animate-spin" />
<span>{{ formatElapsedSeconds(loadingElapsed) }}s</span> <span>{{ formatElapsedSeconds(loadingElapsed) }}s</span>
</div> </div>
@@ -9508,7 +9508,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
background-color: var(--background); background-color: var(--background);
background-color: color-mix(in oklab, var(--background) 96%, var(--primary) 4%); background-color: color-mix(in oklab, var(--background) 96%, var(--primary) 4%);
border: 1px solid color-mix(in oklab, var(--primary) 62%, var(--border)); border: 1px solid color-mix(in oklab, var(--primary) 62%, var(--border));
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
z-index: 90; z-index: 90;
box-shadow: box-shadow:
0 28px 72px rgb(0 0 0 / 34%), 0 28px 72px rgb(0 0 0 / 34%),
@@ -184,7 +184,7 @@ onUnmounted(() => {
:show-close-button="false" :show-close-button="false"
overlay-class="!z-[80]" overlay-class="!z-[80]"
portal-class="!z-[81]" portal-class="!z-[81]"
class="image-preview-dialog !flex !max-w-[92vw] flex-col gap-0 overflow-hidden rounded-xl border-white/10 bg-[#090b0f] p-0 text-white shadow-2xl sm:!max-w-[92vw]" class="image-preview-dialog !flex !max-w-[92vw] flex-col gap-0 overflow-hidden rounded-lg border-white/10 bg-[#090b0f] p-0 text-white shadow-2xl sm:!max-w-[92vw]"
:style="dialogStyle" :style="dialogStyle"
@escape-key-down="close" @escape-key-down="close"
> >
@@ -436,7 +436,7 @@ onBeforeUnmount(() => cleanupMap());
<template> <template>
<Dialog :open="open" @update:open="(value) => emit('update:open', value)"> <Dialog :open="open" @update:open="(value) => emit('update:open', value)">
<DialogContent :show-close-button="false" :style="contentStyle" class="layer-preview-dialog flex w-[96vw] max-w-[1800px] h-[88vh] max-h-[960px] min-w-[640px] min-h-[400px] flex-col gap-0 overflow-hidden rounded-xl border p-0 shadow-2xl" @escape-key-down="close"> <DialogContent :show-close-button="false" :style="contentStyle" class="layer-preview-dialog flex w-[96vw] max-w-[1800px] h-[88vh] max-h-[960px] min-w-[640px] min-h-[400px] flex-col gap-0 overflow-hidden rounded-lg border p-0 shadow-2xl" @escape-key-down="close">
<!-- Header --> <!-- Header -->
<div class="flex h-12 shrink-0 items-center gap-2 border-b bg-muted/20 px-3"> <div class="flex h-12 shrink-0 items-center gap-2 border-b bg-muted/20 px-3">
<div class="flex min-w-0 shrink-0 items-center gap-2"> <div class="flex min-w-0 shrink-0 items-center gap-2">
@@ -503,7 +503,7 @@ onBeforeUnmount(() => cleanupMap());
background: #1a1a2e; background: #1a1a2e;
} }
.layer-preview-dialog .leaflet-popup-content-wrapper { .layer-preview-dialog .leaflet-popup-content-wrapper {
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
font-size: 12px; font-size: 12px;
} }
.layer-preview-dialog .leaflet-popup-content { .layer-preview-dialog .leaflet-popup-content {
@@ -810,7 +810,7 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
<div v-if="activeProductionContext.active" class="production-session-strip flex h-7 shrink-0 items-center gap-2 border-b border-red-500/35 bg-red-500/10 px-3 text-xs font-semibold text-red-800 shadow-[inset_0_1px_0_rgb(239_68_68_/_0.28)] dark:text-red-200"> <div v-if="activeProductionContext.active" class="production-session-strip flex h-7 shrink-0 items-center gap-2 border-b border-red-500/35 bg-red-500/10 px-3 text-xs font-semibold text-red-800 shadow-[inset_0_1px_0_rgb(239_68_68_/_0.28)] dark:text-red-200">
<ShieldAlert class="h-3.5 w-3.5 shrink-0" aria-hidden="true" /> <ShieldAlert class="h-3.5 w-3.5 shrink-0" aria-hidden="true" />
<span class="font-mono uppercase tracking-normal">{{ t("production.title") }}</span> <span class="font-mono uppercase tracking-normal">{{ t("production.title") }}</span>
<span v-if="productionSessionDetail" class="min-w-0 truncate rounded-[4px] border border-red-500/25 bg-background/65 px-1.5 py-0.5 font-medium text-red-700 dark:text-red-200">{{ productionSessionDetail }}</span> <span v-if="productionSessionDetail" class="min-w-0 truncate rounded-md border border-red-500/25 bg-background/65 px-1.5 py-0.5 font-medium text-red-700 dark:text-red-200">{{ productionSessionDetail }}</span>
</div> </div>
<!-- Query mode: editor + results --> <!-- Query mode: editor + results -->
<template v-if="activeTab.mode === 'query'"> <template v-if="activeTab.mode === 'query'">
@@ -930,7 +930,7 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
<Wrench class="h-4 w-4" /> <Wrench class="h-4 w-4" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="end" class="w-max min-w-44 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="end" class="w-max min-w-44 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-3 py-2"> <div class="border-b bg-muted/40 px-3 py-2">
<div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div> <div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div>
</div> </div>
@@ -1259,7 +1259,7 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
<span v-if="(dataGridRef?.hiddenColumnCount ?? 0) > 0" class="tabular-nums"> {{ dataGridRef?.visibleColumnCount }}/{{ dataGridRef?.displayableColumnCount }} </span> <span v-if="(dataGridRef?.hiddenColumnCount ?? 0) > 0" class="tabular-nums"> {{ dataGridRef?.visibleColumnCount }}/{{ dataGridRef?.displayableColumnCount }} </span>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="end" class="w-64 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="end" class="w-64 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-2 py-1.5"> <div class="border-b bg-muted/40 px-2 py-1.5">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
<div class="text-xs font-semibold">{{ t("grid.columnVisibility") }}</div> <div class="text-xs font-semibold">{{ t("grid.columnVisibility") }}</div>
@@ -1307,7 +1307,7 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
<DropdownMenuTrigger as-child> <DropdownMenuTrigger as-child>
<Button variant="ghost" size="sm" class="h-5 text-xs px-1.5 shrink-0" :title="t('tableToolbox.title')"><Toolbox class="h-3.5 w-3.5" />{{ t("tableToolbox.title") }}</Button> <Button variant="ghost" size="sm" class="h-5 text-xs px-1.5 shrink-0" :title="t('tableToolbox.title')"><Toolbox class="h-3.5 w-3.5" />{{ t("tableToolbox.title") }}</Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end" class="w-max min-w-44 gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl"> <DropdownMenuContent align="end" class="w-max min-w-44 gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl">
<div class="border-b bg-muted/40 px-3 py-2"> <div class="border-b bg-muted/40 px-3 py-2">
<div class="text-xs font-semibold">{{ t("tableToolbox.title") }}</div> <div class="text-xs font-semibold">{{ t("tableToolbox.title") }}</div>
</div> </div>
@@ -1343,7 +1343,7 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
<Wrench class="h-4 w-4" /> <Wrench class="h-4 w-4" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent align="end" class="w-max min-w-44 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-xl border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop> <PopoverContent align="end" class="w-max min-w-44 max-w-[calc(100vw-2rem)] gap-0 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-xl" @click.stop @keydown.stop>
<div class="border-b bg-muted/40 px-3 py-2"> <div class="border-b bg-muted/40 px-3 py-2">
<div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div> <div class="text-xs font-semibold">{{ t("grid.viewOptions") }}</div>
</div> </div>
@@ -978,7 +978,7 @@ function createDragGhost(sourceEl: HTMLElement, x: number, y: number) {
z-index: 9999; z-index: 9999;
opacity: 0.9; opacity: 0.9;
box-shadow: 0 2px 8px rgba(0,0,0,0.12); box-shadow: 0 2px 8px rgba(0,0,0,0.12);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--background, #fff); background: var(--background, #fff);
border: 1px solid var(--border, #e5e7eb); border: 1px solid var(--border, #e5e7eb);
max-width: 220px; max-width: 220px;
@@ -242,7 +242,7 @@ onUnmounted(() => {
.refresh-interval { .refresh-interval {
padding: 4px 8px; padding: 4px 8px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
background: var(--color-background); background: var(--color-background);
cursor: pointer; cursor: pointer;
@@ -256,7 +256,7 @@ onUnmounted(() => {
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -315,7 +315,7 @@ onUnmounted(() => {
padding: 16px; padding: 16px;
background: var(--color-background-secondary); background: var(--color-background-secondary);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
transition: all 0.2s; transition: all 0.2s;
} }
@@ -355,7 +355,7 @@ onUnmounted(() => {
.broker-table-wrap { .broker-table-wrap {
overflow-x: auto; overflow-x: auto;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -411,7 +411,7 @@ onUnmounted(() => {
.btn-secondary { .btn-secondary {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -555,7 +555,7 @@ watch(
min-width: 180px; min-width: 180px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -590,7 +590,7 @@ watch(
overflow: auto; overflow: auto;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
} }
table { table {
@@ -640,7 +640,7 @@ td {
.badge { .badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
} }
@@ -682,7 +682,7 @@ td {
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
padding: 12px; padding: 12px;
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -706,7 +706,7 @@ td {
.btn-danger { .btn-danger {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -759,7 +759,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -819,7 +819,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
@@ -586,7 +586,7 @@ watch(topicName, () => {
width: 32px; width: 32px;
height: 32px; height: 32px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text-secondary); color: var(--color-text-secondary);
cursor: pointer; cursor: pointer;
@@ -629,7 +629,7 @@ watch(topicName, () => {
width: 100%; width: 100%;
padding: 7px 10px; padding: 7px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -657,7 +657,7 @@ watch(topicName, () => {
.panel-error { .panel-error {
padding: 10px 14px; padding: 10px 14px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
font-size: 13px; font-size: 13px;
@@ -670,7 +670,7 @@ watch(topicName, () => {
.results-table-wrap { .results-table-wrap {
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
overflow: auto; overflow: auto;
} }
@@ -706,7 +706,7 @@ watch(topicName, () => {
.btn-primary, .btn-primary,
.btn-sm { .btn-sm {
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -750,7 +750,7 @@ watch(topicName, () => {
width: min(720px, calc(100vw - 32px)); width: min(720px, calc(100vw - 32px));
max-height: calc(100vh - 64px); max-height: calc(100vh - 64px);
overflow: auto; overflow: auto;
border-radius: 10px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18); box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
display: flex; display: flex;
@@ -829,7 +829,7 @@ watch(topicName, () => {
.panel-success { .panel-success {
padding: 10px 14px; padding: 10px 14px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: color-mix(in srgb, var(--color-primary) 12%, transparent); background: color-mix(in srgb, var(--color-primary) 12%, transparent);
color: var(--color-primary); color: var(--color-primary);
font-size: 13px; font-size: 13px;
@@ -838,7 +838,7 @@ watch(topicName, () => {
.btn-secondary { .btn-secondary {
padding: 7px 16px; padding: 7px 16px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -851,7 +851,7 @@ watch(topicName, () => {
max-height: 360px; max-height: 360px;
overflow: auto; overflow: auto;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
color: var(--color-text); color: var(--color-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
@@ -1059,7 +1059,7 @@ onUnmounted(() => {
min-height: 32px; min-height: 32px;
padding: 5px 9px; padding: 5px 9px;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 8px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
font-weight: 500; font-weight: 500;
color: var(--monitor-muted); color: var(--monitor-muted);
@@ -1087,7 +1087,7 @@ onUnmounted(() => {
min-height: 34px; min-height: 34px;
padding: 5px 30px 5px 10px; padding: 5px 30px 5px 10px;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
font-weight: 500; font-weight: 500;
background: var(--monitor-surface); background: var(--monitor-surface);
@@ -1122,7 +1122,7 @@ onUnmounted(() => {
min-height: 34px; min-height: 34px;
padding: 7px 12px; padding: 7px 12px;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-4);
background: var(--monitor-surface); background: var(--monitor-surface);
color: var(--monitor-text); color: var(--monitor-text);
cursor: pointer; cursor: pointer;
@@ -1210,7 +1210,7 @@ onUnmounted(() => {
.loading-skeleton-card { .loading-skeleton-card {
height: 96px; height: 96px;
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.45), transparent), var(--monitor-surface); background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.45), transparent), var(--monitor-surface);
background-size: 220% 100%; background-size: 220% 100%;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
@@ -1271,7 +1271,7 @@ onUnmounted(() => {
min-height: 54px; min-height: 54px;
padding: 10px 12px; padding: 10px 12px;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--monitor-surface); background: var(--monitor-surface);
color: var(--monitor-text); color: var(--monitor-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
@@ -1297,7 +1297,7 @@ onUnmounted(() => {
justify-content: flex-start; justify-content: flex-start;
margin-top: 10px; margin-top: 10px;
border: 1px solid color-mix(in srgb, var(--monitor-danger) 22%, transparent); border: 1px solid color-mix(in srgb, var(--monitor-danger) 22%, transparent);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
padding: 10px 12px; padding: 10px 12px;
} }
@@ -1309,7 +1309,7 @@ onUnmounted(() => {
.kafka-message-row { .kafka-message-row {
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--monitor-surface); background: var(--monitor-surface);
overflow: hidden; overflow: hidden;
} }
@@ -1358,7 +1358,7 @@ onUnmounted(() => {
min-height: 260px; min-height: 260px;
padding: 14px; padding: 14px;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--monitor-surface); background: var(--monitor-surface);
box-shadow: var(--monitor-shadow); box-shadow: var(--monitor-shadow);
} }
@@ -1393,7 +1393,7 @@ onUnmounted(() => {
padding: 17px 18px; padding: 17px 18px;
background: var(--monitor-surface); background: var(--monitor-surface);
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
box-shadow: 0 1px 0 rgb(255 255 255 / 0.52) inset; box-shadow: 0 1px 0 rgb(255 255 255 / 0.52) inset;
transition: transition:
transform 0.22s cubic-bezier(0.16, 1, 0.3, 1), transform 0.22s cubic-bezier(0.16, 1, 0.3, 1),
@@ -1453,7 +1453,7 @@ onUnmounted(() => {
height: 42px; height: 42px;
flex: 0 0 42px; flex: 0 0 42px;
border: 1px solid var(--monitor-accent-border); border: 1px solid var(--monitor-accent-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--monitor-accent-soft); background: var(--monitor-accent-soft);
color: var(--monitor-accent); color: var(--monitor-accent);
} }
@@ -1498,7 +1498,7 @@ onUnmounted(() => {
.partition-table-wrap { .partition-table-wrap {
overflow-x: auto; overflow-x: auto;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--monitor-surface); background: var(--monitor-surface);
box-shadow: var(--monitor-shadow); box-shadow: var(--monitor-shadow);
} }
@@ -1595,7 +1595,7 @@ onUnmounted(() => {
.partition-detail { .partition-detail {
padding: 14px; padding: 14px;
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--monitor-surface); background: var(--monitor-surface);
box-shadow: var(--monitor-shadow); box-shadow: var(--monitor-shadow);
} }
@@ -1624,7 +1624,7 @@ onUnmounted(() => {
.empty-state.compact { .empty-state.compact {
padding: 16px; padding: 16px;
border: 1px dashed var(--monitor-border); border: 1px dashed var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: color-mix(in srgb, var(--monitor-surface) 74%, transparent); background: color-mix(in srgb, var(--monitor-surface) 74%, transparent);
} }
@@ -1636,7 +1636,7 @@ onUnmounted(() => {
padding: 13px 15px; padding: 13px 15px;
background: var(--monitor-surface); background: var(--monitor-surface);
border: 1px solid var(--monitor-border); border: 1px solid var(--monitor-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
box-shadow: 0 1px 0 rgb(255 255 255 / 0.48) inset; box-shadow: 0 1px 0 rgb(255 255 255 / 0.48) inset;
} }
@@ -412,7 +412,7 @@ onMounted(async () => {
</div> </div>
<div v-if="isRabbitMqCluster" class="mq-namespace-switcher"> <div v-if="isRabbitMqCluster" class="mq-namespace-switcher">
<Select :model-value="selectedNamespace" @update:model-value="handleNamespaceSelect"> <Select :model-value="selectedNamespace" @update:model-value="handleNamespaceSelect">
<SelectTrigger class="h-7 w-[180px] rounded-[6px] text-xs"> <SelectTrigger class="h-7 w-[180px] rounded-lg text-xs">
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
@@ -601,7 +601,7 @@ onMounted(async () => {
.breadcrumb-button { .breadcrumb-button {
border: none; border: none;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: transparent; background: transparent;
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -629,7 +629,7 @@ onMounted(async () => {
.readonly-badge { .readonly-badge {
padding: 2px 8px; padding: 2px 8px;
border: 1px solid var(--color-warning); border: 1px solid var(--color-warning);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
color: var(--color-warning); color: var(--color-warning);
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 500;
@@ -716,7 +716,7 @@ onMounted(async () => {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -772,7 +772,7 @@ onMounted(async () => {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
@@ -788,7 +788,7 @@ onMounted(async () => {
.btn-secondary { .btn-secondary {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -313,7 +313,7 @@ td {
.btn-danger { .btn-danger {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -365,7 +365,7 @@ button:disabled {
padding: 2px 8px; padding: 2px 8px;
background: var(--color-primary-alpha); background: var(--color-primary-alpha);
color: var(--color-primary); color: var(--color-primary);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 12px; font-size: 12px;
} }
@@ -395,7 +395,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -446,7 +446,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -476,7 +476,7 @@ button:disabled {
padding: 8px 12px; padding: 8px 12px;
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -511,7 +511,7 @@ watch(
.permissions-table { .permissions-table {
padding: 14px; padding: 14px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -545,7 +545,7 @@ input[type="number"] {
width: 100%; width: 100%;
padding: 7px 10px; padding: 7px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
box-sizing: border-box; box-sizing: border-box;
@@ -573,7 +573,7 @@ input.invalid {
.actions-group.invalid { .actions-group.invalid {
padding: 8px; padding: 8px;
border: 1px solid var(--color-error); border: 1px solid var(--color-error);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-error-bg); background: var(--color-error-bg);
} }
@@ -640,7 +640,7 @@ th {
.tag { .tag {
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-primary-alpha); background: var(--color-primary-alpha);
color: var(--color-primary); color: var(--color-primary);
font-size: 12px; font-size: 12px;
@@ -658,7 +658,7 @@ th {
.readonly-hint { .readonly-hint {
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 12px; margin-bottom: 12px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
font-size: 13px; font-size: 13px;
} }
@@ -683,7 +683,7 @@ th {
.btn-danger { .btn-danger {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -716,7 +716,7 @@ th {
max-height: 86vh; max-height: 86vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18); box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
} }
@@ -763,7 +763,7 @@ th {
padding: 12px; padding: 12px;
margin-bottom: 16px; margin-bottom: 16px;
border: 1px solid var(--color-warning); border: 1px solid var(--color-warning);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-warning-alpha); background: var(--color-warning-alpha);
} }
@@ -774,7 +774,7 @@ th {
margin-bottom: 16px; margin-bottom: 16px;
border: 1px solid var(--color-warning); border: 1px solid var(--color-warning);
border-left-width: 4px; border-left-width: 4px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-warning-alpha); background: var(--color-warning-alpha);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -803,7 +803,7 @@ th {
min-height: 96px; min-height: 96px;
padding: 8px 10px; padding: 8px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
@@ -321,7 +321,7 @@ watch(
.json-section { .json-section {
padding: 14px; padding: 14px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -346,7 +346,7 @@ select {
width: 100%; width: 100%;
padding: 7px 10px; padding: 7px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
box-sizing: border-box; box-sizing: border-box;
@@ -367,7 +367,7 @@ pre {
padding: 12px; padding: 12px;
max-height: 360px; max-height: 360px;
overflow: auto; overflow: auto;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 12px; font-size: 12px;
@@ -379,7 +379,7 @@ pre {
.readonly-hint { .readonly-hint {
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 12px; margin-bottom: 12px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
font-size: 13px; font-size: 13px;
} }
@@ -408,7 +408,7 @@ pre {
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -814,7 +814,7 @@ watch(
flex: 1; flex: 1;
height: 32px; height: 32px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -830,7 +830,7 @@ watch(
.btn-secondary { .btn-secondary {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -844,7 +844,7 @@ watch(
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -908,7 +908,7 @@ watch(
min-height: 24px; min-height: 24px;
padding: 2px 8px; padding: 2px 8px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background-secondary); background: var(--color-background-secondary);
color: var(--color-text-secondary); color: var(--color-text-secondary);
overflow: hidden; overflow: hidden;
@@ -928,7 +928,7 @@ watch(
max-width: 320px; max-width: 320px;
height: 30px; height: 30px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -308,7 +308,7 @@ async function executeRequest() {
.response-panel { .response-panel {
padding: 14px; padding: 14px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -370,7 +370,7 @@ async function executeRequest() {
min-height: 58px; min-height: 58px;
padding: 10px; padding: 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
text-align: left; text-align: left;
@@ -385,7 +385,7 @@ async function executeRequest() {
display: inline-flex; display: inline-flex;
justify-content: center; justify-content: center;
padding: 2px 6px; padding: 2px 6px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-primary-alpha); background: var(--color-primary-alpha);
color: var(--color-primary); color: var(--color-primary);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
@@ -439,7 +439,7 @@ textarea {
width: 100%; width: 100%;
padding: 8px 10px; padding: 8px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
box-sizing: border-box; box-sizing: border-box;
@@ -485,7 +485,7 @@ pre {
padding: 12px; padding: 12px;
max-height: 420px; max-height: 420px;
overflow: auto; overflow: auto;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
} }
@@ -500,7 +500,7 @@ pre {
.readonly-hint { .readonly-hint {
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 12px; margin-bottom: 12px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
font-size: 13px; font-size: 13px;
} }
@@ -517,7 +517,7 @@ pre {
.btn-primary { .btn-primary {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-primary); border: 1px solid var(--color-primary);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-primary); background: var(--color-primary);
color: white; color: white;
cursor: pointer; cursor: pointer;
@@ -527,7 +527,7 @@ pre {
.btn-secondary { .btn-secondary {
padding: 5px 10px; padding: 5px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -118,7 +118,7 @@ watch(
width: min(860px, calc(100vw - 32px)); width: min(860px, calc(100vw - 32px));
max-height: calc(100vh - 64px); max-height: calc(100vh - 64px);
overflow: auto; overflow: auto;
border-radius: 10px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18); box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
display: flex; display: flex;
@@ -190,7 +190,7 @@ watch(
.panel-error { .panel-error {
padding: 12px 14px; padding: 12px 14px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
font-size: 13px; font-size: 13px;
@@ -206,7 +206,7 @@ watch(
.message-row { .message-row {
padding: 10px 12px; padding: 10px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -223,7 +223,7 @@ watch(
padding: 10px; padding: 10px;
max-height: 240px; max-height: 240px;
overflow: auto; overflow: auto;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 12px; font-size: 12px;
@@ -241,7 +241,7 @@ watch(
.message-headers span { .message-headers span {
padding: 2px 6px; padding: 2px 6px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 12px; font-size: 12px;
color: var(--color-text-secondary); color: var(--color-text-secondary);
} }
@@ -249,7 +249,7 @@ watch(
.btn-secondary { .btn-secondary {
padding: 7px 16px; padding: 7px 16px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -491,7 +491,7 @@ watch(
.readonly-hint { .readonly-hint {
padding: 10px 14px; padding: 10px 14px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-warning-alpha); background: var(--color-warning-alpha);
color: var(--color-warning); color: var(--color-warning);
font-size: 13px; font-size: 13px;
@@ -499,7 +499,7 @@ watch(
.panel-error { .panel-error {
padding: 10px 14px; padding: 10px 14px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
font-size: 13px; font-size: 13px;
@@ -512,7 +512,7 @@ watch(
padding: 14px 18px; padding: 14px 18px;
border: 1px solid color-mix(in srgb, var(--color-success) 34%, transparent); border: 1px solid color-mix(in srgb, var(--color-success) 34%, transparent);
border-left: 4px solid var(--color-success); border-left: 4px solid var(--color-success);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: color-mix(in srgb, var(--color-success) 13%, var(--color-background)); background: color-mix(in srgb, var(--color-success) 13%, var(--color-background));
color: var(--color-success); color: var(--color-success);
font-size: 15px; font-size: 15px;
@@ -572,7 +572,7 @@ watch(
flex: 1; flex: 1;
padding: 7px 10px; padding: 7px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -592,7 +592,7 @@ watch(
width: 32px; width: 32px;
height: 32px; height: 32px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text-secondary); color: var(--color-text-secondary);
cursor: pointer; cursor: pointer;
@@ -624,7 +624,7 @@ input[type="text"],
input[type="number"] { input[type="number"] {
padding: 7px 10px; padding: 7px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -643,7 +643,7 @@ input[type="number"]:focus {
width: 100%; width: 100%;
padding: 8px 10px; padding: 8px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
@@ -713,7 +713,7 @@ input[type="number"]:focus {
.btn-sm { .btn-sm {
padding: 7px 16px; padding: 7px 16px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -755,7 +755,7 @@ input[type="number"]:focus {
margin-top: 4px; margin-top: 4px;
padding: 14px; padding: 14px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
@@ -777,7 +777,7 @@ input[type="number"]:focus {
.peek-default-hint { .peek-default-hint {
margin: 0 0 12px; margin: 0 0 12px;
padding: 8px 10px; padding: 8px 10px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: color-mix(in srgb, var(--color-primary) 8%, transparent); background: color-mix(in srgb, var(--color-primary) 8%, transparent);
color: var(--color-text-secondary); color: var(--color-text-secondary);
font-size: 12px; font-size: 12px;
@@ -811,7 +811,7 @@ input[type="number"]:focus {
.message-empty { .message-empty {
padding: 18px; padding: 18px;
border: 1px dashed var(--color-border); border: 1px dashed var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
color: var(--color-text-tertiary); color: var(--color-text-tertiary);
text-align: center; text-align: center;
font-size: 13px; font-size: 13px;
@@ -828,7 +828,7 @@ input[type="number"]:focus {
.message-row { .message-row {
padding: 10px 12px; padding: 10px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
} }
@@ -851,7 +851,7 @@ input[type="number"]:focus {
padding: 10px; padding: 10px;
max-height: 160px; max-height: 160px;
overflow: auto; overflow: auto;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-tertiary, var(--color-background-secondary)); background: var(--color-background-tertiary, var(--color-background-secondary));
color: var(--color-text); color: var(--color-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
@@ -871,7 +871,7 @@ input[type="number"]:focus {
.message-headers span { .message-headers span {
padding: 2px 6px; padding: 2px 6px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
color: var(--color-text-secondary); color: var(--color-text-secondary);
background: var(--color-background-secondary); background: var(--color-background-secondary);
font-size: 12px; font-size: 12px;
@@ -700,7 +700,7 @@ watch(
min-width: 180px; min-width: 180px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -721,7 +721,7 @@ watch(
.btn-secondary { .btn-secondary {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -791,7 +791,7 @@ watch(
min-width: 220px; min-width: 220px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
background: var(--color-background); background: var(--color-background);
} }
@@ -864,7 +864,7 @@ td {
.badge { .badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
background: var(--color-background-secondary); background: var(--color-background-secondary);
@@ -888,7 +888,7 @@ td {
.btn-danger { .btn-danger {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -943,7 +943,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -999,7 +999,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
@@ -1023,7 +1023,7 @@ button:disabled {
gap: 8px; gap: 8px;
cursor: pointer; cursor: pointer;
padding: 8px; padding: 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
transition: background 0.2s; transition: background 0.2s;
} }
@@ -1046,7 +1046,7 @@ button:disabled {
padding: 8px 12px; padding: 8px 12px;
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -1067,7 +1067,7 @@ button:disabled {
width: 96px; width: 96px;
padding: 6px 8px; padding: 6px 8px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
} }
@@ -1079,7 +1079,7 @@ button:disabled {
.peek-message { .peek-message {
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
overflow: hidden; overflow: hidden;
} }
@@ -485,7 +485,7 @@ td {
padding: 2px 8px; padding: 2px 8px;
background: var(--color-primary-alpha); background: var(--color-primary-alpha);
color: var(--color-primary); color: var(--color-primary);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 12px; font-size: 12px;
} }
@@ -515,7 +515,7 @@ td {
.btn-danger { .btn-danger {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -569,7 +569,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -619,7 +619,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -648,7 +648,7 @@ button:disabled {
gap: 8px; gap: 8px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -687,7 +687,7 @@ button:disabled {
max-height: 180px; max-height: 180px;
overflow-y: auto; overflow-y: auto;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
} }
@@ -748,7 +748,7 @@ button:disabled {
padding: 8px 12px; padding: 8px 12px;
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -764,7 +764,7 @@ watch(newPartitions, () => {
min-width: 180px; min-width: 180px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -899,7 +899,7 @@ td {
.badge { .badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
} }
@@ -942,7 +942,7 @@ td {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
@@ -955,7 +955,7 @@ td {
.btn-danger { .btn-danger {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -1009,7 +1009,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -1060,7 +1060,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -1086,7 +1086,7 @@ button:disabled {
padding: 8px 12px; padding: 8px 12px;
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -308,7 +308,7 @@ watch(
min-width: 180px; min-width: 180px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -342,7 +342,7 @@ watch(
overflow: auto; overflow: auto;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
} }
table { table {
@@ -412,7 +412,7 @@ td {
.channels-table { .channels-table {
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
overflow: hidden; overflow: hidden;
background: var(--color-background); background: var(--color-background);
} }
@@ -420,7 +420,7 @@ td {
.badge { .badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
} }
@@ -446,7 +446,7 @@ td {
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -307,7 +307,7 @@ onUnmounted(() => {
.refresh-interval { .refresh-interval {
padding: 4px 8px; padding: 4px 8px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -335,7 +335,7 @@ onUnmounted(() => {
padding: 12px 14px; padding: 12px 14px;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
@@ -356,7 +356,7 @@ onUnmounted(() => {
overflow: auto; overflow: auto;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
} }
table { table {
@@ -400,7 +400,7 @@ td {
.status-badge { .status-badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
} }
@@ -418,7 +418,7 @@ td {
.btn-secondary { .btn-secondary {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -504,7 +504,7 @@ watch(
min-width: 160px; min-width: 160px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -527,7 +527,7 @@ watch(
align-items: center; align-items: center;
gap: 4px; gap: 4px;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-primary-alpha); background: var(--color-primary-alpha);
color: var(--color-primary); color: var(--color-primary);
font-size: 12px; font-size: 12px;
@@ -560,7 +560,7 @@ watch(
overflow: auto; overflow: auto;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
} }
table { table {
@@ -622,7 +622,7 @@ td {
.badge { .badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
} }
@@ -644,7 +644,7 @@ td {
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -702,7 +702,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -760,7 +760,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
@@ -389,7 +389,7 @@ watch(
overflow: auto; overflow: auto;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
} }
table { table {
@@ -472,7 +472,7 @@ td {
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -530,7 +530,7 @@ button:disabled {
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 560px; max-width: 560px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -590,7 +590,7 @@ button:disabled {
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 14px; font-size: 14px;
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
@@ -315,7 +315,7 @@ watch(
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 92%; width: 92%;
max-width: 560px; max-width: 560px;
max-height: 86vh; max-height: 86vh;
@@ -422,7 +422,7 @@ watch(
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
@@ -459,7 +459,7 @@ watch(
padding: 8px 12px; padding: 8px 12px;
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -468,7 +468,7 @@ watch(
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -508,7 +508,7 @@ watch(
.dialog { .dialog {
background: var(--color-background); background: var(--color-background);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
width: 90%; width: 90%;
max-width: 520px; max-width: 520px;
max-height: 85vh; max-height: 85vh;
@@ -605,7 +605,7 @@ watch(
.config-value { .config-value {
padding: 7px 10px; padding: 7px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -632,7 +632,7 @@ watch(
width: 100%; width: 100%;
padding: 8px 10px; padding: 8px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
box-sizing: border-box; box-sizing: border-box;
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
@@ -662,7 +662,7 @@ watch(
padding: 8px 12px; padding: 8px 12px;
background: var(--color-error-bg); background: var(--color-error-bg);
color: var(--color-error); color: var(--color-error);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
font-size: 13px; font-size: 13px;
} }
@@ -679,7 +679,7 @@ watch(
.btn-sm { .btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--color-background); background: var(--color-background);
cursor: pointer; cursor: pointer;
font-size: 13px; font-size: 13px;
@@ -153,7 +153,7 @@ const { t } = useI18n();
.detail-payload { .detail-payload {
margin: 0; margin: 0;
padding: 12px; padding: 12px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background-secondary); background: var(--color-background-secondary);
font-family: var(--font-mono, ui-monospace, monospace); font-family: var(--font-mono, ui-monospace, monospace);
font-size: 12px; font-size: 12px;
@@ -165,7 +165,7 @@ const { t } = useI18n();
.panel-error { .panel-error {
padding: 10px 12px; padding: 10px 12px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: color-mix(in srgb, var(--color-error) 12%, transparent); background: color-mix(in srgb, var(--color-error) 12%, transparent);
color: var(--color-error); color: var(--color-error);
font-size: 13px; font-size: 13px;
@@ -173,7 +173,7 @@ const { t } = useI18n();
.panel-success { .panel-success {
padding: 10px 12px; padding: 10px 12px;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: color-mix(in srgb, var(--color-success, #22c55e) 12%, transparent); background: color-mix(in srgb, var(--color-success, #22c55e) 12%, transparent);
color: var(--color-success, #16a34a); color: var(--color-success, #16a34a);
font-size: 13px; font-size: 13px;
@@ -196,7 +196,7 @@ const { t } = useI18n();
flex-direction: column; flex-direction: column;
background: var(--color-background); background: var(--color-background);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: var(--dbx-radius-fixed-6);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
} }
@@ -353,7 +353,7 @@ defineExpose({
align-items: center; align-items: center;
min-height: 34px; min-height: 34px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
transition: transition:
border-color 0.15s ease, border-color 0.15s ease,
@@ -450,7 +450,7 @@ defineExpose({
max-height: 240px; max-height: 240px;
overflow: auto; overflow: auto;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
} }
@@ -33,7 +33,7 @@
min-width: 180px; min-width: 180px;
padding: 6px 10px; padding: 6px 10px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
font-size: 13px; font-size: 13px;
@@ -56,7 +56,7 @@
.mq-btn-sm { .mq-btn-sm {
padding: 6px 12px; padding: 6px 12px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text); color: var(--color-text);
cursor: pointer; cursor: pointer;
@@ -161,7 +161,7 @@
width: 32px; width: 32px;
height: 32px; height: 32px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--color-background); background: var(--color-background);
color: var(--color-text-secondary); color: var(--color-text-secondary);
cursor: pointer; cursor: pointer;
@@ -235,7 +235,7 @@ function adjustSubPosition() {
function itemButtonClass(variant?: "default" | "destructive") { function itemButtonClass(variant?: "default" | "destructive") {
return [ return [
"w-full gap-2 rounded-sm px-2 py-1 text-[13px] leading-4 outline-hidden select-none text-left cursor-default flex items-center disabled:pointer-events-none disabled:opacity-50", "w-full gap-2 rounded-md px-2 py-1 text-[13px] leading-4 outline-hidden select-none text-left cursor-default flex items-center disabled:pointer-events-none disabled:opacity-50",
variant === "destructive" ? "text-destructive hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive" : "hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground", variant === "destructive" ? "text-destructive hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive" : "hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground",
]; ];
} }
@@ -262,7 +262,7 @@ onBeforeUnmount(() => {
<slot :onContextMenu="onContextMenu" /> <slot :onContextMenu="onContextMenu" />
<!-- Main menu --> <!-- Main menu -->
<Teleport to="body"> <Teleport to="body">
<div v-if="show" ref="menuRef" :style="{ position: 'fixed', left: x + 'px', top: y + 'px', zIndex: 9999 }" class="bg-popover text-popover-foreground min-w-40 w-max max-w-[calc(100vw-16px)] rounded-[6px] p-1 overflow-y-auto ring-1 ring-foreground/10 shadow-lg"> <div v-if="show" ref="menuRef" :style="{ position: 'fixed', left: x + 'px', top: y + 'px', zIndex: 9999 }" class="bg-popover text-popover-foreground min-w-40 w-max max-w-[calc(100vw-16px)] rounded-md p-1 overflow-y-auto ring-1 ring-foreground/10 shadow-lg">
<template v-for="(item, index) in activeItems" :key="index"> <template v-for="(item, index) in activeItems" :key="index">
<template v-if="item.visible !== false"> <template v-if="item.visible !== false">
<div v-if="item.separator" class="-mx-1 my-1 flex items-center px-1"> <div v-if="item.separator" class="-mx-1 my-1 flex items-center px-1">
@@ -288,7 +288,7 @@ onBeforeUnmount(() => {
v-if="show && activeSubIndex !== null && activeItems[activeSubIndex]?.children?.length" v-if="show && activeSubIndex !== null && activeItems[activeSubIndex]?.children?.length"
ref="subRef" ref="subRef"
:style="{ position: 'fixed', left: subX + 'px', top: subY + 'px', zIndex: 10000, maxHeight: 'min(420px, calc(100vh - 16px))' }" :style="{ position: 'fixed', left: subX + 'px', top: subY + 'px', zIndex: 10000, maxHeight: 'min(420px, calc(100vh - 16px))' }"
class="bg-popover text-popover-foreground min-w-56 w-max max-w-[calc(100vw-16px)] rounded-[6px] p-1 overflow-y-auto ring-1 ring-foreground/10 shadow-lg" class="bg-popover text-popover-foreground min-w-56 w-max max-w-[calc(100vw-16px)] rounded-md p-1 overflow-y-auto ring-1 ring-foreground/10 shadow-lg"
@mouseenter="onSubMouseEnter" @mouseenter="onSubMouseEnter"
@mouseleave="onSubMouseLeave" @mouseleave="onSubMouseLeave"
> >
@@ -43,7 +43,7 @@ const props = withDefaults(
{ {
ariaLabel: undefined, ariaLabel: undefined,
contentClass: "", contentClass: "",
triggerClass: "flex items-center gap-1 rounded-[6px] border px-2 py-0.5 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground", triggerClass: "flex items-center gap-1 rounded-md border px-2 py-0.5 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground",
triggerTitle: undefined, triggerTitle: undefined,
triggerIcon: undefined, triggerIcon: undefined,
triggerLabel: undefined, triggerLabel: undefined,
@@ -169,7 +169,7 @@ onBeforeUnmount(close);
<ChevronDown v-if="showChevron" class="h-3 w-3 opacity-50" /> <ChevronDown v-if="showChevron" class="h-3 w-3 opacity-50" />
</button> </button>
<Teleport to="body"> <Teleport to="body">
<div v-if="open" ref="menuRef" class="fixed z-50 min-w-32 rounded-[6px] p-1 cn-menu-translucent text-popover-foreground" :class="contentClass" :style="menuStyle" role="menu"> <div v-if="open" ref="menuRef" class="fixed z-50 min-w-32 rounded-md p-1 cn-menu-translucent text-popover-foreground" :class="contentClass" :style="menuStyle" role="menu">
<div v-if="label" :class="labelClass">{{ label }}</div> <div v-if="label" :class="labelClass">{{ label }}</div>
<div v-if="label" class="bg-border -mx-1 my-1 h-px" /> <div v-if="label" class="bg-border -mx-1 my-1 h-px" />
<template v-for="item in items" :key="item.value"> <template v-for="item in items" :key="item.value">
@@ -67,7 +67,7 @@ const props = withDefaults(
sideOffset: 4, sideOffset: 4,
matchTriggerWidth: true, matchTriggerWidth: true,
closeOnSelect: true, closeOnSelect: true,
triggerClass: "flex h-6 items-center gap-1 rounded-[6px] border border-border bg-background px-2 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50 aria-expanded:bg-muted aria-expanded:text-foreground", triggerClass: "flex h-6 items-center gap-1 rounded-md border border-border bg-background px-2 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50 aria-expanded:bg-muted aria-expanded:text-foreground",
triggerIconClass: "h-3 w-3", triggerIconClass: "h-3 w-3",
contentClass: "", contentClass: "",
labelClass: "", labelClass: "",
@@ -260,7 +260,7 @@ watch(
<div <div
v-if="isOpen" v-if="isOpen"
ref="menuRef" ref="menuRef"
class="ring-foreground/10 fixed z-50 max-h-(--reka-dropdown-menu-content-available-height) min-w-32 overflow-x-hidden overflow-y-auto rounded-[6px] p-1 ring-1 cn-menu-translucent text-popover-foreground" class="ring-foreground/10 fixed z-50 max-h-(--reka-dropdown-menu-content-available-height) min-w-32 overflow-x-hidden overflow-y-auto rounded-md p-1 ring-1 cn-menu-translucent text-popover-foreground"
:class="cn(matchTriggerWidth ? 'w-(--reka-dropdown-menu-trigger-width)' : '', contentClass)" :class="cn(matchTriggerWidth ? 'w-(--reka-dropdown-menu-trigger-width)' : '', contentClass)"
:style="menuStyle" :style="menuStyle"
role="menu" role="menu"
@@ -4,7 +4,7 @@ import { cva } from "class-variance-authority";
export { default as Button } from "./Button.vue"; export { default as Button } from "./Button.vue";
export const buttonVariants = cva( export const buttonVariants = cva(
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-[6px] border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 active:not-aria-[haspopup]:translate-y-px [&_svg:not([class*=size-])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-colors outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 active:not-aria-[haspopup]:translate-y-px [&_svg:not([class*=size-])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-colors outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
{ {
variants: { variants: {
variant: { variant: {
@@ -17,12 +17,12 @@ export const buttonVariants = cva(
}, },
size: { size: {
default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
xs: "h-6 gap-1 rounded-[6px] px-2 text-xs in-data-[slot=button-group]:rounded-[6px] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*=size-])]:size-3", xs: "h-6 gap-1 rounded-md px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*=size-])]:size-3",
sm: "h-7 gap-1 rounded-[6px] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-[6px] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*=size-])]:size-3.5", sm: "h-7 gap-1 rounded-md px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*=size-])]:size-3.5",
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
icon: "size-8", icon: "size-8",
"icon-xs": "size-6 rounded-[6px] in-data-[slot=button-group]:rounded-[6px] [&_svg:not([class*=size-])]:size-3", "icon-xs": "size-6 rounded-md in-data-[slot=button-group]:rounded-md [&_svg:not([class*=size-])]:size-3",
"icon-sm": "size-7 rounded-[6px] in-data-[slot=button-group]:rounded-[6px]", "icon-sm": "size-7 rounded-md in-data-[slot=button-group]:rounded-md",
"icon-lg": "size-9", "icon-lg": "size-9",
}, },
}, },
@@ -31,7 +31,7 @@ function guardRepeatedClick(event: MouseEvent) {
@click.capture="guardRepeatedClick" @click.capture="guardRepeatedClick"
:class=" :class="
cn( cn(
'focus:bg-accent focus:text-accent-foreground gap-1.5 rounded-sm py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0', 'focus:bg-accent focus:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
props.class, props.class,
) )
" "
@@ -24,7 +24,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...$attrs, ...forwarded }" v-bind="{ ...$attrs, ...forwarded }"
:class=" :class="
cn( cn(
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 text-popover-foreground min-w-36 rounded-[6px] p-1 duration-100 cn-menu-translucent z-50 max-h-(--reka-context-menu-content-available-height) origin-(--reka-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto', 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 text-popover-foreground min-w-36 rounded-md p-1 duration-100 cn-menu-translucent z-50 max-h-(--reka-context-menu-content-available-height) origin-(--reka-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto',
props.class, props.class,
) )
" "
@@ -42,7 +42,7 @@ function guardRepeatedClick(event: MouseEvent) {
@click.capture="guardRepeatedClick" @click.capture="guardRepeatedClick"
:class=" :class="
cn( cn(
'focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive focus:*:[svg]:text-accent-foreground gap-2 rounded-sm px-2 py-1 text-[13px] data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0', 'focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive focus:*:[svg]:text-accent-foreground gap-2 rounded-md px-2 py-1 text-[13px] data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
props.class, props.class,
) )
" "
@@ -31,7 +31,7 @@ function guardRepeatedClick(event: MouseEvent) {
@click.capture="guardRepeatedClick" @click.capture="guardRepeatedClick"
:class=" :class="
cn( cn(
'focus:bg-accent focus:text-accent-foreground gap-1.5 rounded-sm py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0', 'focus:bg-accent focus:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
props.class, props.class,
) )
" "
@@ -20,7 +20,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( cn(
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 text-popover-foreground min-w-32 rounded-[6px] ring-foreground/10 ring-1 p-1 duration-100 cn-menu-translucent z-50 origin-(--reka-context-menu-content-transform-origin) overflow-hidden', 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 text-popover-foreground min-w-32 rounded-md ring-foreground/10 ring-1 p-1 duration-100 cn-menu-translucent z-50 origin-(--reka-context-menu-content-transform-origin) overflow-hidden',
props.class, props.class,
) )
" "
@@ -21,7 +21,7 @@ const forwardedProps = useForwardProps(delegatedProps);
v-bind="forwardedProps" v-bind="forwardedProps"
:class=" :class="
cn( cn(
'focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground gap-2 rounded-sm px-2 py-1 text-[13px] data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 flex cursor-default items-center outline-hidden select-none [&_svg]:pointer-events-none [&_svg]:shrink-0', 'focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground gap-2 rounded-md px-2 py-1 text-[13px] data-inset:pl-7 [&_svg:not([class*=size-])]:size-4 flex cursor-default items-center outline-hidden select-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
props.class, props.class,
) )
" "
@@ -42,7 +42,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...$attrs, ...forwarded }" v-bind="{ ...$attrs, ...forwarded }"
:class=" :class="
cn( cn(
'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 relative grid max-h-[calc(var(--dbx-viewport-height)-2rem)] w-full max-w-sm gap-4 overflow-hidden rounded-xl border border-border p-4 text-sm shadow-lg duration-100 outline-none pointer-events-auto', 'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 relative grid max-h-[calc(var(--dbx-viewport-height)-2rem)] w-full max-w-sm gap-4 overflow-hidden rounded-lg border border-border p-4 text-sm shadow-lg duration-100 outline-none pointer-events-auto',
props.class, props.class,
) )
" "
@@ -26,7 +26,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
<div class="fixed inset-0 z-50 grid place-items-center p-4 pointer-events-none"> <div class="fixed inset-0 z-50 grid place-items-center p-4 pointer-events-none">
<DialogContent <DialogContent
data-slot="dialog-content" data-slot="dialog-content"
:class="cn('relative z-50 grid max-h-[calc(var(--dbx-viewport-height)-6rem)] w-full max-w-lg my-8 gap-4 border border-border bg-background p-4 shadow-lg duration-200 sm:rounded-lg md:w-full pointer-events-auto', props.class)" :class="cn('relative z-50 grid max-h-[calc(var(--dbx-viewport-height)-6rem)] w-full max-w-lg my-8 gap-4 rounded-lg border border-border bg-background p-4 shadow-lg duration-200 md:w-full pointer-events-auto', props.class)"
v-bind="{ ...$attrs, ...forwarded }" v-bind="{ ...$attrs, ...forwarded }"
@pointer-down-outside=" @pointer-down-outside="
(event) => { (event) => {
@@ -44,7 +44,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
<slot /> <slot />
<DialogClose class="absolute top-4 right-4 p-0.5 transition-colors rounded-md hover:bg-secondary"> <DialogClose class="absolute top-4 right-4 rounded-md p-0.5 transition-colors hover:bg-secondary">
<XIcon class="w-4 h-4" /> <XIcon class="w-4 h-4" />
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
</DialogClose> </DialogClose>
@@ -27,7 +27,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...$attrs, ...forwarded }" v-bind="{ ...$attrs, ...forwarded }"
:class=" :class="
cn( cn(
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 text-popover-foreground min-w-32 rounded-[6px] p-1 ring-1 duration-100 cn-menu-translucent z-50 max-h-(--reka-dropdown-menu-content-available-height) w-(--reka-dropdown-menu-trigger-width) origin-(--reka-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto data-[state=closed]:overflow-hidden', 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 text-popover-foreground min-w-32 rounded-md p-1 ring-1 duration-100 cn-menu-translucent z-50 max-h-(--reka-dropdown-menu-content-available-height) w-(--reka-dropdown-menu-trigger-width) origin-(--reka-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto data-[state=closed]:overflow-hidden',
props.class, props.class,
) )
" "
@@ -19,7 +19,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( cn(
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 text-popover-foreground min-w-[96px] rounded-[6px] p-1 ring-1 duration-100 cn-menu-translucent z-50 origin-(--reka-dropdown-menu-content-transform-origin) overflow-hidden', 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 text-popover-foreground min-w-[96px] rounded-md p-1 ring-1 duration-100 cn-menu-translucent z-50 origin-(--reka-dropdown-menu-content-transform-origin) overflow-hidden',
props.class, props.class,
) )
" "
@@ -29,7 +29,7 @@ const modelValue = useVModel(props, "modelValue", emits, {
data-slot="input" data-slot="input"
:class=" :class="
cn( cn(
'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-[6px] border bg-transparent px-2.5 py-1 text-base transition-colors file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50', 'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-md border bg-transparent px-2.5 py-1 text-base transition-colors file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
props.class, props.class,
) )
" "
@@ -6,7 +6,7 @@ describe("OptionHelpPanel layout", () => {
expect(OPTION_HELP_PANEL_CLASS).toContain("self-start"); expect(OPTION_HELP_PANEL_CLASS).toContain("self-start");
expect(OPTION_HELP_PANEL_CLASS).toContain("max-h-64"); expect(OPTION_HELP_PANEL_CLASS).toContain("max-h-64");
expect(OPTION_HELP_PANEL_CLASS).toContain("overflow-y-auto"); expect(OPTION_HELP_PANEL_CLASS).toContain("overflow-y-auto");
expect(OPTION_HELP_PANEL_CLASS).toContain("rounded-md"); expect(OPTION_HELP_PANEL_CLASS).toContain("rounded-lg");
expect(OPTION_HELP_PANEL_CLASS).toContain("shadow-md"); expect(OPTION_HELP_PANEL_CLASS).toContain("shadow-md");
expect(OPTION_HELP_PANEL_CLASS).toContain("sm:mt-[var(--option-help-offset)]"); expect(OPTION_HELP_PANEL_CLASS).toContain("sm:mt-[var(--option-help-offset)]");
}); });
@@ -1 +1 @@
export const OPTION_HELP_PANEL_CLASS = "w-full shrink-0 self-start max-h-64 overflow-y-auto rounded-md border bg-popover px-3 py-2 text-xs leading-relaxed text-muted-foreground shadow-md sm:mt-[var(--option-help-offset)] sm:w-[min(26rem,calc(100vw-5rem))]"; export const OPTION_HELP_PANEL_CLASS = "w-full shrink-0 self-start max-h-64 overflow-y-auto rounded-lg border bg-popover px-3 py-2 text-xs leading-relaxed text-muted-foreground shadow-md sm:mt-[var(--option-help-offset)] sm:w-[min(26rem,calc(100vw-5rem))]";
@@ -27,7 +27,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...$attrs, ...forwarded }" v-bind="{ ...$attrs, ...forwarded }"
:class=" :class="
cn( cn(
'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-2.5 rounded-[6px] p-2.5 text-sm shadow-md ring-1 duration-100 z-50 w-72 origin-(--reka-popover-content-transform-origin) outline-hidden', 'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-2.5 rounded-md p-2.5 text-sm shadow-md ring-1 duration-100 z-50 w-72 origin-(--reka-popover-content-transform-origin) outline-hidden',
props.class, props.class,
) )
" "
@@ -244,7 +244,7 @@ function handleKeydown(event: KeyboardEvent) {
<PopoverContent :align="SEARCHABLE_SELECT_HELP_PANEL_ALIGN" :class="cn('w-auto max-w-[calc(100vw-1rem)] border-0 bg-transparent p-0 shadow-none ring-0', contentClass)"> <PopoverContent :align="SEARCHABLE_SELECT_HELP_PANEL_ALIGN" :class="cn('w-auto max-w-[calc(100vw-1rem)] border-0 bg-transparent p-0 shadow-none ring-0', contentClass)">
<div class="flex min-w-0 flex-col gap-2 sm:flex-row sm:items-start"> <div class="flex min-w-0 flex-col gap-2 sm:flex-row sm:items-start">
<div ref="listCard" :class="cn('shrink-0 rounded-md border bg-popover p-1.5 shadow-md', listClass)"> <div ref="listCard" :class="cn('shrink-0 rounded-md border bg-popover p-1.5 shadow-md', listClass)">
<div class="relative rounded-sm border bg-background"> <div class="relative rounded-md border bg-background">
<Search class="pointer-events-none absolute left-2 top-1/2 h-3 w-3 -translate-y-1/2 text-muted-foreground" /> <Search class="pointer-events-none absolute left-2 top-1/2 h-3 w-3 -translate-y-1/2 text-muted-foreground" />
<span v-if="!searchText" class="pointer-events-none absolute left-[25px] top-1/2 -translate-y-1/2 text-sm text-muted-foreground">{{ searchPlaceholder }}</span> <span v-if="!searchText" class="pointer-events-none absolute left-[25px] top-1/2 -translate-y-1/2 text-sm text-muted-foreground">{{ searchPlaceholder }}</span>
<Input ref="searchInput" :model-value="searchText" class="h-6 border-0 pl-6 pr-2 text-sm caret-foreground shadow-none focus-visible:ring-0" @update:model-value="(value) => (searchText = String(value))" @keydown="handleKeydown" /> <Input ref="searchInput" :model-value="searchText" class="h-6 border-0 pl-6 pr-2 text-sm caret-foreground shadow-none focus-visible:ring-0" @update:model-value="(value) => (searchText = String(value))" @keydown="handleKeydown" />
@@ -261,7 +261,7 @@ function handleKeydown(event: KeyboardEvent) {
:title="optionTooltip(option) ? undefined : optionTitle(option)" :title="optionTooltip(option) ? undefined : optionTitle(option)"
:class=" :class="
cn( cn(
'group flex h-8 w-full min-w-0 items-center gap-2 rounded-sm px-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none', 'group flex h-8 w-full min-w-0 items-center gap-2 rounded-md px-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none',
props.itemClass, props.itemClass,
index === highlightIndex && 'bg-accent text-accent-foreground', index === highlightIndex && 'bg-accent text-accent-foreground',
) )
@@ -286,7 +286,7 @@ function handleKeydown(event: KeyboardEvent) {
:title="customOptionValue" :title="customOptionValue"
:class=" :class="
cn( cn(
'flex h-8 w-full min-w-0 items-center gap-2 rounded-sm px-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none', 'flex h-8 w-full min-w-0 items-center gap-2 rounded-md px-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none',
props.itemClass, props.itemClass,
filteredOptions.length === highlightIndex && 'bg-accent text-accent-foreground', filteredOptions.length === highlightIndex && 'bg-accent text-accent-foreground',
) )
@@ -308,7 +308,7 @@ function handleKeydown(event: KeyboardEvent) {
:title="customOptionValue" :title="customOptionValue"
:class=" :class="
cn( cn(
'flex h-8 w-full min-w-0 items-center gap-2 rounded-sm px-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none', 'flex h-8 w-full min-w-0 items-center gap-2 rounded-md px-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none',
props.itemClass, props.itemClass,
0 === highlightIndex && 'bg-accent text-accent-foreground', 0 === highlightIndex && 'bg-accent text-accent-foreground',
) )
@@ -41,7 +41,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...$attrs, ...forwarded }" v-bind="{ ...$attrs, ...forwarded }"
:class=" :class="
cn( cn(
'text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-36 rounded-[6px] ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 cn-menu-translucent relative z-50 max-h-(--reka-select-content-available-height) origin-(--reka-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none', 'text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-36 rounded-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 cn-menu-translucent relative z-50 max-h-(--reka-select-content-available-height) origin-(--reka-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none',
position === 'popper' && 'w-fit min-w-[var(--reka-select-trigger-width)] data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', position === 'popper' && 'w-fit min-w-[var(--reka-select-trigger-width)] data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
props.class, props.class,
) )
@@ -20,7 +20,7 @@ const forwardedProps = useForwardProps(delegatedProps);
v-bind="forwardedProps" v-bind="forwardedProps"
:class=" :class="
cn( cn(
'dbx-select-trigger border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-[6px] border bg-transparent py-2 pr-2 pl-2.5 text-sm transition-colors select-none focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*=size-])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0', 'dbx-select-trigger border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-md border bg-transparent py-2 pr-2 pl-2.5 text-sm transition-colors select-none focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*=size-])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0',
props.class, props.class,
) )
" "
+1 -1
View File
@@ -6,7 +6,7 @@ export { default as TabsContent } from "./TabsContent.vue";
export { default as TabsList } from "./TabsList.vue"; export { default as TabsList } from "./TabsList.vue";
export { default as TabsTrigger } from "./TabsTrigger.vue"; export { default as TabsTrigger } from "./TabsTrigger.vue";
export const tabsListVariants = cva("rounded-[6px] p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list inline-flex w-fit select-none items-center justify-center text-muted-foreground group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col", { export const tabsListVariants = cva("rounded-md p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list inline-flex w-fit select-none items-center justify-center text-muted-foreground group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col", {
variants: { variants: {
variant: { variant: {
default: "bg-muted", default: "bg-muted",
+1 -1
View File
@@ -44,7 +44,7 @@ function createGhost(sourceEl: HTMLElement, x: number, y: number) {
z-index: 9999; z-index: 9999;
opacity: 0.9; opacity: 0.9;
box-shadow: 0 2px 8px rgba(0,0,0,0.12); box-shadow: 0 2px 8px rgba(0,0,0,0.12);
border-radius: 4px; border-radius: var(--dbx-radius-fixed-4);
background: var(--background, #fff); background: var(--background, #fff);
border: 1px solid var(--border, #e5e7eb); border: 1px solid var(--border, #e5e7eb);
max-width: 200px; max-width: 200px;
+1 -1
View File
@@ -43,7 +43,7 @@ function createGhost(sourceEl: HTMLElement, x: number, y: number) {
z-index: 9999; z-index: 9999;
opacity: 0.9; opacity: 0.9;
box-shadow: 0 2px 8px rgba(0,0,0,0.15); box-shadow: 0 2px 8px rgba(0,0,0,0.15);
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
background: var(--background, #fff); background: var(--background, #fff);
border: 1px solid var(--border, #e5e7eb); border: 1px solid var(--border, #e5e7eb);
max-width: 200px; max-width: 200px;
+14 -1
View File
@@ -1,5 +1,6 @@
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import { import {
APP_CORNER_STYLE_STORAGE_KEY,
APP_THEME_PALETTE_CLASS_NAMES, APP_THEME_PALETTE_CLASS_NAMES,
APP_THEME_PALETTE_STORAGE_KEY, APP_THEME_PALETTE_STORAGE_KEY,
APP_THEME_STORAGE_KEY, APP_THEME_STORAGE_KEY,
@@ -7,10 +8,12 @@ import {
getTauriThemeForMode, getTauriThemeForMode,
isSystemAppThemeMode, isSystemAppThemeMode,
normalizeAppThemeMode, normalizeAppThemeMode,
normalizeAppCornerStyle,
normalizeAppThemePalette, normalizeAppThemePalette,
resolveAppThemeAppearance, resolveAppThemeAppearance,
type AppThemeMode, type AppThemeMode,
type AppThemePalette, type AppThemePalette,
type AppCornerStyle,
} from "@/lib/app/appTheme"; } from "@/lib/app/appTheme";
import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/backend/safeStorage"; import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/backend/safeStorage";
import { isTauriRuntime } from "@/lib/backend/tauriRuntime"; import { isTauriRuntime } from "@/lib/backend/tauriRuntime";
@@ -19,7 +22,10 @@ const savedThemeMode = safeLocalStorageGet(APP_THEME_STORAGE_KEY);
const themeMode = ref<AppThemeMode>(normalizeAppThemeMode(savedThemeMode)); const themeMode = ref<AppThemeMode>(normalizeAppThemeMode(savedThemeMode));
const savedThemePalette = safeLocalStorageGet(APP_THEME_PALETTE_STORAGE_KEY); const savedThemePalette = safeLocalStorageGet(APP_THEME_PALETTE_STORAGE_KEY);
const themePalette = ref<AppThemePalette>(normalizeAppThemePalette(savedThemePalette)); const themePalette = ref<AppThemePalette>(normalizeAppThemePalette(savedThemePalette));
const savedCornerStyle = safeLocalStorageGet(APP_CORNER_STYLE_STORAGE_KEY);
const cornerStyle = ref<AppCornerStyle>(normalizeAppCornerStyle(savedCornerStyle));
if (savedThemeMode && savedThemeMode !== themeMode.value) safeLocalStorageSet(APP_THEME_STORAGE_KEY, themeMode.value); if (savedThemeMode && savedThemeMode !== themeMode.value) safeLocalStorageSet(APP_THEME_STORAGE_KEY, themeMode.value);
if (savedCornerStyle && savedCornerStyle !== cornerStyle.value) safeLocalStorageSet(APP_CORNER_STYLE_STORAGE_KEY, cornerStyle.value);
const systemPrefersDark = ref(readSystemPrefersDark()); const systemPrefersDark = ref(readSystemPrefersDark());
const isDark = computed(() => resolveAppThemeAppearance(themeMode.value, systemPrefersDark.value) === "dark"); const isDark = computed(() => resolveAppThemeAppearance(themeMode.value, systemPrefersDark.value) === "dark");
@@ -55,6 +61,7 @@ function applyTheme() {
for (const className of APP_THEME_PALETTE_CLASS_NAMES) doc.classList.remove(className); for (const className of APP_THEME_PALETTE_CLASS_NAMES) doc.classList.remove(className);
const paletteClass = getAppThemePaletteClass(themePalette.value); const paletteClass = getAppThemePaletteClass(themePalette.value);
if (paletteClass) doc.classList.add(paletteClass); if (paletteClass) doc.classList.add(paletteClass);
doc.dataset.cornerStyle = cornerStyle.value;
doc.style.colorScheme = dark ? "dark" : "light"; doc.style.colorScheme = dark ? "dark" : "light";
// force reflow so the class toggle takes effect before re-enabling transitions // force reflow so the class toggle takes effect before re-enabling transitions
@@ -90,6 +97,12 @@ function setThemePalette(palette: AppThemePalette) {
applyTheme(); applyTheme();
} }
function setCornerStyle(style: AppCornerStyle) {
cornerStyle.value = normalizeAppCornerStyle(style);
safeLocalStorageSet(APP_CORNER_STYLE_STORAGE_KEY, cornerStyle.value);
applyTheme();
}
export function useTheme() { export function useTheme() {
setupSystemThemeListener(); setupSystemThemeListener();
@@ -97,5 +110,5 @@ export function useTheme() {
setThemeMode(isDark.value ? "light" : "dark"); setThemeMode(isDark.value ? "light" : "dark");
} }
return { isDark, themeMode, themePalette, applyTheme, setThemeMode, setThemePalette, toggleTheme }; return { isDark, themeMode, themePalette, cornerStyle, applyTheme, setThemeMode, setThemePalette, setCornerStyle, toggleTheme };
} }
+4
View File
@@ -3721,6 +3721,10 @@ export default {
uiScale: "UI Scale", uiScale: "UI Scale",
uiScaleDescription: "Scale the entire desktop UI for high-DPI displays. Changes apply immediately and are restored on next launch.", uiScaleDescription: "Scale the entire desktop UI for high-DPI displays. Changes apply immediately and are restored on next launch.",
theme: "Theme", theme: "Theme",
cornerStyle: "Corner style",
cornerStyleNone: "Square",
cornerStyleSmall: "Small",
cornerStyleLarge: "Large",
selectTheme: "Select theme...", selectTheme: "Select theme...",
colorTheme: "Color Theme", colorTheme: "Color Theme",
selectColorTheme: "Select color theme...", selectColorTheme: "Select color theme...",
+4
View File
@@ -3499,6 +3499,10 @@ export default withEnglishFallback({
uiScale: "Escala de interfaz", uiScale: "Escala de interfaz",
uiScaleDescription: "Escala toda la interfaz de escritorio para pantallas de alta densidad. Los cambios se aplican al instante y se restauran al volver a abrir.", uiScaleDescription: "Escala toda la interfaz de escritorio para pantallas de alta densidad. Los cambios se aplican al instante y se restauran al volver a abrir.",
theme: "Tema", theme: "Tema",
cornerStyle: "Estilo de esquinas",
cornerStyleNone: "Sin redondeo",
cornerStyleSmall: "Pequeñas",
cornerStyleLarge: "Grandes",
selectTheme: "Seleccionar tema...", selectTheme: "Seleccionar tema...",
colorTheme: "Tema de color", colorTheme: "Tema de color",
selectColorTheme: "Seleccionar tema de color...", selectColorTheme: "Seleccionar tema de color...",
+4
View File
@@ -3497,6 +3497,10 @@ export default withEnglishFallback({
uiScale: "Scala UI", uiScale: "Scala UI",
uiScaleDescription: "Scala l'intera interfaccia utente desktop per display ad alta densità (High-DPI). Le modifiche si applicano immediatamente e vengono ripristinate al prossimo avvio.", uiScaleDescription: "Scala l'intera interfaccia utente desktop per display ad alta densità (High-DPI). Le modifiche si applicano immediatamente e vengono ripristinate al prossimo avvio.",
theme: "Tema", theme: "Tema",
cornerStyle: "Stile degli angoli",
cornerStyleNone: "Senza arrotondamento",
cornerStyleSmall: "Piccoli",
cornerStyleLarge: "Grandi",
selectTheme: "Seleziona tema...", selectTheme: "Seleziona tema...",
colorTheme: "Tema colore", colorTheme: "Tema colore",
selectColorTheme: "Seleziona tema colore...", selectColorTheme: "Seleziona tema colore...",
+4
View File
@@ -3498,6 +3498,10 @@ export default withEnglishFallback({
uiScale: "UIスケール", uiScale: "UIスケール",
uiScaleDescription: "高DPIディスプレイ向けにデスクトップUI全体をスケーリングします。変更は即座に適用され、次回起動時に復元されます。", uiScaleDescription: "高DPIディスプレイ向けにデスクトップUI全体をスケーリングします。変更は即座に適用され、次回起動時に復元されます。",
theme: "テーマ", theme: "テーマ",
cornerStyle: "角の丸み",
cornerStyleNone: "なし",
cornerStyleSmall: "小",
cornerStyleLarge: "大",
selectTheme: "テーマを選択...", selectTheme: "テーマを選択...",
colorTheme: "配色テーマ", colorTheme: "配色テーマ",
selectColorTheme: "配色テーマを選択...", selectColorTheme: "配色テーマを選択...",
+4
View File
@@ -3499,6 +3499,10 @@ export default withEnglishFallback({
uiScale: "Escala da UI", uiScale: "Escala da UI",
uiScaleDescription: "Dimensione toda a UI do desktop para telas de alta resolução (high-DPI). As alterações são aplicadas imediatamente e restauradas na próxima inicialização.", uiScaleDescription: "Dimensione toda a UI do desktop para telas de alta resolução (high-DPI). As alterações são aplicadas imediatamente e restauradas na próxima inicialização.",
theme: "Tema", theme: "Tema",
cornerStyle: "Estilo dos cantos",
cornerStyleNone: "Sem arredondamento",
cornerStyleSmall: "Pequenos",
cornerStyleLarge: "Grandes",
selectTheme: "Selecionar tema...", selectTheme: "Selecionar tema...",
colorTheme: "Tema de cores", colorTheme: "Tema de cores",
selectColorTheme: "Selecionar tema de cores...", selectColorTheme: "Selecionar tema de cores...",
+4
View File
@@ -3711,6 +3711,10 @@ export default withEnglishFallback({
uiScale: "界面缩放", uiScale: "界面缩放",
uiScaleDescription: "按比例缩放整个桌面端界面,适合高清屏;修改后立即生效,并在下次启动时恢复。", uiScaleDescription: "按比例缩放整个桌面端界面,适合高清屏;修改后立即生效,并在下次启动时恢复。",
theme: "主题", theme: "主题",
cornerStyle: "圆角样式",
cornerStyleNone: "无圆角",
cornerStyleSmall: "小圆角",
cornerStyleLarge: "大圆角",
selectTheme: "选择主题...", selectTheme: "选择主题...",
colorTheme: "配色主题", colorTheme: "配色主题",
selectColorTheme: "选择配色主题...", selectColorTheme: "选择配色主题...",
+4
View File
@@ -3315,6 +3315,10 @@ export default withEnglishFallback({
uiScale: "介面縮放", uiScale: "介面縮放",
uiScaleDescription: "按比例縮放整個桌面端介面,適合高 DPI 螢幕;修改後立即生效,並在下次啟動時復原。", uiScaleDescription: "按比例縮放整個桌面端介面,適合高 DPI 螢幕;修改後立即生效,並在下次啟動時復原。",
theme: "主題", theme: "主題",
cornerStyle: "圓角樣式",
cornerStyleNone: "無圓角",
cornerStyleSmall: "小圓角",
cornerStyleLarge: "大圓角",
selectTheme: "選擇主題……", selectTheme: "選擇主題……",
colorTheme: "配色主題", colorTheme: "配色主題",
selectColorTheme: "選擇配色主題……", selectColorTheme: "選擇配色主題……",
+15
View File
@@ -0,0 +1,15 @@
import { describe, expect, it } from "vitest";
import { normalizeAppCornerStyle } from "@/lib/app/appTheme";
describe("app corner style", () => {
it.each([
[null, "small"],
["", "small"],
["invalid", "small"],
["none", "none"],
["small", "small"],
["large", "large"],
])("normalizes %s to %s", (value, expected) => {
expect(normalizeAppCornerStyle(value)).toBe(expected);
});
});
+18 -5
View File
@@ -9,17 +9,18 @@ if (!startupScript) throw new Error("Startup theme script not found");
type StartupThemeOptions = { type StartupThemeOptions = {
mode?: string | null; mode?: string | null;
cornerStyle?: string | null;
prefersDark?: boolean; prefersDark?: boolean;
storageError?: boolean; storageError?: boolean;
}; };
function runStartupTheme({ mode = null, prefersDark = false, storageError = false }: StartupThemeOptions = {}) { function runStartupTheme({ mode = null, cornerStyle = null, prefersDark = false, storageError = false }: StartupThemeOptions = {}) {
const toggle = vi.fn(); const toggle = vi.fn();
const root = { classList: { toggle }, style: { colorScheme: "" } }; const root = { classList: { toggle }, dataset: { cornerStyle: "" }, style: { colorScheme: "" } };
const localStorage = { const localStorage = {
getItem: vi.fn(() => { getItem: vi.fn((key: string) => {
if (storageError) throw new DOMException("Storage unavailable", "SecurityError"); if (storageError) throw new DOMException("Storage unavailable", "SecurityError");
return mode; return key === "dbx-corner-style" ? cornerStyle : mode;
}), }),
}; };
const matchMedia = vi.fn(() => ({ matches: prefersDark })); const matchMedia = vi.fn(() => ({ matches: prefersDark }));
@@ -64,6 +65,18 @@ describe("startup theme", () => {
expect(root.style.colorScheme).toBe("light"); expect(root.style.colorScheme).toBe("light");
}); });
it.each([
[null, "small"],
["invalid", "small"],
["none", "none"],
["small", "small"],
["large", "large"],
])("normalizes the startup corner style %s to %s", (cornerStyle, expected) => {
const { root } = runStartupTheme({ cornerStyle });
expect(root.dataset.cornerStyle).toBe(expected);
});
it("falls back to light when localStorage is unavailable", () => { it("falls back to light when localStorage is unavailable", () => {
const { root, toggle } = runStartupTheme({ storageError: true, prefersDark: true }); const { root, toggle } = runStartupTheme({ storageError: true, prefersDark: true });
@@ -80,7 +93,7 @@ describe("startup theme", () => {
it("falls back to light when system appearance detection is unavailable", () => { it("falls back to light when system appearance detection is unavailable", () => {
const toggle = vi.fn(); const toggle = vi.fn();
const root = { classList: { toggle }, style: { colorScheme: "" } }; const root = { classList: { toggle }, dataset: { cornerStyle: "" }, style: { colorScheme: "" } };
Function("document", "localStorage", "window", startupScript)({ documentElement: root }, { getItem: () => "system" }, {}); Function("document", "localStorage", "window", startupScript)({ documentElement: root }, { getItem: () => "system" }, {});
+9 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { resolveEditorTheme } from "@/lib/editor/editorThemes"; import { buildSqlCompletionThemeRules, resolveEditorTheme } from "@/lib/editor/editorThemes";
import type { AppThemePalette } from "@/lib/app/appTheme"; import type { AppThemePalette } from "@/lib/app/appTheme";
import type { EditorTheme } from "@/stores/settingsStore"; import type { EditorTheme } from "@/stores/settingsStore";
@@ -43,3 +43,11 @@ describe("resolveEditorTheme", () => {
} }
}); });
}); });
describe("SQL completion theme", () => {
it("uses the configurable large radius for the popup container", () => {
const rules = buildSqlCompletionThemeRules();
expect(rules[".cm-tooltip.cm-tooltip-autocomplete"]).toMatchObject({ borderRadius: "var(--dbx-radius-lg)" });
});
});
+7
View File
@@ -2,10 +2,12 @@ import type { Theme } from "@tauri-apps/api/window";
export const APP_THEME_STORAGE_KEY = "dbx-theme"; export const APP_THEME_STORAGE_KEY = "dbx-theme";
export const APP_THEME_PALETTE_STORAGE_KEY = "dbx-theme-palette"; export const APP_THEME_PALETTE_STORAGE_KEY = "dbx-theme-palette";
export const APP_CORNER_STYLE_STORAGE_KEY = "dbx-corner-style";
export type AppThemeMode = "light" | "dark" | "system"; export type AppThemeMode = "light" | "dark" | "system";
export type AppThemeAppearance = "light" | "dark"; export type AppThemeAppearance = "light" | "dark";
export type AppThemePalette = "pearl" | "mist" | "graphite" | "cobalt" | "sage" | "amber" | "blush" | "vscode" | "idea" | "xcode" | "jetbrains" | "cursor" | "claude"; export type AppThemePalette = "pearl" | "mist" | "graphite" | "cobalt" | "sage" | "amber" | "blush" | "vscode" | "idea" | "xcode" | "jetbrains" | "cursor" | "claude";
export type AppCornerStyle = "none" | "small" | "large";
export type AppThemePaletteOption = { export type AppThemePaletteOption = {
value: AppThemePalette; value: AppThemePalette;
@@ -45,6 +47,11 @@ export function normalizeAppThemePalette(value: string | null): AppThemePalette
return "pearl"; return "pearl";
} }
export function normalizeAppCornerStyle(value: string | null): AppCornerStyle {
if (value === "none" || value === "large") return value;
return "small";
}
export function getAppThemePaletteClass(palette: AppThemePalette): string | null { export function getAppThemePaletteClass(palette: AppThemePalette): string | null {
return APP_THEME_PALETTES.find((option) => option.value === palette)?.className ?? null; return APP_THEME_PALETTES.find((option) => option.value === palette)?.className ?? null;
} }
+3 -3
View File
@@ -780,7 +780,7 @@ export function buildEditorFontThemeRules(opts?: { fixedHeight?: boolean; scroll
alignItems: "center", alignItems: "center",
background: "transparent", background: "transparent",
border: "1px solid transparent", border: "1px solid transparent",
borderRadius: "6px", borderRadius: "var(--dbx-radius-fixed-6)",
boxSizing: "border-box", boxSizing: "border-box",
color: "transparent", color: "transparent",
display: "inline-flex", display: "inline-flex",
@@ -869,7 +869,7 @@ export function buildSqlCompletionThemeRules(): CodeMirrorStyleSpec {
background: "var(--popover)", background: "var(--popover)",
backgroundClip: "padding-box", backgroundClip: "padding-box",
border: colorMixValue("1px solid var(--border)", "1px solid color-mix(in oklch, var(--border) 82%, var(--foreground) 18%)"), border: colorMixValue("1px solid var(--border)", "1px solid color-mix(in oklch, var(--border) 82%, var(--foreground) 18%)"),
borderRadius: "8px", borderRadius: "var(--dbx-radius-lg)",
boxShadow: "0 8px 18px rgb(0 0 0 / 0.14)", boxShadow: "0 8px 18px rgb(0 0 0 / 0.14)",
color: "var(--popover-foreground)", color: "var(--popover-foreground)",
fontFamily: `var(${EDITOR_FONT_FAMILY_CSS_VAR}, var(--font-mono, monospace))`, fontFamily: `var(${EDITOR_FONT_FAMILY_CSS_VAR}, var(--font-mono, monospace))`,
@@ -898,7 +898,7 @@ export function buildSqlCompletionThemeRules(): CodeMirrorStyleSpec {
}, },
".cm-tooltip.cm-tooltip-autocomplete > ul > li": { ".cm-tooltip.cm-tooltip-autocomplete > ul > li": {
alignItems: "center", alignItems: "center",
borderRadius: "6px", borderRadius: "var(--dbx-radius-fixed-6)",
color: "var(--popover-foreground)", color: "var(--popover-foreground)",
display: "flex", display: "flex",
fontSize: `clamp(12px, var(${EDITOR_FONT_SIZE_CSS_VAR}, 13px), 14px)`, fontSize: `clamp(12px, var(${EDITOR_FONT_SIZE_CSS_VAR}, 13px), 14px)`,
+2 -2
View File
@@ -21,7 +21,7 @@ function renderStartupError(error: unknown) {
const panel = document.createElement("div"); const panel = document.createElement("div");
panel.style.cssText = ["display:flex", "min-height:100vh", "align-items:center", "justify-content:center", "background:#ffffff", "color:#111827", "padding:24px", "font-family:ui-sans-serif,system-ui,sans-serif"].join(";"); panel.style.cssText = ["display:flex", "min-height:100vh", "align-items:center", "justify-content:center", "background:#ffffff", "color:#111827", "padding:24px", "font-family:ui-sans-serif,system-ui,sans-serif"].join(";");
const card = document.createElement("div"); const card = document.createElement("div");
card.style.cssText = ["max-width:760px", "width:100%", "border:1px solid #e5e7eb", "border-radius:12px", "padding:20px", "box-shadow:0 10px 30px rgba(0,0,0,0.08)", "background:#fff"].join(";"); card.style.cssText = ["max-width:760px", "width:100%", "border:1px solid #e5e7eb", "border-radius: var(--dbx-radius-fixed-6)", "padding:20px", "box-shadow:0 10px 30px rgba(0,0,0,0.08)", "background:#fff"].join(";");
const title = document.createElement("h1"); const title = document.createElement("h1");
title.textContent = "DBX startup failed"; title.textContent = "DBX startup failed";
title.style.cssText = "margin:0 0 12px;font-size:18px;font-weight:700;"; title.style.cssText = "margin:0 0 12px;font-size:18px;font-weight:700;";
@@ -30,7 +30,7 @@ function renderStartupError(error: unknown) {
text.style.cssText = "margin:0 0 12px;font-size:13px;line-height:1.5;color:#4b5563;"; text.style.cssText = "margin:0 0 12px;font-size:13px;line-height:1.5;color:#4b5563;";
const pre = document.createElement("pre"); const pre = document.createElement("pre");
pre.textContent = message; pre.textContent = message;
pre.style.cssText = ["margin:0", "white-space:pre-wrap", "word-break:break-word", "font-size:12px", "line-height:1.5", "background:#f9fafb", "border-radius:8px", "padding:12px", "overflow:auto"].join(";"); pre.style.cssText = ["margin:0", "white-space:pre-wrap", "word-break:break-word", "font-size:12px", "line-height:1.5", "background:#f9fafb", "border-radius: var(--dbx-radius-fixed-4)", "padding:12px", "overflow:auto"].join(";");
card.append(title, text, pre); card.append(title, text, pre);
panel.append(card); panel.append(card);
root.append(panel); root.append(panel);
@@ -40,4 +40,10 @@ describe("legacy WebView CSS fallbacks", () => {
expect(dialogScrollContentSource).toContain("max-h-[calc(var(--dbx-viewport-height)-6rem)]"); expect(dialogScrollContentSource).toContain("max-h-[calc(var(--dbx-viewport-height)-6rem)]");
expect(connectionDialogSource).toContain("max-height: calc(var(--dbx-viewport-height) - 2rem);"); expect(connectionDialogSource).toContain("max-height: calc(var(--dbx-viewport-height) - 2rem);");
}); });
it("keeps legacy tab triggers connected to the configured corner style", () => {
const tabsTriggerRule = globalsCss.match(/\[data-slot="tabs-trigger"\] \{([\s\S]*?)\n \}/)?.[1];
expect(tabsTriggerRule).toContain("border-radius: var(--dbx-radius-fixed-6);");
});
}); });
+53 -7
View File
@@ -88,10 +88,10 @@
--color-card: var(--card); --color-card: var(--card);
--color-foreground: var(--foreground); --color-foreground: var(--foreground);
--color-background: var(--background); --color-background: var(--background);
--radius-sm: calc(var(--radius) - 4px); --radius-sm: var(--dbx-radius-sm);
--radius-md: calc(var(--radius) - 2px); --radius-md: var(--dbx-radius-md);
--radius-lg: var(--radius); --radius-lg: var(--dbx-radius-lg);
--radius-xl: calc(var(--radius) + 4px); --radius-xl: var(--dbx-radius-xl);
} }
:root { :root {
@@ -119,7 +119,15 @@
--chart-3: rgb(82 82 82); --chart-3: rgb(82 82 82);
--chart-4: rgb(64 64 64); --chart-4: rgb(64 64 64);
--chart-5: rgb(38 38 38); --chart-5: rgb(38 38 38);
--radius: 0.625rem; --radius: var(--dbx-radius-md);
--dbx-radius-default: 4px;
--dbx-radius-sm: 4px;
--dbx-radius-md: 4px;
--dbx-radius-lg: 6px;
--dbx-radius-xl: 6px;
--dbx-radius-fixed-4: 4px;
--dbx-radius-fixed-5: 5px;
--dbx-radius-fixed-6: 6px;
--sidebar: rgb(250 250 250); --sidebar: rgb(250 250 250);
--sidebar-foreground: rgb(10 10 10); --sidebar-foreground: rgb(10 10 10);
--sidebar-primary: rgb(23 23 23); --sidebar-primary: rgb(23 23 23);
@@ -132,6 +140,44 @@
--dbx-viewport-height: 100vh; --dbx-viewport-height: 100vh;
} }
:root[data-corner-style="large"] {
--dbx-radius-default: 6px;
--dbx-radius-sm: 6px;
--dbx-radius-md: 6px;
--dbx-radius-lg: 10px;
--dbx-radius-xl: 14px;
--dbx-radius-fixed-4: 6px;
--dbx-radius-fixed-5: 7px;
--dbx-radius-fixed-6: 10px;
}
:root[data-corner-style="none"] {
--dbx-radius-default: 0px;
--dbx-radius-sm: 0px;
--dbx-radius-md: 0px;
--dbx-radius-lg: 0px;
--dbx-radius-xl: 0px;
--dbx-radius-fixed-4: 0px;
--dbx-radius-fixed-5: 0px;
--dbx-radius-fixed-6: 0px;
}
.rounded {
border-radius: var(--dbx-radius-default);
}
.rounded-\[4px\] {
border-radius: var(--dbx-radius-fixed-4);
}
.rounded-\[5px\] {
border-radius: var(--dbx-radius-fixed-5);
}
.rounded-\[6px\] {
border-radius: var(--dbx-radius-fixed-6);
}
@supports (height: 100dvh) { @supports (height: 100dvh) {
:root { :root {
--dbx-viewport-height: min(100vh, 100dvh); --dbx-viewport-height: min(100vh, 100dvh);
@@ -1550,7 +1596,7 @@ body.dbx-table-reference-dragging * {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: fit-content; width: fit-content;
border-radius: 6px; border-radius: var(--dbx-radius-fixed-6);
color: var(--muted-foreground); color: var(--muted-foreground);
} }
@@ -1583,7 +1629,7 @@ body.dbx-table-reference-dragging * {
padding: 0.125rem 0.375rem; padding: 0.125rem 0.375rem;
gap: 0.375rem; gap: 0.375rem;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 0.375rem; border-radius: var(--dbx-radius-fixed-6);
color: rgba(10, 10, 10, 0.6); color: rgba(10, 10, 10, 0.6);
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 500; font-weight: 500;