feat(tui): migrate core surfaces to V2 themes (#37145)
This commit is contained in:
parent
a5b28c2af2
commit
5fcef6773c
37 changed files with 1389 additions and 815 deletions
|
|
@ -14,22 +14,29 @@ test("provides reactive property, variant, state, and context accessors", () =>
|
|||
return key ? resolved().contexts[key] ?? resolved() : resolved()
|
||||
})
|
||||
|
||||
expect(theme.color.text()).toBe(resolved().color.text.default)
|
||||
expect(theme.color.text.subdued()).toBe(resolved().color.text.subdued)
|
||||
expect(theme.color.text.action()).toBe(resolved().color.text.action.primary.default)
|
||||
expect(theme.color.text.action.primary("pressed")).toBe(resolved().color.text.action.primary.pressed)
|
||||
expect(theme.color.background.action.secondary("disabled")).toBe(
|
||||
resolved().color.background.action.secondary.disabled,
|
||||
expect(theme.text()).toBe(resolved().text.default)
|
||||
expect(theme.hue.accent(500)).toBe(resolved().hue.accent[500])
|
||||
expect(theme.hue.gray(200)).toBe(resolved().hue.gray[200])
|
||||
expect(theme.text.subdued()).toBe(resolved().text.subdued)
|
||||
expect(theme.text.action()).toBe(resolved().text.action.primary.default)
|
||||
expect(theme.text.action.primary("pressed")).toBe(resolved().text.action.primary.pressed)
|
||||
expect(theme.background.action.secondary("disabled")).toBe(
|
||||
resolved().background.action.secondary.disabled,
|
||||
)
|
||||
expect(theme.color.scrollbar()).toBe(resolved().color.scrollbar.default)
|
||||
expect(theme.color.diff.text.added()).toBe(resolved().color.diff.text.added)
|
||||
expect(theme.background.surface.offset()).toBe(resolved().background.surface.offset)
|
||||
expect(theme.background.surface.overlay()).toBe(resolved().background.surface.overlay)
|
||||
expect(theme.scrollbar()).toBe(resolved().scrollbar.default)
|
||||
expect(theme.diff.text.added()).toBe(resolved().diff.text.added)
|
||||
|
||||
setContext("@context:elevated")
|
||||
expect(theme.color.text()).toBe(resolved().contexts["@context:elevated"]!.color.text.default)
|
||||
expect(theme.color.background.action.primary("selected")).toBe(
|
||||
resolved().contexts["@context:elevated"]!.color.background.action.primary.selected,
|
||||
expect(theme.text()).toBe(resolved().contexts["@context:elevated"]!.text.default)
|
||||
expect(theme.background.action.primary("focused")).toBe(
|
||||
resolved().contexts["@context:elevated"]!.background.action.primary.focused,
|
||||
)
|
||||
expect(theme.background.formfield("selected")).toBe(
|
||||
resolved().contexts["@context:elevated"]!.background.formfield.selected,
|
||||
)
|
||||
|
||||
setResolved(resolveTheme(selectTheme(DEFAULT_THEME, "dark")))
|
||||
expect(theme.color.text()).toBe(resolved().contexts["@context:elevated"]!.color.text.default)
|
||||
expect(theme.text()).toBe(resolved().contexts["@context:elevated"]!.text.default)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,32 +14,36 @@ test("resolves independent definitions and hue aliases", () => {
|
|||
|
||||
expect(lightTheme.hue.accent).toBe(lightTheme.hue.blue)
|
||||
expect(lightTheme.hue.neutral).toBe(lightTheme.hue.gray)
|
||||
expect(lightTheme.color.text.default).toBeInstanceOf(RGBA)
|
||||
expect(darkTheme.color.background.default).toBeInstanceOf(RGBA)
|
||||
expect(lightTheme.color.syntax.keyword).toBeInstanceOf(RGBA)
|
||||
expect(lightTheme.color.text.action.primary.default).toBe(lightTheme.hue.neutral[100])
|
||||
expect(lightTheme.contexts["@context:elevated"]?.color.background.action.primary.default).toBe(
|
||||
expect(lightTheme.text.default).toBeInstanceOf(RGBA)
|
||||
expect(darkTheme.background.default).toBeInstanceOf(RGBA)
|
||||
expect(lightTheme.background.surface.offset).toBe(lightTheme.hue.neutral[200])
|
||||
expect(lightTheme.background.surface.overlay).toBe(lightTheme.hue.neutral[300])
|
||||
expect(lightTheme.syntax.keyword).toBeInstanceOf(RGBA)
|
||||
expect(lightTheme.text.action.primary.default).toBe(lightTheme.hue.neutral[100])
|
||||
expect(lightTheme.contexts["@context:elevated"]?.background.action.primary.default).toBe(
|
||||
lightTheme.hue.accent[500],
|
||||
)
|
||||
expect(lightTheme.contexts["@context:elevated"]?.color.text.action.primary.default).toBe(
|
||||
expect(lightTheme.contexts["@context:elevated"]?.background.default).toBe(lightTheme.background.surface.offset)
|
||||
expect(lightTheme.contexts["@context:elevated"]?.text.action.primary.default).toBe(
|
||||
lightTheme.hue.neutral[100],
|
||||
)
|
||||
expect(lightTheme.contexts["@context:overlay"]?.color.background.action.primary.default).toBe(
|
||||
expect(lightTheme.contexts["@context:overlay"]?.background.action.primary.default).toBe(
|
||||
lightTheme.hue.accent[500],
|
||||
)
|
||||
expect(lightTheme.contexts["@context:overlay"]?.color.text.action.primary.default).toBe(
|
||||
expect(lightTheme.contexts["@context:overlay"]?.background.default).toBe(lightTheme.background.surface.overlay)
|
||||
expect(lightTheme.contexts["@context:overlay"]?.text.action.primary.default).toBe(
|
||||
lightTheme.hue.neutral[100],
|
||||
)
|
||||
expect(darkTheme.contexts["@context:elevated"]?.color.background.action.primary.default).toBe(
|
||||
expect(darkTheme.contexts["@context:elevated"]?.background.action.primary.default).toBe(
|
||||
darkTheme.hue.accent[400],
|
||||
)
|
||||
expect(darkTheme.contexts["@context:elevated"]?.color.text.action.primary.default).toBe(
|
||||
expect(darkTheme.contexts["@context:elevated"]?.text.action.primary.default).toBe(
|
||||
darkTheme.hue.neutral[100],
|
||||
)
|
||||
expect(darkTheme.contexts["@context:overlay"]?.color.background.action.primary.default).toBe(
|
||||
expect(darkTheme.contexts["@context:overlay"]?.background.action.primary.default).toBe(
|
||||
darkTheme.hue.accent[400],
|
||||
)
|
||||
expect(darkTheme.contexts["@context:overlay"]?.color.text.action.primary.default).toBe(
|
||||
expect(darkTheme.contexts["@context:overlay"]?.text.action.primary.default).toBe(
|
||||
darkTheme.hue.neutral[900],
|
||||
)
|
||||
})
|
||||
|
|
@ -50,16 +54,16 @@ test("merges partial files with the selected OpenCode defaults", () => {
|
|||
version: 2,
|
||||
light: {
|
||||
hue: light.hue,
|
||||
color: { text: { default: "#123456" } },
|
||||
text: { default: "#123456" },
|
||||
},
|
||||
dark: { hue: dark.hue },
|
||||
},
|
||||
"light",
|
||||
)
|
||||
|
||||
expect(theme.color.text.default.toInts()).toEqual([18, 52, 86, 255])
|
||||
expect(theme.color.text.subdued.toInts()).toEqual([18, 52, 86, 255])
|
||||
expect(theme.color.background.action.destructive.pressed).toBeInstanceOf(RGBA)
|
||||
expect(theme.text.default.toInts()).toEqual([18, 52, 86, 255])
|
||||
expect(theme.text.subdued.toInts()).toEqual([18, 52, 86, 255])
|
||||
expect(theme.background.action.destructive.pressed).toBeInstanceOf(RGBA)
|
||||
})
|
||||
|
||||
test("expands user structural fallbacks before merging defaults", () => {
|
||||
|
|
@ -68,7 +72,7 @@ test("expands user structural fallbacks before merging defaults", () => {
|
|||
version: 2,
|
||||
light: {
|
||||
hue: light.hue,
|
||||
color: { background: { action: { primary: { default: "#123456" } } } },
|
||||
background: { action: { primary: { default: "#123456" } } },
|
||||
},
|
||||
dark: { hue: dark.hue },
|
||||
},
|
||||
|
|
@ -79,17 +83,17 @@ test("expands user structural fallbacks before merging defaults", () => {
|
|||
version: 2,
|
||||
light: {
|
||||
hue: light.hue,
|
||||
color: { background: { action: { primary: { $pressed: "#654321" } } } },
|
||||
background: { action: { primary: { $pressed: "#654321" } } },
|
||||
},
|
||||
dark: { hue: dark.hue },
|
||||
},
|
||||
"light",
|
||||
)
|
||||
|
||||
expect(expanded.color.background.action.primary.pressed.toInts()).toEqual([18, 52, 86, 255])
|
||||
expect(isolatedState.color.background.action.primary.pressed.toInts()).toEqual([101, 67, 33, 255])
|
||||
expect(isolatedState.color.background.action.primary.hovered.toInts()).toEqual(
|
||||
resolveTheme(light).color.background.action.primary.hovered.toInts(),
|
||||
expect(expanded.background.action.primary.pressed.toInts()).toEqual([18, 52, 86, 255])
|
||||
expect(isolatedState.background.action.primary.pressed.toInts()).toEqual([101, 67, 33, 255])
|
||||
expect(isolatedState.background.action.primary.focused.toInts()).toEqual(
|
||||
resolveTheme(light).background.action.primary.focused.toInts(),
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -98,70 +102,89 @@ test("standalone themes skip OpenCode defaults and use the red core fallback", (
|
|||
const lightTheme = resolveThemeFile(file, "light")
|
||||
const darkTheme = resolveThemeFile(file, "dark")
|
||||
|
||||
expect(lightTheme.color.text.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(lightTheme.color.background.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(darkTheme.color.text.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(darkTheme.color.background.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(lightTheme.text.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(lightTheme.background.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(darkTheme.text.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
expect(darkTheme.background.default.toInts()).toEqual([255, 0, 0, 255])
|
||||
})
|
||||
|
||||
test("uses defaults for the selected mode when it merges the other mode", () => {
|
||||
const theme = resolveThemeFile({ version: 2, light: { hue: light.hue }, dark: { mergeMode: true } }, "dark")
|
||||
expect(theme.color.background.default.toInts()).toEqual(resolveTheme(dark).color.background.default.toInts())
|
||||
expect(theme.background.default.toInts()).toEqual(resolveTheme(dark).background.default.toInts())
|
||||
})
|
||||
|
||||
test("resolves matched action variants and states", () => {
|
||||
const theme = resolveTheme(light)
|
||||
|
||||
expect(theme.color.text.action.primary.pressed).toBeInstanceOf(RGBA)
|
||||
expect(theme.color.background.action.primary.pressed).toBeInstanceOf(RGBA)
|
||||
expect(theme.color.text.action.secondary.default).toBeInstanceOf(RGBA)
|
||||
expect(theme.color.background.action.destructive.disabled).toBeInstanceOf(RGBA)
|
||||
expect(theme.text.action.primary.pressed).toBeInstanceOf(RGBA)
|
||||
expect(theme.background.action.primary.pressed).toBeInstanceOf(RGBA)
|
||||
expect(theme.text.action.secondary.default).toBeInstanceOf(RGBA)
|
||||
expect(theme.background.action.destructive.disabled).toBeInstanceOf(RGBA)
|
||||
})
|
||||
|
||||
test("resolves transparent colors", () => {
|
||||
const theme = resolveThemeFile({
|
||||
version: 2,
|
||||
light: { background: { formfield: { default: "transparent" } } },
|
||||
dark: { background: { formfield: { default: "transparent" } } },
|
||||
})
|
||||
expect(theme.background.formfield.default.toInts()).toEqual([0, 0, 0, 0])
|
||||
})
|
||||
|
||||
test("reports theme decoding failures as native errors", () => {
|
||||
expect(() =>
|
||||
resolveThemeFile(
|
||||
{
|
||||
version: 2,
|
||||
light: { text: { default: "opaque" } },
|
||||
dark: {},
|
||||
} as never,
|
||||
"light",
|
||||
"custom",
|
||||
),
|
||||
).toThrow('Invalid theme: custom "opaque" is an invalid value')
|
||||
})
|
||||
|
||||
test("context overrides rewire semantic references and apply state precedence", () => {
|
||||
const definition = override(light, {
|
||||
color: {
|
||||
text: {
|
||||
default: "#111111",
|
||||
action: {
|
||||
primary: { default: "$color.text.default", $pressed: "#222222" },
|
||||
secondary: { default: "$color.text.default" },
|
||||
},
|
||||
text: {
|
||||
default: "#111111",
|
||||
action: {
|
||||
primary: { default: "$text.default", $pressed: "#222222" },
|
||||
secondary: { default: "$text.default" },
|
||||
},
|
||||
},
|
||||
"@context:elevated": {
|
||||
color: {
|
||||
text: {
|
||||
default: "#333333",
|
||||
action: { primary: { default: "#444444", $selected: "#555555" } },
|
||||
},
|
||||
text: {
|
||||
default: "#333333",
|
||||
action: { primary: { default: "#444444", $focused: "#555555" } },
|
||||
},
|
||||
},
|
||||
})
|
||||
const theme = resolveTheme(definition)
|
||||
const overlay = theme.contexts["@context:elevated"]!
|
||||
|
||||
expect(overlay.color.text.default.toInts()).toEqual([51, 51, 51, 255])
|
||||
expect(overlay.color.text.action.secondary.default.toInts()).toEqual([51, 51, 51, 255])
|
||||
expect(overlay.color.text.action.primary.pressed.toInts()).toEqual([68, 68, 68, 255])
|
||||
expect(overlay.color.text.action.primary.selected.toInts()).toEqual([85, 85, 85, 255])
|
||||
expect(overlay.text.default.toInts()).toEqual([51, 51, 51, 255])
|
||||
expect(overlay.text.action.secondary.default.toInts()).toEqual([51, 51, 51, 255])
|
||||
expect(overlay.text.action.primary.pressed.toInts()).toEqual([68, 68, 68, 255])
|
||||
expect(overlay.text.action.primary.focused.toInts()).toEqual([85, 85, 85, 255])
|
||||
})
|
||||
|
||||
test("rejects missing, base, and contextual reference cycles", () => {
|
||||
expect(() => resolveTheme(override(light, { color: { text: { default: "$missing.color" } } }))).toThrow(
|
||||
'Theme reference "$missing.color" was not found',
|
||||
expect(() => resolveTheme(override(light, { text: { default: "$missing" } }))).toThrow(
|
||||
'Theme reference "$missing" was not found',
|
||||
)
|
||||
expect(() =>
|
||||
resolveTheme(
|
||||
override(light, {
|
||||
color: { text: { default: "$color.text.subdued", subdued: "$color.text.default" } },
|
||||
text: { default: "$text.subdued", subdued: "$text.default" },
|
||||
}),
|
||||
),
|
||||
).toThrow("Circular theme reference")
|
||||
expect(() =>
|
||||
resolveTheme(
|
||||
override(light, {
|
||||
"@context:elevated": { color: { text: { default: "$color.text.default" } } },
|
||||
"@context:elevated": { text: { default: "$text.default" } },
|
||||
}),
|
||||
),
|
||||
).toThrow("Circular theme reference")
|
||||
|
|
@ -179,9 +202,9 @@ test("validates complete hues, resolved groups, and hue-only syntax", () => {
|
|||
expect(() =>
|
||||
resolveTheme({
|
||||
...light,
|
||||
color: { ...light.color, syntax: { ...light.color?.syntax, keyword: "$color.text.default" } },
|
||||
syntax: { ...light.syntax, keyword: "$text.default" },
|
||||
} as unknown as ThemeDefinition),
|
||||
).toThrow("$color.text.default")
|
||||
).toThrow("$text.default")
|
||||
})
|
||||
|
||||
function override(base: ThemeDefinition, value: Partial<ThemeDefinition>) {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import type { HueDefinition, ThemeDefinition, ThemeFile } from "../../../src/the
|
|||
import { selectTheme, selectThemeMode } from "../../../src/theme/v2/select"
|
||||
|
||||
const hue = {} as HueDefinition
|
||||
const light = { hue, color: { text: { default: "#111111", subdued: "#222222" } } } satisfies ThemeDefinition
|
||||
const dark = { hue, color: { text: { default: "#eeeeee", subdued: "#dddddd" } } } satisfies ThemeDefinition
|
||||
const light = { hue, text: { default: "#111111", subdued: "#222222" } } satisfies ThemeDefinition
|
||||
const dark = { hue, text: { default: "#eeeeee", subdued: "#dddddd" } } satisfies ThemeDefinition
|
||||
|
||||
test("requires and selects independent light and dark themes", () => {
|
||||
const file = { version: 2, light, dark } satisfies ThemeFile
|
||||
|
|
@ -18,13 +18,13 @@ test("merges an expanded mode override over the other mode", () => {
|
|||
const file = {
|
||||
version: 2,
|
||||
light,
|
||||
dark: { mergeMode: true, color: { text: { default: "#ffffff" } } },
|
||||
dark: { mergeMode: true, text: { default: "#ffffff" } },
|
||||
} satisfies ThemeFile
|
||||
const selected = selectTheme(file, "dark")
|
||||
|
||||
expect(selected.hue).toBeDefined()
|
||||
expect(selected.color?.text?.default).toBe("#ffffff")
|
||||
expect(selected.color?.text?.subdued).toBe("$color.text.default")
|
||||
expect(selected.text?.default).toBe("#ffffff")
|
||||
expect(selected.text?.subdued).toBe("$text.default")
|
||||
})
|
||||
|
||||
test("rejects mutual mode merging", () => {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const text = {
|
|||
secondary: { default: "$hue.neutral.900" },
|
||||
destructive: { default: "$hue.red.100", $disabled: "$hue.neutral.500" },
|
||||
},
|
||||
formfield: { default: "$hue.neutral.600", $selected: "$hue.neutral.100" },
|
||||
feedback: {
|
||||
error: { default: "$hue.red.700", subdued: "$hue.red.600" },
|
||||
},
|
||||
|
|
@ -16,32 +17,36 @@ const text = {
|
|||
|
||||
const background = {
|
||||
default: "$hue.neutral.100",
|
||||
surface: { offset: "$hue.neutral.200", overlay: "$hue.neutral.300" },
|
||||
action: {
|
||||
primary: { default: "$hue.accent.600", $pressed: "$hue.accent.800" },
|
||||
secondary: { default: "$hue.neutral.200" },
|
||||
destructive: { default: "$hue.red.600" },
|
||||
},
|
||||
formfield: { default: "$hue.neutral.100", $selected: "$hue.accent.600" },
|
||||
feedback: { error: { default: "$hue.red.100" } },
|
||||
} satisfies BackgroundDefinition
|
||||
|
||||
const definition = {
|
||||
hue: {} as ThemeDefinition["hue"],
|
||||
color: { text, background, border: { default: "$hue.neutral.300" } },
|
||||
text,
|
||||
background,
|
||||
border: { default: "$hue.neutral.300" },
|
||||
"@context:elevated": {
|
||||
color: {
|
||||
text: { default: "$hue.neutral.800" },
|
||||
background: { default: "$hue.neutral.200" },
|
||||
},
|
||||
text: { default: "$hue.neutral.800" },
|
||||
background: { default: "$hue.neutral.200" },
|
||||
},
|
||||
"@context:overlay": { color: { background: { default: "$hue.neutral.300" } } },
|
||||
"@context:overlay": { background: { default: "$hue.neutral.300" } },
|
||||
} satisfies ThemeDefinition
|
||||
|
||||
const file = { version: 2, light: definition, dark: definition } satisfies ThemeFile
|
||||
|
||||
test("supports property-first definitions, variants, states, and contexts", () => {
|
||||
expect(text.action.primary.$pressed).toBe("$hue.neutral.200")
|
||||
expect(text.formfield.$selected).toBe("$hue.neutral.100")
|
||||
expect(background.action.destructive.default).toBe("$hue.red.600")
|
||||
expect(definition["@context:elevated"].color?.text?.default).toBe("$hue.neutral.800")
|
||||
expect(definition["@context:overlay"].color?.background?.default).toBe("$hue.neutral.300")
|
||||
expect(background.surface.offset).toBe("$hue.neutral.200")
|
||||
expect(definition["@context:elevated"].text?.default).toBe("$hue.neutral.800")
|
||||
expect(definition["@context:overlay"].background?.default).toBe("$hue.neutral.300")
|
||||
expect(file.light).toBe(definition)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,24 +8,47 @@ test("migrates resolved V1 modes into literal V2 tokens", () => {
|
|||
const legacy = resolveV1(DEFAULT_THEMES.opencode, "light")
|
||||
const resolved = resolveThemeFile(migrated, "light")
|
||||
|
||||
expect(migrated.standalone).toBeUndefined()
|
||||
expect(migrated.standalone).toBeTrue()
|
||||
expect(migrated.light.hue?.accent).toBeObject()
|
||||
if (typeof migrated.light.hue?.accent !== "object") throw new Error("Expected a concrete accent scale")
|
||||
expect(migrated.light.hue.accent[300]).toBe(hex(legacy.accent))
|
||||
expect(migrated.light.color?.background?.default).toBe(hex(legacy.background))
|
||||
expect(migrated.light.color?.background?.action?.primary?.default).toBe(hex(legacy.primary))
|
||||
expect(migrated.light.color?.text?.action?.primary?.default).toBe(hex(selectedForeground(legacy, legacy.primary)))
|
||||
expect(migrated.light.color?.scrollbar?.default).toBe(hex(legacy.borderActive))
|
||||
expect(migrated.light.color?.diff?.lineNumber?.background?.removed).toBe(hex(legacy.diffRemovedLineNumberBg))
|
||||
expect(migrated.light.color?.markdown?.emphasis).toBe(hex(legacy.markdownEmph))
|
||||
expect(resolved.color.background.action.secondary.hovered.toInts()).toEqual(legacy.backgroundElement.toInts())
|
||||
expect(resolved.color.background.feedback.error.default.toInts()).toEqual(legacy.background.toInts())
|
||||
expect(resolved.contexts["@context:elevated"]?.color.background.default.toInts()).toEqual(
|
||||
expect(migrated.light.hue.accent[500]).toBe(hex(legacy.secondary))
|
||||
expect(migrated.light.background?.default).toBe(hex(legacy.background))
|
||||
expect(migrated.light.background?.action?.primary?.default).toBe(hex(legacy.primary))
|
||||
expect(migrated.light.text?.action?.primary?.default).toBe(hex(selectedForeground(legacy, legacy.primary)))
|
||||
expect(migrated.light.scrollbar?.default).toBe(hex(legacy.borderActive))
|
||||
expect(migrated.light.diff?.lineNumber?.background?.removed).toBe(hex(legacy.diffRemovedLineNumberBg))
|
||||
expect(migrated.light.markdown?.emphasis).toBe(hex(legacy.markdownEmph))
|
||||
expect(resolved.background.action.secondary.focused.toInts()).toEqual(legacy.backgroundElement.toInts())
|
||||
expect(resolved.background.surface.offset.toInts()).toEqual(legacy.backgroundPanel.toInts())
|
||||
expect(resolved.background.surface.overlay.toInts()).toEqual(legacy.backgroundMenu.toInts())
|
||||
expect(resolved.background.formfield.selected.toInts()).toEqual(legacy.background.toInts())
|
||||
expect(resolved.background.formfield.focused.toInts()).toEqual(legacy.background.toInts())
|
||||
expect(resolved.text.formfield.default.toInts()).toEqual(legacy.text.toInts())
|
||||
expect(resolved.text.formfield.selected.toInts()).toEqual(legacy.primary.toInts())
|
||||
expect(resolved.text.formfield.focused.toInts()).toEqual(legacy.primary.toInts())
|
||||
expect(resolved.hue.accent[500].toInts()).toEqual(legacy.secondary.toInts())
|
||||
expect(resolved.hue.accent[300].r + resolved.hue.accent[300].g + resolved.hue.accent[300].b).toBeGreaterThan(
|
||||
resolved.hue.accent[500].r + resolved.hue.accent[500].g + resolved.hue.accent[500].b,
|
||||
)
|
||||
expect(resolved.background.feedback.error.default.toInts()).toEqual(legacy.background.toInts())
|
||||
expect(resolved.contexts["@context:elevated"]?.background.default.toInts()).toEqual(
|
||||
legacy.backgroundPanel.toInts(),
|
||||
)
|
||||
expect(resolved.contexts["@context:overlay"]?.color.background.default.toInts()).toEqual(
|
||||
expect(resolved.contexts["@context:elevated"]?.background.action.secondary.default.toInts()).toEqual(
|
||||
legacy.backgroundPanel.toInts(),
|
||||
)
|
||||
expect(resolved.contexts["@context:elevated"]?.background.action.primary.default.toInts()).toEqual(
|
||||
legacy.primary.toInts(),
|
||||
)
|
||||
expect(resolved.contexts["@context:elevated"]?.text.action.primary.default.toInts()).toEqual(
|
||||
selectedForeground(legacy, legacy.primary).toInts(),
|
||||
)
|
||||
expect(resolved.contexts["@context:overlay"]?.background.default.toInts()).toEqual(
|
||||
legacy.backgroundMenu.toInts(),
|
||||
)
|
||||
expect(resolved.contexts["@context:overlay"]?.background.action.primary.default.toInts()).toEqual(
|
||||
legacy.primary.toInts(),
|
||||
)
|
||||
})
|
||||
|
||||
test("preserves V1 selected foreground behavior on transparent backgrounds", () => {
|
||||
|
|
@ -35,8 +58,8 @@ test("preserves V1 selected foreground behavior on transparent backgrounds", ()
|
|||
delete source.theme.selectedListItemText
|
||||
const migrated = migrateV1(source)
|
||||
|
||||
expect(migrated.light.color?.text?.action?.primary?.default).toBe("#000000")
|
||||
expect(migrated.dark.color?.text?.action?.primary?.default).toBe("#ffffff")
|
||||
expect(migrated.light.text?.action?.primary?.default).toBe("#000000")
|
||||
expect(migrated.dark.text?.action?.primary?.default).toBe("#ffffff")
|
||||
})
|
||||
|
||||
test("retains V1 circular reference errors", () => {
|
||||
|
|
@ -50,8 +73,8 @@ test("retains V1 circular reference errors", () => {
|
|||
test("migrates every built-in V1 theme in both modes", () => {
|
||||
for (const source of Object.values(DEFAULT_THEMES)) {
|
||||
const migrated = migrateV1(source)
|
||||
expect(resolveThemeFile(migrated, "light").color.text.default).toBeDefined()
|
||||
expect(resolveThemeFile(migrated, "dark").color.text.default).toBeDefined()
|
||||
expect(resolveThemeFile(migrated, "light").text.default).toBeDefined()
|
||||
expect(resolveThemeFile(migrated, "dark").text.default).toBeDefined()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue