diff --git a/apps/desktop/src/components/common/QueryLoadingState.vue b/apps/desktop/src/components/common/QueryLoadingState.vue index a842fe66b..5f7cbf21c 100644 --- a/apps/desktop/src/components/common/QueryLoadingState.vue +++ b/apps/desktop/src/components/common/QueryLoadingState.vue @@ -36,10 +36,28 @@ const { t } = useI18n(); {{ t(labelKey) }} ยท {{ elapsedSeconds }}s - + {{ t(cancelLabelKey) }} + + diff --git a/apps/desktop/src/components/config/DriverStoreDialog.vue b/apps/desktop/src/components/config/DriverStoreDialog.vue index 56d14a5c2..17d71ddf6 100644 --- a/apps/desktop/src/components/config/DriverStoreDialog.vue +++ b/apps/desktop/src/components/config/DriverStoreDialog.vue @@ -1059,12 +1059,12 @@ watch(driverStoreTab, (tab) => { - - - - - - + + + + + + {{ t("driverStore.agentDrivers") }} @@ -1090,7 +1090,7 @@ watch(driverStoreTab, (tab) => { - + @@ -1157,7 +1157,7 @@ watch(driverStoreTab, (tab) => { {{ t("driverStore.noMatchingDrivers") }} - + {{ t("driverStore.driversUpdatable", { count: updatableCount }) }} @@ -1166,14 +1166,14 @@ watch(driverStoreTab, (tab) => { {{ upgradingAll ? t("driverStore.upgradingProgress", { current: upgradingIndex, total: upgradingTotal }) : t("driverStore.upgradeAll") }} - + - + {{ driver.label }} - + JRE {{ driver.jre }} v{{ driver.installed_version }} @@ -1184,7 +1184,7 @@ watch(driverStoreTab, (tab) => { {{ formatSize(driver.size) }} - + {{ t("driverStore.queued") }} @@ -1232,7 +1232,7 @@ watch(driverStoreTab, (tab) => { - + @@ -1311,7 +1311,7 @@ watch(driverStoreTab, (tab) => { - + {{ t("common.loading") }} @@ -1322,8 +1322,8 @@ watch(driverStoreTab, (tab) => { {{ t("driverStore.noMatchingDrivers") }} - - + + {{ item.title }} @@ -1342,7 +1342,7 @@ watch(driverStoreTab, (tab) => { - + @@ -1528,3 +1528,156 @@ watch(driverStoreTab, (tab) => { + + diff --git a/apps/desktop/src/components/connection/ConnectionDialog.vue b/apps/desktop/src/components/connection/ConnectionDialog.vue index a1067b34a..c3d944d61 100644 --- a/apps/desktop/src/components/connection/ConnectionDialog.vue +++ b/apps/desktop/src/components/connection/ConnectionDialog.vue @@ -3616,13 +3616,13 @@ function openExternalUrl(url: string) { {{ category.title }} - + diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index e1dbbaa4e..e5cc33d35 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -9419,8 +9419,8 @@ const gridContextMenuItems = computed(() => { @scroll="onTransposeScroll" > - - + + {{ t("grid.columnName") }} @@ -9432,7 +9432,7 @@ const gridContextMenuItems = computed(() => { :class="{ 'transpose-record-header-selected text-primary font-semibold': transposeRecordUsesFramedHeader(recordIndex), 'transpose-record-header-active text-primary': transposeRecordUsesActiveHighlight(recordIndex) && !transposeRecordUsesFramedHeader(recordIndex), - 'bg-[rgb(239_239_239)] dark:bg-muted': !transposeRecordUsesActiveHighlight(recordIndex) && !transposeRecordUsesFramedHeader(recordIndex), + 'data-grid-header-cell': !transposeRecordUsesActiveHighlight(recordIndex) && !transposeRecordUsesFramedHeader(recordIndex), }" :style="{ width: `${getTransposeRecordWidth(recordIndex)}px` }" @click="selectTransposeRecord(recordIndex, $event)" @@ -9577,10 +9577,10 @@ const gridContextMenuItems = computed(() => { - + @@ -9589,7 +9589,7 @@ const gridContextMenuItems = computed(() => { (() => { @reference "../../styles/globals.css"; [data-grid-root] { - --data-grid-row-muted-bg: rgb(248 248 248); - --data-grid-row-new-bg: rgb(243 243 243); - --data-grid-row-deleted-bg: rgb(255 244 244); - --data-grid-cell-active-bg: rgb(232 232 232); - --data-grid-cell-dirty-bg: rgb(255 248 230); - --data-grid-cell-selected-bg: rgb(226 226 226); - --data-grid-cell-selected-dirty-bg: rgb(244 229 186); - --data-grid-cell-selected-border: rgb(90 90 90); - --data-grid-cell-hover-bg: rgb(245 245 245); - --data-grid-cell-search-bg: rgb(253 245 184); - --data-grid-cell-current-search-bg: rgb(253 224 71 / 52%); - --data-grid-cell-current-search-border: rgb(234 179 8 / 82%); - --data-grid-row-number-default-bg: rgb(255 255 255); - --data-grid-row-number-new-bg: rgb(219 244 233); - --data-grid-row-number-edited-bg: rgb(253 241 219); - --data-grid-row-number-deleted-bg: rgb(255 244 244); - --data-grid-row-number-active-bg: rgb(232 232 232); - --data-grid-row-number-selected-bg: rgb(226 226 226); + --data-grid-row-muted-bg: rgb(248, 248, 248); + --data-grid-row-new-bg: rgb(243, 243, 243); + --data-grid-row-deleted-bg: rgb(255, 244, 244); + --data-grid-cell-active-bg: rgb(232, 232, 232); + --data-grid-cell-dirty-bg: rgb(255, 248, 230); + --data-grid-cell-selected-bg: rgb(226, 226, 226); + --data-grid-cell-selected-dirty-bg: rgb(244, 229, 186); + --data-grid-cell-selected-border: rgb(90, 90, 90); + --data-grid-cell-hover-bg: rgb(245, 245, 245); + --data-grid-cell-search-bg: rgb(253, 245, 184); + --data-grid-cell-current-search-bg: rgba(253, 224, 71, 0.52); + --data-grid-cell-current-search-border: rgba(234, 179, 8, 0.82); + --data-grid-row-number-default-bg: rgb(255, 255, 255); + --data-grid-row-number-new-bg: rgb(219, 244, 233); + --data-grid-row-number-edited-bg: rgb(253, 241, 219); + --data-grid-row-number-deleted-bg: rgb(255, 244, 244); + --data-grid-row-number-active-bg: rgb(232, 232, 232); + --data-grid-row-number-selected-bg: rgb(226, 226, 226); --data-grid-scrollbar-thumb: color-mix(in oklch, var(--foreground) 30%, transparent); --data-grid-scrollbar-thumb-hover: color-mix(in oklch, var(--foreground) 48%, transparent); --data-grid-scrollbar-track: transparent; } :global(.dark) [data-grid-root] { - --data-grid-row-muted-bg: rgb(32 32 34); - --data-grid-row-new-bg: rgb(51 51 55); - --data-grid-row-deleted-bg: rgb(55 31 32); - --data-grid-cell-active-bg: rgb(64 64 64); - --data-grid-cell-dirty-bg: rgb(94 75 26); - --data-grid-cell-selected-bg: rgb(66 67 70); - --data-grid-cell-selected-dirty-bg: rgb(94 75 26); - --data-grid-cell-selected-border: rgb(170 170 175); - --data-grid-cell-hover-bg: rgb(46 47 51); - --data-grid-cell-search-bg: rgb(72 57 8); - --data-grid-cell-current-search-bg: rgb(116 87 0); - --data-grid-cell-current-search-border: rgb(239 177 0); - --data-grid-row-number-default-bg: rgb(35 37 42); - --data-grid-row-number-new-bg: rgb(33 45 40); - --data-grid-row-number-edited-bg: rgb(48 41 28); - --data-grid-row-number-deleted-bg: rgb(55 31 32); - --data-grid-row-number-active-bg: rgb(64 64 64); - --data-grid-row-number-selected-bg: rgb(66 67 70); + --data-grid-row-muted-bg: rgb(32, 32, 34); + --data-grid-row-new-bg: rgb(51, 51, 55); + --data-grid-row-deleted-bg: rgb(55, 31, 32); + --data-grid-cell-active-bg: rgb(64, 64, 64); + --data-grid-cell-dirty-bg: rgb(94, 75, 26); + --data-grid-cell-selected-bg: rgb(66, 67, 70); + --data-grid-cell-selected-dirty-bg: rgb(94, 75, 26); + --data-grid-cell-selected-border: rgb(170, 170, 175); + --data-grid-cell-hover-bg: rgb(46, 47, 51); + --data-grid-cell-search-bg: rgb(72, 57, 8); + --data-grid-cell-current-search-bg: rgb(116, 87, 0); + --data-grid-cell-current-search-border: rgb(239, 177, 0); + --data-grid-row-number-default-bg: rgb(35, 37, 42); + --data-grid-row-number-new-bg: rgb(33, 45, 40); + --data-grid-row-number-edited-bg: rgb(48, 41, 28); + --data-grid-row-number-deleted-bg: rgb(55, 31, 32); + --data-grid-row-number-active-bg: rgb(64, 64, 64); + --data-grid-row-number-selected-bg: rgb(66, 67, 70); } @supports (background: color-mix(in oklab, white 50%, transparent)) { @@ -11249,6 +11249,50 @@ const gridContextMenuItems = computed(() => { } } +.data-grid-header-shell, +.data-grid-header-cell { + background-color: rgb(239, 239, 239); +} + +:global(.dark) [data-grid-root] .data-grid-header-shell, +:global(.dark) [data-grid-root] .data-grid-header-cell { + background-color: rgb(32, 32, 34) !important; +} + +:global(.dark) [data-grid-root] .data-grid-header-row { + color: rgb(215, 215, 219); +} + +:global(.dark) [data-grid-root] .data-grid-header-cell:hover { + background-color: rgb(46, 47, 51) !important; +} + +.data-grid-row--striped { + background-color: rgb(248, 248, 248); +} + +.data-grid-row--draft, +.data-grid-row--new { + background-color: rgb(243, 243, 243); +} + +.data-grid-row--deleted { + background-color: rgb(255, 244, 244); +} + +:global(.dark) .data-grid-row--striped { + background-color: rgb(32, 32, 34); +} + +:global(.dark) .data-grid-row--draft, +:global(.dark) .data-grid-row--new { + background-color: rgb(51, 51, 55); +} + +:global(.dark) .data-grid-row--deleted { + background-color: rgb(55, 31, 32); +} + .data-grid-topbar { --data-grid-topbar-transition-duration: 340ms; --data-grid-topbar-transition-easing: cubic-bezier(0.22, 1, 0.36, 1); diff --git a/apps/desktop/src/components/layout/WelcomeScreen.vue b/apps/desktop/src/components/layout/WelcomeScreen.vue index 030657007..281de7779 100644 --- a/apps/desktop/src/components/layout/WelcomeScreen.vue +++ b/apps/desktop/src/components/layout/WelcomeScreen.vue @@ -43,8 +43,8 @@ function welcomeConnectionSubtitle(connection: ConnectionConfig): string { - - + + {{ t("welcome.connections") }} @@ -65,7 +65,7 @@ function welcomeConnectionSubtitle(connection: ConnectionConfig): string { - + {{ t("welcome.quickConnections") }} @@ -163,3 +163,21 @@ function welcomeConnectionSubtitle(connection: ConnectionConfig): string { + + diff --git a/apps/desktop/src/components/objects/ObjectBrowser.vue b/apps/desktop/src/components/objects/ObjectBrowser.vue index ee7c94813..fa8f651e8 100644 --- a/apps/desktop/src/components/objects/ObjectBrowser.vue +++ b/apps/desktop/src/components/objects/ObjectBrowser.vue @@ -680,12 +680,12 @@ function iconClass(type: ObjectBrowserRow["type"]) { } function iconBgClass(type: ObjectBrowserRow["type"]) { - if (type === "VIEW" || type === "MATERIALIZED_VIEW") return "bg-purple-500/10"; - if (type === "PROCEDURE") return "bg-blue-500/10"; - if (type === "FUNCTION") return "bg-amber-500/10"; - if (type === "SEQUENCE") return "bg-emerald-500/10"; - if (type === "PACKAGE" || type === "PACKAGE_BODY") return "bg-cyan-500/10"; - return "bg-green-500/10"; + if (type === "VIEW" || type === "MATERIALIZED_VIEW") return "object-browser-icon-bg object-browser-icon-bg-view"; + if (type === "PROCEDURE") return "object-browser-icon-bg object-browser-icon-bg-procedure"; + if (type === "FUNCTION") return "object-browser-icon-bg object-browser-icon-bg-function"; + if (type === "SEQUENCE") return "object-browser-icon-bg object-browser-icon-bg-sequence"; + if (type === "PACKAGE" || type === "PACKAGE_BODY") return "object-browser-icon-bg object-browser-icon-bg-package"; + return "object-browser-icon-bg object-browser-icon-bg-table"; } function isPartitionParentExpanded(row: ObjectBrowserRow) { @@ -2588,8 +2588,10 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] { {{ item.displayName }} {{ typeLabel(item.type) }} - {{ formatObjectBrowserCount(item.estimatedRows) }} - {{ formatObjectBrowserBytes(item.totalBytes) }} + {{ + formatObjectBrowserCount(item.estimatedRows) + }} + {{ formatObjectBrowserBytes(item.totalBytes) }} {{ formatObjectBrowserTimestamp(item.created_at) }} @@ -3029,6 +3031,52 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] { align-items: start; } +.object-browser-icon-bg-table { + background-color: rgba(34, 197, 94, 0.1); +} + +.object-browser-icon-bg-view { + background-color: rgba(168, 85, 247, 0.1); +} + +.object-browser-icon-bg-procedure { + background-color: rgba(59, 130, 246, 0.1); +} + +.object-browser-icon-bg-function { + background-color: rgba(245, 158, 11, 0.1); +} + +.object-browser-icon-bg-sequence { + background-color: rgba(16, 185, 129, 0.1); +} + +.object-browser-icon-bg-package { + background-color: rgba(6, 182, 212, 0.1); +} + +.object-browser-stat-badge { + display: inline-flex; + align-items: center; + max-width: 100%; + line-height: 1rem; + white-space: nowrap; +} + +.object-browser-stat-badge-rows { + color: var(--primary); + background-color: rgba(23, 23, 23, 0.1); +} + +.object-browser-stat-badge-bytes { + color: var(--muted-foreground); + background-color: var(--muted); +} + +:global(.dark) .object-browser-stat-badge-rows { + background-color: rgba(208, 208, 214, 0.12); +} + .side-panel-resizing { user-select: none; pointer-events: none; diff --git a/apps/desktop/src/components/ui/dialog/DialogContent.vue b/apps/desktop/src/components/ui/dialog/DialogContent.vue index 919caedb6..373d25b82 100644 --- a/apps/desktop/src/components/ui/dialog/DialogContent.vue +++ b/apps/desktop/src/components/ui/dialog/DialogContent.vue @@ -42,7 +42,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); v-bind="{ ...$attrs, ...forwarded }" :class=" 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 ring-foreground/10 relative grid max-h-[calc(100dvh-2rem)] w-full max-w-full gap-4 overflow-hidden rounded-xl p-4 text-sm ring-1 duration-100 outline-none pointer-events-auto sm:max-w-sm', + '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(100dvh-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', props.class, ) " diff --git a/apps/desktop/src/components/ui/dialog/DialogScrollContent.vue b/apps/desktop/src/components/ui/dialog/DialogScrollContent.vue index c38828ebc..a83373348 100644 --- a/apps/desktop/src/components/ui/dialog/DialogScrollContent.vue +++ b/apps/desktop/src/components/ui/dialog/DialogScrollContent.vue @@ -25,6 +25,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); { return props.displayName(props.modelValue); }); +const triggerBaseClass = computed(() => + props.triggerVariant === "outline" + ? "dbx-searchable-select-trigger h-6 w-auto max-w-56 min-w-0 justify-between gap-1 px-2 text-xs font-normal shadow-none" + : "h-6 w-auto max-w-56 min-w-0 justify-between gap-1 border-0 bg-transparent px-1 text-xs font-normal shadow-none hover:bg-muted/50 focus-visible:ring-0", +); + const filteredOptions = computed(() => filterDatabaseOptions(props.options, searchText.value, props.displayName)); const customOptionValue = computed(() => props.normalizeCustom(searchText.value.trim())); const canSelectCustom = computed(() => props.allowCustom && !!customOptionValue.value && !props.options.includes(customOptionValue.value)); @@ -162,7 +168,7 @@ function handleKeydown(event: KeyboardEvent) { - + {{ loading ? loadingText : selectedLabel }} @@ -244,3 +250,36 @@ function handleKeydown(event: KeyboardEvent) { + + diff --git a/apps/desktop/src/components/ui/select/SelectTrigger.vue b/apps/desktop/src/components/ui/select/SelectTrigger.vue index 5922ad6ef..ae168996b 100644 --- a/apps/desktop/src/components/ui/select/SelectTrigger.vue +++ b/apps/desktop/src/components/ui/select/SelectTrigger.vue @@ -20,7 +20,7 @@ const forwardedProps = useForwardProps(delegatedProps); v-bind="forwardedProps" :class=" cn( - '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-[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', props.class, ) " @@ -31,3 +31,36 @@ const forwardedProps = useForwardProps(delegatedProps); + + diff --git a/apps/desktop/src/components/ui/switch/Switch.vue b/apps/desktop/src/components/ui/switch/Switch.vue index 050a4b9d6..a89e549dd 100644 --- a/apps/desktop/src/components/ui/switch/Switch.vue +++ b/apps/desktop/src/components/ui/switch/Switch.vue @@ -32,16 +32,92 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); v-bind="forwarded" :class=" cn( - 'data-checked:bg-primary data-unchecked:bg-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 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-colors outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50', + 'dbx-switch data-checked:bg-primary data-unchecked:bg-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 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-colors outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50', props.class, ) " > - + + + diff --git a/apps/desktop/src/lib/dataGrid/dataGridPaintTheme.ts b/apps/desktop/src/lib/dataGrid/dataGridPaintTheme.ts index 32b5d32a2..264b3ae1f 100644 --- a/apps/desktop/src/lib/dataGrid/dataGridPaintTheme.ts +++ b/apps/desktop/src/lib/dataGrid/dataGridPaintTheme.ts @@ -45,6 +45,7 @@ const DATA_GRID_LIGHT_ROW_NUMBER_DELETED_BG = "rgb(255, 244, 244)"; const CANVAS_SAFE_COLOR_RE = /^(#|rgb\(|rgba\(|hsl\(|hsla\()/i; const ADVANCED_COLOR_RE = /^(oklch\(|oklab\(|lab\(|lch\(|color\(|color-mix\()/i; let browserColorProbe: HTMLElement | null = null; +let canvasColorProbe: CanvasRenderingContext2D | null | undefined; interface RgbaColor { r: number; @@ -180,14 +181,35 @@ function normalizeCssColorWithBrowser(value: string): string | null { } } +function normalizeColorWithCanvas(value: string): string | null { + if (!value || typeof document === "undefined") return value || null; + try { + if (canvasColorProbe === undefined) { + canvasColorProbe = document.createElement("canvas").getContext("2d"); + } + const ctx = canvasColorProbe; + if (!ctx) return value; + + ctx.fillStyle = "#010203"; + ctx.fillStyle = value; + const first = String(ctx.fillStyle); + if (first !== "#010203") return first; + + ctx.fillStyle = "#040506"; + ctx.fillStyle = value; + const second = String(ctx.fillStyle); + return second !== "#040506" ? second : null; + } catch { + return null; + } +} + function toCanvasSafeColor(value: string, fallback: string): string { const trimmed = value.trim(); if (!trimmed) return fallback; const rgb = parseRgbColor(trimmed); - if (rgb) return formatRgb(rgb); - if (CANVAS_SAFE_COLOR_RE.test(trimmed)) return trimmed; - if (ADVANCED_COLOR_RE.test(trimmed)) return normalizeCssColorWithBrowser(trimmed) ?? parseColorMix(trimmed) ?? fallback; - return `hsl(${trimmed})`; + const candidate = rgb ? formatRgb(rgb) : CANVAS_SAFE_COLOR_RE.test(trimmed) ? trimmed : ADVANCED_COLOR_RE.test(trimmed) ? (normalizeCssColorWithBrowser(trimmed) ?? parseColorMix(trimmed) ?? fallback) : `hsl(${trimmed})`; + return normalizeColorWithCanvas(candidate) ?? normalizeColorWithCanvas(fallback) ?? fallback; } export function cssVarColor(getVar: (name: string) => string, name: string, fallback: string): string { @@ -243,26 +265,26 @@ export function resolveDataGridPaintTheme(options: { getVar: (name: string) => s foreground, mutedForeground, primary, - rowMuted: paintToken(getVar, "--data-grid-row-muted-bg", rowMuted), - rowNew: paintToken(getVar, "--data-grid-row-new-bg", rowNew), - rowDeleted: paintToken(getVar, "--data-grid-row-deleted-bg", rowDeleted), - cellActive: paintToken(getVar, "--data-grid-cell-active-bg", cellActive), - cellDirty: paintToken(getVar, "--data-grid-cell-dirty-bg", cellDirty), - cellSelected: paintToken(getVar, "--data-grid-cell-selected-bg", cellSelected), - cellSelectedDirty: paintToken(getVar, "--data-grid-cell-selected-dirty-bg", cellSelectedDirty), - cellSelectedBorder: paintToken(getVar, "--data-grid-cell-selected-border", cellSelectedBorder), - cellSelectedSingle: paintToken(getVar, "--data-grid-cell-selected-single-bg", cellSelectedSingle), - cellSelectedSingleBorder: paintToken(getVar, "--data-grid-cell-selected-single-border", primary), - cellHover: paintToken(getVar, "--data-grid-cell-hover-bg", cellHover), - cellSearch: paintToken(getVar, "--data-grid-cell-search-bg", cellSearch), - cellCurrentSearch: paintToken(getVar, "--data-grid-cell-current-search-bg", cellCurrentSearch), - cellCurrentSearchBorder: paintToken(getVar, "--data-grid-cell-current-search-border", cellCurrentSearchBorder), + rowMuted: isDark ? rowMuted : paintToken(getVar, "--data-grid-row-muted-bg", rowMuted), + rowNew: isDark ? rowNew : paintToken(getVar, "--data-grid-row-new-bg", rowNew), + rowDeleted: isDark ? rowDeleted : paintToken(getVar, "--data-grid-row-deleted-bg", rowDeleted), + cellActive: isDark ? cellActive : paintToken(getVar, "--data-grid-cell-active-bg", cellActive), + cellDirty: isDark ? cellDirty : paintToken(getVar, "--data-grid-cell-dirty-bg", cellDirty), + cellSelected: isDark ? cellSelected : paintToken(getVar, "--data-grid-cell-selected-bg", cellSelected), + cellSelectedDirty: isDark ? cellSelectedDirty : paintToken(getVar, "--data-grid-cell-selected-dirty-bg", cellSelectedDirty), + cellSelectedBorder: isDark ? cellSelectedBorder : paintToken(getVar, "--data-grid-cell-selected-border", cellSelectedBorder), + cellSelectedSingle: isDark ? cellSelectedSingle : paintToken(getVar, "--data-grid-cell-selected-single-bg", cellSelectedSingle), + cellSelectedSingleBorder: isDark ? primary : paintToken(getVar, "--data-grid-cell-selected-single-border", primary), + cellHover: isDark ? cellHover : paintToken(getVar, "--data-grid-cell-hover-bg", cellHover), + cellSearch: isDark ? cellSearch : paintToken(getVar, "--data-grid-cell-search-bg", cellSearch), + cellCurrentSearch: isDark ? cellCurrentSearch : paintToken(getVar, "--data-grid-cell-current-search-bg", cellCurrentSearch), + cellCurrentSearchBorder: isDark ? cellCurrentSearchBorder : paintToken(getVar, "--data-grid-cell-current-search-border", cellCurrentSearchBorder), rowNumberDefault, - rowNumberNew: paintToken(getVar, "--data-grid-row-number-new-bg", rowNumberNew), - rowNumberEdited: paintToken(getVar, "--data-grid-row-number-edited-bg", rowNumberEdited), - rowNumberDeleted: paintToken(getVar, "--data-grid-row-number-deleted-bg", rowNumberDeleted), - rowNumberActive: paintToken(getVar, "--data-grid-row-number-active-bg", rowNumberActive), - rowNumberSelected: paintToken(getVar, "--data-grid-row-number-selected-bg", rowNumberSelected), + rowNumberNew: isDark ? rowNumberNew : paintToken(getVar, "--data-grid-row-number-new-bg", rowNumberNew), + rowNumberEdited: isDark ? rowNumberEdited : paintToken(getVar, "--data-grid-row-number-edited-bg", rowNumberEdited), + rowNumberDeleted: isDark ? rowNumberDeleted : paintToken(getVar, "--data-grid-row-number-deleted-bg", rowNumberDeleted), + rowNumberActive: isDark ? rowNumberActive : paintToken(getVar, "--data-grid-row-number-active-bg", rowNumberActive), + rowNumberSelected: isDark ? rowNumberSelected : paintToken(getVar, "--data-grid-row-number-selected-bg", rowNumberSelected), rowNumberTextClean: mutedForeground, rowNumberTextNew: isDark ? "rgb(94, 233, 181)" : "rgb(0, 122, 85)", rowNumberTextEdited: isDark ? "rgb(255, 210, 48)" : "rgb(187, 77, 0)", diff --git a/apps/desktop/src/styles/globals.css b/apps/desktop/src/styles/globals.css index 4688833bc..3cd2c5582 100644 --- a/apps/desktop/src/styles/globals.css +++ b/apps/desktop/src/styles/globals.css @@ -1345,6 +1345,471 @@ body.dbx-table-reference-dragging * { font-size: 12.5px; } +@media (min-width: 640px) { + .sm\:flex-row { + flex-direction: row !important; + } + + .sm\:justify-end { + justify-content: flex-end !important; + } + + .sm\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + } +} + +@media (min-width: 768px) { + .md\:w-full { + width: 100% !important; + } + + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } + + .md\:grid-cols-\[1fr_auto\] { + grid-template-columns: 1fr auto !important; + } + + .md\:grid-cols-\[minmax\(0\,1fr\)_180px_auto\] { + grid-template-columns: minmax(0, 1fr) 180px auto !important; + } +} + +@media (min-width: 1024px) { + .lg\:block { + display: block !important; + } + + .lg\:hidden { + display: none !important; + } + + .lg\:grid { + display: grid !important; + } + + .lg\:flex-row { + flex-direction: row !important; + } + + .lg\:flex-col { + flex-direction: column !important; + } + + .lg\:items-center { + align-items: center !important; + } + + .lg\:justify-between { + justify-content: space-between !important; + } + + .lg\:justify-end { + justify-content: flex-end !important; + } + + .lg\:w-40 { + width: 10rem !important; + } + + .lg\:overflow-x-hidden { + overflow-x: hidden !important; + } + + .lg\:overflow-y-auto { + overflow-y: auto !important; + } + + .lg\:border-b-0 { + border-bottom-width: 0 !important; + } + + .lg\:border-r { + border-right-width: 1px !important; + } + + .lg\:pb-0 { + padding-bottom: 0 !important; + } + + .lg\:pr-3 { + padding-right: 0.75rem !important; + } + + .lg\:text-right { + text-align: right !important; + } + + .lg\:grid-cols-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)) !important; + } + + .lg\:grid-cols-\[1\.2fr_0\.8fr\] { + grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr) !important; + } + + .lg\:grid-cols-\[minmax\(0\,1\.6fr\)_72px_56px_76px_58px_76px_72px\] { + grid-template-columns: minmax(0, 1.6fr) 72px 56px 76px 58px 76px 72px !important; + } +} + +[data-slot="dialog-content"] { + width: calc(100vw - 2rem); + max-width: 24rem; + border: 1px solid rgb(229, 229, 229); + border-color: rgb(229, 229, 229) !important; + box-shadow: 0 18px 50px rgba(0, 0, 0, 0.16); +} + +.dark [data-slot="dialog-content"] { + border-color: rgba(110, 110, 114, 0.28) !important; + box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45); +} + +[data-slot="dialog-content"][class~="max-w-sm"] { + max-width: 24rem !important; +} + +[data-slot="dialog-content"][class~="max-w-md"] { + max-width: 28rem !important; +} + +[data-slot="dialog-content"][class~="max-w-lg"] { + max-width: 32rem !important; +} + +[data-slot="dialog-content"][class~="max-w-xl"] { + max-width: 36rem !important; +} + +[data-slot="dialog-content"][class~="max-w-2xl"] { + max-width: 42rem !important; +} + +[data-slot="dialog-content"][class~="max-w-4xl"] { + max-width: 56rem !important; +} + +[data-slot="dialog-content"][class~="max-w-5xl"] { + max-width: 64rem !important; +} + +[data-slot="dialog-content"][class~="max-w-190"] { + max-width: 47.5rem !important; +} + +[data-slot="dialog-content"][class*="max-w-[92vw]"] { + max-width: 92vw !important; +} + +[data-slot="dialog-content"][class*="max-w-[94vw]"] { + max-width: 94vw !important; +} + +[data-slot="dialog-content"][class*="max-w-[1100px]"] { + max-width: 1100px !important; +} + +[data-slot="tabs"][data-orientation="horizontal"] { + flex-direction: column !important; +} + +[data-slot="tabs"][data-orientation="vertical"] { + flex-direction: row !important; +} + +[data-slot="tabs-list"] { + display: inline-flex; + align-items: center; + justify-content: center; + width: fit-content; + border-radius: 6px; + color: var(--muted-foreground); +} + +[data-slot="tabs-list"][data-variant="default"] { + min-height: 2rem; + padding: 3px; + background: var(--muted); +} + +[data-slot="tabs-list"][data-variant="line"] { + gap: 0.25rem; + padding: 3px; + background: transparent; + border-radius: 0; +} + +[data-slot="tabs"][data-orientation="vertical"] > [data-slot="tabs-list"] { + flex-direction: column !important; + height: fit-content; +} + +[data-slot="tabs-trigger"] { + position: relative; + display: inline-flex; + flex: 1 1 0%; + align-items: center; + justify-content: center; + min-width: 0; + height: calc(100% - 1px); + padding: 0.125rem 0.375rem; + gap: 0.375rem; + border: 1px solid transparent; + border-radius: 0.375rem; + color: rgba(10, 10, 10, 0.6); + font-size: 0.875rem; + font-weight: 500; + line-height: 1.25rem; + white-space: nowrap; + transition: + color 150ms ease, + background-color 150ms ease, + border-color 150ms ease, + box-shadow 150ms ease; +} + +[data-slot="tabs"][data-orientation="vertical"] [data-slot="tabs-trigger"] { + width: 100%; + justify-content: flex-start; +} + +[data-slot="tabs-trigger"]:hover { + color: var(--foreground); +} + +[data-slot="tabs-trigger"]:focus-visible { + border-color: var(--ring); + outline: 1px solid var(--ring); + box-shadow: 0 0 0 3px rgba(161, 161, 161, 0.5); +} + +[data-slot="tabs-list"][data-variant="default"] > [data-slot="tabs-trigger"][aria-selected="true"], +[data-slot="tabs-list"][data-variant="default"] > [data-slot="tabs-trigger"][data-state="active"], +[data-slot="tabs-list"][data-variant="default"] > [data-slot="tabs-trigger"][data-active] { + color: var(--foreground); + background: var(--background); + border-color: transparent; + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.08), + 0 1px 1px rgba(0, 0, 0, 0.04); +} + +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"] { + background: transparent; + box-shadow: none; +} + +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"][aria-selected="true"], +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"][data-state="active"], +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"][data-active] { + color: var(--foreground); + background: transparent; + border-color: transparent; + box-shadow: none; +} + +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"]::after { + content: ""; + position: absolute; + background: var(--foreground); + opacity: 0; + transition: opacity 150ms ease; +} + +[data-slot="tabs"][data-orientation="horizontal"] [data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"]::after { + left: 0; + right: 0; + bottom: -5px; + height: 2px; +} + +[data-slot="tabs"][data-orientation="vertical"] [data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"]::after { + top: 0; + right: -4px; + bottom: 0; + width: 2px; +} + +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"][aria-selected="true"]::after, +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"][data-state="active"]::after, +[data-slot="tabs-list"][data-variant="line"] > [data-slot="tabs-trigger"][data-active]::after { + opacity: 1; +} + +.dark [data-slot="tabs-trigger"] { + color: var(--muted-foreground); +} + +.dark [data-slot="tabs-trigger"]:hover { + color: var(--foreground); +} + +.dark [data-slot="tabs-list"][data-variant="default"] > [data-slot="tabs-trigger"][aria-selected="true"], +.dark [data-slot="tabs-list"][data-variant="default"] > [data-slot="tabs-trigger"][data-state="active"], +.dark [data-slot="tabs-list"][data-variant="default"] > [data-slot="tabs-trigger"][data-active] { + color: var(--foreground); + background: rgba(110, 110, 114, 0.3); + border-color: var(--input); + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.22), + 0 1px 1px rgba(0, 0, 0, 0.16); +} + +[data-slot="tabs-content"] { + min-width: 0; +} + +.dark [data-grid-root] .data-grid-header-shell, +.dark [data-grid-root] .data-grid-header-cell, +.dark [data-grid-root] .data-grid-transpose-header, +.dark [data-grid-root] [data-grid-column-index] { + background-color: rgb(24, 25, 27) !important; +} + +.dark [data-grid-root] .data-grid-header-row, +.dark [data-grid-root] .data-grid-transpose-header { + color: rgb(215, 215, 219) !important; +} + +.dark [data-grid-root] .data-grid-header-cell:hover, +.dark [data-grid-root] [data-grid-column-index]:hover { + background-color: rgb(38, 39, 42) !important; +} + +@media (min-width: 640px) { + [data-slot="dialog-footer"] { + flex-direction: row !important; + justify-content: flex-end !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-sm"] { + max-width: 24rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-md"] { + max-width: 28rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-lg"] { + max-width: 32rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-xl"] { + max-width: 36rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-2xl"] { + max-width: 42rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-3xl"] { + max-width: 48rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-4xl"] { + max-width: 56rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-5xl"] { + max-width: 64rem !important; + } + + [data-slot="dialog-content"][class~="sm:max-w-190"] { + max-width: 47.5rem !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[360px]"] { + max-width: 360px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[380px]"] { + max-width: 380px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[400px]"] { + max-width: 400px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[420px]"] { + max-width: 420px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[440px]"] { + max-width: 440px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[460px]"] { + max-width: 460px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[480px]"] { + max-width: 480px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[500px]"] { + max-width: 500px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[520px]"] { + max-width: 520px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[560px]"] { + max-width: 560px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[660px]"] { + max-width: 660px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[720px]"] { + max-width: 720px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[760px]"] { + max-width: 760px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[780px]"] { + max-width: 780px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[840px]"] { + max-width: 840px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[860px]"] { + max-width: 860px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[900px]"] { + max-width: 900px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[960px]"] { + max-width: 960px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[980px]"] { + max-width: 980px !important; + } + + [data-slot="dialog-content"][class*="sm:max-w-[calc(100vw-2rem)]"] { + max-width: calc(100vw - 2rem) !important; + } + + [data-slot="dialog-content"][class*="sm:!max-w-[92vw]"] { + max-width: 92vw !important; + } + + [data-slot="dialog-content"][class*="sm:!max-w-[min(920px,calc(100vw-48px))]"] { + max-width: min(920px, calc(100vw - 48px)) !important; + } +} + /* Splitpanes */ .splitpanes--horizontal .splitpanes__pane { transition: none !important; @@ -1458,6 +1923,151 @@ body.dbx-table-reference-dragging * { border-color: oklch(1 0 0 / 0.1) !important; } +[data-slot="context-menu-content"], +[data-slot="context-menu-sub-content"], +[data-slot="dropdown-menu-content"], +[data-slot="dropdown-menu-sub-content"], +[data-slot="select-content"], +.cn-menu-translucent { + background-color: rgba(255, 255, 255, 0.96) !important; + border: 1px solid rgba(0, 0, 0, 0.1) !important; + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12) !important; + --tw-ring-color: transparent !important; + --tw-ring-shadow: 0 0 transparent !important; + --tw-shadow: 0 0 transparent !important; +} + +.dark [data-slot="context-menu-content"], +.dark [data-slot="context-menu-sub-content"], +.dark [data-slot="dropdown-menu-content"], +.dark [data-slot="dropdown-menu-sub-content"], +.dark [data-slot="select-content"], +.dark .cn-menu-translucent { + background-color: rgba(23, 23, 23, 0.94) !important; + border-color: rgba(255, 255, 255, 0.12) !important; + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45) !important; +} + +[data-slot="context-menu-item"]:hover, +[data-slot="context-menu-item"]:focus, +[data-slot="context-menu-item"][data-highlighted], +[data-slot="context-menu-checkbox-item"]:hover, +[data-slot="context-menu-checkbox-item"]:focus, +[data-slot="context-menu-checkbox-item"][data-highlighted], +[data-slot="context-menu-radio-item"]:hover, +[data-slot="context-menu-radio-item"]:focus, +[data-slot="context-menu-radio-item"][data-highlighted], +[data-slot="context-menu-sub-trigger"]:hover, +[data-slot="context-menu-sub-trigger"]:focus, +[data-slot="context-menu-sub-trigger"][data-highlighted], +[data-slot="context-menu-sub-trigger"][data-state="open"], +[data-slot="context-menu-sub-trigger"][data-open], +[data-slot="dropdown-menu-item"]:hover, +[data-slot="dropdown-menu-item"]:focus, +[data-slot="dropdown-menu-item"][data-highlighted], +[data-slot="dropdown-menu-checkbox-item"]:hover, +[data-slot="dropdown-menu-checkbox-item"]:focus, +[data-slot="dropdown-menu-checkbox-item"][data-highlighted], +[data-slot="dropdown-menu-radio-item"]:hover, +[data-slot="dropdown-menu-radio-item"]:focus, +[data-slot="dropdown-menu-radio-item"][data-highlighted], +[data-slot="dropdown-menu-sub-trigger"]:hover, +[data-slot="dropdown-menu-sub-trigger"]:focus, +[data-slot="dropdown-menu-sub-trigger"][data-highlighted], +[data-slot="dropdown-menu-sub-trigger"][data-state="open"], +[data-slot="dropdown-menu-sub-trigger"][data-open], +[data-slot="select-item"]:hover, +[data-slot="select-item"]:focus, +[data-slot="select-item"][data-highlighted], +[role="menuitem"]:hover, +[role="menuitem"]:focus { + background-color: rgba(23, 23, 23, 0.08) !important; + color: rgb(23, 23, 23) !important; +} + +[data-slot="context-menu-item"]:hover svg, +[data-slot="context-menu-item"]:focus svg, +[data-slot="context-menu-item"][data-highlighted] svg, +[data-slot="context-menu-checkbox-item"]:hover svg, +[data-slot="context-menu-checkbox-item"]:focus svg, +[data-slot="context-menu-checkbox-item"][data-highlighted] svg, +[data-slot="context-menu-radio-item"]:hover svg, +[data-slot="context-menu-radio-item"]:focus svg, +[data-slot="context-menu-radio-item"][data-highlighted] svg, +[data-slot="context-menu-sub-trigger"]:hover svg, +[data-slot="context-menu-sub-trigger"]:focus svg, +[data-slot="context-menu-sub-trigger"][data-highlighted] svg, +[data-slot="context-menu-sub-trigger"][data-state="open"] svg, +[data-slot="context-menu-sub-trigger"][data-open] svg, +[data-slot="dropdown-menu-item"]:hover svg, +[data-slot="dropdown-menu-item"]:focus svg, +[data-slot="dropdown-menu-item"][data-highlighted] svg, +[data-slot="dropdown-menu-checkbox-item"]:hover svg, +[data-slot="dropdown-menu-checkbox-item"]:focus svg, +[data-slot="dropdown-menu-checkbox-item"][data-highlighted] svg, +[data-slot="dropdown-menu-radio-item"]:hover svg, +[data-slot="dropdown-menu-radio-item"]:focus svg, +[data-slot="dropdown-menu-radio-item"][data-highlighted] svg, +[data-slot="dropdown-menu-sub-trigger"]:hover svg, +[data-slot="dropdown-menu-sub-trigger"]:focus svg, +[data-slot="dropdown-menu-sub-trigger"][data-highlighted] svg, +[data-slot="dropdown-menu-sub-trigger"][data-state="open"] svg, +[data-slot="dropdown-menu-sub-trigger"][data-open] svg, +[data-slot="select-item"]:hover svg, +[data-slot="select-item"]:focus svg, +[data-slot="select-item"][data-highlighted] svg, +[role="menuitem"]:hover svg, +[role="menuitem"]:focus svg { + color: currentColor !important; +} + +[data-slot="context-menu-item"][data-variant="destructive"]:hover, +[data-slot="context-menu-item"][data-variant="destructive"]:focus, +[data-slot="context-menu-item"][data-variant="destructive"][data-highlighted], +[data-slot="dropdown-menu-item"][data-variant="destructive"]:hover, +[data-slot="dropdown-menu-item"][data-variant="destructive"]:focus, +[data-slot="dropdown-menu-item"][data-variant="destructive"][data-highlighted] { + background-color: rgba(var(--destructive-rgb), 0.1) !important; + color: rgb(var(--destructive-rgb)) !important; +} + +.dark [data-slot="context-menu-item"]:hover, +.dark [data-slot="context-menu-item"]:focus, +.dark [data-slot="context-menu-item"][data-highlighted], +.dark [data-slot="context-menu-checkbox-item"]:hover, +.dark [data-slot="context-menu-checkbox-item"]:focus, +.dark [data-slot="context-menu-checkbox-item"][data-highlighted], +.dark [data-slot="context-menu-radio-item"]:hover, +.dark [data-slot="context-menu-radio-item"]:focus, +.dark [data-slot="context-menu-radio-item"][data-highlighted], +.dark [data-slot="context-menu-sub-trigger"]:hover, +.dark [data-slot="context-menu-sub-trigger"]:focus, +.dark [data-slot="context-menu-sub-trigger"][data-highlighted], +.dark [data-slot="context-menu-sub-trigger"][data-state="open"], +.dark [data-slot="context-menu-sub-trigger"][data-open], +.dark [data-slot="dropdown-menu-item"]:hover, +.dark [data-slot="dropdown-menu-item"]:focus, +.dark [data-slot="dropdown-menu-item"][data-highlighted], +.dark [data-slot="dropdown-menu-checkbox-item"]:hover, +.dark [data-slot="dropdown-menu-checkbox-item"]:focus, +.dark [data-slot="dropdown-menu-checkbox-item"][data-highlighted], +.dark [data-slot="dropdown-menu-radio-item"]:hover, +.dark [data-slot="dropdown-menu-radio-item"]:focus, +.dark [data-slot="dropdown-menu-radio-item"][data-highlighted], +.dark [data-slot="dropdown-menu-sub-trigger"]:hover, +.dark [data-slot="dropdown-menu-sub-trigger"]:focus, +.dark [data-slot="dropdown-menu-sub-trigger"][data-highlighted], +.dark [data-slot="dropdown-menu-sub-trigger"][data-state="open"], +.dark [data-slot="dropdown-menu-sub-trigger"][data-open], +.dark [data-slot="select-item"]:hover, +.dark [data-slot="select-item"]:focus, +.dark [data-slot="select-item"][data-highlighted], +.dark [role="menuitem"]:hover, +.dark [role="menuitem"]:focus { + background-color: rgba(255, 255, 255, 0.12) !important; + color: rgb(245, 245, 245) !important; +} + /* Tailwind 4 falls back from bg-destructive/ to solid --destructive when color-mix() is unavailable in older WebKit. Keep dangerous-action surfaces translucent so red text/icons remain legible on macOS 12 WebView. */