diff options
| author | Adam <[email protected]> | 2026-01-06 15:21:00 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-20 07:33:44 -0600 |
| commit | 8bcbfd63960120efa3cb770f8e07de1bb57e93b0 (patch) | |
| tree | 75429fd33bf5bc2d3a81e27db72b5671a2eb7629 /packages/app/src/components | |
| parent | e521fee0023a604bb6d5ef39b4b892cbf1a0f9d4 (diff) | |
| download | opencode-8bcbfd63960120efa3cb770f8e07de1bb57e93b0.tar.gz opencode-8bcbfd63960120efa3cb770f8e07de1bb57e93b0.zip | |
wip(app): settings
Diffstat (limited to 'packages/app/src/components')
| -rw-r--r-- | packages/app/src/components/dialog-settings.tsx | 87 | ||||
| -rw-r--r-- | packages/app/src/components/settings-agents.tsx | 12 | ||||
| -rw-r--r-- | packages/app/src/components/settings-commands.tsx | 12 | ||||
| -rw-r--r-- | packages/app/src/components/settings-general.tsx | 134 | ||||
| -rw-r--r-- | packages/app/src/components/settings-keybinds.tsx | 12 | ||||
| -rw-r--r-- | packages/app/src/components/settings-mcp.tsx | 12 | ||||
| -rw-r--r-- | packages/app/src/components/settings-models.tsx | 12 | ||||
| -rw-r--r-- | packages/app/src/components/settings-permissions.tsx | 12 | ||||
| -rw-r--r-- | packages/app/src/components/settings-providers.tsx | 12 |
9 files changed, 305 insertions, 0 deletions
diff --git a/packages/app/src/components/dialog-settings.tsx b/packages/app/src/components/dialog-settings.tsx new file mode 100644 index 000000000..872cc4c80 --- /dev/null +++ b/packages/app/src/components/dialog-settings.tsx @@ -0,0 +1,87 @@ +import { Component, createSignal } from "solid-js" +import { Dialog } from "@opencode-ai/ui/dialog" +import { Tabs } from "@opencode-ai/ui/tabs" +import { Icon } from "@opencode-ai/ui/icon" +import { TextField } from "@opencode-ai/ui/text-field" +import { SettingsGeneral } from "./settings-general" +import { SettingsKeybinds } from "./settings-keybinds" +import { SettingsPermissions } from "./settings-permissions" +import { SettingsProviders } from "./settings-providers" +import { SettingsModels } from "./settings-models" +import { SettingsAgents } from "./settings-agents" +import { SettingsCommands } from "./settings-commands" +import { SettingsMcp } from "./settings-mcp" + +export const DialogSettings: Component = () => { + const [search, setSearch] = createSignal("") + + return ( + <Dialog size="large"> + <Tabs orientation="vertical" variant="settings" defaultValue="general" class="h-full settings-dialog"> + <Tabs.List> + <div class="settings-dialog__search px-3 pb-3"> + <TextField placeholder="Search" value={search()} onChange={setSearch} variant="normal" /> + </div> + <Tabs.SectionTitle>Desktop</Tabs.SectionTitle> + <Tabs.Trigger value="general"> + <Icon name="settings-gear" /> + General + </Tabs.Trigger> + <Tabs.Trigger value="shortcuts"> + <Icon name="console" /> + Shortcuts + </Tabs.Trigger> + <Tabs.SectionTitle>Server</Tabs.SectionTitle> + <Tabs.Trigger value="permissions"> + <Icon name="checklist" /> + Permissions + </Tabs.Trigger> + <Tabs.Trigger value="providers"> + <Icon name="server" /> + Providers + </Tabs.Trigger> + <Tabs.Trigger value="models"> + <Icon name="brain" /> + Models + </Tabs.Trigger> + <Tabs.Trigger value="agents"> + <Icon name="task" /> + Agents + </Tabs.Trigger> + <Tabs.Trigger value="commands"> + <Icon name="console" /> + Commands + </Tabs.Trigger> + <Tabs.Trigger value="mcp"> + <Icon name="mcp" /> + MCP + </Tabs.Trigger> + </Tabs.List> + <Tabs.Content value="general" class="no-scrollbar"> + <SettingsGeneral /> + </Tabs.Content> + <Tabs.Content value="shortcuts" class="no-scrollbar"> + <SettingsKeybinds /> + </Tabs.Content> + <Tabs.Content value="permissions" class="no-scrollbar"> + <SettingsPermissions /> + </Tabs.Content> + <Tabs.Content value="providers" class="no-scrollbar"> + <SettingsProviders /> + </Tabs.Content> + <Tabs.Content value="models" class="no-scrollbar"> + <SettingsModels /> + </Tabs.Content> + <Tabs.Content value="agents" class="no-scrollbar"> + <SettingsAgents /> + </Tabs.Content> + <Tabs.Content value="commands" class="no-scrollbar"> + <SettingsCommands /> + </Tabs.Content> + <Tabs.Content value="mcp" class="no-scrollbar"> + <SettingsMcp /> + </Tabs.Content> + </Tabs> + </Dialog> + ) +} diff --git a/packages/app/src/components/settings-agents.tsx b/packages/app/src/components/settings-agents.tsx new file mode 100644 index 000000000..892be152b --- /dev/null +++ b/packages/app/src/components/settings-agents.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsAgents: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">Agents</h2> + <p class="text-14-regular text-text-weak">Agent settings will be configurable here.</p> + </div> + </div> + ) +} diff --git a/packages/app/src/components/settings-commands.tsx b/packages/app/src/components/settings-commands.tsx new file mode 100644 index 000000000..e98c0eeb0 --- /dev/null +++ b/packages/app/src/components/settings-commands.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsCommands: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">Commands</h2> + <p class="text-14-regular text-text-weak">Command settings will be configurable here.</p> + </div> + </div> + ) +} diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx new file mode 100644 index 000000000..e9965b0fa --- /dev/null +++ b/packages/app/src/components/settings-general.tsx @@ -0,0 +1,134 @@ +import { Component, createMemo, type JSX } from "solid-js" +import { Select } from "@opencode-ai/ui/select" +import { Switch } from "@opencode-ai/ui/switch" +import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme" +import { useSettings } from "@/context/settings" + +export const SettingsGeneral: Component = () => { + const theme = useTheme() + const settings = useSettings() + + const themeOptions = createMemo(() => + Object.entries(theme.themes()).map(([id, def]) => ({ id, name: def.name ?? id })), + ) + + const colorSchemeOptions: { value: ColorScheme; label: string }[] = [ + { value: "system", label: "System setting" }, + { value: "light", label: "Light" }, + { value: "dark", label: "Dark" }, + ] + + const fontOptions = [ + { value: "ibm-plex-mono", label: "IBM Plex Mono" }, + { value: "fira-code", label: "Fira Code" }, + { value: "jetbrains-mono", label: "JetBrains Mono" }, + { value: "source-code-pro", label: "Source Code Pro" }, + ] + + return ( + <div class="flex flex-col h-full overflow-y-auto no-scrollbar"> + <div class="flex flex-col gap-8 p-8 max-w-[720px]"> + {/* Header */} + <h2 class="text-16-medium text-text-strong">General</h2> + + {/* Appearance Section */} + <div class="flex flex-col gap-1"> + <h3 class="text-14-medium text-text-strong pb-2">Appearance</h3> + + <SettingsRow title="Appearance" description="Customise how OpenCode looks on your device"> + <Select + options={colorSchemeOptions} + current={colorSchemeOptions.find((o) => o.value === theme.colorScheme())} + value={(o) => o.value} + label={(o) => o.label} + onSelect={(option) => option && theme.setColorScheme(option.value)} + variant="secondary" + size="small" + /> + </SettingsRow> + + <SettingsRow + title="Theme" + description={ + <> + Customise how OpenCode is themed.{" "} + <a href="#" class="text-text-interactive-base"> + Learn more + </a> + </> + } + > + <Select + options={themeOptions()} + current={themeOptions().find((o) => o.id === theme.themeId())} + value={(o) => o.id} + label={(o) => o.name} + onSelect={(option) => option && theme.setTheme(option.id)} + variant="secondary" + size="small" + /> + </SettingsRow> + + <SettingsRow title="Font" description="Customise the mono font used in code blocks"> + <Select + options={fontOptions} + current={fontOptions.find((o) => o.value === settings.appearance.font())} + value={(o) => o.value} + label={(o) => o.label} + onSelect={(option) => option && settings.appearance.setFont(option.value)} + variant="secondary" + size="small" + /> + </SettingsRow> + </div> + + {/* System notifications Section */} + <div class="flex flex-col gap-1"> + <h3 class="text-14-medium text-text-strong pb-2">System notifications</h3> + + <SettingsRow + title="Agent" + description="Show system notification when the agent is complete or needs attention" + > + <Switch + checked={settings.notifications.agent()} + onChange={(checked) => settings.notifications.setAgent(checked)} + /> + </SettingsRow> + + <SettingsRow title="Permissions" description="Show system notification when a permission is required"> + <Switch + checked={settings.notifications.permissions()} + onChange={(checked) => settings.notifications.setPermissions(checked)} + /> + </SettingsRow> + + <SettingsRow title="Errors" description="Show system notification when an error occurs"> + <Switch + checked={settings.notifications.errors()} + onChange={(checked) => settings.notifications.setErrors(checked)} + /> + </SettingsRow> + </div> + </div> + </div> + ) +} + +interface SettingsRowProps { + title: string + description: string | JSX.Element + children: JSX.Element +} + +const SettingsRow: Component<SettingsRowProps> = (props) => { + return ( + <div class="flex items-center justify-between gap-4 py-3 border-b border-border-weak-base last:border-none"> + <div class="flex flex-col gap-0.5"> + <span class="text-14-medium text-text-strong">{props.title}</span> + <span class="text-12-regular text-text-weak">{props.description}</span> + </div> + <div class="flex-shrink-0">{props.children}</div> + </div> + ) +} diff --git a/packages/app/src/components/settings-keybinds.tsx b/packages/app/src/components/settings-keybinds.tsx new file mode 100644 index 000000000..3688559bc --- /dev/null +++ b/packages/app/src/components/settings-keybinds.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsKeybinds: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">Shortcuts</h2> + <p class="text-14-regular text-text-weak">Keyboard shortcuts will be configurable here.</p> + </div> + </div> + ) +} diff --git a/packages/app/src/components/settings-mcp.tsx b/packages/app/src/components/settings-mcp.tsx new file mode 100644 index 000000000..ea6bf350f --- /dev/null +++ b/packages/app/src/components/settings-mcp.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsMcp: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">MCP</h2> + <p class="text-14-regular text-text-weak">MCP settings will be configurable here.</p> + </div> + </div> + ) +} diff --git a/packages/app/src/components/settings-models.tsx b/packages/app/src/components/settings-models.tsx new file mode 100644 index 000000000..5fbeb144e --- /dev/null +++ b/packages/app/src/components/settings-models.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsModels: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">Models</h2> + <p class="text-14-regular text-text-weak">Model settings will be configurable here.</p> + </div> + </div> + ) +} diff --git a/packages/app/src/components/settings-permissions.tsx b/packages/app/src/components/settings-permissions.tsx new file mode 100644 index 000000000..67c3bfb62 --- /dev/null +++ b/packages/app/src/components/settings-permissions.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsPermissions: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">Permissions</h2> + <p class="text-14-regular text-text-weak">Permission settings will be configurable here.</p> + </div> + </div> + ) +} diff --git a/packages/app/src/components/settings-providers.tsx b/packages/app/src/components/settings-providers.tsx new file mode 100644 index 000000000..cf90b6c13 --- /dev/null +++ b/packages/app/src/components/settings-providers.tsx @@ -0,0 +1,12 @@ +import { Component } from "solid-js" + +export const SettingsProviders: Component = () => { + return ( + <div class="flex flex-col h-full overflow-y-auto"> + <div class="flex flex-col gap-6 p-6 max-w-[600px]"> + <h2 class="text-16-medium text-text-strong">Providers</h2> + <p class="text-14-regular text-text-weak">Provider settings will be configurable here.</p> + </div> + </div> + ) +} |
