From 890a7864f4c0ec8e3b2a590a8e767db0a0f087dd Mon Sep 17 00:00:00 2001 From: Gagan Date: Fri, 10 Jul 2026 00:38:30 +0530 Subject: [PATCH] =?UTF-8?q?style(x):=20settings=20redesign=20=E2=80=94=20g?= =?UTF-8?q?rouped=20nav,=20brand=20logos,=20blurred=20overlay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dialog shell: sectioned sidebar nav (Configure / App), larger header without divider, more padding - Connections & Mobile: real brand logos (Google, Fireflies, Slack, WhatsApp, Telegram), no icon tiles, no separator lines - Models: provider logos on the your-own-providers cards - Code Mode: Anthropic/OpenAI marks for Claude Code and Codex - Help: GitHub and Discord logos, tile-free rows - Dialog overlay: frosted backdrop blur --- .../components/onboarding/provider-icons.tsx | 32 ++++++ .../src/components/settings-dialog.tsx | 108 +++++++++++------- .../settings/connected-accounts-settings.tsx | 35 ++---- .../settings/mobile-channels-settings.tsx | 18 +-- .../renderer/src/components/ui/dialog.tsx | 2 +- 5 files changed, 113 insertions(+), 82 deletions(-) diff --git a/apps/x/apps/renderer/src/components/onboarding/provider-icons.tsx b/apps/x/apps/renderer/src/components/onboarding/provider-icons.tsx index c58c7bf0..24eea525 100644 --- a/apps/x/apps/renderer/src/components/onboarding/provider-icons.tsx +++ b/apps/x/apps/renderer/src/components/onboarding/provider-icons.tsx @@ -75,6 +75,38 @@ export function SlackIcon({ className }: IconProps) { ) } +export function GitHubIcon({ className }: IconProps) { + return ( + + + + ) +} + +export function DiscordIcon({ className }: IconProps) { + return ( + + + + ) +} + +export function WhatsAppIcon({ className }: IconProps) { + return ( + + + + ) +} + +export function TelegramIcon({ className }: IconProps) { + return ( + + + + ) +} + export function FirefliesIcon({ className }: IconProps) { return ( diff --git a/apps/x/apps/renderer/src/components/settings-dialog.tsx b/apps/x/apps/renderer/src/components/settings-dialog.tsx index 248c6cc6..4b56eb51 100644 --- a/apps/x/apps/renderer/src/components/settings-dialog.tsx +++ b/apps/x/apps/renderer/src/components/settings-dialog.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { useState, useEffect, useCallback, useMemo } from "react" -import { Server, Key, Shield, Palette, Monitor, Sun, Moon, Loader2, CheckCircle2, Plus, X, Wrench, Search, ChevronRight, Link2, Tags, Mail, BookOpen, User, Plug, HelpCircle, MessageCircle, Bug, Terminal, AlertTriangle, RefreshCw, PanelRight, Bell, Smartphone } from "lucide-react" +import { Server, Key, Shield, Palette, Monitor, Sun, Moon, Loader2, CheckCircle2, Plus, X, Wrench, Search, ChevronRight, Link2, Tags, Mail, BookOpen, User, Plug, HelpCircle, MessageCircle, Terminal, AlertTriangle, RefreshCw, PanelRight, Bell, Smartphone } from "lucide-react" import { Dialog, @@ -23,6 +23,7 @@ import { Switch } from "@/components/ui/switch" import { cn } from "@/lib/utils" import { useTheme } from "@/contexts/theme-context" import { toast } from "sonner" +import { AnthropicIcon, DiscordIcon, GenericApiIcon, GitHubIcon, GoogleIcon, OllamaIcon, OpenAIIcon, OpenRouterIcon, VercelIcon } from "@/components/onboarding/provider-icons" import { AccountSettings } from "@/components/settings/account-settings" import { ConnectedAccountsSettings } from "@/components/settings/connected-accounts-settings" import { MobileChannelsSettings } from "@/components/settings/mobile-channels-settings" @@ -112,6 +113,13 @@ const tabs: TabConfig[] = [ }, ] +/** Sidebar nav grouping: identity first, capabilities, then app-level. */ +const NAV_SECTIONS: { label: string | null; ids: ConfigTab[] }[] = [ + { label: null, ids: ["account", "connections", "mobile"] }, + { label: "Configure", ids: ["models", "mcp", "security", "code-mode", "note-tagging"] }, + { label: "App", ids: ["appearance", "notifications", "help"] }, +] + interface SettingsDialogProps { /** Optional trigger element. Omit when controlling `open` externally. */ children?: React.ReactNode @@ -136,9 +144,7 @@ function HelpSettings() { className="w-full justify-start gap-3 h-auto py-3" onClick={() => window.open("https://github.com/rowboatlabs/rowboat/issues/new", "_blank")} > -
- -
+
Report a bug Send feedback to the Rowboat team @@ -149,9 +155,7 @@ function HelpSettings() { className="w-full justify-start gap-3 h-auto py-3" onClick={() => window.open("https://discord.com/invite/wajrgmJQ6b", "_blank")} > -
- -
+
Join our Discord Chat with the community @@ -162,9 +166,7 @@ function HelpSettings() { className="w-full justify-start gap-3 h-auto py-3" onClick={() => window.open("mailto:contact@rowboatlabs.com", "_blank")} > -
- -
+
Contact us contact@rowboatlabs.com @@ -313,17 +315,17 @@ interface LlmModelOption { release_date?: string } -const primaryProviders: Array<{ id: LlmProviderFlavor; name: string; description: string }> = [ - { id: "openai", name: "OpenAI", description: "GPT models" }, - { id: "anthropic", name: "Anthropic", description: "Claude models" }, - { id: "google", name: "Gemini", description: "Google AI Studio" }, - { id: "ollama", name: "Ollama (Local)", description: "Run models locally" }, +const primaryProviders: Array<{ id: LlmProviderFlavor; name: string; description: string; icon: React.ElementType }> = [ + { id: "openai", name: "OpenAI", description: "GPT models", icon: OpenAIIcon }, + { id: "anthropic", name: "Anthropic", description: "Claude models", icon: AnthropicIcon }, + { id: "google", name: "Gemini", description: "Google AI Studio", icon: GoogleIcon }, + { id: "ollama", name: "Ollama (Local)", description: "Run models locally", icon: OllamaIcon }, ] -const moreProviders: Array<{ id: LlmProviderFlavor; name: string; description: string }> = [ - { id: "openrouter", name: "OpenRouter", description: "Multiple models, one key" }, - { id: "aigateway", name: "AI Gateway (Vercel)", description: "Vercel's AI Gateway" }, - { id: "openai-compatible", name: "OpenAI-Compatible", description: "Custom OpenAI-compatible API" }, +const moreProviders: Array<{ id: LlmProviderFlavor; name: string; description: string; icon: React.ElementType }> = [ + { id: "openrouter", name: "OpenRouter", description: "Multiple models, one key", icon: OpenRouterIcon }, + { id: "aigateway", name: "AI Gateway (Vercel)", description: "Vercel's AI Gateway", icon: VercelIcon }, + { id: "openai-compatible", name: "OpenAI-Compatible", description: "Custom OpenAI-compatible API", icon: GenericApiIcon }, ] const preferredDefaults: Partial> = { @@ -647,7 +649,7 @@ function ModelSettings({ dialogOpen, rowboatConnected = false }: { dialogOpen: b } }, [defaultProvider, providerConfigs, rowboatConnected]) - const renderProviderCard = (p: { id: LlmProviderFlavor; name: string; description: string }) => { + const renderProviderCard = (p: { id: LlmProviderFlavor; name: string; description: string; icon: React.ElementType }) => { const isDefault = defaultProvider === p.id const isSelected = provider === p.id const hasModel = providerConfigs[p.id].models[0]?.trim().length > 0 @@ -665,7 +667,8 @@ function ModelSettings({ dialogOpen, rowboatConnected = false }: { dialogOpen: b : "border-border hover:bg-accent" )} > -
+
+ {p.name} {isDefault && !rowboatConnected && ( @@ -1869,7 +1872,11 @@ function AgentStatusRow({ const ready = installed && status?.signedIn return (
- + {agent === 'claude' ? ( + + ) : ( + + )}
{name}
@@ -2323,34 +2330,47 @@ export function SettingsDialog({ children, defaultTab = "account", open: control
{/* Sidebar */}
-
-

Settings

+
+

Settings

-
{/* Main content */}
{/* Header */} -
-

{activeTabConfig.label}

-

+

+

{activeTabConfig.label}

+

{activeTab === "models" && rowboatConnected ? "Select your default models" : activeTabConfig.description} @@ -2358,7 +2378,7 @@ export function SettingsDialog({ children, defaultTab = "account", open: control

{/* Content */} -
+
{activeTab === "account" ? ( ) : activeTab === "connections" ? ( diff --git a/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx b/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx index 4b9eb802..08db114d 100644 --- a/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx +++ b/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx @@ -1,9 +1,9 @@ "use client" import * as React from "react" -import { Loader2, Mic, Mail, Calendar, MessageSquare } from "lucide-react" +import { Loader2, Calendar } from "lucide-react" +import { FirefliesIcon, GoogleIcon, SlackIcon } from "@/components/onboarding/provider-icons" import { Button } from "@/components/ui/button" -import { Separator } from "@/components/ui/separator" import { Switch } from "@/components/ui/switch" import { Textarea } from "@/components/ui/textarea" import { GoogleClientIdModal } from "@/components/google-client-id-modal" @@ -47,9 +47,7 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti className="flex items-center justify-between gap-2 rounded-md px-3 py-2 hover:bg-accent/50 transition-colors" >
-
- {icon} -
+ {icon}
{displayName} {state.isLoading ? ( @@ -145,9 +143,7 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti {c.useComposioForGoogle ? (
-
- -
+
Gmail {c.gmailLoading ? ( @@ -189,14 +185,12 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti
) : ( - c.providers.includes('google') && renderOAuthProvider('google', 'Google', , 'Sync emails and calendar') + c.providers.includes('google') && renderOAuthProvider('google', 'Google', , 'Sync emails and calendar') )} {c.useComposioForGoogleCalendar && (
-
- -
+
Google Calendar {c.googleCalendarLoading ? ( @@ -238,7 +232,6 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti
)} - )} @@ -252,14 +245,13 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti
{/* Fireflies */} - {renderOAuthProvider('fireflies-ai', 'Fireflies', , 'AI meeting transcripts')} + {renderOAuthProvider('fireflies-ai', 'Fireflies', , 'AI meeting transcripts')} )} {/* Team Communication Section */} <> - -
+
Team Communication @@ -267,9 +259,7 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti
-
- -
+
Slack {c.slackLoading ? ( @@ -408,8 +398,7 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti {/* Knowledge Sources Section */} {c.slackEnabled && ( <> - -
+
Knowledge Sources @@ -417,9 +406,7 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti
-
- -
+
Slack to knowledge diff --git a/apps/x/apps/renderer/src/components/settings/mobile-channels-settings.tsx b/apps/x/apps/renderer/src/components/settings/mobile-channels-settings.tsx index 9974ee94..0e34c08e 100644 --- a/apps/x/apps/renderer/src/components/settings/mobile-channels-settings.tsx +++ b/apps/x/apps/renderer/src/components/settings/mobile-channels-settings.tsx @@ -2,10 +2,10 @@ import { useCallback, useEffect, useState } from "react" import type { z } from "zod" -import { Coffee, Loader2, MessageCircle, Send, Smartphone } from "lucide-react" +import { Coffee, Loader2, Smartphone } from "lucide-react" +import { TelegramIcon, WhatsAppIcon } from "@/components/onboarding/provider-icons" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" -import { Separator } from "@/components/ui/separator" import { Switch } from "@/components/ui/switch" import { toast } from "sonner" import type { ChannelsConfig, ChannelsStatus } from "@x/shared/src/channels.js" @@ -104,9 +104,7 @@ export function MobileChannelsSettings({ dialogOpen }: { dialogOpen: boolean }) {/* Caffeinate */}
-
- -
+
Caffeinate @@ -131,15 +129,12 @@ export function MobileChannelsSettings({ dialogOpen }: { dialogOpen: boolean }) />
- {/* WhatsApp */}
-
- -
+
WhatsApp @@ -228,15 +223,12 @@ export function MobileChannelsSettings({ dialogOpen }: { dialogOpen: boolean }) )}
- {/* Telegram */}
-
- -
+
Telegram diff --git a/apps/x/apps/renderer/src/components/ui/dialog.tsx b/apps/x/apps/renderer/src/components/ui/dialog.tsx index 60cc10e1..7ba2cb4b 100644 --- a/apps/x/apps/renderer/src/components/ui/dialog.tsx +++ b/apps/x/apps/renderer/src/components/ui/dialog.tsx @@ -36,7 +36,7 @@ function DialogOverlay({