Skip to content

Bring OpenCode theme presets into the UI foundation - #155

Open
itz4blitz wants to merge 12 commits into
chriswritescode-dev:mainfrom
itz4blitz:feat/ui-theme-foundation
Open

Bring OpenCode theme presets into the UI foundation#155
itz4blitz wants to merge 12 commits into
chriswritescode-dev:mainfrom
itz4blitz:feat/ui-theme-foundation

Conversation

@itz4blitz

@itz4blitz itz4blitz commented Mar 8, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR upgrades the existing UI theme foundation work from a generic semantic cleanup into a real OpenCode theme system pass.

The app now uses actual OpenCode theme preset data, exposes the same preset-style picker in Settings, and maps those palette tokens into the app shell so the product feels much closer to OpenCode instead of just being loosely inspired by it.

What Changed

  • import the real built-in OpenCode theme presets and resolve them into the app's CSS variable system
  • add themePreset alongside appearance mode so users can independently choose a palette and render it in dark, light, or system mode
  • rework Settings > General Settings into a theme showcase panel with palette selection, appearance selection, and a live preview of key tokens
  • retune high-traffic shared surfaces and primitives so buttons, inputs, selects, cards, dialogs, headers, and the login screen inherit the new OpenCode-driven visual language
  • keep the rest of the PR focused on UI, theme, and look-and-feel only

OpenCode Theme Presets Included

This PR installs and exposes all 33 imported OpenCode presets:

OpenCode, GitHub, Tokyo Night, Vesper, Carbonfox, Cursor, Dracula, Night Owl, Everforest, Flexoki, Gruvbox, Kanagawa, Catppuccin, Catppuccin Frappe, Catppuccin Macchiato, Ayu, One Dark, Material, Monokai, Palenight, Rose Pine, Solarized, Aura, Cobalt2, Matrix, Mercury, Nord, Orng, Lucent Orng, Osaka Jade, Synthwave 84, Vercel, Zenburn

Why This Matters

  • brings the app materially closer to the actual OpenCode /theme experience
  • gives the UI a consistent token source for surfaces, borders, syntax, markdown, and diff states
  • makes the theme system extensible without needing one-off per-screen palette styling

Validation

  • pnpm lint
  • pnpm --filter frontend build

Theme Previews

These screenshots were captured from the Docker preview in Settings > General Settings at 1920x1080 after switching presets through the new theme picker.

OpenCode (Dark)

OpenCode dark theme switcher

GitHub (Light)

GitHub light theme switcher

Tokyo Night (Dark)

Tokyo Night dark theme switcher

Replace hardcoded status styling with semantic tokens and add shared drawer and resizable patterns so settings, repo, session, and file flows feel consistent across desktop and mobile.
Let the settings nav wrap naturally and widen the resize handle so the desktop sidebar is easier to read and drag while reviewing account and config sections.
Copilot AI review requested due to automatic review settings March 8, 2026 21:45
Use percentage-based panel sizes with react-resizable-panels so the settings sidebar opens at a usable width and can be resized normally on desktop.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the frontend UI theme system from hardcoded Tailwind color classes (e.g., text-blue-500, bg-red-600) to semantic design tokens (e.g., text-primary, text-destructive, text-warning, text-info, text-success), using oklch color space. It also introduces new UI primitives (Drawer via vaul, resizable panels via react-resizable-panels) and applies them to the settings dialog for a resizable sidebar layout. The shadcn/ui configuration is updated from "default" to "new-york" style.

Changes:

  • Replace all hardcoded color classes across ~45 files with semantic theme tokens (text-primary, text-destructive, text-warning, text-info, text-success), and rebuild the CSS theme foundation in index.css with oklch tokens, scrollbar styling, surface utilities, and a prefers-reduced-motion media query.
  • Add vaul (Drawer) and react-resizable-panels (Resizable) UI primitives, and refactor the SettingsDialog from a horizontal tab bar to a resizable sidebar + content panel layout (desktop), with a mobile-friendly menu-then-detail flow using section intro cards.
  • Update base UI components (Button, Badge, Card, Input, Select, Switch, Tabs, Dialog) with refined styling (rounded corners, backdrop blur, subtle borders, shadows) consistent with the new theme tokens.

Reviewed changes

Copilot reviewed 79 out of 80 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/index.css Complete theme overhaul: oklch tokens, semantic color variables, surface utilities, scrollbar styling, reduced-motion support
frontend/components.json shadcn config updated from "default" to "new-york" style
frontend/package.json Added vaul and react-resizable-panels dependencies
pnpm-lock.yaml Lock file entries for new dependencies
frontend/src/components/ui/drawer.tsx New Drawer primitive wrapping vaul
frontend/src/components/ui/resizable.tsx New Resizable primitives wrapping react-resizable-panels
frontend/src/components/ui/button.tsx Refined variants with semantic tokens, active translate, new focus ring
frontend/src/components/ui/badge.tsx Added info, success, warning variants; updated existing variants
frontend/src/components/ui/card.tsx Rounded-xl, backdrop-blur, border/bg adjustments
frontend/src/components/ui/input.tsx Panel-based bg, ring focus style, shadow-xs
frontend/src/components/ui/select.tsx Consistent styling with input and card updates
frontend/src/components/ui/switch.tsx Semantic tokens for checked/unchecked states
frontend/src/components/ui/tabs.tsx Updated TabsList/TabsTrigger styling
frontend/src/components/ui/dialog.tsx Backdrop blur, data-slot attrs, updated close button
frontend/src/components/ui/page-header.tsx Border-b with backdrop-blur header
frontend/src/components/ui/back-button.tsx Semantic tokens, cn() utility
frontend/src/components/ui/copy-button.tsx text-success for copied state
frontend/src/components/ui/pending-action-badge.tsx Color type renamed from orange/blue to warning/info
frontend/src/components/ui/session-status-indicator.tsx Semantic token replacements
frontend/src/components/ui/mini-scanner.tsx Semantic token replacements
frontend/src/components/ui/virtualized-text-view.tsx bg-warning/20 for highlights
frontend/src/components/ui/delete-dialog.tsx Removed hardcoded red button classes
frontend/src/components/ui/discard-dialog.tsx Removed hardcoded red button classes
frontend/src/components/ui/header.tsx Semantic tokens for notification indicators
frontend/src/components/settings/SettingsDialog.tsx Major refactor: resizable sidebar layout, section intros, typed menu items
frontend/src/components/settings/TTSSettings.tsx Semantic tokens for provider selection and status
frontend/src/components/settings/STTSettings.tsx Semantic tokens for test results and warnings
frontend/src/components/settings/ProviderSettings.tsx Badge variant="success" for connected state
frontend/src/components/settings/OpenCodeConfigManager.tsx Semantic tokens throughout
frontend/src/components/settings/OpenCodeConfigEditor.tsx text-destructive for errors
frontend/src/components/settings/NotificationSettings.tsx text-warning for denied state
frontend/src/components/settings/MemoryPluginConfig.tsx Semantic icon colors
frontend/src/components/settings/McpServerCard.tsx Badge variants for status, semantic destructive colors
frontend/src/components/settings/McpOAuthDialog.tsx Semantic tokens for spinners and success
frontend/src/components/settings/GeneralSettings.tsx text-success for version link
frontend/src/components/settings/CreateConfigDialog.tsx text-destructive for errors
frontend/src/components/settings/CommandsEditor.tsx Semantic destructive for delete buttons
frontend/src/components/settings/AgentsMdEditor.tsx Semantic tokens
frontend/src/components/settings/AgentsEditor.tsx Semantic destructive for delete
frontend/src/components/settings/AccountSettings.tsx Success border/text for alerts
frontend/src/components/settings/VersionSelectDialog.tsx Semantic tokens for current version
frontend/src/components/repo/AddRepoDialog.tsx Major refactor: Drawer for mobile, structured form sections
frontend/src/components/repo/RepoCard.tsx Semantic tokens throughout
frontend/src/components/repo/RepoList.tsx text-muted-foreground for empty states
frontend/src/components/repo/RepoMcpServerList.tsx Badge variants, semantic tokens
frontend/src/components/repo/SwitchConfigDialog.tsx Semantic tokens, removed hardcoded blue button
frontend/src/components/session/SessionCard.tsx Semantic tokens for selection, status, delete
frontend/src/components/session/QuestionPrompt.tsx Comprehensive semantic token migration
frontend/src/components/session/PermissionRequestDialog.tsx Warning tokens
frontend/src/components/session/EditSessionTitleDialog.tsx Destructive tokens
frontend/src/components/session/ContextUsageIndicator.tsx Success/warning/destructive for usage levels
frontend/src/components/notifications/PendingActionsGroup.tsx Updated color prop names
frontend/src/components/model/ModelSelectDialog.tsx Semantic tokens for selection and loading
frontend/src/components/model/ModelQuickSelect.tsx text-warning for variant display
frontend/src/components/message/ToolCallPart.tsx Semantic tokens for all status states
frontend/src/components/message/TodoItem.tsx Semantic success/warning tokens
frontend/src/components/message/TextPart.tsx Destructive tokens for mermaid errors
frontend/src/components/message/SessionTodoDisplay.tsx bg-success for progress bars
frontend/src/components/message/RetryPart.tsx Warning tokens for retry UI
frontend/src/components/message/PromptInput.tsx Comprehensive semantic migration
frontend/src/components/message/PatchPart.tsx text-info for file links
frontend/src/components/message/MessageThread.tsx Primary/warning tokens for messages
frontend/src/components/message/MessageSkeleton.tsx Primary tokens for skeletons
frontend/src/components/message/MessagePart.tsx Info/destructive tokens
frontend/src/components/message/FileToolRender.tsx Success/info tokens
frontend/src/components/message/EditableUserMessage.tsx Primary hover token
frontend/src/components/message/DiffStats.tsx Success/destructive tokens
frontend/src/components/message/ContentDiffViewer.tsx Success/destructive for diff lines
frontend/src/components/memory/MemoryList.tsx Semantic scope colors
frontend/src/components/file-browser/FileTree.tsx Destructive for delete action
frontend/src/components/file-browser/FilePreview.tsx Warning/info/success tokens
frontend/src/components/file-browser/FileDiffView.tsx Comprehensive semantic diff styling
frontend/src/components/ssh/SSHHostKeyDialog.tsx Destructive/warning tokens
frontend/src/lib/git-status-styles.ts All colors migrated to semantic tokens
frontend/src/pages/SessionDetail.tsx Semantic tokens for parent session, subtitle, actions
frontend/src/pages/RepoDetail.tsx Badge variant, removed hardcoded blue button
frontend/src/pages/Memories.tsx text-info for brain icon
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

You can also share your feedback on Copilot code review. Take the survey.

Comment thread frontend/src/components/message/ToolCallPart.tsx Outdated
Comment thread frontend/src/components/message/ToolCallPart.tsx Outdated
Comment thread frontend/src/components/settings/GeneralSettings.tsx Outdated
Comment thread frontend/src/components/settings/SettingsDialog.tsx Outdated
Simplify the running-state warning styles in tool call output and restore a visible hover state for the version update link so the semantic theme cleanup keeps its interaction cues.
Copilot AI review requested due to automatic review settings March 8, 2026 23:07
@itz4blitz itz4blitz changed the title Refine UI theme foundation and responsive settings patterns Bring OpenCode theme presets into the UI foundation Mar 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 84 out of 89 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

You can also share your feedback on Copilot code review. Take the survey.

Comment thread frontend/src/components/ui/page-header.tsx
Comment thread frontend/src/components/settings/SettingsDialog.tsx Outdated
Comment thread frontend/src/components/settings/SettingsDialog.tsx Outdated
Use numeric resizable panel sizes so the settings layout behaves correctly and keep page header tests aligned with the refreshed header styling.
@itz4blitz itz4blitz closed this Mar 9, 2026
@itz4blitz itz4blitz reopened this Mar 9, 2026
Copilot AI review requested due to automatic review settings April 1, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 85 out of 90 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +218 to +232
<label className="text-sm font-medium text-foreground">{sourceLabel}</label>
<Input
placeholder={sourcePlaceholder}
value={sourceValue}
onChange={(e) => {
if (repoType === 'remote') {
handleRepoUrlChange(e.target.value)
} else if (repoType === 'local') {
setLocalPath(e.target.value)
} else {
setFolderPath(e.target.value)
}
}}
disabled={mutation.isPending}
/>

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plain <label> for the source field isn't associated with the Input control (no htmlFor on the label and no id on the input). This reduces accessibility/screen-reader usability. Consider using the shared Label component with htmlFor, and pass a stable id into the Input so the label is programmatically linked.

Copilot uses AI. Check for mistakes.
Comment on lines 235 to 242
<div className="space-y-2">
<label className="text-sm text-zinc-400">Branch</label>
<label className="text-sm font-medium text-foreground">Branch</label>
<Input
placeholder="Optional - uses default if empty"
value={branch}
onChange={(e) => setBranch(e.target.value)}
disabled={mutation.isPending || repoType === 'folder'}
className="bg-[#1a1a1a] border-[#2a2a2a] text-white placeholder:text-zinc-500"
/>

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the source field: the "Branch" <label> isn't linked to its Input (missing htmlFor/id). Hooking these up (or using the existing Label component) improves keyboard and assistive-tech navigation.

Copilot uses AI. Check for mistakes.
gollum added 2 commits August 8, 2026 12:04
Resolve conflicts with current main while preserving OpenCode theme presets, theme picker UI, and semantic surface styling. Drop memory plugin UI that was removed upstream.
Restore broken conflicted UI files from main, keep themed back-button, load .env.local overrides for a parallel dev stack on 5004/5174/5552.
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@itz4blitz, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d8f6e174-3fd0-497b-b253-6ad03a960570

📥 Commits

Reviewing files that changed from the base of the PR and between 1666d0d and c2e340b.

⛔ Files ignored due to path filters (4)
  • .github/screenshots/theme-switcher-github-light.png is excluded by !**/*.png
  • .github/screenshots/theme-switcher-opencode-dark.png is excluded by !**/*.png
  • .github/screenshots/theme-switcher-tokyonight-dark.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (78)
  • .env.example
  • .gitignore
  • backend/src/auth/index.ts
  • backend/src/index.ts
  • backend/src/routes/auth.ts
  • frontend/components.json
  • frontend/package.json
  • frontend/src/api/types/settings.ts
  • frontend/src/components/file-browser/FileDiffView.tsx
  • frontend/src/components/file-browser/FilePreview.tsx
  • frontend/src/components/file-browser/FileTree.tsx
  • frontend/src/components/message/ContentDiffViewer.tsx
  • frontend/src/components/message/DiffStats.tsx
  • frontend/src/components/message/EditableUserMessage.tsx
  • frontend/src/components/message/FileToolRender.tsx
  • frontend/src/components/message/MessagePart.tsx
  • frontend/src/components/message/MessageSkeleton.tsx
  • frontend/src/components/message/MessageThread.tsx
  • frontend/src/components/message/PatchPart.tsx
  • frontend/src/components/message/RetryPart.tsx
  • frontend/src/components/message/SessionTodoDisplay.tsx
  • frontend/src/components/message/TextPart.tsx
  • frontend/src/components/message/TodoItem.tsx
  • frontend/src/components/message/ToolCallPart.tsx
  • frontend/src/components/model/ModelSelectDialog.tsx
  • frontend/src/components/notifications/PendingActionsGroup.tsx
  • frontend/src/components/repo/RepoCard.tsx
  • frontend/src/components/repo/RepoMcpServerList.tsx
  • frontend/src/components/repo/SwitchConfigDialog.tsx
  • frontend/src/components/session/ContextUsageIndicator.tsx
  • frontend/src/components/session/EditSessionTitleDialog.tsx
  • frontend/src/components/session/PermissionRequestDialog.tsx
  • frontend/src/components/session/QuestionPrompt.tsx
  • frontend/src/components/settings/AccountSettings.tsx
  • frontend/src/components/settings/AgentsMdEditor.tsx
  • frontend/src/components/settings/CreateConfigDialog.tsx
  • frontend/src/components/settings/GeneralSettings.tsx
  • frontend/src/components/settings/McpOAuthDialog.tsx
  • frontend/src/components/settings/McpServerCard.tsx
  • frontend/src/components/settings/NotificationSettings.tsx
  • frontend/src/components/settings/OpenCodeConfigManager.tsx
  • frontend/src/components/settings/ProviderSettings.tsx
  • frontend/src/components/settings/STTSettings.tsx
  • frontend/src/components/settings/TTSSettings.tsx
  • frontend/src/components/settings/VersionSelectDialog.tsx
  • frontend/src/components/source-control/BranchesTab.tsx
  • frontend/src/components/source-control/GitFlatFileItem.tsx
  • frontend/src/components/source-control/GitFlatFileList.tsx
  • frontend/src/components/ssh/SSHHostKeyDialog.tsx
  • frontend/src/components/ui/back-button.tsx
  • frontend/src/components/ui/badge.tsx
  • frontend/src/components/ui/button.tsx
  • frontend/src/components/ui/card.tsx
  • frontend/src/components/ui/copy-button.tsx
  • frontend/src/components/ui/dialog.tsx
  • frontend/src/components/ui/drawer.tsx
  • frontend/src/components/ui/input.tsx
  • frontend/src/components/ui/page-header.test.tsx
  • frontend/src/components/ui/page-header.tsx
  • frontend/src/components/ui/pending-action-badge.tsx
  • frontend/src/components/ui/resizable.tsx
  • frontend/src/components/ui/select.tsx
  • frontend/src/components/ui/session-status-indicator.tsx
  • frontend/src/components/ui/switch.tsx
  • frontend/src/components/ui/tabs.tsx
  • frontend/src/components/ui/virtualized-text-view.tsx
  • frontend/src/contexts/AuthContext.tsx
  • frontend/src/hooks/useTheme.ts
  • frontend/src/index.css
  • frontend/src/lib/auth-loaders.ts
  • frontend/src/lib/git-status-styles.ts
  • frontend/src/lib/opencode-themes.json
  • frontend/src/lib/opencodeThemes.ts
  • frontend/src/pages/Login.tsx
  • frontend/vite.config.ts
  • package.json
  • shared/src/config/env.ts
  • shared/src/schemas/settings.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@itz4blitz

Copy link
Copy Markdown
Contributor Author

Rebased/merged onto current main

This branch is now updated against latest main (merge commit + follow-up fixes).

Conflict resolution notes

  • Kept OpenCode theme presets, theme picker, and semantic surface tokens
  • Accepted main deletions for removed memory plugin UI (MemoryList, Memories, MemoryPluginConfig, mini-scanner)
  • Restored heavily-conflicted structural files from main where JSX broke (AddRepoDialog, PromptInput, SessionDetail, SettingsDialog, etc.) and re-applied themed back-button styling
  • Frontend tsc typecheck passes

Local HMR (does not touch production Docker on :5003)

  • .env.local overrides ports: API 5004, Vite HMR 5174, OpenCode 5552, separate DB/workspace
  • pnpm dev:local starts backend watch + Vite HMR without the bash predev gate (Windows PATH-friendly)
  • Production instance remains healthy on :5003 / OpenCode :5551

gollum added 2 commits August 8, 2026 12:17
Omit fixed PASSKEY_ORIGIN so WebAuthn verifies against the request Origin. Keeps RP ID as the Tailscale hostname so prod passkeys work on :5174 HMR as well as :5003. Vite allows Tailscale hosts and pins HMR clientPort for Serve TLS.
Inject allowCredentials for discoverable passkey login (fixes Windows Hello cancel), isolate dev cookies, expose RP ID to login page, and preserve Origin through the Vite proxy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants