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

@itz4blitzitz4blitz 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.
CopilotAI 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.

CopilotAI 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
FileDescription
frontend/src/index.cssComplete theme overhaul: oklch tokens, semantic color variables, surface utilities, scrollbar styling, reduced-motion support
frontend/components.jsonshadcn config updated from "default" to "new-york" style
frontend/package.jsonAdded vaul and react-resizable-panels dependencies
pnpm-lock.yamlLock file entries for new dependencies
frontend/src/components/ui/drawer.tsxNew Drawer primitive wrapping vaul
frontend/src/components/ui/resizable.tsxNew Resizable primitives wrapping react-resizable-panels
frontend/src/components/ui/button.tsxRefined variants with semantic tokens, active translate, new focus ring
frontend/src/components/ui/badge.tsxAdded info, success, warning variants; updated existing variants
frontend/src/components/ui/card.tsxRounded-xl, backdrop-blur, border/bg adjustments
frontend/src/components/ui/input.tsxPanel-based bg, ring focus style, shadow-xs
frontend/src/components/ui/select.tsxConsistent styling with input and card updates
frontend/src/components/ui/switch.tsxSemantic tokens for checked/unchecked states
frontend/src/components/ui/tabs.tsxUpdated TabsList/TabsTrigger styling
frontend/src/components/ui/dialog.tsxBackdrop blur, data-slot attrs, updated close button
frontend/src/components/ui/page-header.tsxBorder-b with backdrop-blur header
frontend/src/components/ui/back-button.tsxSemantic tokens, cn() utility
frontend/src/components/ui/copy-button.tsxtext-success for copied state
frontend/src/components/ui/pending-action-badge.tsxColor type renamed from orange/blue to warning/info
frontend/src/components/ui/session-status-indicator.tsxSemantic token replacements
frontend/src/components/ui/mini-scanner.tsxSemantic token replacements
frontend/src/components/ui/virtualized-text-view.tsxbg-warning/20 for highlights
frontend/src/components/ui/delete-dialog.tsxRemoved hardcoded red button classes
frontend/src/components/ui/discard-dialog.tsxRemoved hardcoded red button classes
frontend/src/components/ui/header.tsxSemantic tokens for notification indicators
frontend/src/components/settings/SettingsDialog.tsxMajor refactor: resizable sidebar layout, section intros, typed menu items
frontend/src/components/settings/TTSSettings.tsxSemantic tokens for provider selection and status
frontend/src/components/settings/STTSettings.tsxSemantic tokens for test results and warnings
frontend/src/components/settings/ProviderSettings.tsxBadge variant="success" for connected state
frontend/src/components/settings/OpenCodeConfigManager.tsxSemantic tokens throughout
frontend/src/components/settings/OpenCodeConfigEditor.tsxtext-destructive for errors
frontend/src/components/settings/NotificationSettings.tsxtext-warning for denied state
frontend/src/components/settings/MemoryPluginConfig.tsxSemantic icon colors
frontend/src/components/settings/McpServerCard.tsxBadge variants for status, semantic destructive colors
frontend/src/components/settings/McpOAuthDialog.tsxSemantic tokens for spinners and success
frontend/src/components/settings/GeneralSettings.tsxtext-success for version link
frontend/src/components/settings/CreateConfigDialog.tsxtext-destructive for errors
frontend/src/components/settings/CommandsEditor.tsxSemantic destructive for delete buttons
frontend/src/components/settings/AgentsMdEditor.tsxSemantic tokens
frontend/src/components/settings/AgentsEditor.tsxSemantic destructive for delete
frontend/src/components/settings/AccountSettings.tsxSuccess border/text for alerts
frontend/src/components/settings/VersionSelectDialog.tsxSemantic tokens for current version
frontend/src/components/repo/AddRepoDialog.tsxMajor refactor: Drawer for mobile, structured form sections
frontend/src/components/repo/RepoCard.tsxSemantic tokens throughout
frontend/src/components/repo/RepoList.tsxtext-muted-foreground for empty states
frontend/src/components/repo/RepoMcpServerList.tsxBadge variants, semantic tokens
frontend/src/components/repo/SwitchConfigDialog.tsxSemantic tokens, removed hardcoded blue button
frontend/src/components/session/SessionCard.tsxSemantic tokens for selection, status, delete
frontend/src/components/session/QuestionPrompt.tsxComprehensive semantic token migration
frontend/src/components/session/PermissionRequestDialog.tsxWarning tokens
frontend/src/components/session/EditSessionTitleDialog.tsxDestructive tokens
frontend/src/components/session/ContextUsageIndicator.tsxSuccess/warning/destructive for usage levels
frontend/src/components/notifications/PendingActionsGroup.tsxUpdated color prop names
frontend/src/components/model/ModelSelectDialog.tsxSemantic tokens for selection and loading
frontend/src/components/model/ModelQuickSelect.tsxtext-warning for variant display
frontend/src/components/message/ToolCallPart.tsxSemantic tokens for all status states
frontend/src/components/message/TodoItem.tsxSemantic success/warning tokens
frontend/src/components/message/TextPart.tsxDestructive tokens for mermaid errors
frontend/src/components/message/SessionTodoDisplay.tsxbg-success for progress bars
frontend/src/components/message/RetryPart.tsxWarning tokens for retry UI
frontend/src/components/message/PromptInput.tsxComprehensive semantic migration
frontend/src/components/message/PatchPart.tsxtext-info for file links
frontend/src/components/message/MessageThread.tsxPrimary/warning tokens for messages
frontend/src/components/message/MessageSkeleton.tsxPrimary tokens for skeletons
frontend/src/components/message/MessagePart.tsxInfo/destructive tokens
frontend/src/components/message/FileToolRender.tsxSuccess/info tokens
frontend/src/components/message/EditableUserMessage.tsxPrimary hover token
frontend/src/components/message/DiffStats.tsxSuccess/destructive tokens
frontend/src/components/message/ContentDiffViewer.tsxSuccess/destructive for diff lines
frontend/src/components/memory/MemoryList.tsxSemantic scope colors
frontend/src/components/file-browser/FileTree.tsxDestructive for delete action
frontend/src/components/file-browser/FilePreview.tsxWarning/info/success tokens
frontend/src/components/file-browser/FileDiffView.tsxComprehensive semantic diff styling
frontend/src/components/ssh/SSHHostKeyDialog.tsxDestructive/warning tokens
frontend/src/lib/git-status-styles.tsAll colors migrated to semantic tokens
frontend/src/pages/SessionDetail.tsxSemantic tokens for parent session, subtitle, actions
frontend/src/pages/RepoDetail.tsxBadge variant, removed hardcoded blue button
frontend/src/pages/Memories.tsxtext-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 threadfrontend/src/components/message/ToolCallPart.tsx Outdated
Comment threadfrontend/src/components/message/ToolCallPart.tsx Outdated
Comment threadfrontend/src/components/settings/GeneralSettings.tsx Outdated
Comment threadfrontend/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.
CopilotAI review requested due to automatic review settings March 8, 2026 23:07
@itz4blitzitz4blitz changed the title Refine UI theme foundation and responsive settings patternsBring OpenCode theme presets into the UI foundationMar 8, 2026

CopilotAI 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 threadfrontend/src/components/ui/page-header.tsx
Comment threadfrontend/src/components/settings/SettingsDialog.tsx Outdated
Comment threadfrontend/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.
@itz4blitzitz4blitz reopened this Mar 9, 2026
CopilotAI review requested due to automatic review settings April 1, 2026 20:27

CopilotAI 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}
/>

CopilotAIApr 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"
/>

CopilotAIApr 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

coderabbitaiBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

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
ContributorAuthor

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 freeto 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

@itz4blitz