diff --git a/webui/src/components/GlobalDialog.tsx b/webui/src/components/GlobalDialog.tsx
index c567852..dd734ce 100644
--- a/webui/src/components/GlobalDialog.tsx
+++ b/webui/src/components/GlobalDialog.tsx
@@ -61,9 +61,9 @@ export const GlobalDialog: React.FC<{
{(kind === 'confirm' || kind === 'prompt') && (
-
+
)}
-
diff --git a/webui/src/index.css b/webui/src/index.css
index a11135e..15c8d1f 100644
--- a/webui/src/index.css
+++ b/webui/src/index.css
@@ -56,6 +56,26 @@ html {
--button-start: #fb923c;
--button-end: #f97316;
--button-shadow: rgb(249 115 22 / 0.16);
+ --button-neutral-bg: rgb(226 232 240 / 0.9);
+ --button-neutral-bg-hover: rgb(203 213 225 / 0.96);
+ --button-neutral-border: rgb(203 213 225 / 0.98);
+ --button-neutral-text: rgb(51 65 85 / 0.96);
+ --button-primary-bg: rgb(255 237 213 / 0.96);
+ --button-primary-bg-hover: rgb(255 224 189 / 0.98);
+ --button-primary-border: rgb(251 146 60 / 0.34);
+ --button-primary-text: rgb(154 52 18 / 0.98);
+ --button-success-bg: rgb(220 252 231 / 0.96);
+ --button-success-bg-hover: rgb(187 247 208 / 0.98);
+ --button-success-border: rgb(52 211 153 / 0.34);
+ --button-success-text: rgb(6 95 70 / 0.98);
+ --button-warning-bg: rgb(254 243 199 / 0.98);
+ --button-warning-bg-hover: rgb(253 230 138 / 0.98);
+ --button-warning-border: rgb(245 158 11 / 0.34);
+ --button-warning-text: rgb(146 64 14 / 0.98);
+ --button-danger-bg: rgb(255 228 230 / 0.98);
+ --button-danger-bg-hover: rgb(254 205 211 / 0.98);
+ --button-danger-border: rgb(244 63 94 / 0.28);
+ --button-danger-text: rgb(159 18 57 / 0.98);
--chip-bg: rgb(226 232 240 / 0.82);
--chip-bg-hover: rgb(203 213 225 / 0.92);
--chip-border: rgb(203 213 225 / 0.96);
@@ -125,6 +145,26 @@ html.theme-dark {
--button-start: #ee9852;
--button-end: #d96b25;
--button-shadow: rgb(217 107 37 / 0.18);
+ --button-neutral-bg: rgb(36 49 69 / 0.9);
+ --button-neutral-bg-hover: rgb(48 63 87 / 0.96);
+ --button-neutral-border: rgb(93 109 135 / 0.82);
+ --button-neutral-text: rgb(226 232 240 / 0.96);
+ --button-primary-bg: rgb(232 132 58 / 0.16);
+ --button-primary-bg-hover: rgb(232 132 58 / 0.24);
+ --button-primary-border: rgb(232 132 58 / 0.3);
+ --button-primary-text: rgb(255 228 205 / 0.96);
+ --button-success-bg: rgb(16 185 129 / 0.14);
+ --button-success-bg-hover: rgb(16 185 129 / 0.22);
+ --button-success-border: rgb(52 211 153 / 0.24);
+ --button-success-text: rgb(209 250 229 / 0.96);
+ --button-warning-bg: rgb(245 158 11 / 0.14);
+ --button-warning-bg-hover: rgb(245 158 11 / 0.22);
+ --button-warning-border: rgb(251 191 36 / 0.24);
+ --button-warning-text: rgb(254 243 199 / 0.96);
+ --button-danger-bg: rgb(244 63 94 / 0.14);
+ --button-danger-bg-hover: rgb(244 63 94 / 0.22);
+ --button-danger-border: rgb(251 113 133 / 0.24);
+ --button-danger-text: rgb(255 228 230 / 0.96);
--chip-bg: rgb(36 49 69 / 0.9);
--chip-bg-hover: rgb(48 63 87 / 0.96);
--chip-border: rgb(93 109 135 / 0.82);
@@ -299,6 +339,108 @@ html.theme-dark .brand-button {
box-shadow: 0 10px 24px var(--button-shadow);
}
+.ui-button {
+ border-radius: var(--radius-button);
+ border: 1px solid transparent;
+ transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease;
+}
+
+.ui-button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.ui-button-neutral {
+ background: var(--button-neutral-bg);
+ border-color: var(--button-neutral-border);
+ color: var(--button-neutral-text);
+}
+
+.ui-button-neutral:hover:not(:disabled) {
+ background: var(--button-neutral-bg-hover);
+}
+
+.ui-button-primary {
+ background: var(--button-primary-bg);
+ border-color: var(--button-primary-border);
+ color: var(--button-primary-text);
+}
+
+.ui-button-primary:hover:not(:disabled) {
+ background: var(--button-primary-bg-hover);
+}
+
+.ui-button-success {
+ background: var(--button-success-bg);
+ border-color: var(--button-success-border);
+ color: var(--button-success-text);
+}
+
+.ui-button-success:hover:not(:disabled) {
+ background: var(--button-success-bg-hover);
+}
+
+.ui-button-warning {
+ background: var(--button-warning-bg);
+ border-color: var(--button-warning-border);
+ color: var(--button-warning-text);
+}
+
+.ui-button-warning:hover:not(:disabled) {
+ background: var(--button-warning-bg-hover);
+}
+
+.ui-button-danger {
+ background: var(--button-danger-bg);
+ border-color: var(--button-danger-border);
+ color: var(--button-danger-text);
+}
+
+.ui-button-danger:hover:not(:disabled) {
+ background: var(--button-danger-bg-hover);
+}
+
+.chat-bubble-user {
+ background: linear-gradient(135deg, var(--button-start) 0%, var(--button-end) 100%);
+ color: white;
+}
+
+.chat-bubble-tool {
+ background: rgb(255 247 237 / 0.96);
+ border: 1px solid rgb(253 186 116 / 0.7);
+ color: rgb(124 45 18 / 0.98);
+}
+
+.chat-bubble-agent {
+ background: rgb(226 232 240 / 0.9);
+ border: 1px solid rgb(203 213 225 / 0.95);
+ color: rgb(51 65 85 / 0.98);
+}
+
+.chat-bubble-system {
+ background: rgb(226 232 240 / 0.72);
+ border: 1px solid rgb(203 213 225 / 0.9);
+ color: rgb(51 65 85 / 0.98);
+}
+
+html.theme-dark .chat-bubble-tool {
+ background: rgb(123 58 24 / 0.24);
+ border-color: rgb(232 132 58 / 0.28);
+ color: rgb(255 237 213 / 0.96);
+}
+
+html.theme-dark .chat-bubble-agent {
+ background: rgb(22 32 50 / 0.82);
+ border-color: rgb(71 85 105 / 0.76);
+ color: rgb(226 232 240 / 0.96);
+}
+
+html.theme-dark .chat-bubble-system {
+ background: rgb(36 49 69 / 0.74);
+ border-color: rgb(71 85 105 / 0.74);
+ color: rgb(226 232 240 / 0.96);
+}
+
.control-chip {
border-radius: var(--radius-chip);
background: var(--chip-bg);
diff --git a/webui/src/pages/Chat.tsx b/webui/src/pages/Chat.tsx
index 433cfce..0cf00b0 100644
--- a/webui/src/pages/Chat.tsx
+++ b/webui/src/pages/Chat.tsx
@@ -558,13 +558,13 @@ const Chat: React.FC = () => {
setChatTab('main')}
- className={`px-3 py-1.5 rounded-xl text-xs ${chatTab === 'main' ? 'brand-button text-white' : 'bg-zinc-900/70 border border-zinc-700 text-zinc-300'}`}
+ className={`ui-button px-3 py-1.5 text-xs ${chatTab === 'main' ? 'ui-button-primary' : 'ui-button-neutral'}`}
>
{t('mainChat')}
setChatTab('subagents')}
- className={`px-3 py-1.5 rounded-xl text-xs ${chatTab === 'subagents' ? 'bg-amber-600 text-white' : 'bg-zinc-900/70 border border-zinc-700 text-zinc-300'}`}
+ className={`ui-button px-3 py-1.5 text-xs ${chatTab === 'subagents' ? 'ui-button-primary' : 'ui-button-neutral'}`}
>
{t('subagentGroup')}
@@ -574,14 +574,14 @@ const Chat: React.FC = () => {
)}
- { if (chatTab === 'main') { void loadHistory(); } else { void loadSubagentGroup(); } }} className="flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-xl bg-zinc-800 hover:bg-zinc-700">{t('reloadHistory')}
+ { if (chatTab === 'main') { void loadHistory(); } else { void loadSubagentGroup(); } }} className="ui-button ui-button-neutral flex items-center gap-1 px-2.5 py-1.5 text-xs">{t('reloadHistory')}
{chatTab === 'subagents' && (
setSelectedStreamAgents([])}
- className={`px-2.5 py-1 rounded-full text-xs border ${selectedStreamAgents.length === 0 ? 'bg-amber-600 text-white border-amber-500' : 'bg-zinc-900/70 border-zinc-700 text-zinc-300'}`}
+ className={`ui-button px-2.5 py-1 rounded-full text-xs ${selectedStreamAgents.length === 0 ? 'ui-button-primary' : 'ui-button-neutral'}`}
>
{t('allAgents')}
@@ -589,7 +589,7 @@ const Chat: React.FC = () => {
toggleStreamAgent(agent)}
- className={`px-2.5 py-1 rounded-full text-xs border ${selectedStreamAgents.includes(agent) ? 'bg-zinc-100 text-zinc-950 border-zinc-100' : 'bg-zinc-900/70 border-zinc-700 text-zinc-300'}`}
+ className={`ui-button px-2.5 py-1 rounded-full text-xs ${selectedStreamAgents.includes(agent) ? 'ui-button-primary' : 'ui-button-neutral'}`}
>
{formatAgentName(agent)}
@@ -631,7 +631,7 @@ const Chat: React.FC = () => {
{t('dispatchToSubagent')}
@@ -689,14 +689,24 @@ const Chat: React.FC = () => {
const isExec = m.role === 'tool' || m.role === 'exec';
const isSystem = m.role === 'system';
const bubbleClass = isUser
- ? 'bg-indigo-600 text-white rounded-br-sm'
+ ? 'chat-bubble-user rounded-br-sm'
: isExec
- ? 'bg-amber-500/10 text-amber-100 rounded-bl-sm border border-amber-500/30'
+ ? 'chat-bubble-tool rounded-bl-sm'
: isSystem
- ? 'bg-zinc-700/40 text-zinc-100 rounded-bl-sm border border-zinc-600/40'
+ ? 'chat-bubble-system rounded-bl-sm'
: m.isReadonlyGroup
- ? 'bg-zinc-900/85 text-zinc-200 rounded-bl-sm border border-zinc-700/60'
- : 'bg-zinc-800/80 text-zinc-200 rounded-bl-sm border border-zinc-700/50';
+ ? 'chat-bubble-system rounded-bl-sm'
+ : 'chat-bubble-agent rounded-bl-sm';
+ const metaClass = isUser
+ ? 'text-white/75'
+ : isExec
+ ? 'text-amber-800/75 dark:text-amber-100/75'
+ : 'text-zinc-500 dark:text-zinc-400';
+ const subLabelClass = isUser
+ ? 'text-white/70'
+ : isExec
+ ? 'text-amber-700/80 dark:text-amber-100/70'
+ : 'text-zinc-500 dark:text-zinc-400';
return (
{
{m.avatarText || (isUser ? 'U' : 'A')}
-
{m.actorName || m.label || (isUser ? t('user') : isExec ? t('exec') : isSystem ? t('system') : t('agent'))}
- {m.metaLine &&
{m.metaLine}
}
+
{m.actorName || m.label || (isUser ? t('user') : isExec ? t('exec') : isSystem ? t('system') : t('agent'))}
+ {m.metaLine &&
{m.metaLine}
}
{m.label && m.actorName && m.label !== m.actorName && (
-
{m.label}
+
{m.label}
)}
{m.text}
diff --git a/webui/src/pages/Config.tsx b/webui/src/pages/Config.tsx
index b543199..e89c104 100644
--- a/webui/src/pages/Config.tsx
+++ b/webui/src/pages/Config.tsx
@@ -282,18 +282,18 @@ const Config: React.FC = () => {
{t('configuration')}
- setShowRaw(false)} className={`px-4 py-1.5 text-sm font-medium rounded-lg transition-all ${!showRaw ? 'brand-button text-white shadow-sm' : 'text-zinc-400 hover:text-zinc-200'}`}>{t('form')}
- setShowRaw(true)} className={`px-4 py-1.5 text-sm font-medium rounded-lg transition-all ${showRaw ? 'brand-button text-white shadow-sm' : 'text-zinc-400 hover:text-zinc-200'}`}>{t('rawJson')}
+ setShowRaw(false)} className={`ui-button px-4 py-1.5 text-sm font-medium rounded-lg ${!showRaw ? 'ui-button-primary' : 'ui-button-neutral'}`}>{t('form')}
+ setShowRaw(true)} className={`ui-button px-4 py-1.5 text-sm font-medium rounded-lg ${showRaw ? 'ui-button-primary' : 'ui-button-neutral'}`}>{t('rawJson')}
@@ -345,7 +345,7 @@ const Config: React.FC = () => {
{t('configProxies')}
setNewProxyName(e.target.value)} placeholder={t('configNewProviderName')} className="px-2 py-1 rounded-lg bg-zinc-900/70 border border-zinc-700 text-xs" />
- {t('add')}
+ {t('add')}
@@ -355,7 +355,7 @@ const Config: React.FC = () => {
updateProxyField(name, 'api_base', e.target.value)} placeholder={t('configLabels.api_base')} className="md:col-span-2 px-2 py-1 rounded-lg bg-zinc-950/70 border border-zinc-800" />
updateProxyField(name, 'api_key', e.target.value)} placeholder={t('configLabels.api_key')} className="md:col-span-2 px-2 py-1 rounded-lg bg-zinc-950/70 border border-zinc-800" />
updateProxyField(name, 'models', e.target.value.split(',').map(s=>s.trim()).filter(Boolean))} placeholder={`${t('configLabels.models')}${t('configCommaSeparatedHint')}`} className="md:col-span-1 px-2 py-1 rounded-lg bg-zinc-950/70 border border-zinc-800" />
- removeProxy(name)} className="md:col-span-1 px-2 py-1 rounded bg-red-900/60 hover:bg-red-800 text-red-100">{t('delete')}
+ removeProxy(name)} className="ui-button ui-button-danger md:col-span-1 px-2 py-1 rounded text-xs">{t('delete')}
))}
{Object.keys(((cfg as any)?.providers?.proxies || {}) as Record).length === 0 && (
@@ -403,7 +403,7 @@ const Config: React.FC = () => {
{t('configNodeP2PIceServers')}
-
{t('add')}
+
{t('add')}
{Array.isArray((cfg as any)?.gateway?.nodes?.p2p?.ice_servers) && (cfg as any).gateway.nodes.p2p.ice_servers.length > 0 ? (
((cfg as any).gateway.nodes.p2p.ice_servers as Array
).map((server, index) => (
@@ -426,7 +426,7 @@ const Config: React.FC = () => {
placeholder={t('configNodeP2PIceCredential')}
className="md:col-span-2 px-2 py-1 rounded-lg bg-zinc-950/70 border border-zinc-800"
/>
- removeGatewayIceServer(index)} className="md:col-span-1 px-2 py-1 rounded bg-red-900/60 hover:bg-red-800 text-red-100">{t('delete')}
+ removeGatewayIceServer(index)} className="ui-button ui-button-danger md:col-span-1 px-2 py-1 rounded text-xs">{t('delete')}
))
) : (
diff --git a/webui/src/pages/Cron.tsx b/webui/src/pages/Cron.tsx
index c4d3059..10a4701 100644
--- a/webui/src/pages/Cron.tsx
+++ b/webui/src/pages/Cron.tsx
@@ -172,10 +172,10 @@ const Cron: React.FC = () => {
{t('cronJobs')}
-
refreshCron()} className="flex items-center gap-2 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 rounded-lg text-sm font-medium transition-colors">
+ refreshCron()} className="ui-button ui-button-neutral flex items-center gap-2 px-4 py-2 text-sm font-medium">
{t('refresh')}
- openCronModal()} className="brand-button flex items-center gap-2 px-4 py-2 text-white rounded-xl text-sm font-medium transition-colors shadow-sm">
+ openCronModal()} className="ui-button ui-button-primary flex items-center gap-2 px-4 py-2 text-sm font-medium">
{t('addJob')}
@@ -215,20 +215,20 @@ const Cron: React.FC = () => {
openCronModal(j)}
- className="flex-1 flex items-center justify-center gap-2 py-2 bg-zinc-800/70 hover:bg-zinc-700 rounded-xl text-xs font-medium transition-colors text-zinc-300"
+ className="ui-button ui-button-neutral flex-1 flex items-center justify-center gap-2 py-2 text-xs font-medium"
>
{t('editJob')}
cronAction(j.enabled ? 'disable' : 'enable', j.id)}
- className={`p-2 rounded-lg transition-colors ${j.enabled ? 'bg-amber-500/10 text-amber-500 hover:bg-amber-500/20' : 'bg-emerald-500/10 text-emerald-500 hover:bg-emerald-500/20'}`}
+ className={`ui-button p-2 rounded-lg ${j.enabled ? 'ui-button-warning' : 'ui-button-success'}`}
title={j.enabled ? t('pauseJob') : t('startJob')}
>
{j.enabled ? : }
cronAction('delete', j.id)}
- className="p-2 bg-red-500/10 text-red-500 hover:bg-red-500/20 rounded-lg transition-colors"
+ className="ui-button ui-button-danger p-2 rounded-lg"
title={t('deleteJob')}
>
@@ -263,7 +263,7 @@ const Cron: React.FC = () => {
>
{editingCron ? t('editJob') : t('addJob')}
- setIsCronModalOpen(false)} className="p-2 hover:bg-zinc-800 rounded-full transition-colors text-zinc-400 hover:text-zinc-200">
+ setIsCronModalOpen(false)} className="ui-button ui-button-neutral p-2 rounded-full">
@@ -368,13 +368,13 @@ const Cron: React.FC = () => {
setIsCronModalOpen(false)}
- className="px-4 py-2 text-sm font-medium text-zinc-400 hover:text-zinc-200 transition-colors"
+ className="ui-button ui-button-neutral px-4 py-2 text-sm font-medium"
>
{t('cancel')}
{editingCron ? t('update') : t('create')}
diff --git a/webui/src/pages/Logs.tsx b/webui/src/pages/Logs.tsx
index 97430d3..cd8f9c6 100644
--- a/webui/src/pages/Logs.tsx
+++ b/webui/src/pages/Logs.tsx
@@ -176,19 +176,19 @@ const Logs: React.FC = () => {
setShowRaw(!showRaw)}
- className="flex items-center gap-2 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 rounded-xl text-sm font-medium transition-colors text-zinc-300"
+ className="ui-button ui-button-neutral flex items-center gap-2 px-4 py-2 text-sm font-medium"
>
{showRaw ? t('pretty') : t('raw')}
setIsStreaming(!isStreaming)}
- className={`flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-medium transition-colors ${
- isStreaming ? 'bg-zinc-800 hover:bg-zinc-700 text-zinc-300' : 'brand-button text-white'
+ className={`ui-button flex items-center gap-2 px-4 py-2 text-sm font-medium ${
+ isStreaming ? 'ui-button-neutral' : 'ui-button-primary'
}`}
>
{isStreaming ? <> {t('pause')}> : <> {t('resume')}>}
-
+
{t('clear')}
diff --git a/webui/src/pages/MCP.tsx b/webui/src/pages/MCP.tsx
index ebccc99..05f9b1c 100644
--- a/webui/src/pages/MCP.tsx
+++ b/webui/src/pages/MCP.tsx
@@ -275,7 +275,7 @@ const MCP: React.FC = () => {
{ setBaseline(null); await loadConfig(true); }}
- className="flex items-center gap-2 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 rounded-xl text-sm font-medium transition-colors"
+ className="ui-button ui-button-neutral flex items-center gap-2 px-4 py-2 text-sm font-medium"
>
{t('reload')}
@@ -285,7 +285,7 @@ const MCP: React.FC = () => {
{t('saveChanges')}
@@ -296,7 +296,7 @@ const MCP: React.FC = () => {
{t('configMCPServers')}
setNewMCPServerName(e.target.value)} placeholder={t('configNewMCPServerName')} className="px-2 py-1 rounded-lg bg-zinc-900/70 border border-zinc-700 text-xs" />
- {t('add')}
+ {t('add')}
@@ -356,9 +356,9 @@ const MCP: React.FC = () => {
)}
updateMCPServerField(name, 'description', e.target.value)} placeholder={t('configLabels.description')} className="md:col-span-2 px-2 py-1 rounded-lg bg-zinc-950/70 border border-zinc-800" />
{isStdio && (
- installMCPServerPackage(name, server)} className="md:col-span-1 px-2 py-1 rounded bg-emerald-900/60 hover:bg-emerald-800 text-emerald-100">{t('install')}
+ installMCPServerPackage(name, server)} className="ui-button ui-button-success md:col-span-1 px-2 py-1 rounded text-xs">{t('install')}
)}
- removeMCPServer(name)} className="md:col-span-1 px-2 py-1 rounded bg-red-900/60 hover:bg-red-800 text-red-100">{t('delete')}
+ removeMCPServer(name)} className="ui-button ui-button-danger md:col-span-1 px-2 py-1 rounded text-xs">{t('delete')}
{(() => {
const check = mcpServerChecks.find((item) => item.name === name);
if (!check || check.status === 'ok' || check.status === 'disabled' || check.status === 'not_applicable') return null;
@@ -371,7 +371,7 @@ const MCP: React.FC = () => {
)}
{check.installable && (
-
installMCPServerCheckPackage(check)} className="px-2 py-1 rounded bg-amber-700 hover:bg-amber-600 text-white">
+ installMCPServerCheckPackage(check)} className="ui-button ui-button-warning px-2 py-1 rounded text-xs">
{t('install')}
)}
diff --git a/webui/src/pages/Memory.tsx b/webui/src/pages/Memory.tsx
index 071a7b3..369a981 100644
--- a/webui/src/pages/Memory.tsx
+++ b/webui/src/pages/Memory.tsx
@@ -115,19 +115,19 @@ const Memory: React.FC = () => {
{active || t('noFileSelected')}
- {t('save')}
+ {t('save')}
diff --git a/webui/src/pages/NodeArtifacts.tsx b/webui/src/pages/NodeArtifacts.tsx
index 8baad1e..53348e6 100644
--- a/webui/src/pages/NodeArtifacts.tsx
+++ b/webui/src/pages/NodeArtifacts.tsx
@@ -141,10 +141,10 @@ const NodeArtifacts: React.FC = () => {
{t('nodeArtifactsHint')}
@@ -185,7 +185,7 @@ const NodeArtifacts: React.FC = () => {
{prunePending ? t('loading') : t('nodeArtifactsPrune')}
@@ -224,10 +224,10 @@ const NodeArtifacts: React.FC = () => {
{String(selected?.node || '-')} · {String(selected?.action || '-')} · {formatLocalDateTime(selected?.time)}
-
+
{t('download')}
-
deleteArtifact(String(selected?.id || ''))} className="rounded-xl bg-red-900/60 px-3 py-1.5 text-xs text-red-100">
+ deleteArtifact(String(selected?.id || ''))} className="ui-button ui-button-danger px-3 py-1.5 text-xs">
{t('delete')}
diff --git a/webui/src/pages/Nodes.tsx b/webui/src/pages/Nodes.tsx
index 8dfa151..dbd3d3f 100644
--- a/webui/src/pages/Nodes.tsx
+++ b/webui/src/pages/Nodes.tsx
@@ -221,7 +221,7 @@ const Nodes: React.FC = () => {
{t('nodes')}
{t('nodesDetailHint')}
- { refreshNodes(); setReloadTick((value) => value + 1); }} className="brand-button px-3 py-1.5 rounded-xl text-sm text-white">
+ { refreshNodes(); setReloadTick((value) => value + 1); }} className="ui-button ui-button-primary px-3 py-1.5 text-sm">
{loading ? t('loading') : t('refresh')}
@@ -296,13 +296,13 @@ const Nodes: React.FC = () => {
{t('nodeArtifacts')}
{t('export')}
@@ -454,14 +454,14 @@ const Nodes: React.FC = () => {
{t('resetReplayDraft')}
{replayPending ? t('replaying') : t('replayDispatch')}
diff --git a/webui/src/pages/Skills.tsx b/webui/src/pages/Skills.tsx
index b83bfb2..e0587f2 100644
--- a/webui/src/pages/Skills.tsx
+++ b/webui/src/pages/Skills.tsx
@@ -190,7 +190,7 @@ const Skills: React.FC = () => {
{t('skills')}
setInstallName(e.target.value)} placeholder={t('skillsNamePlaceholder')} className="w-full sm:w-72 px-3 py-2 bg-zinc-950/70 border border-zinc-800 rounded-xl text-sm disabled:opacity-60" />
- {installingSkill ? t('loading') : t('install')}
+ {installingSkill ? t('loading') : t('install')}
-
+
{t('skillsClawhubStatus')}: {clawhubInstalled ? t('installed') : t('notInstalled')}
{!clawhubInstalled && (
{t('skillsInstallNow')}
)}
-
refreshSkills()} className="flex items-center gap-2 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 rounded-xl text-sm font-medium transition-colors">
+ refreshSkills()} className="ui-button ui-button-neutral flex items-center gap-2 px-4 py-2 text-sm font-medium">
{t('refresh')}
-
+
{t('skillsAdd')}
diff --git a/webui/src/pages/SubagentProfiles.tsx b/webui/src/pages/SubagentProfiles.tsx
index e787927..c0baf74 100644
--- a/webui/src/pages/SubagentProfiles.tsx
+++ b/webui/src/pages/SubagentProfiles.tsx
@@ -272,10 +272,10 @@ const SubagentProfiles: React.FC = () => {
{t('subagentProfiles')}
- load()} className="px-3 py-1.5 rounded-xl bg-zinc-800 hover:bg-zinc-700 text-sm">
+ load()} className="ui-button ui-button-neutral px-3 py-1.5 text-sm">
{t('refresh')}
-
+
{t('newProfile')}
@@ -405,7 +405,7 @@ const SubagentProfiles: React.FC = () => {
key={g.name}
type="button"
onClick={() => addAllowlistToken(`group:${g.name}`)}
- className="px-2 py-1 text-[11px] rounded bg-zinc-800 hover:bg-zinc-700 text-zinc-200"
+ className="ui-button ui-button-neutral px-2 py-1 text-[11px] rounded"
title={g.description || g.name}
>
{`group:${g.name}`}
@@ -430,7 +430,7 @@ const SubagentProfiles: React.FC = () => {
type="button"
onClick={savePromptFile}
disabled={!String(draft.system_prompt_file || '').trim()}
- className="px-3 py-1.5 text-xs rounded bg-zinc-800 hover:bg-zinc-700 disabled:opacity-50"
+ className="ui-button ui-button-neutral px-3 py-1.5 text-xs rounded disabled:opacity-50"
>
{t('savePromptFile')}
@@ -482,28 +482,28 @@ const SubagentProfiles: React.FC = () => {
{selected ? t('update') : t('create')}
setStatus('active')}
disabled={!draft.agent_id}
- className="px-3 py-1.5 text-xs rounded-xl border border-emerald-400/30 bg-emerald-500/14 text-emerald-100 hover:bg-emerald-500/22 disabled:opacity-50"
+ className="ui-button ui-button-success px-3 py-1.5 text-xs"
>
{t('enable')}
setStatus('disabled')}
disabled={!draft.agent_id}
- className="px-3 py-1.5 text-xs rounded-xl border border-amber-400/30 bg-amber-500/14 text-amber-100 hover:bg-amber-500/22 disabled:opacity-50"
+ className="ui-button ui-button-warning px-3 py-1.5 text-xs"
>
{t('disable')}
{t('delete')}
diff --git a/webui/src/pages/TaskAudit.tsx b/webui/src/pages/TaskAudit.tsx
index 4995ed8..62cb14e 100644
--- a/webui/src/pages/TaskAudit.tsx
+++ b/webui/src/pages/TaskAudit.tsx
@@ -128,7 +128,7 @@ const TaskAudit: React.FC = () => {
-
{loading ? t('loading') : t('refresh')}
+
{loading ? t('loading') : t('refresh')}