feat: customisation page (#178)

* feat: v1 prefs page

* feat: customisation updates
This commit is contained in:
Nikhil
2026-01-07 16:33:26 -08:00
committed by GitHub
parent 3b838d0f94
commit 9e1aed99f2
6 changed files with 169 additions and 0 deletions

View File

@@ -2,6 +2,7 @@ import type { FC } from 'react'
import { HashRouter, Navigate, Route, Routes } from 'react-router'
import { AISettingsPage } from './ai-settings/AISettingsPage'
import { ConnectMCP } from './connect-mcp/ConnectMCP'
import { CustomizationPage } from './customization/CustomizationPage'
import { DashboardLayout } from './layout/DashboardLayout'
import { LlmHubPage } from './llm-hub/LlmHubPage'
import { MCPSettingsPage } from './mcp-settings/MCPSettingsPage'
@@ -18,6 +19,7 @@ export const App: FC = () => {
<Route path="search" element={null} />
<Route path="connect-mcp" element={<ConnectMCP />} />
<Route path="mcp" element={<MCPSettingsPage />} />
<Route path="customization" element={<CustomizationPage />} />
<Route
path="onboarding"
element={<AISettingsPage key="onboarding" />}

View File

@@ -0,0 +1,20 @@
import { Palette } from 'lucide-react'
import type { FC } from 'react'
export const CustomizationHeader: FC = () => {
return (
<div className="rounded-xl border border-border bg-card p-6 shadow-sm transition-all hover:shadow-md">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-[var(--accent-orange)]/10">
<Palette className="h-6 w-6 text-[var(--accent-orange)]" />
</div>
<div className="flex-1">
<h2 className="mb-1 font-semibold text-xl">Customization</h2>
<p className="text-muted-foreground text-sm">
Personalize your toolbar and browser interface
</p>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,12 @@
import type { FC } from 'react'
import { CustomizationHeader } from './CustomizationHeader'
import { ToolbarSettingsCard } from './ToolbarSettingsCard'
export const CustomizationPage: FC = () => {
return (
<div className="fade-in slide-in-from-bottom-5 animate-in space-y-6 duration-500">
<CustomizationHeader />
<ToolbarSettingsCard />
</div>
)
}

View File

@@ -0,0 +1,125 @@
import { type FC, useEffect, useState } from 'react'
import { toast } from 'sonner'
import { Label } from '@/components/ui/label'
import { Switch } from '@/components/ui/switch'
import { getBrowserOSAdapter } from '@/lib/browseros/adapter'
import { BROWSEROS_PREFS } from '@/lib/browseros/prefs'
export const ToolbarSettingsCard: FC = () => {
const [showLlmChat, setShowLlmChat] = useState(true)
const [showLlmHub, setShowLlmHub] = useState(true)
const [showToolbarLabels, setShowToolbarLabels] = useState(true)
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
const loadPrefs = async () => {
try {
const adapter = getBrowserOSAdapter()
const [chatPref, hubPref, labelsPref] = await Promise.all([
adapter.getPref(BROWSEROS_PREFS.SHOW_LLM_CHAT),
adapter.getPref(BROWSEROS_PREFS.SHOW_LLM_HUB),
adapter.getPref(BROWSEROS_PREFS.SHOW_TOOLBAR_LABELS),
])
setShowLlmChat(chatPref?.value !== false)
setShowLlmHub(hubPref?.value !== false)
setShowToolbarLabels(labelsPref?.value !== false)
} catch {
// API not available - use defaults
} finally {
setIsLoading(false)
}
}
loadPrefs()
}, [])
const handleToggle = async (
prefKey: string,
value: boolean,
setter: (v: boolean) => void,
) => {
try {
const adapter = getBrowserOSAdapter()
await adapter.setPref(prefKey, value)
setter(value)
} catch {
toast.error('Failed to update setting')
}
}
return (
<div className="rounded-xl border border-border bg-card p-6 shadow-sm transition-all hover:shadow-md">
<h3 className="mb-4 font-semibold text-lg">Toolbar Settings</h3>
<div className="space-y-4">
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<Label htmlFor="show-llm-chat" className="font-medium text-sm">
Show Chat Button
</Label>
<p className="text-muted-foreground text-xs">
Display the Chat button in the browser toolbar
</p>
</div>
<Switch
id="show-llm-chat"
checked={showLlmChat}
onCheckedChange={(checked) =>
handleToggle(
BROWSEROS_PREFS.SHOW_LLM_CHAT,
checked,
setShowLlmChat,
)
}
disabled={isLoading}
/>
</div>
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<Label htmlFor="show-llm-hub" className="font-medium text-sm">
Show Hub Button
</Label>
<p className="text-muted-foreground text-xs">
Display the Hub button in the browser toolbar
</p>
</div>
<Switch
id="show-llm-hub"
checked={showLlmHub}
onCheckedChange={(checked) =>
handleToggle(BROWSEROS_PREFS.SHOW_LLM_HUB, checked, setShowLlmHub)
}
disabled={isLoading}
/>
</div>
<div className="flex items-center justify-between border-border border-t pt-4">
<div className="space-y-0.5">
<Label
htmlFor="show-toolbar-labels"
className="font-medium text-sm"
>
Show Button Labels
</Label>
<p className="text-muted-foreground text-xs">
Display text labels next to toolbar button icons
</p>
</div>
<Switch
id="show-toolbar-labels"
checked={showToolbarLabels}
onCheckedChange={(checked) =>
handleToggle(
BROWSEROS_PREFS.SHOW_TOOLBAR_LABELS,
checked,
setShowToolbarLabels,
)
}
disabled={isLoading}
/>
</div>
</div>
</div>
)
}

View File

@@ -5,6 +5,7 @@ import {
type LucideIcon,
Menu,
MessageSquare,
Palette,
PlugZap,
RotateCcw,
Search,
@@ -65,6 +66,12 @@ const navigationItems: NavItem[] = [
icon: Server,
enabled: true,
},
{
name: 'Customization',
to: '/customization',
icon: Palette,
enabled: true,
},
{
name: 'Revisit Onboarding',
to: chrome.runtime.getURL('onboarding.html'),

View File

@@ -6,4 +6,7 @@ export const BROWSEROS_PREFS = {
THIRD_PARTY_LLM_PROVIDERS: 'browseros.third_party_llm.providers',
ALLOW_REMOTE_MCP: 'browseros.server.allow_remote_in_mcp',
RESTART_SERVER: 'browseros.server.restart_requested',
SHOW_LLM_CHAT: 'browseros.show_llm_chat',
SHOW_LLM_HUB: 'browseros.show_llm_hub',
SHOW_TOOLBAR_LABELS: 'browseros.show_toolbar_labels',
} as const