feat: add github dark mode variant switchable in user settings (#10002)

* feat: add github dark mode variant switchable in user settings

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: boot the UI Builder iframe into the current theme

Seed the UI Builder iframe URL with the live dark/variant state
(`?dark=&variant=`) so the VS Code workbench boots straight into GitHub
Dark / Nord / Light instead of flashing the dark default until the host's
`setDarkMode` message lands. Read from the <html> classes rather than the
reactive state so the src is computed once at mount — a later theme toggle
still updates the workbench via postMessage and does not reload the iframe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat: align github-dark surfaces to GitHub Primer's elevation scale

Snap the invented mid-greys to Primer's real dark canvas scale
(inset=neutral.0, default=neutral.1, muted=neutral.2). Recessed surfaces
now use true inset (#010409) instead of washed-out half-steps that sat in
no-man's-land between inset and the page; raised surfaces align to muted.

- surface-secondary  #0b0e13 → #010409  (true inset)
- surface-input      #0c0f14 → #010409  (true inset)
- surface-disabled   #0b0e13 → #151b23  (muted)
- surface-tertiary   #161b22 → #151b23  (Primer neutral.2)
- component-virtual-node #161b22 → #151b23
- surface-selected   #21262d → #212830  (Primer neutral.3)

surface-sunken (#010409) and surface-primary (#0d1117) already matched
Primer inset/default exactly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: keep github-dark inputs subtle instead of full inset

surface-input at true inset (#010409) made form fields read as recessed as
the sidebar rail — too much contrast against the canvas. Inputs aren't
sunken, so keep the subtle #0c0f14 (a hair below the page) while the
recessed panel surfaces stay at inset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump UI Builder pin to the github-dark build (76ee616)

windmill-code-ui-builder PR #16 is merged and published to R2, so pin the
artifact to that build. The embedded raw-app editor now renders GitHub Dark
(and honors the `variant` message) natively from the pinned build — no local
swap needed. Reword the variant comment now that the dependency is resolved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: address codex review nits on the github-dark theme

- UserSettings: re-read the dark variant when the settings drawer opens, so a
  change made through one mounted instance (page-local drawer) isn't shown
  stale by another (the always-mounted layout instance).
- PublicApp / OAuth login callback: restore the `github-dark` variant class,
  not just the base `dark` class. These routes bypass the (root) layout, so
  they previously fell back to the default dark palette despite the saved
  preference.
- RawAppEditor: condense the two new theme comments to the durable constraints
  per AGENTS.md (drop narration and the ephemeral artifact-pin history).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: address CI review findings on the github-dark theme

- Move the hand-authored `github-dark` token set out of the Figma-generated
  tokens.json into githubDark.json, merged back in at the two consumers
  (tailwind.config.cjs before the rgb pass, utils.ts) so a Figma re-export of
  tokens.json can no longer drop the set and crash the build.
- Restore the default-dark sidebar divider to #374151 — the PR must leave the
  Default variant unchanged; only the github variant adapts it to border-light.
- Extract the `github-dark` DOM-class read into getAppliedDarkModeVariant() and
  reuse it across RawAppEditor and vscode.ts; drop the redundant `void darkVariant`.
- Override the Monaco popup vars (suggest/hover widgets) in the github variant so
  they match the GitHub palette instead of VS Code's greys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
This commit is contained in:
Guilhem
2026-07-28 18:34:41 +02:00
committed by GitHub
parent 91b8ce581a
commit bd246644c9
16 changed files with 254 additions and 45 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
{
"baseUrl": "https://pub-06154ed168a24e73a86ab84db6bf15d8.r2.dev",
"version": "1f1fe4f",
"sha256": "4c20b2b51f324e93dda3b46d914ebf7bc7d0cb4dc7eb2d37068408191220d206"
"version": "76ee616",
"sha256": "1d696d38a152179ef6e1cada5df302d078cc677b6dbc244b5c42335e11feabac"
}
@@ -0,0 +1,35 @@
{
"surface-accent-primary": "#506ab8",
"surface-accent-hover": "#5873c8",
"surface-accent-clicked": "#425797",
"text-primary": "#d5dbe2",
"text-secondary": "#8b949e",
"text-primary-inverse": "#24292f",
"text-secondary-inverse": "#57606a",
"text-tertiary-inverse": "#6e7781",
"surface-selected": "#212830",
"surface-disabled": "#151b23",
"surface-secondary": "#010409",
"surface-hover": "#6e768119",
"surface-primary": "#0d1117",
"border-light": "#242a32",
"border-normal": "#6e7681",
"border-accent": "#4a6ed6",
"surface-accent-selected": "#141a2e",
"surface-accent-secondary": "#e3e8ee",
"surface-tertiary": "#151b23",
"text-emphasis": "#dfe5eb",
"text-hint": "#6e7681",
"text-disabled": "#484f58",
"surface-accent-secondary-hover": "#d0d7de",
"surface-accent-secondary-clicked": "#afb8c1",
"component-button-accent-secondary": "#f0f6fc",
"text-emphasis-inverse": "#1f2328",
"reserved-ai": "#d2a8ff",
"component-virtual-node": "#151b23",
"text-accent": "#bdc8ee",
"border-selected": "#5a72c4",
"surface-sunken": "#010409",
"text-tertiary": "#6e7681",
"surface-input": "#0c0f14"
}
+6 -1
View File
@@ -239,7 +239,12 @@
"magenta-950": "#6e2ba1"
}
},
"guidelines": { "mode-1": { "blue": "#5e81ac", "demo-background": "#ffffff00" } },
"guidelines": {
"mode-1": {
"blue": "#5e81ac",
"demo-background": "#ffffff00"
}
},
"tailwind-c-s-s-v-3-3-2": {
"mode-1": {
"black": "#000000",
@@ -1,5 +1,5 @@
<script lang="ts">
import { isInitialized } from './vscode'
import { getEditorTheme, isInitialized } from './vscode'
import { editor as meditor } from 'monaco-editor'
@@ -8,11 +8,7 @@
function onThemeChange() {
if (isInitialized) {
if (document.documentElement.classList.contains('dark')) {
meditor.setTheme('nord')
} else {
meditor.setTheme('myTheme')
}
meditor.setTheme(getEditorTheme())
}
}
@@ -2505,7 +2505,7 @@
{/snippet}
{#snippet editorContent()}
<div class="h-full !overflow-visible bg-surface dark:bg-[#272D38] relative flex flex-col">
<div class="h-full !overflow-visible bg-surface dark:bg-surface-secondary relative flex flex-col">
{#if supportsModules}
<div
class="flex items-center border-b border-tertiary/30 bg-surface-secondary px-1 gap-0.5 text-xs overflow-x-auto shrink-0"
@@ -3,10 +3,17 @@
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
import Version from './Version.svelte'
import DarkModeToggle from './sidebar/DarkModeToggle.svelte'
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
import TokensTable from './settings/TokensTable.svelte'
import { createEventDispatcher } from 'svelte'
import UserInfoSettings from './settings/UserInfoSettings.svelte'
import AIUserSettings from './settings/AIUserSettings.svelte'
import {
getDarkModeVariant,
setDarkModeVariant,
type DarkModeVariant
} from '$lib/darkModeVariant'
interface Props {
scopes?: string[] | undefined
@@ -28,6 +35,7 @@
let drawer: Drawer | undefined = $state()
let openWithMcpMode = $state(false)
let darkVariant = $state<DarkModeVariant>(getDarkModeVariant())
const dispatch = createEventDispatcher()
@@ -51,15 +59,39 @@
}
</script>
<Drawer bind:this={drawer} size="900px" on:close={removeHash} {disableChatOffset}>
<Drawer
bind:this={drawer}
size="900px"
on:open={() => (darkVariant = getDarkModeVariant())}
on:close={removeHash}
{disableChatOffset}
>
<DrawerContent title="User settings" on:close={closeDrawer}>
<div class="flex flex-col gap-6 pb-8">
{#if scopes == undefined}
<div
class="flex flex-row justify-between items-start gap-2 border border-border-light p-4 rounded-md"
>
<div class="font-semibold text-emphasis text-xs flex items-center">
Theme <DarkModeToggle forcedDarkMode={false} />
<div class="flex flex-col gap-2">
<div class="font-semibold text-emphasis text-xs flex items-center">
Theme <DarkModeToggle forcedDarkMode={false} />
</div>
<div class="flex items-center gap-2">
<span class="text-xs text-secondary">Dark variant</span>
<ToggleButtonGroup
selected={darkVariant}
class="w-fit"
onSelected={(v) => {
darkVariant = v
setDarkModeVariant(v)
}}
>
{#snippet children({ item })}
<ToggleButton value="default" label="Default" size="sm" {item} />
<ToggleButton value="github" label="GitHub" size="sm" {item} />
{/snippet}
</ToggleButtonGroup>
</div>
</div>
<div class="text-xs text-emphasis flex-col flex">
Windmill <Version />
@@ -1,5 +1,6 @@
<script lang="ts">
import { User, UserRoundX } from 'lucide-svelte'
import { applyDarkModeVariant } from '$lib/darkModeVariant'
import { enterpriseLicense, userStore } from '$lib/stores'
import { base } from '$app/paths'
import { page } from '$app/state'
@@ -73,6 +74,8 @@
} else {
document.documentElement.classList.remove('dark')
}
// This route bypasses the (root) layout, so restore the variant class too.
applyDarkModeVariant()
let globalUser = $state<GlobalWhoamiResponse | undefined>(undefined)
async function loadGlobalUser() {
@@ -29,6 +29,7 @@
import { runDomQueryOnHtml, type RawAppDomQuery, type RawAppDomRequester } from './rawAppDom'
import InlineElementPrompt from './InlineElementPrompt.svelte'
import DarkModeObserver from '../DarkModeObserver.svelte'
import { getAppliedDarkModeVariant, type DarkModeVariant } from '$lib/darkModeVariant'
import RawAppSidebar from './RawAppSidebar.svelte'
import type { Modules } from './RawAppModules.svelte'
import { isRunnableByName, isRunnableByPath } from '../apps/inputType'
@@ -1304,7 +1305,7 @@
// it always matches the editor's current state. Plain rebuilds use
// `syncExternalPreview` alone (the theme hasn't changed).
function feedExternalPreview() {
postToExternalPreview({ type: 'setDarkMode', dark: darkMode })
postToExternalPreview({ type: 'setDarkMode', dark: darkMode, variant: darkVariant })
syncExternalPreview()
}
@@ -1697,6 +1698,17 @@
})
let darkMode: boolean = $state(false)
// Mirrors the `github-dark` class (the runtime source of truth); the
// DarkModeObserver below must keep it in sync or it goes stale.
let darkVariant: DarkModeVariant = $state(getAppliedDarkModeVariant())
// Read the DOM classes, not reactive state, so the src stays constant after
// mount: a reactive src would reload the iframe on every theme toggle. Live
// theme changes travel through postMessage instead (see the $effect below).
function uiBuilderIframeSrc(): string {
const dark = document.documentElement.classList.contains('dark')
const variant = getAppliedDarkModeVariant()
return `/ui_builder/index.html?dark=${dark}&variant=${variant}`
}
// Host's computed `text-xs` size in px. Windmill bumps :root to 18px at
// ≥1760px viewports, so this re-evaluates on resize via the listener below.
let editorFontSize = $state(12)
@@ -1746,12 +1758,18 @@
// Push dark mode to both children. The UI Builder iframe and the
// preview iframe each listen for `setDarkMode` separately.
if (iframe && iframeLoaded) {
iframe.contentWindow?.postMessage({ type: 'setDarkMode', dark: darkMode }, '*')
iframe.contentWindow?.postMessage(
{ type: 'setDarkMode', dark: darkMode, variant: darkVariant },
'*'
)
}
if (previewIframe && previewIframeLoaded) {
previewIframe.contentWindow?.postMessage({ type: 'setDarkMode', dark: darkMode }, '*')
previewIframe.contentWindow?.postMessage(
{ type: 'setDarkMode', dark: darkMode, variant: darkVariant },
'*'
)
}
postToExternalPreview({ type: 'setDarkMode', dark: darkMode })
postToExternalPreview({ type: 'setDarkMode', dark: darkMode, variant: darkVariant })
})
$effect(() => {
// Match VS Code's editor font size to Windmill's text-xs.
@@ -2036,7 +2054,12 @@
</script>
<svelte:window onmessage={listener} onkeydown={handleKeydown} />
<DarkModeObserver bind:darkMode />
<DarkModeObserver
bind:darkMode
on:change={() => {
darkVariant = getAppliedDarkModeVariant()
}}
/>
<RawAppBackgroundRunner
workspace={opWorkspace ?? ''}
@@ -2214,7 +2237,7 @@
<iframe
bind:this={iframe}
title="UI builder"
src="/ui_builder/index.html"
src={uiBuilderIframeSrc()}
class="w-full h-full block"
onload={attachIframeSaveShortcut}
></iframe>
@@ -1,5 +1,6 @@
// Sidebar rail background. Deliberately raw hex — no theme token exists for
// the rail chrome — kept here as the single source for every host that renders
// or mimics the sidebar (app layout, kitchen-sink harness).
// Sidebar rail background. Kept here as the single source for every host that
// renders or mimics the sidebar (app layout, kitchen-sink harness).
// The dark value is a theme-driven CSS variable so it adapts across dark
// variants (default vs GitHub dark) — see tailwind.config.cjs `--sidebar-bg-dark`.
export const SIDEBAR_BG = '#F3F3F7'
export const SIDEBAR_BG_DARK = '#1e232e'
export const SIDEBAR_BG_DARK = 'var(--sidebar-bg-dark)'
+52 -5
View File
@@ -1,6 +1,7 @@
import '@codingame/monaco-vscode-standalone-typescript-language-features'
import { editor as meditor, Uri as mUri } from 'monaco-editor'
import { getAppliedDarkModeVariant } from '$lib/darkModeVariant'
export let isInitialized = false
export let isInitializing = false
@@ -12,6 +13,15 @@ import {
import getLanguagesServiceOverride from '@codingame/monaco-vscode-languages-service-override'
import { getCssColor } from '$lib/utils'
// Monaco theme name matching the current document theme (light / dark / GitHub dark variant).
export function getEditorTheme(): string {
const classes = document.documentElement.classList
if (!classes.contains('dark')) {
return 'myTheme'
}
return getAppliedDarkModeVariant() === 'github' ? 'github-dark' : 'nord'
}
export function buildWorkerDefinition() {
const envEnhanced = getEnhancedMonacoEnvironment()
const getWorker = (moduleId: string, label: string) => {
@@ -248,6 +258,47 @@ export async function initializeVscode(caller?: string, htmlContainer?: HTMLElem
}
})
meditor.defineTheme('github-dark', {
base: 'vs-dark',
inherit: true,
rules: [
{ background: '0D1117', token: '' },
{ foreground: '8b949e', token: 'comment' },
{ foreground: 'a5d6ff', token: 'string' },
{ foreground: '79c0ff', token: 'constant.numeric' },
{ foreground: '79c0ff', token: 'constant.language' },
{ foreground: 'ff7b72', token: 'keyword' },
{ foreground: 'ff7b72', token: 'storage' },
{ foreground: 'ff7b72', token: 'storage.type' },
{ foreground: 'ffa657', token: 'entity.name.class' },
{ foreground: 'ffa657', fontStyle: 'bold', token: 'entity.other.inherited-class' },
{ foreground: 'd2a8ff', token: 'entity.name.function' },
{ foreground: '7ee787', token: 'entity.name.tag' },
{ foreground: '79c0ff', token: 'entity.other.attribute-name' },
{ foreground: 'd2a8ff', token: 'support.function' },
{ foreground: 'f0f6fc', background: 'f85149', token: 'invalid' },
{ foreground: 'f0f6fc', background: 'bd561d', token: 'invalid.deprecated' },
{ foreground: '79c0ff', token: 'constant.color.other.rgb-value' },
{ foreground: '79c0ff', token: 'constant.character.escape' },
{ foreground: 'ffa657', token: 'variable.other.constant' },
{ token: 'string.value.json', foreground: 'a5d6ff' }, // string values in JSON
{ token: 'keyword.json', foreground: '79c0ff' } // true, false, null in JSON
],
colors: {
'editor.foreground': '#e6edf3',
'editor.background': getCssColor('surface-input', { format: 'hex-github-dark' }),
'editor.selectionBackground': '#3392FF44',
'editor.inactiveSelectionBackground': '#3392FF22',
'editor.lineHighlightBackground': '#161b22',
'editorCursor.foreground': '#e6edf3',
'editorWhitespace.foreground': '#484f58',
'editorIndentGuide.background1': '#21262d',
'editorIndentGuide.activeBackground1': '#30363d',
'editorLineNumber.foreground': '#6e7681',
'editorLineNumber.activeForeground': '#e6edf3'
}
})
meditor.defineTheme('myTheme', {
base: 'vs',
inherit: true,
@@ -262,11 +313,7 @@ export async function initializeVscode(caller?: string, htmlContainer?: HTMLElem
}
})
if (document.documentElement.classList.contains('dark')) {
meditor.setTheme('nord')
} else {
meditor.setTheme('myTheme')
}
meditor.setTheme(getEditorTheme())
} catch (e) {
console.error('Failed to initialize monaco services', e)
} finally {
+27
View File
@@ -0,0 +1,27 @@
export type DarkModeVariant = 'default' | 'github'
const DARK_MODE_VARIANT_KEY = 'dark-mode-variant'
export function getDarkModeVariant(): DarkModeVariant {
return window.localStorage.getItem(DARK_MODE_VARIANT_KEY) === 'github' ? 'github' : 'default'
}
// The variant currently applied to the DOM (the `github-dark` class) — the
// runtime source of truth, as opposed to the persisted preference above.
export function getAppliedDarkModeVariant(): DarkModeVariant {
return typeof document !== 'undefined' &&
document.documentElement.classList.contains('github-dark')
? 'github'
: 'default'
}
// The `github-dark` class only takes effect when `dark` is also present (see tailwind.config.cjs).
// It lives on <html> permanently so it survives the many independent `dark` toggle sites.
export function applyDarkModeVariant(variant: DarkModeVariant = getDarkModeVariant()): void {
document.documentElement.classList.toggle('github-dark', variant === 'github')
}
export function setDarkModeVariant(variant: DarkModeVariant): void {
window.localStorage.setItem(DARK_MODE_VARIANT_KEY, variant)
applyDarkModeVariant(variant)
}
+6 -1
View File
@@ -2029,6 +2029,8 @@ export function validateRetryConfig(retry: Retry | undefined): string | null {
}
export type CssColor = keyof (typeof tokensFile)['tokens']['light']
import tokensFile from './assets/tokens/tokens.json'
// Hand-authored variant kept out of the Figma-generated tokens.json.
import githubDarkTokens from './assets/tokens/githubDark.json'
import { darkModeName, lightModeName } from './assets/tokens/colorTokensConfig'
import BarsStaggered from './components/icons/BarsStaggered.svelte'
import { GitIcon } from './components/icons'
@@ -2041,7 +2043,7 @@ export function getCssColor(
format = 'css-var'
}: {
alpha?: number
format?: 'css-var' | 'hex-dark' | 'hex-light'
format?: 'css-var' | 'hex-dark' | 'hex-light' | 'hex-github-dark'
}
): string {
if (format === 'hex-light') {
@@ -2050,6 +2052,9 @@ export function getCssColor(
if (format === 'hex-dark') {
return tokensFile.tokens[darkModeName][color]
}
if (format === 'hex-github-dark') {
return githubDarkTokens[color]
}
return `rgb(var(--color-${color}) / ${alpha})`
}
@@ -1052,7 +1052,7 @@
style:width="{railWidth}rem"
>
<div
class="flex-1 flex flex-col min-h-0 h-screen shadow-[inset_-1px_0_0_0_rgb(var(--color-border-light))] dark:shadow-[inset_-1px_0_0_0_#374151]"
class="flex-1 flex flex-col min-h-0 h-screen shadow-[inset_-1px_0_0_0_rgb(var(--color-border-light))] dark:shadow-[inset_-1px_0_0_0_#374151] [html.github-dark_&]:shadow-[inset_-1px_0_0_0_rgb(var(--color-border-light))]"
style:background-color={darkMode ? SIDEBAR_BG_DARK : SIDEBAR_BG}
>
{#if !isCollapsed}
@@ -19,6 +19,7 @@
// import EditorTheme from '$lib/components/EditorTheme.svelte'
import { computeDrift } from '$lib/forLater'
import { setLicense } from '$lib/enterpriseUtils'
import { applyDarkModeVariant } from '$lib/darkModeVariant'
import { deepEqual } from 'fast-equals'
interface Props {
children?: import('svelte').Snippet
@@ -255,6 +256,8 @@
} else {
document.documentElement.classList.remove('dark')
}
applyDarkModeVariant()
</script>
{@render children?.()}
@@ -1,5 +1,6 @@
<script lang="ts">
import { goto } from '$lib/navigation'
import { applyDarkModeVariant } from '$lib/darkModeVariant'
import { sendUserToast } from '$lib/toast'
import { onMount } from 'svelte'
import { UserService, WorkspaceService } from '$lib/gen'
@@ -132,6 +133,8 @@
} else {
document.documentElement.classList.remove('dark')
}
// This route bypasses the (root) layout, so restore the variant class too.
applyDarkModeVariant()
function closeUponLoginSuccess() {
const message = { type: 'success' }
+44 -15
View File
@@ -4,10 +4,18 @@ const {
} = require('./src/lib/components/apps/editor/componentsPanel/tailwindUtils')
const { zIndexes } = require('./src/lib/zIndexes')
const figmaTokens = makeRgb(require('./src/lib/assets/tokens/tokens.json'))
const rawTokens = require('./src/lib/assets/tokens/tokens.json')
// `github-dark` is a hand-authored variant kept out of the Figma-generated
// tokens.json (a re-export would drop it); merge it in before the rgb pass.
rawTokens.tokens['github-dark'] = require('./src/lib/assets/tokens/githubDark.json')
const figmaTokens = makeRgb(rawTokens)
const { darkModeName, lightModeName } = require('./src/lib/assets/tokens/colorTokensConfig')
const tokens = { dark: figmaTokens.tokens[darkModeName], light: figmaTokens.tokens[lightModeName] }
const tokens = {
dark: figmaTokens.tokens[darkModeName],
light: figmaTokens.tokens[lightModeName],
githubDark: figmaTokens.tokens['github-dark']
}
const primitives = figmaTokens.primitives.light
// Helper function to create color definition based on whether the value contains alpha
@@ -571,6 +579,12 @@ const config = {
...Object.entries(tokens.dark).map(([key, value]) => [`--color-${key}`, value]),
...Object.entries(tokens.light).map(([key, value]) => [`--color-${key}-inverse`, value])
])
// GitHub dark variant: overrides the default dark variables when the
// `github-dark` class is present alongside `dark` (see html.&.dark.github-dark below).
let githubDarkColorVariables = Object.fromEntries([
...Object.entries(tokens.githubDark).map(([key, value]) => [`--color-${key}`, value]),
...Object.entries(tokens.light).map(([key, value]) => [`--color-${key}-inverse`, value])
])
addBase({
html: {
@@ -600,10 +614,31 @@ const config = {
...darkColorVariables,
// Sidebar rail chrome — consumed via var(--sidebar-bg-dark) (see sidebarChrome.ts).
'--sidebar-bg-dark': '#1e232e',
'--vscode-editorSuggestWidget-background': '#252526',
'--vscode-editorHoverWidget-foreground': '#cccccc',
'--vscode-editorHoverWidget-border': '#454545',
'--vscode-editorHoverWidget-statusBarBackground': '#2c2c2d'
},
'&.dark.github-dark': {
backgroundColor: `rgb(${tokens.githubDark['surface-primary']})`,
color: `rgb(${tokens.githubDark['text-primary']})`,
...githubDarkColorVariables,
// GitHub's canvas.inset — the authentic recessed surface, sitting below
// the canvas (#0d1117) like the sidebar-vs-primary relationship in the
// default dark theme.
'--sidebar-bg-dark': '#010409',
// Monaco popup chrome — the &.dark defaults above are VS Code's greys;
// override so the widgets match the GitHub Dark palette in this variant.
'--vscode-editorSuggestWidget-background': '#1c2128',
'--vscode-editorHoverWidget-foreground': '#c9d1d9',
'--vscode-editorHoverWidget-border': '#30363d',
'--vscode-editorHoverWidget-statusBarBackground': '#1c2128'
}
},
h1: {
@@ -842,20 +877,20 @@ const config = {
'colors.gray.600'
)})`
},
// Drive pane/splitter chrome off the theme CSS variables (not literal token
// values) so every theme — light, dark, and the GitHub dark variant — is
// covered by a single rule. A `.dark`-specific literal here would freeze the
// default dark color and ignore the variant.
'.splitpanes__pane': {
backgroundColor: `rgb(${tokens.light['surface-primary']})` + ' !important',
overflow: 'auto !important'
},
'.dark .splitpanes__pane': {
backgroundColor: `rgb(${tokens.dark['surface-primary']})` + ' !important',
backgroundColor: 'rgb(var(--color-surface-primary)) !important',
overflow: 'auto !important'
},
'.splitpanes__splitter': {
backgroundColor: `rgb(${tokens.light['border-light']})` + ' !important',
backgroundColor: 'rgb(var(--color-border-light)) !important',
margin: '0 !important',
border: 'none !important',
'&::after': {
backgroundColor: `rgb(${tokens.light['border-light']})` + ' !important',
backgroundColor: 'rgb(var(--color-border-light)) !important',
margin: '0 !important',
transform: 'none !important',
transition: 'opacity 200ms !important',
@@ -868,12 +903,6 @@ const config = {
zIndex: '1001 !important'
}
},
'.dark .splitpanes__splitter': {
backgroundColor: `rgb(${tokens.dark['border-light']})` + ' !important',
'&::after': {
backgroundColor: `rgb(${tokens.dark['border-light']})` + ' !important'
}
},
'.splitpanes--vertical>.splitpanes__splitter': {
width: '1px !important',
'&::before': {