feat(ui): consolidate buttons — 3 variants (primary/secondary/tertiary) + danger tone (#4057)

This commit is contained in:
Cyrus Gray
2026-06-25 16:29:52 +05:30
committed by GitHub
parent af29f92c2d
commit 171cedc6ef
184 changed files with 2236 additions and 2269 deletions
@@ -10,6 +10,8 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import { useT } from '../../../lib/i18n/I18nContext';
import { mcpClientsApi } from '../../../services/api/mcpClientsApi';
import ChipTabs from '../../layout/ChipTabs';
import Button from '../../ui/Button';
import InstallDialog from './InstallDialog';
import InstalledServerDetail from './InstalledServerDetail';
import McpInventoryPanel from './McpInventoryPanel';
@@ -225,20 +227,22 @@ const McpServersTab = () => {
if (view.mode === 'detail' && selectedServer) {
return (
<div className="space-y-3">
<button
type="button"
<Button
variant="tertiary"
size="xs"
onClick={() => setView({ mode: 'home' })}
className="inline-flex items-center gap-1.5 text-xs font-medium text-stone-500 dark:text-neutral-400 hover:text-stone-700 dark:hover:text-neutral-200 transition-colors">
<svg
className="w-3.5 h-3.5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
</svg>
leadingIcon={
<svg
className="w-3.5 h-3.5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
</svg>
}>
{t('mcp.install.back')}
</button>
</Button>
<InstalledServerDetail
server={selectedServer}
connStatus={selectedConnStatus}
@@ -253,20 +257,22 @@ const McpServersTab = () => {
if (view.mode === 'install') {
return (
<div className="space-y-3">
<button
type="button"
<Button
variant="tertiary"
size="xs"
onClick={() => setView({ mode: 'home' })}
className="inline-flex items-center gap-1.5 text-xs font-medium text-stone-500 dark:text-neutral-400 hover:text-stone-700 dark:hover:text-neutral-200 transition-colors">
<svg
className="w-3.5 h-3.5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
</svg>
leadingIcon={
<svg
className="w-3.5 h-3.5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
</svg>
}>
{t('mcp.install.back')}
</button>
</Button>
<InstallDialog
qualifiedName={view.qualifiedName}
prefillEnv={view.prefillEnv}
@@ -290,34 +296,33 @@ const McpServersTab = () => {
aria-label={t('mcp.catalog.searchAria')}
className="flex-1 rounded-lg border border-stone-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 px-3 py-2 text-sm text-stone-800 dark:text-neutral-100 placeholder:text-stone-400 dark:placeholder:text-neutral-500 focus:outline-none focus:ring-2 focus:ring-primary-500/40"
/>
<button
type="button"
<Button
variant="secondary"
size="md"
onClick={() => setInventoryOpen(true)}
aria-label={t('mcp.inventory.openAria')}
className="shrink-0 rounded-lg border border-stone-200 dark:border-neutral-700 px-3 py-2 text-xs font-medium text-stone-600 dark:text-neutral-300 hover:bg-stone-50 dark:hover:bg-neutral-800">
className="shrink-0">
{t('mcp.inventory.openButton')}
</button>
</Button>
</div>
{/* Filter chips */}
<div className="flex items-center gap-2">
{(['all', 'installed', 'registry'] as FilterChip[]).map(chip => (
<button
key={chip}
type="button"
onClick={() => setActiveChip(chip)}
className={`rounded-full px-3 py-1 text-xs font-medium transition-colors ${
activeChip === chip
? 'bg-primary-500 text-white'
: 'bg-stone-100 dark:bg-neutral-800 text-stone-600 dark:text-neutral-300 hover:bg-stone-200 dark:hover:bg-neutral-700'
}`}>
{chip === 'all' && t('mcp.tab.filter.all')}
{chip === 'installed' &&
t('mcp.tab.filter.installed').replace('{count}', String(filteredInstalled.length))}
{chip === 'registry' && t('mcp.tab.filter.registry')}
</button>
))}
</div>
<ChipTabs<FilterChip>
className="flex flex-wrap items-center gap-2"
value={activeChip}
onChange={setActiveChip}
items={[
{ id: 'all', label: t('mcp.tab.filter.all') },
{
id: 'installed',
label: t('mcp.tab.filter.installed').replace(
'{count}',
String(filteredInstalled.length)
),
},
{ id: 'registry', label: t('mcp.tab.filter.registry') },
]}
/>
{loadError && (
<div className="rounded-lg border border-coral-200 dark:border-coral-500/30 bg-coral-50 dark:bg-coral-500/10 px-3 py-2 text-xs text-coral-700 dark:text-coral-300">
@@ -495,12 +500,13 @@ const McpServersTab = () => {
catalogPage < catalogTotalPages &&
(activeChip === 'all' || activeChip === 'registry') && (
<div className="py-3 text-center border-t border-stone-100 dark:border-neutral-800">
<button
type="button"
<Button
variant="tertiary"
size="xs"
onClick={handleLoadMore}
className="text-xs font-medium text-primary-600 dark:text-primary-400 hover:underline">
className="text-primary-600 dark:text-primary-400 hover:underline">
{t('mcp.catalog.loadMore')}
</button>
</Button>
</div>
)}
</div>