diff --git a/packages/tui/src/component/dialog-session-list.tsx b/packages/tui/src/component/dialog-session-list.tsx
index 04783790e46..b1067fa8598 100644
--- a/packages/tui/src/component/dialog-session-list.tsx
+++ b/packages/tui/src/component/dialog-session-list.tsx
@@ -20,7 +20,7 @@ export function DialogSessionList() {
const dialog = useDialog()
const route = useRoute()
const data = useData()
- const { theme } = useTheme()
+ const { themeV2, mode } = useTheme().contextual("elevated")
const client = useClient()
const local = useLocal()
const toast = useToast()
@@ -109,12 +109,13 @@ export function DialogSessionList() {
value: session.id,
category,
footer,
- bg: deleting ? theme.error : undefined,
+ bg: deleting ? themeV2.background.action.destructive.focused : undefined,
+ fg: deleting ? themeV2.text.action.destructive.focused : undefined,
gutter: data.session.family(session.id).some((id) => data.session.status(id) === "running")
? () =>
: slot === undefined
? undefined
- : () => {slot},
+ : () => {slot},
}
}
@@ -142,12 +143,14 @@ export function DialogSessionList() {
}}
emptyView={
- No sessions available
+ No sessions available
}
noMatchView={
- {searchState().message}
+
+ {searchState().message}
+
}
onMove={() => setToDelete(undefined)}
diff --git a/packages/tui/src/component/dialog-stash.tsx b/packages/tui/src/component/dialog-stash.tsx
index cefe315ee3a..80aa75250cb 100644
--- a/packages/tui/src/component/dialog-stash.tsx
+++ b/packages/tui/src/component/dialog-stash.tsx
@@ -29,7 +29,7 @@ function getStashPreview(input: string, maxLength: number = 50): string {
export function DialogStash(props: { onSelect: (entry: StashEntry) => void }) {
const dialog = useDialog()
const stash = usePromptStash()
- const { theme } = useTheme()
+ const { themeV2 } = useTheme().contextual("elevated")
const shortcuts = Keymap.useShortcuts()
const [toDelete, setToDelete] = createSignal()
@@ -45,7 +45,8 @@ export function DialogStash(props: { onSelect: (entry: StashEntry) => void }) {
title: isDeleting
? `Press ${shortcuts.get("stash.delete")} again to confirm`
: getStashPreview(entry.prompt.text),
- bg: isDeleting ? theme.error : undefined,
+ bg: isDeleting ? themeV2.background.action.destructive.focused : undefined,
+ fg: isDeleting ? themeV2.text.action.destructive.focused : undefined,
value: index,
description: getRelativeTime(entry.timestamp),
footer: lineCount > 1 ? `~${lineCount} lines` : undefined,
diff --git a/packages/tui/src/component/prompt/autocomplete.tsx b/packages/tui/src/component/prompt/autocomplete.tsx
index 5dd80ee3967..921d096819c 100644
--- a/packages/tui/src/component/prompt/autocomplete.tsx
+++ b/packages/tui/src/component/prompt/autocomplete.tsx
@@ -12,7 +12,7 @@ import { getScrollAcceleration } from "../../util/scroll"
import { useTuiPaths } from "../../context/runtime"
import { useConfig } from "../../config"
import { useLocation } from "../../context/location"
-import { useTheme, selectedForeground } from "../../context/theme"
+import { useTheme } from "../../context/theme"
import { SplitBorder } from "../../ui/border"
import { useTerminalDimensions } from "@opentui/solid"
import { Locale } from "../../util/locale"
@@ -57,7 +57,7 @@ export function Autocomplete(props: {
const data = useData()
const keymap = Keymap.use()
const keymapCommands = Keymap.useCommands()
- const { theme } = useTheme()
+ const { themeV2 } = useTheme().contextual("overlay")
const dimensions = useTerminalDimensions()
const frecency = useFrecency()
const config = useConfig().data
@@ -698,11 +698,11 @@ export function Autocomplete(props: {
width={position().width}
zIndex={100}
{...SplitBorder}
- borderColor={theme.border}
+ borderColor={themeV2.border.default}
>
(scroll = r)}
- backgroundColor={theme.backgroundMenu}
+ backgroundColor={themeV2.background.default}
height={height()}
scrollbarOptions={{ visible: false }}
scrollAcceleration={scrollAcceleration()}
@@ -711,7 +711,9 @@ export function Autocomplete(props: {
each={options()}
fallback={
- {emptyMessage()}
+
+ {emptyMessage()}
+
}
>
@@ -719,7 +721,7 @@ export function Autocomplete(props: {
{
setStore("input", "mouse")
@@ -734,11 +736,17 @@ export function Autocomplete(props: {
}}
onMouseUp={() => select()}
>
-
+
{option().display}
-
+
{" " + option().description?.trimStart()}
diff --git a/packages/tui/src/ui/dialog-select.tsx b/packages/tui/src/ui/dialog-select.tsx
index 257de75b179..88248c92d34 100644
--- a/packages/tui/src/ui/dialog-select.tsx
+++ b/packages/tui/src/ui/dialog-select.tsx
@@ -1,6 +1,6 @@
import { InputRenderable, RGBA, ScrollBoxRenderable, TextAttributes } from "@opentui/core"
import { Keymap, type KeymapCommand } from "../context/keymap"
-import { useTheme, selectedForeground } from "../context/theme"
+import { useTheme } from "../context/theme"
import { entries, filter, flatMap, groupBy, pipe } from "remeda"
import { batch, createEffect, createMemo, createSignal, For, Show, type JSX, on, onCleanup } from "solid-js"
import { createStore } from "solid-js/store"
@@ -74,6 +74,7 @@ export interface DialogSelectOption {
categoryView?: JSX.Element
disabled?: boolean
bg?: RGBA
+ fg?: RGBA
gutter?: () => JSX.Element
margin?: JSX.Element
onSelect?: (ctx: DialogContext) => void
@@ -91,7 +92,7 @@ export function DialogSelect(props: DialogSelectProps) {
type VisibleAction = (Action & { label: string }) | FooterHint
const dialog = useDialog()
- const { theme } = useTheme()
+ const { themeV2, mode } = useTheme().contextual("elevated")
const config = useConfig().data
const scrollAcceleration = createMemo(() => getScrollAcceleration(config))
@@ -517,29 +518,44 @@ export function DialogSelect(props: DialogSelectProps) {
if (!isActionItem(action.item))
return (
-
+
{action.item.title}{" "}
- {action.item.label}
+ {action.item.label}
)
const item = action.item
const active = createMemo(() => isActionFocused(item))
const disabled = createMemo(() => isActionDisabled(item))
- const fg = selectedForeground(theme)
return (
trigger(item)}
>
{item.title}
- {item.label}
+
+ {" " + item.label}
+
)
}
@@ -549,11 +565,11 @@ export function DialogSelect(props: DialogSelectProps) {
{props.titleView ?? (
-
+
{props.title}
)}
- dialog.clear()}>
+ dialog.clear()}>
esc
@@ -567,9 +583,9 @@ export function DialogSelect(props: DialogSelectProps) {
props.onFilter?.(e)
})
}}
- focusedBackgroundColor={theme.backgroundPanel}
- cursorColor={theme.primary}
- focusedTextColor={theme.textMuted}
+ focusedBackgroundColor={themeV2.background.formfield.focused}
+ cursorColor={themeV2.text.formfield.focused}
+ focusedTextColor={themeV2.text.formfield.focused}
ref={(r) => {
input = r
input.traits = { status: "FILTER" }
@@ -580,7 +596,7 @@ export function DialogSelect(props: DialogSelectProps) {
}, 1)
}}
placeholder={props.placeholder ?? "Search"}
- placeholderColor={theme.textMuted}
+ placeholderColor={themeV2.text.subdued}
/>
@@ -594,14 +610,14 @@ export function DialogSelect(props: DialogSelectProps) {
fallback={
props.emptyView ?? (
- No items available
+ No items available
)
}
>
{props.noMatchView ?? (
- No results found
+ No results found
)}
@@ -623,7 +639,10 @@ export function DialogSelect(props: DialogSelectProps) {
+
{category}
}
@@ -672,8 +691,8 @@ export function DialogSelect(props: DialogSelectProps) {
backgroundColor={
active()
? actionFocused()
- ? theme.backgroundElement
- : (option.bg ?? theme.primary)
+ ? themeV2.background.surface.overlay
+ : (option.bg ?? themeV2.background.action.primary.focused)
: RGBA.fromInts(0, 0, 0, 0)
}
>
@@ -692,6 +711,7 @@ export function DialogSelect(props: DialogSelectProps) {
active={active()}
current={current()}
muted={actionFocused()}
+ activeColor={option.fg}
gutter={option.gutter}
/>
@@ -699,7 +719,7 @@ export function DialogSelect(props: DialogSelectProps) {
{(detail) => (
{option.detailsWrap
@@ -745,15 +765,15 @@ function Option(props: {
titleWidth?: number
truncateTitle?: boolean | "left"
gutter?: () => JSX.Element
+ activeColor?: RGBA
onMouseOver?: () => void
}) {
- const { theme } = useTheme()
- const fg = selectedForeground(theme)
+ const { themeV2 } = useTheme().contextual("elevated")
const text = createMemo(() => {
- if (props.active && !props.muted) return fg
- if (props.muted && (props.active || props.current)) return theme.textMuted
- if (props.current) return theme.primary
- return theme.text
+ if (props.active && !props.muted) return props.activeColor ?? themeV2.text.action.primary.focused
+ if (props.muted && (props.active || props.current)) return themeV2.text.subdued
+ if (props.current) return themeV2.text.formfield.selected
+ return themeV2.text.default
})
return (
@@ -783,12 +803,14 @@ function Option(props: {
? Locale.truncateLeft(props.title, props.titleWidth ?? 61)
: Locale.truncate(props.title, props.titleWidth ?? 61))}
- {props.description}
+
+ {" " + props.description}
+
- {props.footer}
+ {props.footer}
>