feat(tui): support single-mode themes (#37930)
This commit is contained in:
parent
3f4fb3f9db
commit
7be95bcd6a
13 changed files with 283 additions and 77 deletions
72
packages/tui/test/cli/tui/theme-mode.test.tsx
Normal file
72
packages/tui/test/cli/tui/theme-mode.test.tsx
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/** @jsxImportSource @opentui/solid */
|
||||
import { testRender } from "@opentui/solid"
|
||||
import { expect, test } from "bun:test"
|
||||
import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
|
||||
import { DEFAULT_THEMES } from "../../../src/theme"
|
||||
import { ConfigProvider } from "../../../src/config"
|
||||
import { ThemeProvider, useTheme } from "../../../src/context/theme"
|
||||
|
||||
async function wait(fn: () => boolean) {
|
||||
const started = Date.now()
|
||||
while (!fn()) {
|
||||
if (Date.now() - started > 2000) throw new Error("timed out waiting for theme mode")
|
||||
await Bun.sleep(10)
|
||||
}
|
||||
}
|
||||
|
||||
test("uses an available mode while retaining the pinned preference", async () => {
|
||||
const lightOnly = structuredClone(DEFAULT_THEMES.opencode)
|
||||
lightOnly.theme.background = "#eeeeee"
|
||||
lightOnly.theme.text = "#111111"
|
||||
const dual = structuredClone(DEFAULT_THEMES.opencode)
|
||||
dual.theme.background = { light: "#eeeeee", dark: "#111111" }
|
||||
dual.theme.text = { light: "#111111", dark: "#eeeeee" }
|
||||
const darkOnly = structuredClone(DEFAULT_THEMES.opencode)
|
||||
darkOnly.theme.background = "#111111"
|
||||
darkOnly.theme.text = "#eeeeee"
|
||||
let theme: ReturnType<typeof useTheme> | undefined
|
||||
|
||||
function Probe() {
|
||||
const value = useTheme()
|
||||
theme = value
|
||||
return <text>{value.mode()}</text>
|
||||
}
|
||||
|
||||
function current() {
|
||||
if (!theme) throw new Error("Theme provider is not mounted")
|
||||
return theme
|
||||
}
|
||||
|
||||
const app = await testRender(
|
||||
() => (
|
||||
<ConfigProvider config={createTuiResolvedConfig({ theme: { name: "light-only", mode: "dark" } })}>
|
||||
<ThemeProvider
|
||||
mode="dark"
|
||||
source={{ discover: () => Promise.resolve({ "light-only": lightOnly, "dark-only": darkOnly, dual }) }}
|
||||
>
|
||||
<Probe />
|
||||
</ThemeProvider>
|
||||
</ConfigProvider>
|
||||
),
|
||||
{ width: 20, height: 2 },
|
||||
)
|
||||
app.renderer.start()
|
||||
|
||||
try {
|
||||
await wait(() => theme?.ready === true)
|
||||
expect(current().mode()).toBe("light")
|
||||
expect(current().modes()).toEqual(["light"])
|
||||
expect(current().supports("dark")).toBeFalse()
|
||||
expect(current().setMode("dark")).toBeFalse()
|
||||
expect(current().set("dark-only")).toBeTrue()
|
||||
await wait(() => current().mode() === "dark")
|
||||
expect(current().modes()).toEqual(["dark"])
|
||||
expect(current().set("light-only")).toBeTrue()
|
||||
await wait(() => current().mode() === "light")
|
||||
expect(current().set("dual")).toBeTrue()
|
||||
await wait(() => current().mode() === "dark")
|
||||
expect(current().modes()).toEqual(["light", "dark"])
|
||||
} finally {
|
||||
app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue