From c73bad9a9c68470a68b9dd2b54333d5e335a503c Mon Sep 17 00:00:00 2001 From: Andrew Harvard Date: Mon, 23 Feb 2026 11:41:08 -0500 Subject: [PATCH] refactor: MCP-compliant theme tokens and CSS class rename (#7275) --- ui/desktop/src/App.tsx | 8 +- .../src/components/AnnouncementModal.tsx | 2 +- ui/desktop/src/components/ApiKeyTester.tsx | 16 +- ui/desktop/src/components/BaseChat.tsx | 14 +- ui/desktop/src/components/ChatInput.tsx | 46 +-- .../src/components/ElicitationRequest.tsx | 14 +- ui/desktop/src/components/ErrorBoundary.tsx | 4 +- ui/desktop/src/components/GooseMessage.tsx | 8 +- .../components/GooseSidebar/AppSidebar.tsx | 20 +- .../components/GooseSidebar/ThemeSelector.tsx | 14 +- ui/desktop/src/components/Hub.tsx | 2 +- ui/desktop/src/components/ImagePreview.tsx | 4 +- ui/desktop/src/components/LauncherView.tsx | 4 +- .../src/components/Layout/AppLayout.tsx | 4 +- .../src/components/Layout/MainPanelLayout.tsx | 2 +- ui/desktop/src/components/LoadingGoose.tsx | 2 +- .../src/components/MCPUIResourceRenderer.tsx | 2 +- ui/desktop/src/components/MarkdownContent.tsx | 8 +- .../src/components/McpApps/McpAppRenderer.tsx | 10 +- ui/desktop/src/components/MentionPopover.tsx | 14 +- ui/desktop/src/components/MessageCopyLink.tsx | 2 +- ui/desktop/src/components/MessageQueue.tsx | 2 +- ui/desktop/src/components/OllamaSetup.tsx | 28 +- .../src/components/ParameterInputModal.tsx | 24 +- .../src/components/PopularChatTopics.tsx | 10 +- .../src/components/ProgressiveMessageList.tsx | 2 +- ui/desktop/src/components/ProviderGuard.tsx | 38 +- ui/desktop/src/components/RecipeHeader.tsx | 6 +- .../src/components/TelemetryOptOutModal.tsx | 12 +- .../src/components/ToolCallArguments.tsx | 16 +- .../src/components/ToolCallConfirmation.tsx | 4 +- .../components/ToolCallStatusIndicator.tsx | 2 +- .../src/components/ToolCallWithResponse.tsx | 16 +- ui/desktop/src/components/UserMessage.tsx | 14 +- ui/desktop/src/components/apps/AppsView.tsx | 18 +- .../src/components/apps/StandaloneAppView.tsx | 6 +- .../bottom_menu/BottomMenuAlertPopover.tsx | 2 +- .../BottomMenuExtensionSelection.tsx | 8 +- .../bottom_menu/BottomMenuModeSelection.tsx | 2 +- .../components/bottom_menu/CostTracker.tsx | 16 +- .../components/bottom_menu/DirSwitcher.tsx | 2 +- .../src/components/common/InlineEditText.tsx | 2 +- .../src/components/conversation/SearchBar.tsx | 2 +- .../components/extensions/ExtensionsView.tsx | 6 +- .../components/parameter/ParameterInput.tsx | 40 +-- .../recipes/CreateEditRecipeModal.tsx | 26 +- .../recipes/CreateRecipeFromSessionModal.tsx | 26 +- .../components/recipes/ImportRecipeForm.tsx | 28 +- .../components/recipes/RecipeActivities.tsx | 2 +- .../recipes/RecipeActivityEditor.tsx | 20 +- .../recipes/RecipeExpandableInfo.tsx | 6 +- .../components/recipes/RecipeInfoModal.tsx | 10 +- .../src/components/recipes/RecipesView.tsx | 18 +- .../recipes/shared/InstructionsEditor.tsx | 18 +- .../recipes/shared/JsonSchemaEditor.tsx | 16 +- .../recipes/shared/RecipeFormFields.tsx | 48 +-- .../recipes/shared/RecipeNameField.tsx | 8 +- .../schedule/ScheduleDetailView.tsx | 54 +-- .../schedule/ScheduleFromRecipeModal.tsx | 4 +- .../src/components/schedule/ScheduleModal.tsx | 10 +- .../src/components/schedule/SchedulesView.tsx | 14 +- .../sessions/SessionHistoryView.tsx | 18 +- .../src/components/sessions/SessionItem.tsx | 2 +- .../components/sessions/SessionListView.tsx | 36 +- .../sessions/SessionViewComponents.tsx | 14 +- .../components/sessions/SessionsInsights.tsx | 52 +-- .../components/sessions/SharedSessionView.tsx | 10 +- .../settings/PromptsSettingsSection.tsx | 16 +- .../src/components/settings/SettingsView.tsx | 2 +- .../settings/app/AppSettingsSection.tsx | 21 +- .../settings/app/ExternalBackendSection.tsx | 10 +- .../settings/app/TelemetrySettings.tsx | 8 +- .../components/settings/app/UpdateSection.tsx | 22 +- .../settings/chat/GoosehintsModal.tsx | 6 +- .../settings/chat/GoosehintsSection.tsx | 4 +- .../settings/chat/SpellcheckToggle.tsx | 6 +- .../settings/config/ConfigSettings.tsx | 6 +- .../settings/dictation/DictationSettings.tsx | 26 +- .../settings/dictation/LocalModelManager.tsx | 26 +- .../extensions/modal/EnvVarsSection.tsx | 18 +- .../modal/ExtensionConfigFields.tsx | 8 +- .../extensions/modal/ExtensionInfoFields.tsx | 10 +- .../extensions/modal/ExtensionModal.tsx | 14 +- .../modal/ExtensionTimeoutField.tsx | 4 +- .../extensions/modal/HeadersSection.tsx | 14 +- .../subcomponents/ExtensionItem.tsx | 4 +- .../subcomponents/ExtensionList.tsx | 6 +- .../keyboard/KeyboardShortcutsSection.tsx | 16 +- .../settings/keyboard/ShortcutRecorder.tsx | 14 +- .../settings/mode/ConfigureApproveMode.tsx | 10 +- .../mode/ConversationLimitsDropdown.tsx | 12 +- .../settings/mode/ModeSelectionItem.tsx | 12 +- .../settings/models/ModelsSection.tsx | 4 +- .../models/bottom_bar/ModelsBottomBar.tsx | 4 +- .../subcomponents/LeadWorkerSettings.tsx | 34 +- .../models/subcomponents/SwitchModelModal.tsx | 30 +- .../settings/permission/PermissionModal.tsx | 18 +- .../permission/PermissionRulesModal.tsx | 10 +- .../settings/permission/PermissionSetting.tsx | 12 +- .../providers/ProviderSettingsPage.tsx | 6 +- .../modal/ProviderConfiguationModal.tsx | 2 +- .../subcomponents/ProviderSetupActions.tsx | 16 +- .../forms/CustomProviderForm.tsx | 24 +- .../forms/DefaultProviderSetupForm.tsx | 6 +- .../providers/subcomponents/CardContainer.tsx | 10 +- .../providers/subcomponents/CardHeader.tsx | 2 +- .../subcomponents/utils/StringUtils.tsx | 2 +- .../reset_provider/ResetProviderSection.tsx | 2 +- .../ResponseStyleSelectionItem.tsx | 10 +- .../settings/security/SecurityToggle.tsx | 58 +-- .../sessions/SessionSharingSection.tsx | 4 +- .../settings/tunnel/TunnelSection.tsx | 12 +- ui/desktop/src/components/ui/BackButton.tsx | 2 +- ui/desktop/src/components/ui/Diagnostics.tsx | 12 +- ui/desktop/src/components/ui/Expand.tsx | 2 +- .../src/components/ui/JsonSchemaForm.tsx | 10 +- .../src/components/ui/RecipeWarningModal.tsx | 12 +- ui/desktop/src/components/ui/Select.tsx | 10 +- ui/desktop/src/components/ui/Tooltip.tsx | 4 +- ui/desktop/src/components/ui/button.tsx | 10 +- ui/desktop/src/components/ui/card.tsx | 4 +- ui/desktop/src/components/ui/dialog.tsx | 6 +- .../src/components/ui/dropdown-menu.tsx | 16 +- ui/desktop/src/components/ui/input.tsx | 2 +- ui/desktop/src/components/ui/scroll-area.tsx | 2 +- ui/desktop/src/components/ui/separator.tsx | 2 +- ui/desktop/src/components/ui/sheet.tsx | 8 +- ui/desktop/src/components/ui/sidebar.tsx | 2 +- ui/desktop/src/components/ui/skeleton.tsx | 2 +- ui/desktop/src/components/ui/switch.tsx | 4 +- ui/desktop/src/components/ui/tabs.tsx | 6 +- ui/desktop/src/contexts/ThemeContext.tsx | 10 +- ui/desktop/src/preload.ts | 3 +- ui/desktop/src/renderer.tsx | 5 + ui/desktop/src/styles/main.css | 330 +++++++++--------- ui/desktop/src/suspense-loader.tsx | 2 +- ui/desktop/src/theme/theme-tokens.ts | 292 ++++++++++++++++ 137 files changed, 1274 insertions(+), 963 deletions(-) create mode 100644 ui/desktop/src/theme/theme-tokens.ts diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 8a9d1fcd..2e9b0655 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -231,7 +231,7 @@ const ConfigureProvidersRoute = () => { const navigate = useNavigate(); return ( -
+
navigate('/settings', { state: { section: 'models' } })} isOnboarding={false} @@ -248,7 +248,7 @@ const WelcomeRoute = ({ onSelectProvider }: WelcomeRouteProps) => { const navigate = useNavigate(); return ( -
+
{ navigate('/', { replace: true }); @@ -625,7 +625,7 @@ export function AppInner() { toastClassName={() => `relative min-h-16 mb-4 p-2 rounded-lg flex justify-between overflow-hidden cursor-pointer - text-text-on-accent bg-background-inverse + text-text-inverse bg-background-inverse ` } style={{ width: '450px' }} @@ -636,7 +636,7 @@ export function AppInner() { pauseOnHover /> -
+
diff --git a/ui/desktop/src/components/AnnouncementModal.tsx b/ui/desktop/src/components/AnnouncementModal.tsx index 197a60c8..72be7be9 100644 --- a/ui/desktop/src/components/AnnouncementModal.tsx +++ b/ui/desktop/src/components/AnnouncementModal.tsx @@ -135,7 +135,7 @@ export default function AnnouncementModal() { diff --git a/ui/desktop/src/components/ApiKeyTester.tsx b/ui/desktop/src/components/ApiKeyTester.tsx index 7017849b..a49fed7e 100644 --- a/ui/desktop/src/components/ApiKeyTester.tsx +++ b/ui/desktop/src/components/ApiKeyTester.tsx @@ -73,14 +73,14 @@ export default function ApiKeyTester({ onSuccess, onStartTesting }: ApiKeyTester
-
+
- +
-

+

Quick Setup with API Key

- Auto-detect your provider + Auto-detect your provider
@@ -92,7 +92,7 @@ export default function ApiKeyTester({ onSuccess, onStartTesting }: ApiKeyTester value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="Enter your API key (OpenAI, Anthropic, Google, etc.)" - className="flex-1 px-3 py-2 border rounded-lg bg-background-default text-text-default placeholder-text-muted focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" + className="flex-1 px-3 py-2 border rounded-lg bg-background-primary text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" disabled={isLoading} onKeyDown={(e) => { if (e.key === 'Enter' && canSubmit) { @@ -116,7 +116,7 @@ export default function ApiKeyTester({ onSuccess, onStartTesting }: ApiKeyTester {/* Loading state */} {isLoading && ( -
+
Detecting provider and validating key...
@@ -148,8 +148,8 @@ export default function ApiKeyTester({ onSuccess, onStartTesting }: ApiKeyTester
-

Suggestions:

-
    +

    Suggestions:

    +
    • diff --git a/ui/desktop/src/components/BaseChat.tsx b/ui/desktop/src/components/BaseChat.tsx index 34f2df82..ef169181 100644 --- a/ui/desktop/src/components/BaseChat.tsx +++ b/ui/desktop/src/components/BaseChat.tsx @@ -346,13 +346,13 @@ export default function BaseChat({ return (
      {renderHeader && renderHeader()}
      -
      +

      Failed to Load Session

      @@ -362,7 +362,7 @@ export default function BaseChat({ onClick={() => { setView('chat'); }} - className="px-4 py-2 text-center cursor-pointer text-text-default border border-border-default hover:bg-background-muted rounded-lg transition-all duration-150" + className="px-4 py-2 text-center cursor-pointer text-text-primary border border-border-primary hover:bg-background-secondary rounded-lg transition-all duration-150" > Go home @@ -377,7 +377,7 @@ export default function BaseChat({ return (
      @@ -394,14 +394,14 @@ export default function BaseChat({ className="no-drag flex flex-row items-center gap-1 hover:opacity-80 transition-opacity" > - goose + goose
      {recipe?.title && ( -
      +
      )} diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index 347382d3..e68f8bc6 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -1165,9 +1165,9 @@ export default function ChatInput({ disableAnimation ? '' : 'page-transition' } ${ isFocused - ? 'border-border-strong hover:border-border-strong' - : 'border-border-default hover:border-border-default' - } bg-background-default z-10 rounded-t-2xl`} + ? 'border-border-secondary hover:border-border-secondary' + : 'border-border-primary hover:border-border-primary' + } bg-background-primary z-10 rounded-t-2xl`} data-drop-zone="true" onDrop={handleLocalDrop} onDragOver={handleLocalDragOver} @@ -1191,7 +1191,7 @@ export default function ChatInput({ onTriggerQueueProcessing={handleResumeQueue} editingMessageIdRef={editingMessageIdRef} isPaused={queuePausedRef.current} - className="border-b border-border-default" + className="border-b border-border-primary" /> )} {/* Input row with inline action buttons wrapped in form */} @@ -1219,7 +1219,7 @@ export default function ChatInput({ overflowY: 'auto', paddingRight: dictationProvider ? '180px' : '120px', }} - className="w-full outline-none border-none focus:ring-0 bg-transparent px-3 pt-3 pb-1.5 text-sm resize-none text-text-default placeholder:text-text-muted" + className="w-full outline-none border-none focus:ring-0 bg-transparent px-3 pt-3 pb-1.5 text-sm resize-none text-text-primary placeholder:text-text-secondary" /> {/* Inline action buttons - absolutely positioned on the right */} @@ -1346,15 +1346,15 @@ export default function ChatInput({ {/* Recording/transcribing status indicator - positioned above the button row */} {(isRecording || isTranscribing) && ( -
      +
      {isRecording && ( - + Listening )} - {isRecording && isTranscribing && } + {isRecording && isTranscribing && } {isTranscribing && ( @@ -1370,7 +1370,7 @@ export default function ChatInput({ {/* Combined files and images preview */} {(pastedImages.length > 0 || allDroppedFiles.length > 0) && ( -
      +
      {/* Render pasted images first */} {pastedImages.map((img) => (
      @@ -1378,7 +1378,7 @@ export default function ChatInput({ {`Pasted )} {img.isLoading && ( @@ -1419,7 +1419,7 @@ export default function ChatInput({ {file.name} )} {file.isLoading && ( @@ -1437,15 +1437,15 @@ export default function ChatInput({
      ) : ( // File box preview -
      -
      +
      +
      {file.name.split('.').pop()?.toUpperCase() || 'FILE'}
      -

      +

      {file.name}

      -

      {file.type || 'Unknown type'}

      +

      {file.type || 'Unknown type'}

      )} @@ -1482,7 +1482,7 @@ export default function ChatInput({ onRestartStart={() => setChatState?.(ChatState.RestartingAgent)} onRestartEnd={() => setChatState?.(ChatState.Idle)} /> -
      +
      Attach file -
      +
      {/* Model selector, mode selector, alerts, summarize button */}
      {/* Cost Tracker */} @@ -1523,13 +1523,13 @@ export default function ChatInput({ />
      -
      +
      -
      +
      {sessionId && messages.length > 0 && ( <> -
      +
      @@ -1545,7 +1545,7 @@ export default function ChatInput({ }} variant="ghost" size="sm" - className="flex items-center justify-center text-text-default/70 hover:text-text-default text-xs cursor-pointer" + className="flex items-center justify-center text-text-primary/70 hover:text-text-primary text-xs cursor-pointer" > @@ -1568,7 +1568,7 @@ export default function ChatInput({ }} variant="ghost" size="sm" - className="flex items-center justify-center text-text-default/70 hover:text-text-default text-xs cursor-pointer transition-colors" + className="flex items-center justify-center text-text-primary/70 hover:text-text-primary text-xs cursor-pointer transition-colors" > diff --git a/ui/desktop/src/components/ElicitationRequest.tsx b/ui/desktop/src/components/ElicitationRequest.tsx index b1720d3d..b8b6c3cf 100644 --- a/ui/desktop/src/components/ElicitationRequest.tsx +++ b/ui/desktop/src/components/ElicitationRequest.tsx @@ -57,7 +57,7 @@ export default function ElicitationRequest({ if (isCancelledMessage) { return ( -
      +
      Information request was cancelled.
      ); @@ -65,7 +65,7 @@ export default function ElicitationRequest({ if (submitted) { return ( -
      +
      -
      +
      +
      -
      +
      {message || 'Goose needs some information from you.'}
      -
      +
      Honk! {window?.appConfig?.get('GOOSE_VERSION') !== undefined ? ( -

      +

      An error occurred in Goose v{window?.appConfig?.get('GOOSE_VERSION') as string}.

      ) : ( -

      +

      An error occurred.

      )} diff --git a/ui/desktop/src/components/GooseMessage.tsx b/ui/desktop/src/components/GooseMessage.tsx index b6f04f83..794ae59f 100644 --- a/ui/desktop/src/components/GooseMessage.tsx +++ b/ui/desktop/src/components/GooseMessage.tsx @@ -143,8 +143,8 @@ export default function GooseMessage({ )} {cotText && ( -
      - +
      + Show thinking
      @@ -172,7 +172,7 @@ export default function GooseMessage({ {toolRequests.length === 0 && (
      {!isStreaming && ( -
      +
      {timestamp}
      )} @@ -213,7 +213,7 @@ export default function GooseMessage({ ); })}
      -
      +
      {!isStreaming && !hideTimestamp && timestamp}
      diff --git a/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx b/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx index b80fd519..3342f9df 100644 --- a/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx +++ b/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx @@ -155,18 +155,18 @@ const SessionList = React.memo<{
      {/* Vertical line segment - full height except last item stops at middle */}
      {/* Horizontal branch line */} -
      +
      @@ -185,10 +185,10 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {

      Downloading {getPreferredModel()}...

      {downloadProgress && ( <> -

      {downloadProgress.status}

      +

      {downloadProgress.status}

      {downloadProgress.total && downloadProgress.completed && (
      -
      +
      -

      +

      {Math.round((downloadProgress.completed / downloadProgress.total) * 100)}%

      @@ -209,7 +209,7 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) { @@ -228,8 +228,8 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
      -

      Waiting for Ollama to start...

      -

      +

      Waiting for Ollama to start...

      +

      Once Ollama is installed and running, we'll automatically detect it.

      @@ -239,7 +239,7 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) { target="_blank" rel="noopener noreferrer" onClick={handleInstallClick} - className="block w-full px-6 py-3 bg-background-muted text-text-default rounded-lg transition-colors font-medium text-center" + className="block w-full px-6 py-3 bg-background-secondary text-text-primary rounded-lg transition-colors font-medium text-center" > Install Ollama @@ -249,7 +249,7 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) { diff --git a/ui/desktop/src/components/ParameterInputModal.tsx b/ui/desktop/src/components/ParameterInputModal.tsx index bd0ea678..17a0d170 100644 --- a/ui/desktop/src/components/ParameterInputModal.tsx +++ b/ui/desktop/src/components/ParameterInputModal.tsx @@ -90,9 +90,9 @@ const ParameterInputModal: React.FC = ({
      {showCancelOptions ? ( // Cancel options modal -
      -

      Cancel Recipe Setup

      -

      What would you like to do?

      +
      +

      Cancel Recipe Setup

      +

      What would you like to do?

      ) : ( // Main parameter form -
      +
      -

      Recipe Parameters

      +

      Recipe Parameters

      {parameters.map((param) => (
      -