feat(plugins): add theme contributions

Adds plugin-contributed light and dark app themes, including persistence, host-aware coalescing, fallback behavior, documentation, examples, and browser/iOS QA.
This commit is contained in:
Okan YILDIRIM
2026-08-21 11:48:12 +02:00
committed by GitHub
parent a7f3bf7abb
commit e1805ef542
41 changed files with 1238 additions and 203 deletions
+65 -7
View File
@@ -13,6 +13,7 @@ Local plugins are directory sources installed into one Paseo daemon. A plugin ca
- React Native surfaces and sidebar items to Paseo clients;
- workspace and agent panels opened as workspace tabs;
- global, workspace, and agent actions in the Command Center;
- dark themes in Settings → Appearance;
- schema-validated RPC handlers running beside the daemon;
- normal Paseo operations through the TypeScript SDK;
- searchable external resources in the message composer.
@@ -150,13 +151,16 @@ Plugin UI runs on desktop, browser, iOS, and Android, across every Paseo theme.
Recreate styles when `theme` or `layout.compact` changes.
| Key | Required for | Use it for |
| ------------------------------ | -------------------------- | ----------------------------------- |
| `theme.colors.foreground` | Every primary `Text` | Titles and body copy |
| `theme.colors.foregroundMuted` | Secondary `Text` | Labels and supporting copy |
| `theme.colors.surface0` | Root view | Panel background |
| `layout.compact` | Padding and stacking | `true` on mobile and narrow windows |
| `layout.platform` | Platform-specific behavior | `ios`, `android`, or `web` |
| Key | Required for | Use it for |
| ------------------------------- | -------------------------- | ----------------------------------- |
| `theme.colors.foreground` | Every primary `Text` | Titles and body copy |
| `theme.colors.foregroundMuted` | Secondary `Text` | Labels and supporting copy |
| `theme.colors.surface0` | Root view | Panel background |
| `theme.colors.accent` | Primary action fills | Buttons and selected states |
| `theme.colors.accentForeground` | Text on an accent fill | Button labels |
| `theme.colors.statusDanger` | Failure copy | Error messages and destructive text |
| `layout.compact` | Padding and stacking | `true` on mobile and narrow windows |
| `layout.platform` | Platform-specific behavior | `ios`, `android`, or `web` |
Do not hardcode `#000`, `#fff`, or React Native's default text color. Primary copy uses `foreground`. Labels use `foregroundMuted`. Tighten padding when `layout.compact` is true.
@@ -164,6 +168,60 @@ Workspace and agent panels receive the same `theme` and `layout` fields.
Client code can import `react`, `react-native`, `@tanstack/react-query`, `zod`, `@getpaseo/plugin`, and `@getpaseo/plugin/server`. Install them locally for typechecking; Paseo provides the client runtime instances.
## Contribute a theme
`addTheme` adds a light or dark theme to Settings → Appearance, listed under the built-ins by its `name`. A
theme is data, so it needs no client file:
```ts
import type { PluginContext } from "@getpaseo/plugin";
export default function contribute(plugin: PluginContext) {
plugin.addTheme({
id: "mocha",
name: "Catppuccin Mocha",
appearance: "dark",
colors: {
background: "#1e1e2e",
foreground: "#cdd6f4",
raised: "#313244",
control: "#45475a",
border: "#45475a",
accent: "#cba6f7",
mutedForeground: "#a6adc8",
ring: "#6c7086",
},
});
return () => {};
}
```
Every color is a hex string; anything else fails to load. Paseo expands the palette into the full
token set the built-in dark themes use, so a contributed theme covers panels, menus, diffs, status
colors, and the terminal without listing them.
| Color | Becomes |
| ----------------- | ----------------------------------------------------------------- |
| `background` | App, workspace, and terminal background |
| `foreground` | Primary text, terminal foreground and cursor |
| `raised` | Cards, popovers, and hovered rows |
| `control` | Inputs, secondary fills, and the light-theme sidebar |
| `border` | Borders and the highest raised-surface tint |
| `accent` | Buttons, selection, and focus. Optional; `foreground` if omitted. |
| `mutedForeground` | Secondary text |
| `ring` | Focus rings, scrollbars, and terminal bright black |
`appearance` is `"light"` or `"dark"`. Paseo uses it to select the matching surface, status,
diff, syntax, terminal, and shadow derivation.
Only one contributed theme is active at a time. Selecting one persists the choice; if the plugin is
later disabled or removed, Paseo falls back to the default theme rather than leaving the app
unpainted.
Themes need a host that supports them. A daemon released before `addTheme` compiles the call into
the plugin's backend bundle, where it does not exist, and the plugin fails to start with
`plugin.addTheme is not a function`. Update the host.
## Workspace panels
Register one panel for workspace or agent context: