overmux 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +16 -2
- package/dist/docs/200-getting-started/500-set-up-overmux-with-packages.md +42 -0
- package/dist/docs/400-reference/200-configuration.md +1 -1
- package/dist/docs/400-reference/500-server/500-api.md +1 -1
- package/dist/docs/400-reference/600-client/005-setting-up-your-ui.md +137 -0
- package/dist/docs/400-reference/600-client/007-deep-links.md +87 -0
- package/dist/docs/400-reference/600-client/010-commands.md +189 -0
- package/dist/docs/400-reference/600-client/020-shortcuts.md +171 -0
- package/dist/docs/400-reference/600-client/100-api.md +1 -1
- package/dist/docs/400-reference/600-client/200-theming.md +179 -64
- package/docs/200-getting-started/500-set-up-overmux-with-packages.md +42 -0
- package/docs/400-reference/200-configuration.md +1 -1
- package/docs/400-reference/500-server/500-api.md +1 -1
- package/docs/400-reference/600-client/005-setting-up-your-ui.md +137 -0
- package/docs/400-reference/600-client/007-deep-links.md +87 -0
- package/docs/400-reference/600-client/010-commands.md +189 -0
- package/docs/400-reference/600-client/020-shortcuts.md +171 -0
- package/docs/400-reference/600-client/100-api.md +1 -1
- package/docs/400-reference/600-client/200-theming.md +179 -64
- package/package.json +2 -2
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Commands
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Commands let you centralize a collection of named actions in your Overmux UI, such as “Close pane” or “Open settings”, so you can build a command palette, menu, or similar feature. They could also be triggered by [keyboard shortcuts](./shortcuts) or buttons.
|
|
6
|
+
|
|
7
|
+
Packages may also provide commands that you can use in your UI.
|
|
8
|
+
|
|
9
|
+
## Registering a command
|
|
10
|
+
|
|
11
|
+
Declare a command with `defineCommandRegistry`, then register its behavior inside a React component with `useCommand`.
|
|
12
|
+
|
|
13
|
+
### Basic registration
|
|
14
|
+
|
|
15
|
+
The handler can access the component’s state:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { useState } from "react";
|
|
19
|
+
import {
|
|
20
|
+
defineCommandRegistry,
|
|
21
|
+
defineOvermuxClient,
|
|
22
|
+
useCommand,
|
|
23
|
+
} from "overmux/client";
|
|
24
|
+
import type { serverConfig } from "./server";
|
|
25
|
+
|
|
26
|
+
const commands = defineCommandRegistry<typeof serverConfig>()({
|
|
27
|
+
openSettings: {
|
|
28
|
+
title: "Open settings",
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const App = () => {
|
|
33
|
+
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
34
|
+
|
|
35
|
+
useCommand(commands.openSettings, {
|
|
36
|
+
run: () => setSettingsOpen(true),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return settingsOpen ? <Settings /> : <Workspace />;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const client = defineOvermuxClient({
|
|
43
|
+
commands,
|
|
44
|
+
component: App,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`openSettings` is the command’s ID; `title` is its display name. `Settings` and `Workspace` represent your own components.
|
|
49
|
+
|
|
50
|
+
The handler is registered while `App` is mounted and removed when it unmounts. Registration does not execute the command.
|
|
51
|
+
|
|
52
|
+
### Disabling a command
|
|
53
|
+
|
|
54
|
+
Set `enabled` to prevent execution while keeping the command registered and visible through `useCommands()`:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
useCommand(commands.openSettings, {
|
|
58
|
+
enabled: !settingsOpen,
|
|
59
|
+
run: () => setSettingsOpen(true),
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`enabled` defaults to `true`.
|
|
64
|
+
|
|
65
|
+
### Passing parameters to a shared handler
|
|
66
|
+
|
|
67
|
+
Declare `params` with a Zod schema and provide `run` in the registry when the behavior can live outside React:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { z } from "zod";
|
|
71
|
+
|
|
72
|
+
const commands = defineCommandRegistry<typeof serverConfig>()({
|
|
73
|
+
killTmuxPane: {
|
|
74
|
+
title: "Kill pane",
|
|
75
|
+
params: z.object({ paneId: z.string() }),
|
|
76
|
+
run: ({ params, overmuxServerApi }) =>
|
|
77
|
+
overmuxServerApi.executeOperation("killTmuxPane", params),
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This assumes your server defines a `killTmuxPane` operation accepting `{ paneId: string }`. The handler runs client-side and calls that server operation.
|
|
83
|
+
|
|
84
|
+
The component supplies the current values:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
useCommand(commands.killTmuxPane, {
|
|
88
|
+
params: { paneId: pane.id },
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Parameters are type-checked and validated before execution. A registration can supply its own `run` to override the shared handler; that local handler takes no arguments and can read component state directly.
|
|
93
|
+
|
|
94
|
+
### Conditional registration
|
|
95
|
+
|
|
96
|
+
Pass `skipToken` when a parameterized command’s required context is missing:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { skipToken } from "overmux/client";
|
|
100
|
+
|
|
101
|
+
useCommand(
|
|
102
|
+
commands.killTmuxPane,
|
|
103
|
+
pane ? { params: { paneId: pane.id } } : skipToken,
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Unlike `enabled: false`, this skips registration entirely. Without another registration, the command will not appear in `useCommands()`. Keep the hook call unconditional.
|
|
108
|
+
|
|
109
|
+
### Registering a command in multiple components
|
|
110
|
+
|
|
111
|
+
Use `element` to associate each registration with a UI region:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
const paneRef = useRef<HTMLDivElement>(null);
|
|
115
|
+
|
|
116
|
+
useCommand(commands.killTmuxPane, {
|
|
117
|
+
params: { paneId: pane.id },
|
|
118
|
+
element: paneRef,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return <div ref={paneRef}>...</div>;
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Import `useRef` from React. When the command is triggered, Overmux prefers the registration whose element contains keyboard focus. For nested elements, the innermost wins.
|
|
125
|
+
|
|
126
|
+
If none contains focus, the most recently registered handler wins. `element` is a preference, not a restriction; use `enabled` to control availability. If the selected registration is disabled, nothing runs.
|
|
127
|
+
|
|
128
|
+
### Adding keyboard shortcuts
|
|
129
|
+
|
|
130
|
+
Set `defaultBindings` on a command declaration to give it keyboard triggers. See [Shortcuts](./shortcuts) for bindings and client overrides.
|
|
131
|
+
|
|
132
|
+
## Listing all registered commands
|
|
133
|
+
|
|
134
|
+
Use `useCommands()` to build a menu or command palette with all your registered commands.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { useCommands } from "overmux/client";
|
|
138
|
+
|
|
139
|
+
const CommandMenu = () => {
|
|
140
|
+
const commands = useCommands();
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<div>
|
|
144
|
+
{commands.map((command) => (
|
|
145
|
+
<button
|
|
146
|
+
key={command.id}
|
|
147
|
+
disabled={!command.enabled}
|
|
148
|
+
onClick={() => void command.execute()}
|
|
149
|
+
>
|
|
150
|
+
{command.title}
|
|
151
|
+
</button>
|
|
152
|
+
))}
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Each entry exposes `id`, `title`, `bindings`, `enabled`, and `execute()`. The list includes disabled commands but excludes commands without a registration.
|
|
159
|
+
|
|
160
|
+
Each command appears once, even if multiple components register it. `execute()` selects the handler using the current focus and runs it only if enabled.
|
|
161
|
+
|
|
162
|
+
## Using commands from packages
|
|
163
|
+
|
|
164
|
+
Packages can export commands to include alongside your own:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { sourceControlCommands } from "@overmux/git/react";
|
|
168
|
+
|
|
169
|
+
export const client = defineOvermuxClient({
|
|
170
|
+
commands: {
|
|
171
|
+
...commands,
|
|
172
|
+
...sourceControlCommands,
|
|
173
|
+
},
|
|
174
|
+
component: App,
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Adding commands to the registry does not register their handlers. For this package, pass the commands to `SourceControlView`:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
<SourceControlView
|
|
182
|
+
{...sourceControlProps}
|
|
183
|
+
commandHandles={sourceControlCommands}
|
|
184
|
+
/>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The view registers handlers for navigating changed files and scrolling diffs. They then appear in `useCommands()` alongside your own registered commands.
|
|
188
|
+
|
|
189
|
+
Keep command IDs unique when combining registries, and pass the same command objects to the client and the component.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shortcuts
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Shortcuts trigger [commands](./commands) from the keyboard. Define bindings on commands, then customize them in your client configuration.
|
|
6
|
+
|
|
7
|
+
## Adding shortcuts
|
|
8
|
+
|
|
9
|
+
Set `defaultBindings` on a command:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
const commands = defineCommandRegistry<typeof serverConfig>()({
|
|
13
|
+
openSettings: {
|
|
14
|
+
title: "Open settings",
|
|
15
|
+
defaultBindings: ["Mod+,"],
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The command must have a registered, enabled handler. See [Registering a command](./commands#registering-a-command).
|
|
21
|
+
|
|
22
|
+
## Binding syntax
|
|
23
|
+
|
|
24
|
+
A binding combines optional modifiers with a key:
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
defaultBindings: ["Mod+K"]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Use `Control`, `Alt`, `Shift`, or `Meta` for explicit modifiers. `Mod` means `Meta` (Command) on macOS and `Control` elsewhere.
|
|
31
|
+
|
|
32
|
+
Key names include uppercase letters, digits, `F1`–`F12`, and named keys such as `Enter`, `Escape`, `Space`, `Tab`, and `ArrowLeft`. Supported punctuation includes `/`, `[`, `]`, `\`, `=`, `-`, `,`, `.`, `;`, `:`, backtick, `'`, and `§`.
|
|
33
|
+
|
|
34
|
+
Modifiers use a fixed order: `Control+Alt+Shift+Meta`. With `Mod`, use `Mod+Alt+Shift`. Omit modifiers you do not need.
|
|
35
|
+
|
|
36
|
+
Use `Shift` with letters, function keys, or named keys, not digits or punctuation. For a colon, use `":"`, not `"Shift+;"`.
|
|
37
|
+
|
|
38
|
+
Multiple bindings provide alternative ways to trigger the same command:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
defaultBindings: ["Mod+K", "F2"]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Bindings match the key reported by the keyboard layout, not a physical key position. Holding a key does not repeatedly execute its command.
|
|
45
|
+
|
|
46
|
+
## Key sequences (chords)
|
|
47
|
+
|
|
48
|
+
Nest an array to require keys pressed in order:
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
defaultBindings: [["F12", "X"]]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Press F12, then X to trigger the command. Each step can include modifiers:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
defaultBindings: [["Control+K", "Control+C"]]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Overmux waits up to one second between steps. Escape cancels the pending sequence. A nonmatching key ends it.
|
|
61
|
+
|
|
62
|
+
Avoid assigning a complete shortcut to another sequence’s prefix: the complete shortcut runs immediately rather than waiting for more keys.
|
|
63
|
+
|
|
64
|
+
## Overriding shortcuts
|
|
65
|
+
|
|
66
|
+
Use `shortcutOverrides` in your client configuration, keyed by command ID:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
export const client = defineOvermuxClient({
|
|
70
|
+
commands,
|
|
71
|
+
component: App,
|
|
72
|
+
shortcutOverrides: {
|
|
73
|
+
openSettings: ["Mod+Shift+O"],
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
An override replaces all default bindings for that command. An empty array removes its keyboard shortcuts without disabling the command:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
shortcutOverrides: {
|
|
82
|
+
openSettings: [],
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Conditional shortcuts
|
|
87
|
+
|
|
88
|
+
Wrap a binding with `when.media` to activate it only while a CSS media query matches:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
defaultBindings: [
|
|
92
|
+
{
|
|
93
|
+
binding: "Mod+,",
|
|
94
|
+
when: { media: "(min-width: 800px)" },
|
|
95
|
+
},
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Conditional bindings work in both `defaultBindings` and `shortcutOverrides`, and update when the media query changes.
|
|
100
|
+
|
|
101
|
+
## Text inputs and terminals
|
|
102
|
+
|
|
103
|
+
Shortcuts do not run while an ordinary input, textarea, select, or editable text element has focus.
|
|
104
|
+
|
|
105
|
+
Terminals are an exception: modified keys, function keys, and multi-key sequences can trigger commands while typing. Plain single-key shortcuts are also allowed in terminal copy mode.
|
|
106
|
+
|
|
107
|
+
Matched shortcuts prevent the key’s normal browser or terminal behavior. Browser or operating-system shortcuts that never reach the page cannot be handled by Overmux.
|
|
108
|
+
|
|
109
|
+
### Replaying unmatched sequences
|
|
110
|
+
|
|
111
|
+
By default, keys intercepted for an incomplete sequence are discarded when it times out or fails to match.
|
|
112
|
+
|
|
113
|
+
Configure a prefix to replay those keys into a registered input instead. For example, suppose F12, then X closes a pane:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
const commands = defineCommandRegistry<typeof serverConfig>()({
|
|
117
|
+
closePane: {
|
|
118
|
+
title: "Close pane",
|
|
119
|
+
defaultBindings: [["F12", "X"]],
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Enable replay for F12 in your client configuration:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
export const client = defineOvermuxClient({
|
|
128
|
+
commands,
|
|
129
|
+
component: App,
|
|
130
|
+
chordPrefixes: [
|
|
131
|
+
{ binding: "F12", unmatched: "replay-to-focused-input" },
|
|
132
|
+
],
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
With the command’s handler registered and enabled, while a terminal has focus:
|
|
137
|
+
|
|
138
|
+
- **F12 → X:** closes the pane; neither key reaches the terminal.
|
|
139
|
+
- **F12 → Y:** no shortcut matches, so both F12 and Y are forwarded to the terminal.
|
|
140
|
+
- **F12 → wait one second:** F12 is forwarded to the terminal.
|
|
141
|
+
- **F12 → Escape:** cancels; neither key reaches the terminal.
|
|
142
|
+
|
|
143
|
+
This lets Overmux share a prefix with a terminal application rather than always swallowing it.
|
|
144
|
+
|
|
145
|
+
The tmux and Zellij terminal components already register replay targets. Custom terminal integrations can register one with:
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { useShortcutInputTarget } from "overmux/client";
|
|
149
|
+
|
|
150
|
+
useShortcutInputTarget({
|
|
151
|
+
container: containerRef,
|
|
152
|
+
input: inputRef,
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`container` identifies the focused UI region; `input` receives replayed keyboard events. If regions are nested, the innermost containing focus is selected when the sequence begins. Without a matching input target, intercepted keys cannot be replayed.
|
|
157
|
+
|
|
158
|
+
## Displaying bindings
|
|
159
|
+
|
|
160
|
+
Use `formatShortcutBinding` to format a binding for the current platform:
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
import { formatShortcutBinding } from "overmux/client";
|
|
164
|
+
|
|
165
|
+
formatShortcutBinding("Mod+K");
|
|
166
|
+
formatShortcutBinding(["F12", "X"]);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
On macOS, modifiers appear as symbols such as `⌘`; sequences display their steps separated by spaces.
|
|
170
|
+
|
|
171
|
+
Entries returned by [`useCommands()`](./commands#listing-all-registered-commands) expose their active, overridden bindings through `bindings`. Format those values to show shortcuts alongside command titles.
|
|
@@ -2,93 +2,208 @@
|
|
|
2
2
|
title: Theming and CSS
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Your
|
|
5
|
+
Your Overmux UI owns its CSS. Overmux provides shared theme variables, light/dark defaults, and theme scopes for individual sections.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Load your CSS
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Import your stylesheet from your browser entry point:
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
```tsx
|
|
12
|
+
import { OvermuxHost } from "overmux/client";
|
|
13
|
+
import { createRoot } from "react-dom/client";
|
|
14
|
+
|
|
15
|
+
import definition from "./app";
|
|
16
|
+
import "./styles.css";
|
|
17
|
+
|
|
18
|
+
createRoot(document.getElementById("root")!).render(
|
|
19
|
+
<OvermuxHost definition={definition} />,
|
|
20
|
+
);
|
|
21
|
+
```
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
Overmux components load their own styles automatically. Use ordinary CSS and component `className` props to customize them. Overmux defaults use CSS layers, so normal unlayered application styles take precedence.
|
|
17
24
|
|
|
18
|
-
##
|
|
25
|
+
## Choose light or dark
|
|
19
26
|
|
|
20
|
-
Set
|
|
27
|
+
Set appearance in your client definition:
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
| `--om-font-sans` | Font-family list | Interface text |
|
|
35
|
-
| `--om-font-mono` | Font-family list | Code and diagnostics |
|
|
36
|
-
| `--om-spacing` | Length | Spacing unit; components may scale it |
|
|
37
|
-
| `--om-radius` | Length | Corner radius; components may scale it |
|
|
38
|
-
| `--om-elevation` | Box-shadow | Panel and popover shadows |
|
|
39
|
-
| `--om-focus-ring` | Box-shadow | Focus-ring shadows |
|
|
40
|
-
| `--om-motion-duration` | Time | Transition duration |
|
|
29
|
+
```tsx
|
|
30
|
+
import { defineOvermuxClient } from "overmux/client";
|
|
31
|
+
|
|
32
|
+
export default defineOvermuxClient({
|
|
33
|
+
commands: {},
|
|
34
|
+
component: App,
|
|
35
|
+
appearance: {
|
|
36
|
+
scheme: "dark",
|
|
37
|
+
contrast: "auto",
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
- `scheme`: `"system"` (default), `"light"`, or `"dark"`.
|
|
43
|
+
- `contrast`: `"auto"` (default), `"normal"`, or `"high"`.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
`"system"` follows the system color preference. `"auto"` follows the system preference for increased contrast.
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
Appearance applies to your app and Overmux-owned UI inside `OvermuxHost`. It changes built-in defaults, not custom CSS variables.
|
|
48
|
+
|
|
49
|
+
## Set colors, fonts, and other theme variables
|
|
50
|
+
|
|
51
|
+
Define shared variables in your stylesheet. This example supplies a custom dark palette and every shared theme variable:
|
|
52
|
+
|
|
53
|
+
```css
|
|
54
|
+
:root {
|
|
55
|
+
--om-color-canvas: #111318;
|
|
56
|
+
--om-color-surface: #191c24;
|
|
57
|
+
--om-color-panel: #222735;
|
|
58
|
+
--om-color-fg: #eef0f6;
|
|
59
|
+
--om-color-muted: #a3adc2;
|
|
60
|
+
--om-color-border: #394156;
|
|
61
|
+
--om-color-accent: #b59aff;
|
|
62
|
+
--om-color-accent-fg: #111318;
|
|
63
|
+
--om-color-danger: #ff8b82;
|
|
64
|
+
--om-color-success: #65d6a2;
|
|
65
|
+
|
|
66
|
+
--om-font-sans: "Inter", sans-serif;
|
|
67
|
+
--om-font-mono: "JetBrains Mono", monospace;
|
|
68
|
+
|
|
69
|
+
--om-spacing: 0.75rem;
|
|
70
|
+
--om-radius: 0.5rem;
|
|
71
|
+
--om-elevation: 0 0.75rem 2rem rgb(0 0 0 / 30%);
|
|
72
|
+
--om-focus-ring: 0 0 0 3px rgb(181 154 255 / 30%);
|
|
73
|
+
--om-motion-duration: 120ms;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Colors
|
|
78
|
+
|
|
79
|
+
- `--om-color-canvas`: page background.
|
|
80
|
+
- `--om-color-surface`: content surface background.
|
|
81
|
+
- `--om-color-panel`: panel and grouped-content background.
|
|
82
|
+
- `--om-color-fg`: primary text.
|
|
83
|
+
- `--om-color-muted`: secondary text.
|
|
84
|
+
- `--om-color-border`: borders and separators.
|
|
85
|
+
- `--om-color-accent`: highlighted controls and actions.
|
|
86
|
+
- `--om-color-accent-fg`: text on an accent background.
|
|
87
|
+
- `--om-color-danger`: errors and destructive states.
|
|
88
|
+
- `--om-color-success`: success states.
|
|
89
|
+
|
|
90
|
+
### Fonts
|
|
91
|
+
|
|
92
|
+
- `--om-font-sans`: interface font family.
|
|
93
|
+
- `--om-font-mono`: monospace font family.
|
|
94
|
+
|
|
95
|
+
Load custom fonts yourself; these variables only select them.
|
|
96
|
+
|
|
97
|
+
#### Loading custom fonts
|
|
98
|
+
|
|
99
|
+
Load fonts with `@font-face`, then reference their family names in your theme variables:
|
|
100
|
+
|
|
101
|
+
```css
|
|
102
|
+
@font-face {
|
|
103
|
+
font-family: "My Font";
|
|
104
|
+
src: url("./fonts/my-font.woff2") format("woff2");
|
|
105
|
+
font-display: swap;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
:root {
|
|
109
|
+
--om-font-sans: "My Font", sans-serif;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For a monospace font, use the same approach with `--om-font-mono`.
|
|
114
|
+
|
|
115
|
+
### Spacing and effects
|
|
116
|
+
|
|
117
|
+
- `--om-spacing`: base spacing used by components.
|
|
118
|
+
- `--om-radius`: base corner radius.
|
|
119
|
+
- `--om-elevation`: elevated-surface box shadow.
|
|
120
|
+
- `--om-focus-ring`: additional focus box shadow.
|
|
121
|
+
- `--om-motion-duration`: transition duration.
|
|
122
|
+
|
|
123
|
+
Components decide which variables they use.
|
|
124
|
+
|
|
125
|
+
### Applying your theme
|
|
126
|
+
|
|
127
|
+
Variables on `:root` reach both your application and Overmux-owned UI, including recovery, update, and settings screens. The separate login screen does not load userland CSS.
|
|
128
|
+
|
|
129
|
+
Use the same variables in your own components:
|
|
130
|
+
|
|
131
|
+
```css
|
|
132
|
+
body {
|
|
133
|
+
margin: 0;
|
|
134
|
+
background: var(--om-color-canvas);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.panel {
|
|
138
|
+
color: var(--om-color-fg);
|
|
139
|
+
background: var(--om-color-surface);
|
|
140
|
+
border: 1px solid var(--om-color-border);
|
|
141
|
+
border-radius: var(--om-radius);
|
|
142
|
+
padding: var(--om-spacing);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Overmux does not paint your application's page background for you.
|
|
147
|
+
|
|
148
|
+
Public `--om-*` variables are override inputs: Overmux does not populate them with its built-in palette. Define them before using them in your own CSS, or supply CSS fallbacks.
|
|
149
|
+
|
|
150
|
+
Custom values remain in effect when `scheme` changes. If you supply a custom palette, you also own its light/dark variants and any saved theme preference.
|
|
151
|
+
|
|
152
|
+
## Theme one section
|
|
153
|
+
|
|
154
|
+
Wrap a section in `OvermuxThemeScope`:
|
|
47
155
|
|
|
48
156
|
```tsx
|
|
49
|
-
|
|
157
|
+
import { OvermuxThemeScope } from "overmux/client";
|
|
158
|
+
|
|
159
|
+
<OvermuxThemeScope
|
|
160
|
+
scheme="light"
|
|
161
|
+
contrast="normal"
|
|
162
|
+
className="preview"
|
|
163
|
+
style={{ "--om-color-accent": "rebeccapurple" }}
|
|
164
|
+
>
|
|
50
165
|
<Preview />
|
|
51
|
-
</OvermuxThemeScope
|
|
166
|
+
</OvermuxThemeScope>;
|
|
52
167
|
```
|
|
53
168
|
|
|
54
|
-
|
|
55
|
-
| --- | --- | --- |
|
|
56
|
-
| `children` | `ReactNode` | Required |
|
|
57
|
-
| `scheme` | `OvermuxScheme` | `"system"` |
|
|
58
|
-
| `contrast` | `OvermuxContrast` | `"auto"` |
|
|
59
|
-
| `className` | `string` | Unset |
|
|
60
|
-
| `style` | `OvermuxStyle` | Unset |
|
|
169
|
+
The scope renders a wrapper `<div>` and applies appearance to its contents.
|
|
61
170
|
|
|
62
|
-
|
|
171
|
+
Custom CSS variables inherit normally. A light scope inside a custom dark palette will still inherit those custom colors unless you override them.
|
|
63
172
|
|
|
64
|
-
|
|
173
|
+
`OvermuxHost` already creates an application-wide scope. A scope inside your app affects only that section, not surrounding Overmux-owned UI.
|
|
65
174
|
|
|
66
|
-
##
|
|
175
|
+
## Keep overlays themed
|
|
67
176
|
|
|
68
|
-
|
|
177
|
+
Use `OvermuxPortal` for menus, dialogs, and other overlays:
|
|
69
178
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
179
|
+
```tsx
|
|
180
|
+
import { OvermuxPortal, OvermuxThemeScope } from "overmux/client";
|
|
181
|
+
|
|
182
|
+
<OvermuxThemeScope scheme="dark">
|
|
183
|
+
<Editor />
|
|
184
|
+
<OvermuxPortal>
|
|
185
|
+
<EditorMenu />
|
|
186
|
+
</OvermuxPortal>
|
|
187
|
+
</OvermuxThemeScope>;
|
|
188
|
+
```
|
|
76
189
|
|
|
77
|
-
The overlay
|
|
190
|
+
The overlay renders inside the nearest theme scope, preserving its appearance and inherited variables.
|
|
78
191
|
|
|
79
|
-
|
|
192
|
+
If you supply an external container, you own its theme attributes and CSS variables:
|
|
80
193
|
|
|
81
|
-
|
|
194
|
+
```tsx
|
|
195
|
+
<OvermuxPortal
|
|
196
|
+
external={{
|
|
197
|
+
container: overlayElement,
|
|
198
|
+
scopeAttributesAndVariables: "caller-owned",
|
|
199
|
+
}}
|
|
200
|
+
>
|
|
201
|
+
<EditorMenu />
|
|
202
|
+
</OvermuxPortal>;
|
|
203
|
+
```
|
|
82
204
|
|
|
83
|
-
|
|
205
|
+
## Packages
|
|
84
206
|
|
|
85
|
-
|
|
86
|
-
| --- | --- | --- |
|
|
87
|
-
| Runtime host UI | Theme tokens where consumed | Client `appearance` |
|
|
88
|
-
| UI split views | Border and accent tokens | App owns pane contents |
|
|
89
|
-
| Git React UI | Colors, fonts, spacing, radius | Diff options and themes; `registerGitDiffTheme` registers custom themes |
|
|
90
|
-
| Pi React UI | Colors, fonts, spacing, radius, elevation | Code highlighting uses Tokyo Night |
|
|
91
|
-
| xterm | Wrapper background: `--om-xterm-terminal-background` | `options.theme` for terminal colors; options such as `fontFamily` for fonts |
|
|
92
|
-
| tmux / Zellij terminal wrappers | xterm wrapper styles | Forwarded xterm props |
|
|
207
|
+
Packages use shared `--om-*` variables where applicable. They may also expose additional CSS variables, `className`, `classNames`, or other styling props.
|
|
93
208
|
|
|
94
|
-
|
|
209
|
+
Some rendered content has separate theme options rather than inheriting CSS colors. See each package's documentation for its styling controls.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "overmux",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"homepage": "https://github.com/richardgill/overmux",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"web-push": "3.6.7",
|
|
53
53
|
"ws": "8.21.3",
|
|
54
54
|
"zod": "4.4.3",
|
|
55
|
-
"@overmux/keybindings": "0.0.
|
|
55
|
+
"@overmux/keybindings": "0.0.4"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@playwright/test": "1.58.0",
|