Major UI refresh: sidebar redesign, theme expansion, and chat performance optimizations (#706)
## Summary Complete sidebar redesign and comprehensive UI polish pass with performance optimizations, theme system refinements, and desktop integration improvements. ## Key Changes **Sidebar & Navigation Redesign** - Redesigned sessions sidebar layout with unified button primitives - Added activity sections with project grouping and improved session organization - Refined sidebar corners, spacing, and visual hierarchy - Removed NavRail component in favor of streamlined sidebar - Stabilized sessions bar toggle position in fullscreen mode **Performance Optimizations** - Reduced chat streaming CPU usage and storage churn - Optimized task tool polling and live timers with debouncing - Prevented chat state races and reduced background request load - Debounced draft writes and coalesced session reloads - Optimized message store updates and turn tracking **Theme & Visual System** - Added theme-aware window corners (desktop) and border radius tokens - Introduced glassmorphism effects on desktop sidebar - Added backdrop blur to UI elements **Chat Experience** - Added session-based permission auto-accept toggle in chat input - Polished permission shield UX with improved icon sizing and spacing - Fixed chat scroll-to-bottom behavior and timeline tracking - Enhanced tool output display with better path label detection - Removed duplicate draft context details in chat header - Added text selection menu to chat messages **Git Improvements** - Refreshed git history visual design with cleaner dividers - Added remote removal action in sync selector - Stabilized git polling to prevent excessive requests - Improved tool output rendering for git operations **Settings & Panels** - Fixed mobile scrolling on settings pages - Made outside-click settings close instantly - Reduced settings load churn and CPU spikes - Improved services dropdown layout and spacing - Softened panel resize handles **Desktop Integration** - Synced macOS window theme with app theme - Restored window dragging in sidebar header zones - Fixed system window corners on macOS - Improved header session metadata and action controls **Button & Component Standardization** - Unified button primitives across all components - Standardized destructive action patterns - Removed unused button variants (button-large, button-small) - Aligned context tab close hit areas --------- Co-authored-by: Iuliia Ivashko <yulia.ivashko@gmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Iuliia Ivashko
parent
359879153a
commit
321cc7252a
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { NumberInput } from '@/components/ui/number-input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
@@ -685,7 +685,7 @@ export const AgentsPage: React.FC = () => {
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setMode('primary')}
|
||||
@@ -697,8 +697,8 @@ export const AgentsPage: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
Primary
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setMode('subagent')}
|
||||
@@ -710,8 +710,8 @@ export const AgentsPage: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
Subagent
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setMode('all')}
|
||||
@@ -723,7 +723,7 @@ export const AgentsPage: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
All
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -790,7 +790,7 @@ export const AgentsPage: React.FC = () => {
|
||||
className="w-16"
|
||||
/>
|
||||
{temperature !== undefined && (
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setTemperature(undefined)}
|
||||
@@ -799,7 +799,7 @@ export const AgentsPage: React.FC = () => {
|
||||
title="Clear"
|
||||
>
|
||||
<RiCloseLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -834,7 +834,7 @@ export const AgentsPage: React.FC = () => {
|
||||
className="w-16"
|
||||
/>
|
||||
{topP !== undefined && (
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setTopP(undefined)}
|
||||
@@ -843,7 +843,7 @@ export const AgentsPage: React.FC = () => {
|
||||
title="Clear"
|
||||
>
|
||||
<RiCloseLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -876,14 +876,14 @@ export const AgentsPage: React.FC = () => {
|
||||
<h3 className="typography-ui-header font-medium text-foreground">
|
||||
Tool Permissions
|
||||
</h3>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
onClick={() => setShowPermissionEditor((prev) => !prev)}
|
||||
>
|
||||
{showPermissionEditor ? 'Hide Editor' : 'Advanced Editor'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{!showPermissionEditor ? (
|
||||
@@ -961,13 +961,13 @@ export const AgentsPage: React.FC = () => {
|
||||
<span className="typography-micro text-muted-foreground">Pattern</span>
|
||||
<span className="typography-micro font-mono text-foreground bg-[var(--surface-muted)] px-1 rounded">*</span>
|
||||
{wildcardOverride && (
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => revertRule(permissionName, '*')}
|
||||
className="px-1.5 py-0 h-5"
|
||||
>
|
||||
<RiSubtractLine className="h-3.5 w-3.5 text-muted-foreground hover:text-foreground" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<Select
|
||||
@@ -1008,13 +1008,13 @@ export const AgentsPage: React.FC = () => {
|
||||
{isAdded && <span className="typography-micro text-[var(--status-success)]">New</span>}
|
||||
{isModified && <span className="typography-micro text-[var(--status-warning)]">Modified</span>}
|
||||
{(isAdded || isModified) && (
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => isAdded ? removeRule(rule.permission, rule.pattern) : revertRule(rule.permission, rule.pattern)}
|
||||
className="px-1.5 py-0 h-5"
|
||||
>
|
||||
<RiSubtractLine className="h-3.5 w-3.5 text-muted-foreground hover:text-foreground" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<Select
|
||||
@@ -1069,9 +1069,9 @@ export const AgentsPage: React.FC = () => {
|
||||
/>
|
||||
|
||||
<div className="flex gap-1">
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => applyPendingRule('allow')}>Allow</ButtonSmall>
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => applyPendingRule('ask')}>Ask</ButtonSmall>
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => applyPendingRule('deny')}>Deny</ButtonSmall>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => applyPendingRule('allow')}>Allow</Button>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => applyPendingRule('ask')}>Ask</Button>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => applyPendingRule('deny')}>Deny</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1081,14 +1081,14 @@ export const AgentsPage: React.FC = () => {
|
||||
|
||||
{/* Save action */}
|
||||
<div className="px-2 py-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={isSaving || !isDirty}
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
>
|
||||
{isSaving ? 'Saving...' : 'Save Changes'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { toast } from '@/components/ui';
|
||||
import { isMobileDeviceViaCSS } from '@/lib/device';
|
||||
@@ -324,13 +323,13 @@ export const AgentsSidebar: React.FC<AgentsSidebarProps> = ({ onItemSelect }) =>
|
||||
<SettingsProjectSelector className="mb-3" />
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="typography-meta text-muted-foreground">Total {visibleAgents.length}</span>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 -my-1 text-muted-foreground"
|
||||
onClick={handleCreateNew}
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -446,16 +445,17 @@ export const AgentsSidebar: React.FC<AgentsSidebarProps> = ({ onItemSelect }) =>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={closeConfirmActionDialog}
|
||||
disabled={isConfirmActionPending}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleConfirmAction} disabled={isConfirmActionPending}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleConfirmAction} disabled={isConfirmActionPending}>
|
||||
{confirmActionType === 'delete' ? 'Delete' : 'Reset'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -481,15 +481,16 @@ export const AgentsSidebar: React.FC<AgentsSidebarProps> = ({ onItemSelect }) =>
|
||||
}}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => setRenameDialogAgent(null)}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleRenameAgent}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleRenameAgent}>
|
||||
Rename
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -563,12 +564,12 @@ const AgentListItem: React.FC<AgentListItemProps> = ({
|
||||
|
||||
<DropdownMenu open={isMenuOpen} onOpenChange={onMenuOpenChange}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-6 w-6 px-0 flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100"
|
||||
>
|
||||
<RiMore2Line className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit min-w-20">
|
||||
{onRename && (
|
||||
|
||||
@@ -630,8 +630,8 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
||||
|
||||
{/* Favorites Section */}
|
||||
{filteredFavorites.length > 0 && (
|
||||
<>
|
||||
<DropdownMenuLabel style={{ backgroundColor: 'var(--surface-elevated)' }} className="typography-micro font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2 -mx-1 px-3 py-1.5 sticky top-0 z-10 border-b border-border/30">
|
||||
<div>
|
||||
<DropdownMenuLabel className="typography-micro font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2 -mx-1 px-3 py-1.5 border-b border-border/30">
|
||||
<RiStarFill className="h-4 w-4 text-primary" />
|
||||
Favorites
|
||||
</DropdownMenuLabel>
|
||||
@@ -639,14 +639,14 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
||||
const idx = currentFlatIndex++;
|
||||
return renderModelRow(model, providerID, modelID, 'fav', idx, selectedIndex === idx);
|
||||
})}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Recents Section */}
|
||||
{filteredRecents.length > 0 && (
|
||||
<>
|
||||
<div>
|
||||
{filteredFavorites.length > 0 && <DropdownMenuSeparator />}
|
||||
<DropdownMenuLabel style={{ backgroundColor: 'var(--surface-elevated)' }} className="typography-micro font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2 -mx-1 px-3 py-1.5 sticky top-0 z-10 border-b border-border/30">
|
||||
<DropdownMenuLabel className="typography-micro font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2 -mx-1 px-3 py-1.5 border-b border-border/30">
|
||||
<RiTimeLine className="h-4 w-4" />
|
||||
Recent
|
||||
</DropdownMenuLabel>
|
||||
@@ -654,7 +654,7 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
||||
const idx = currentFlatIndex++;
|
||||
return renderModelRow(model, providerID, modelID, 'recent', idx, selectedIndex === idx);
|
||||
})}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Separator before providers */}
|
||||
@@ -664,9 +664,9 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
||||
|
||||
{/* All Providers - Flat List */}
|
||||
{filteredProviders.map((provider, index) => (
|
||||
<React.Fragment key={provider.id}>
|
||||
<div key={provider.id}>
|
||||
{index > 0 && <DropdownMenuSeparator />}
|
||||
<DropdownMenuLabel style={{ backgroundColor: 'var(--surface-elevated)' }} className="typography-micro font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2 -mx-1 px-3 py-1.5 sticky top-0 z-10 border-b border-border/30">
|
||||
<DropdownMenuLabel className="typography-micro font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2 -mx-1 px-3 py-1.5 border-b border-border/30">
|
||||
<ProviderLogo
|
||||
providerId={provider.id}
|
||||
className="h-4 w-4 flex-shrink-0"
|
||||
@@ -677,7 +677,7 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
||||
const idx = currentFlatIndex++;
|
||||
return renderModelRow(model, provider.id as string, model.id as string, 'provider', idx, selectedIndex === idx);
|
||||
})}
|
||||
</React.Fragment>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ScrollableOverlay>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { toast } from '@/components/ui';
|
||||
@@ -321,14 +321,14 @@ export const CommandsPage: React.FC = () => {
|
||||
|
||||
{/* Save action */}
|
||||
<div className="px-2 py-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={isSaving || !isDirty}
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
>
|
||||
{isSaving ? 'Saving...' : 'Save Changes'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { toast } from '@/components/ui';
|
||||
import { isMobileDeviceViaCSS } from '@/lib/device';
|
||||
@@ -221,13 +220,13 @@ export const CommandsSidebar: React.FC<CommandsSidebarProps> = ({ onItemSelect }
|
||||
<SettingsProjectSelector className="mb-3" />
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="typography-meta text-muted-foreground">Total {commandOnlyItems.length}</span>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 -my-1 text-muted-foreground"
|
||||
onClick={handleCreateNew}
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -310,16 +309,17 @@ export const CommandsSidebar: React.FC<CommandsSidebarProps> = ({ onItemSelect }
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={closeConfirmActionDialog}
|
||||
disabled={isConfirmActionPending}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleConfirmAction} disabled={isConfirmActionPending}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleConfirmAction} disabled={isConfirmActionPending}>
|
||||
{confirmActionType === 'delete' ? 'Delete' : 'Reset'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -345,15 +345,16 @@ export const CommandsSidebar: React.FC<CommandsSidebarProps> = ({ onItemSelect }
|
||||
}}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => setRenameDialogCommand(null)}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleRenameCommand}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleRenameCommand}>
|
||||
Rename
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -422,12 +423,12 @@ const CommandListItem: React.FC<CommandListItemProps> = ({
|
||||
|
||||
<DropdownMenu open={isMenuOpen} onOpenChange={onMenuOpenChange}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-6 w-6 px-0 flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100"
|
||||
>
|
||||
<RiMore2Line className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit min-w-20">
|
||||
{onRename && (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { toast } from '@/components/ui';
|
||||
import {
|
||||
@@ -351,7 +350,7 @@ export const GitIdentityEditorDialog: React.FC<GitIdentityEditorDialogProps> = (
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="typography-ui-label text-foreground">Auth Method</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => setAuthType('ssh')}
|
||||
@@ -362,8 +361,8 @@ export const GitIdentityEditorDialog: React.FC<GitIdentityEditorDialogProps> = (
|
||||
)}
|
||||
>
|
||||
<RiLock2Line className="w-3.5 h-3.5 mr-1" /> SSH
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => setAuthType('token')}
|
||||
@@ -374,7 +373,7 @@ export const GitIdentityEditorDialog: React.FC<GitIdentityEditorDialogProps> = (
|
||||
)}
|
||||
>
|
||||
<RiKeyLine className="w-3.5 h-3.5 mr-1" /> Token
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -467,7 +466,7 @@ export const GitIdentityEditorDialog: React.FC<GitIdentityEditorDialogProps> = (
|
||||
<Button variant="ghost" onClick={() => setIsDeleteDialogOpen(false)} disabled={isDeleting}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button size="sm" onClick={() => void handleConfirmDelete()} disabled={isDeleting} className="bg-[var(--status-error)] hover:bg-[var(--status-error)]/90 text-white border-0">
|
||||
<Button size="sm" variant="destructive" onClick={() => void handleConfirmDelete()} disabled={isDeleting}>
|
||||
Delete
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { toast } from '@/components/ui';
|
||||
import {
|
||||
Dialog,
|
||||
@@ -10,7 +9,6 @@ import {
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -124,9 +122,9 @@ export const GitPage: React.FC = () => {
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="typography-ui-header font-semibold text-foreground">Identities</h3>
|
||||
</div>
|
||||
<ButtonSmall variant="outline" onClick={() => openEditor('new')}>
|
||||
<Button size="sm" variant="outline" onClick={() => openEditor('new')}>
|
||||
<RiAddLine className="w-3.5 h-3.5 mr-1" /> New
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg bg-[var(--surface-elevated)]/70 overflow-hidden flex flex-col">
|
||||
@@ -213,9 +211,9 @@ export const GitPage: React.FC = () => {
|
||||
<Button variant="ghost" onClick={() => setDeleteDialogProfile(null)} disabled={isDeletePending}>
|
||||
Cancel
|
||||
</Button>
|
||||
<ButtonLarge onClick={() => void handleConfirmDelete()} disabled={isDeletePending} className="bg-[var(--status-error)] hover:bg-[var(--status-error)]/90 text-white border-0">
|
||||
<Button size="sm" variant="destructive" onClick={() => void handleConfirmDelete()} disabled={isDeletePending}>
|
||||
Delete
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -340,10 +338,10 @@ const DiscoveredRow: React.FC<DiscoveredRowProps> = ({ credential, onImport, has
|
||||
{isRepoSpecific ? credential.host : credential.username}
|
||||
</span>
|
||||
</div>
|
||||
<ButtonSmall variant="ghost" onClick={onImport} className="gap-1 shrink-0">
|
||||
<Button size="sm" variant="ghost" onClick={onImport} className="gap-1 shrink-0">
|
||||
<RiDownloadLine className="h-3 w-3" />
|
||||
Import
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
@@ -110,7 +108,7 @@ const CommandTextarea: React.FC<CommandTextareaProps> = ({ value, onChange }) =>
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal gap-1 text-muted-foreground"
|
||||
@@ -120,7 +118,7 @@ const CommandTextarea: React.FC<CommandTextareaProps> = ({ value, onChange }) =>
|
||||
>
|
||||
<RiClipboardLine className="h-3 w-3" />
|
||||
Paste command
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Textarea
|
||||
@@ -252,7 +250,7 @@ const EnvEditor: React.FC<EnvEditorProps> = ({ value, onChange }) => {
|
||||
<span className="typography-micro text-muted-foreground w-32 shrink-0">Key</span>
|
||||
<span className="typography-micro text-muted-foreground">Value</span>
|
||||
</div>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal gap-1 text-muted-foreground"
|
||||
@@ -262,7 +260,7 @@ const EnvEditor: React.FC<EnvEditorProps> = ({ value, onChange }) => {
|
||||
>
|
||||
<RiClipboardLine className="h-3 w-3" />
|
||||
Paste .env
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Rows */}
|
||||
@@ -299,18 +297,18 @@ const EnvEditor: React.FC<EnvEditorProps> = ({ value, onChange }) => {
|
||||
</button>
|
||||
</div>
|
||||
{/* Remove */}
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 shrink-0 text-muted-foreground hover:text-[var(--status-error)]"
|
||||
onClick={() => removeRow(idx)}
|
||||
>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal gap-1.5"
|
||||
@@ -319,7 +317,7 @@ const EnvEditor: React.FC<EnvEditorProps> = ({ value, onChange }) => {
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
Add variable
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
|
||||
{hasSensitiveValues && (
|
||||
<p className="typography-micro text-muted-foreground/60">
|
||||
@@ -535,7 +533,7 @@ export const McpPage: React.FC = () => {
|
||||
{isNewServer ? 'Configure a new MCP server' : `${mcpType === 'local' ? 'Local · stdio' : 'Remote · SSE'} transport`}
|
||||
</p>
|
||||
{!isNewServer && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant={isConnected ? 'outline' : 'default'}
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -543,7 +541,7 @@ export const McpPage: React.FC = () => {
|
||||
disabled={isConnecting || !enabled}
|
||||
>
|
||||
{isConnecting ? 'Working...' : isConnected ? 'Disconnect' : 'Connect'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -618,7 +616,7 @@ export const McpPage: React.FC = () => {
|
||||
<div className="flex min-w-0 flex-col gap-1.5">
|
||||
<span className="typography-ui-label text-foreground">Transport Mode</span>
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setMcpType('local')}
|
||||
@@ -630,8 +628,8 @@ export const McpPage: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
Local · stdio
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setMcpType('remote')}
|
||||
@@ -643,7 +641,7 @@ export const McpPage: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
Remote · SSE
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -693,23 +691,23 @@ export const McpPage: React.FC = () => {
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center gap-2 px-2 py-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={isSaving || (!isDirty && !isNewServer)}
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
>
|
||||
{isSaving ? 'Saving...' : isNewServer ? 'Create' : 'Save Changes'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
{!isNewServer && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal text-[var(--status-error)] hover:text-[var(--status-error)]"
|
||||
onClick={() => setShowDeleteConfirm(true)}
|
||||
>
|
||||
Delete
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -736,9 +734,9 @@ export const McpPage: React.FC = () => {
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<ButtonLarge onClick={handleDelete} disabled={isDeleting}>
|
||||
<Button size="sm" onClick={handleDelete} disabled={isDeleting}>
|
||||
{isDeleting ? 'Deleting…' : 'Delete'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -130,14 +129,14 @@ export const McpSidebar: React.FC<McpSidebarProps> = ({ onItemSelect }) => {
|
||||
<span className="typography-meta text-muted-foreground">
|
||||
Total {mcpServers.length}
|
||||
</span>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 -my-1 text-muted-foreground"
|
||||
onClick={handleCreateNew}
|
||||
title="Add MCP server"
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -198,9 +197,9 @@ export const McpSidebar: React.FC<McpSidebarProps> = ({ onItemSelect }) => {
|
||||
|
||||
<DropdownMenu open={openMenuMcp === server.name} onOpenChange={(open) => setOpenMenuMcp(open ? server.name : null)}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ButtonSmall variant="ghost" className="h-6 w-6 px-0 flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100">
|
||||
<Button size="xs" variant="ghost" className="flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100">
|
||||
<RiMore2Line className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit min-w-20">
|
||||
<DropdownMenuItem
|
||||
@@ -268,9 +267,9 @@ export const McpSidebar: React.FC<McpSidebarProps> = ({ onItemSelect }) => {
|
||||
|
||||
<DropdownMenu open={openMenuMcp === server.name} onOpenChange={(open) => setOpenMenuMcp(open ? server.name : null)}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ButtonSmall variant="ghost" className="h-6 w-6 px-0 flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100">
|
||||
<Button size="xs" variant="ghost" className="flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100">
|
||||
<RiMore2Line className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit min-w-20">
|
||||
<DropdownMenuItem
|
||||
@@ -308,16 +307,17 @@ export const McpSidebar: React.FC<McpSidebarProps> = ({ onItemSelect }) => {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => setDeleteTarget(null)}
|
||||
disabled={isDeleting}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleDelete} disabled={isDeleting}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleDelete} disabled={isDeleting}>
|
||||
{isDeleting ? 'Deleting…' : 'Delete'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { UpdateDialog } from '@/components/ui/UpdateDialog';
|
||||
import { useDeviceInfo } from '@/lib/device';
|
||||
import { toast } from '@/components/ui';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const GITHUB_URL = 'https://github.com/btriapitsyn/openchamber';
|
||||
|
||||
@@ -155,26 +155,26 @@ export const AboutSettings: React.FC = () => {
|
||||
)}
|
||||
|
||||
{!updateStore.checking && updateStore.available && (
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="default"
|
||||
onClick={() => setUpdateDialogOpen(true)}
|
||||
>
|
||||
<RiDownloadLine className="h-4 w-4 mr-1" />
|
||||
Update to {updateStore.info?.version}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{!updateStore.checking && !updateStore.available && !updateStore.error && (
|
||||
<span className="typography-meta text-muted-foreground">Up to date</span>
|
||||
)}
|
||||
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="outline"
|
||||
onClick={() => updateStore.checkForUpdates()}
|
||||
disabled={updateStore.checking}
|
||||
>
|
||||
Check for updates
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { toast } from '@/components/ui';
|
||||
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
||||
import { useGitHubAuthStore } from '@/stores/useGitHubAuthStore';
|
||||
@@ -304,18 +303,18 @@ export const GitHubSettings: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ButtonSmall variant="outline" onClick={disconnect} disabled={isBusy} className={cn("text-[var(--status-error)] hover:text-[var(--status-error)]", isMobile ? "w-full" : undefined)}>
|
||||
<Button size="sm" variant="outline" onClick={disconnect} disabled={isBusy} className={cn("text-[var(--status-error)] hover:text-[var(--status-error)]", isMobile ? "w-full" : undefined)}>
|
||||
Disconnect
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-between gap-4 px-4 py-4">
|
||||
<div className="flex min-w-0 flex-col">
|
||||
<span className="typography-ui-label text-foreground">Not Connected</span>
|
||||
</div>
|
||||
<ButtonSmall variant="default" onClick={startConnect} disabled={isBusy}>
|
||||
<Button size="sm" variant="default" onClick={startConnect} disabled={isBusy}>
|
||||
Connect GitHub
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -359,13 +358,13 @@ export const GitHubSettings: React.FC = () => {
|
||||
{isCurrent ? (
|
||||
<span className="typography-micro text-[var(--primary-base)] bg-[var(--primary-base)]/10 px-1.5 py-0.5 rounded">Active</span>
|
||||
) : (
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => activateAccount(account.id)}
|
||||
disabled={isBusy}
|
||||
>
|
||||
Switch to
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -378,14 +377,14 @@ export const GitHubSettings: React.FC = () => {
|
||||
|
||||
{connected && (
|
||||
<div className="mt-2 px-2 pb-2">
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="outline"
|
||||
onClick={startConnect}
|
||||
disabled={isBusy}
|
||||
className={cn(isMobile ? 'w-full' : undefined)}
|
||||
>
|
||||
Add Account
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -413,12 +412,12 @@ export const GitHubSettings: React.FC = () => {
|
||||
<span className="typography-micro text-muted-foreground animate-pulse">
|
||||
Waiting for approval… (auto-refresh)
|
||||
</span>
|
||||
<ButtonSmall variant="ghost" disabled={isBusy} onClick={() => {
|
||||
<Button size="sm" variant="ghost" disabled={isBusy} onClick={() => {
|
||||
stopPolling();
|
||||
setFlow(null);
|
||||
}}>
|
||||
Cancel
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { RiInformationLine } from '@remixicon/react';
|
||||
@@ -132,7 +132,7 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
||||
<div className="mb-1 px-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="typography-ui-header font-medium text-foreground">Keyboard Shortcuts</h3>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -146,7 +146,7 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
Reset All
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
<Tooltip delayDuration={1000}>
|
||||
<TooltipTrigger asChild>
|
||||
<RiInformationLine className="h-3.5 w-3.5 text-muted-foreground/60 cursor-help" />
|
||||
@@ -166,8 +166,8 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
||||
This combo is already used by another shortcut. Overwrite and clear that other mapping?
|
||||
</span>
|
||||
<div className="flex gap-2 shrink-0">
|
||||
<ButtonSmall type="button" size="xs" className="!font-normal" onClick={confirmOverwrite}>Overwrite</ButtonSmall>
|
||||
<ButtonSmall type="button" size="xs" className="!font-normal" variant="ghost" onClick={() => setPendingOverwrite(null)}>Cancel</ButtonSmall>
|
||||
<Button type="button" size="xs" className="!font-normal" onClick={confirmOverwrite}>Overwrite</Button>
|
||||
<Button type="button" size="xs" className="!font-normal" variant="ghost" onClick={() => setPendingOverwrite(null)}>Cancel</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -233,7 +233,7 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
||||
}}
|
||||
className="h-7 w-40 min-w-0 typography-ui-label text-center"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="xs"
|
||||
@@ -249,10 +249,10 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
||||
disabled={!hasDraft}
|
||||
>
|
||||
Save
|
||||
</ButtonSmall>
|
||||
<ButtonSmall type="button" size="xs" className="!font-normal" variant="ghost" onClick={() => resetOne(action.id)}>
|
||||
</Button>
|
||||
<Button type="button" size="xs" className="!font-normal" variant="ghost" onClick={() => resetOne(action.id)}>
|
||||
Reset
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
||||
import { GridLoader } from '@/components/ui/grid-loader';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { NumberInput } from '@/components/ui/number-input';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -800,7 +800,7 @@ export const NotificationSettings: React.FC = () => {
|
||||
step={50}
|
||||
className="w-20 tabular-nums"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setSummaryThreshold(DEFAULT_SUMMARY_THRESHOLD)}
|
||||
@@ -810,7 +810,7 @@ export const NotificationSettings: React.FC = () => {
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-8 py-1.5">
|
||||
@@ -827,7 +827,7 @@ export const NotificationSettings: React.FC = () => {
|
||||
step={10}
|
||||
className="w-20 tabular-nums"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setSummaryLength(DEFAULT_SUMMARY_LENGTH)}
|
||||
@@ -837,7 +837,7 @@ export const NotificationSettings: React.FC = () => {
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -856,7 +856,7 @@ export const NotificationSettings: React.FC = () => {
|
||||
step={10}
|
||||
className="w-20 tabular-nums"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setMaxLastMessageLength(DEFAULT_MAX_LAST_MESSAGE_LENGTH)}
|
||||
@@ -866,7 +866,7 @@ export const NotificationSettings: React.FC = () => {
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -99,7 +99,7 @@ const ShortcutsSectionContent: React.FC = () => {
|
||||
return <KeyboardShortcutsSettings />;
|
||||
};
|
||||
|
||||
// Visual section: Theme Mode, Font Size, Spacing, Corner Radius, Input Bar Offset (mobile), Nav Rail
|
||||
// Visual section: Theme Mode, Font Size, Spacing, Input Bar Offset (mobile), Nav Rail
|
||||
const VisualSectionContent: React.FC = () => {
|
||||
const isVSCode = isVSCodeRuntime();
|
||||
return <OpenChamberVisualSettings visibleSettings={[
|
||||
@@ -108,9 +108,8 @@ const VisualSectionContent: React.FC = () => {
|
||||
'fontSize',
|
||||
'terminalFontSize',
|
||||
'spacing',
|
||||
'cornerRadius',
|
||||
'inputBarOffset',
|
||||
...(!isVSCode ? ['terminalQuickKeys' as const, 'navRail' as const] : []),
|
||||
...(!isVSCode ? ['terminalQuickKeys' as const] : []),
|
||||
]} />;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { ThemeMode } from '@/types/theme';
|
||||
import { useUIStore } from '@/stores/useUIStore';
|
||||
import { useMessageQueueStore } from '@/stores/messageQueueStore';
|
||||
import { cn, getModifierLabel } from '@/lib/utils';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { NumberInput } from '@/components/ui/number-input';
|
||||
import { Radio } from '@/components/ui/radio';
|
||||
@@ -143,7 +143,7 @@ const normalizeUserMessageRenderingMode = (mode: unknown): 'markdown' | 'plain'
|
||||
return mode === 'markdown' ? 'markdown' : 'plain';
|
||||
};
|
||||
|
||||
export type VisibleSetting = 'theme' | 'pwaInstallName' | 'fontSize' | 'terminalFontSize' | 'spacing' | 'cornerRadius' | 'inputBarOffset' | 'navRail' | 'mermaidRendering' | 'userMessageRendering' | 'chatRenderMode' | 'activityRenderMode' | 'stickyUserHeader' | 'diffLayout' | 'mobileStatusBar' | 'dotfiles' | 'reasoning' | 'showToolFileIcons' | 'expandedTools' | 'queueMode' | 'terminalQuickKeys' | 'persistDraft' | 'inputSpellcheck';
|
||||
export type VisibleSetting = 'theme' | 'pwaInstallName' | 'fontSize' | 'terminalFontSize' | 'spacing' | 'inputBarOffset' | 'mermaidRendering' | 'userMessageRendering' | 'chatRenderMode' | 'activityRenderMode' | 'stickyUserHeader' | 'diffLayout' | 'mobileStatusBar' | 'dotfiles' | 'reasoning' | 'showToolFileIcons' | 'expandedTools' | 'queueMode' | 'terminalQuickKeys' | 'persistDraft' | 'inputSpellcheck';
|
||||
|
||||
interface OpenChamberVisualSettingsProps {
|
||||
/** Which settings to show. If undefined, shows all. */
|
||||
@@ -173,8 +173,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
const setTerminalFontSize = useUIStore(state => state.setTerminalFontSize);
|
||||
const padding = useUIStore(state => state.padding);
|
||||
const setPadding = useUIStore(state => state.setPadding);
|
||||
const cornerRadius = useUIStore(state => state.cornerRadius);
|
||||
const setCornerRadius = useUIStore(state => state.setCornerRadius);
|
||||
const inputBarOffset = useUIStore(state => state.inputBarOffset);
|
||||
const setInputBarOffset = useUIStore(state => state.setInputBarOffset);
|
||||
const diffLayoutPreference = useUIStore(state => state.diffLayoutPreference);
|
||||
@@ -195,10 +193,9 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
const setShowExpandedBashTools = useUIStore(state => state.setShowExpandedBashTools);
|
||||
const showExpandedEditTools = useUIStore(state => state.showExpandedEditTools);
|
||||
const setShowExpandedEditTools = useUIStore(state => state.setShowExpandedEditTools);
|
||||
const isNavRailExpanded = useUIStore(state => state.isNavRailExpanded);
|
||||
const setNavRailExpanded = useUIStore(state => state.setNavRailExpanded);
|
||||
const showMobileSessionStatusBar = useUIStore(state => state.showMobileSessionStatusBar);
|
||||
const setShowMobileSessionStatusBar = useUIStore(state => state.setShowMobileSessionStatusBar);
|
||||
const isSettingsDialogOpen = useUIStore(state => state.isSettingsDialogOpen);
|
||||
const {
|
||||
themeMode,
|
||||
setThemeMode,
|
||||
@@ -214,7 +211,14 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
const [themesReloading, setThemesReloading] = React.useState(false);
|
||||
const [chatRenderPreviewTick, setChatRenderPreviewTick] = React.useState(0);
|
||||
|
||||
const shouldAnimateChatPreview = isSettingsDialogOpen
|
||||
&& (visibleSettings ? visibleSettings.includes('chatRenderMode') : true);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!shouldAnimateChatPreview) {
|
||||
return;
|
||||
}
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
setChatRenderPreviewTick((prev) => (prev + 1) % 24);
|
||||
}, 420);
|
||||
@@ -222,7 +226,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, []);
|
||||
}, [shouldAnimateChatPreview]);
|
||||
|
||||
const handleUserMessageRenderingModeChange = React.useCallback((mode: 'markdown' | 'plain') => {
|
||||
setUserMessageRenderingMode(mode);
|
||||
@@ -305,8 +309,8 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
|
||||
const isVSCode = isVSCodeRuntime();
|
||||
const hasAppearanceSettings = (shouldShow('theme') || shouldShow('pwaInstallName')) && !isVSCode;
|
||||
const hasLayoutSettings = shouldShow('fontSize') || shouldShow('terminalFontSize') || shouldShow('spacing') || shouldShow('cornerRadius') || shouldShow('inputBarOffset');
|
||||
const hasNavigationSettings = (!isMobile && shouldShow('navRail')) || (shouldShow('terminalQuickKeys') && !isMobile);
|
||||
const hasLayoutSettings = shouldShow('fontSize') || shouldShow('terminalFontSize') || shouldShow('spacing') || shouldShow('inputBarOffset');
|
||||
const hasNavigationSettings = shouldShow('terminalQuickKeys') && !isMobile;
|
||||
const hasBehaviorSettings = shouldShow('mermaidRendering')
|
||||
|| shouldShow('userMessageRendering')
|
||||
|| shouldShow('chatRenderMode')
|
||||
@@ -402,7 +406,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
<span className="typography-ui-header font-medium text-foreground">Color Mode</span>
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
{THEME_MODE_OPTIONS.map((option) => (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
key={option.value}
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -415,7 +419,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
onClick={() => setThemeMode(option.value)}
|
||||
>
|
||||
{option.label}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -516,7 +520,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
maxLength={64}
|
||||
aria-label="PWA install app name"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
@@ -528,7 +532,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -558,7 +562,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
aria-label="Font size percentage"
|
||||
className="w-16"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setFontSize(100)}
|
||||
@@ -568,7 +572,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -587,7 +591,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
step={1}
|
||||
className="w-16"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setTerminalFontSize(13)}
|
||||
@@ -597,7 +601,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -616,7 +620,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
step={5}
|
||||
className="w-16"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setPadding(100)}
|
||||
@@ -626,36 +630,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldShow('cornerRadius') && (
|
||||
<div className={cn("py-1", isMobile ? "flex flex-col gap-3" : "flex items-center gap-8")}>
|
||||
<div className={cn("flex min-w-0 flex-col", isMobile ? "w-full" : "w-56 shrink-0")}>
|
||||
<span className="typography-ui-label text-foreground">Corner Radius</span>
|
||||
</div>
|
||||
<div className={cn("flex items-center gap-2", isMobile ? "w-full" : "w-fit")}>
|
||||
<NumberInput
|
||||
value={cornerRadius}
|
||||
onValueChange={setCornerRadius}
|
||||
min={0}
|
||||
max={32}
|
||||
step={1}
|
||||
className="w-16"
|
||||
/>
|
||||
<ButtonSmall
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setCornerRadius(12)}
|
||||
disabled={cornerRadius === 12}
|
||||
className="h-7 w-7 px-0 text-muted-foreground hover:text-foreground"
|
||||
aria-label="Reset corner radius"
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -684,7 +659,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
step={5}
|
||||
className="w-16"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setInputBarOffset(0)}
|
||||
@@ -694,7 +669,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -710,38 +685,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
<div className="space-y-3">
|
||||
<section className="px-2 pb-2 pt-0">
|
||||
<h4 className="typography-ui-header font-medium text-foreground">Navigation</h4>
|
||||
{shouldShow('navRail') && !isMobile && (
|
||||
<div
|
||||
className="group mt-1.5 flex cursor-pointer items-center gap-2 py-1.5"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={() => setNavRailExpanded(!isNavRailExpanded)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
setNavRailExpanded(!isNavRailExpanded);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
checked={isNavRailExpanded}
|
||||
onChange={setNavRailExpanded}
|
||||
ariaLabel="Expand project rail by default"
|
||||
/>
|
||||
<div className="flex min-w-0 items-center gap-1.5">
|
||||
<span className="typography-ui-label text-foreground">Expand project rail</span>
|
||||
<Tooltip delayDuration={1000}>
|
||||
<TooltipTrigger asChild>
|
||||
<RiInformationLine className="h-3.5 w-3.5 text-muted-foreground/60 cursor-help" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent sideOffset={8} className="max-w-xs">
|
||||
Show project names in the left rail when multiple projects are open. Auto-collapses with a single project.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldShow('terminalQuickKeys') && !isMobile && (
|
||||
<div
|
||||
className="group flex cursor-pointer items-center gap-2 py-1.5"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { RiFolderLine, RiInformationLine } from '@remixicon/react';
|
||||
@@ -111,7 +111,7 @@ export const OpenCodeCliSettings: React.FC = () => {
|
||||
disabled={isLoading || isSaving}
|
||||
className="h-7 min-w-0 flex-1 font-mono text-xs"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -122,7 +122,7 @@ export const OpenCodeCliSettings: React.FC = () => {
|
||||
title="Browse"
|
||||
>
|
||||
<RiFolderLine className="h-4 w-4" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -133,7 +133,7 @@ export const OpenCodeCliSettings: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="flex justify-start py-1.5">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
size="xs"
|
||||
onClick={handleSaveAndReload}
|
||||
@@ -141,7 +141,7 @@ export const OpenCodeCliSettings: React.FC = () => {
|
||||
className="shrink-0 !font-normal"
|
||||
>
|
||||
{isSaving ? 'Saving…' : 'Save + Reload'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip
|
||||
import { RiInformationLine, RiRestartLine } from '@remixicon/react';
|
||||
import { toast } from '@/components/ui';
|
||||
import { NumberInput } from '@/components/ui/number-input';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { useUIStore } from '@/stores/useUIStore';
|
||||
import { useSessionAutoCleanup } from '@/hooks/useSessionAutoCleanup';
|
||||
@@ -90,7 +90,7 @@ export const SessionRetentionSettings: React.FC = () => {
|
||||
className="w-20 tabular-nums"
|
||||
/>
|
||||
<span className="typography-ui-label text-muted-foreground">days</span>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => setAutoDeleteAfterDays(DEFAULT_RETENTION_DAYS)}
|
||||
@@ -100,7 +100,7 @@ export const SessionRetentionSettings: React.FC = () => {
|
||||
title="Reset"
|
||||
>
|
||||
<RiRestartLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -111,7 +111,7 @@ export const SessionRetentionSettings: React.FC = () => {
|
||||
<p className="typography-meta text-foreground font-medium">Manual Cleanup</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:w-fit">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -120,7 +120,7 @@ export const SessionRetentionSettings: React.FC = () => {
|
||||
className="!font-normal"
|
||||
>
|
||||
{isRunning ? 'Cleaning up...' : 'Run cleanup now'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="typography-meta text-muted-foreground">
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
RiRestartLine,
|
||||
} from '@remixicon/react';
|
||||
import { toast } from '@/components/ui';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
||||
import { GridLoader } from '@/components/ui/grid-loader';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@@ -1121,7 +1121,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
{TUNNEL_MODE_OPTIONS.map((option) => (
|
||||
<Tooltip key={option.value} delayDuration={700}>
|
||||
<TooltipTrigger asChild>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className={cn(
|
||||
@@ -1136,7 +1136,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={isSavingMode || state === 'starting' || state === 'stopping'}
|
||||
>
|
||||
{option.label}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent sideOffset={8} className="max-w-xs">
|
||||
{option.tooltip}
|
||||
@@ -1217,7 +1217,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
|
||||
<div className="mb-1 flex items-center justify-between gap-3">
|
||||
<p className="typography-ui-label text-foreground">Saved managed remote tunnels</p>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -1226,7 +1226,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
Add
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{managedRemoteTunnelPresets.length > 0 ? (
|
||||
@@ -1263,7 +1263,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
<span className="typography-ui-label min-w-0 flex-1 truncate text-foreground">{preset.name}</span>
|
||||
</CollapsibleTrigger>
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="h-7 w-7 p-0 text-muted-foreground hover:text-[var(--status-error)]"
|
||||
@@ -1274,7 +1274,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={state === 'starting' || state === 'stopping' || isSavingMode}
|
||||
>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<CollapsibleContent className="pt-1.5">
|
||||
@@ -1305,7 +1305,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={state === 'starting' || state === 'stopping'}
|
||||
/>
|
||||
<div className="flex items-center justify-end">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -1320,7 +1320,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
Save token
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
@@ -1363,7 +1363,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
</p>
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -1373,8 +1373,8 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={isSavingMode || state === 'starting' || state === 'stopping'}
|
||||
>
|
||||
Save
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -1387,7 +1387,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={isSavingMode || state === 'starting' || state === 'stopping'}
|
||||
>
|
||||
Cancel
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -1442,7 +1442,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
className="h-7"
|
||||
disabled={state === 'starting' || state === 'stopping' || isSavingMode}
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="h-7 w-7 p-0"
|
||||
@@ -1453,9 +1453,9 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={state === 'starting' || state === 'stopping' || isSavingMode}
|
||||
>
|
||||
<RiFolderLine className="size-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
{managedLocalConfigPath && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="h-7 w-7 p-0"
|
||||
@@ -1466,7 +1466,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
disabled={state === 'starting' || state === 'stopping' || isSavingMode}
|
||||
>
|
||||
<RiCloseLine className="size-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<p className="typography-meta text-muted-foreground/70">
|
||||
@@ -1566,7 +1566,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="outline"
|
||||
onClick={handleStart}
|
||||
disabled={
|
||||
@@ -1580,7 +1580,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
{state === 'starting'
|
||||
? <><RiLoader4Line className="size-3.5 animate-spin" /> Starting tunnel...</>
|
||||
: 'Start Tunnel'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1610,12 +1610,12 @@ export const TunnelSettings: React.FC = () => {
|
||||
<code className="typography-code flex-1 truncate rounded bg-muted/50 px-2 py-1 text-xs text-foreground">
|
||||
{tunnelInfo.connectUrl}
|
||||
</code>
|
||||
<ButtonSmall variant="ghost" onClick={handleCopyUrl} className="shrink-0 gap-1.5">
|
||||
<Button size="sm" variant="ghost" onClick={handleCopyUrl} className="shrink-0 gap-1.5">
|
||||
{copied
|
||||
? <RiCheckLine className="size-3.5 text-[var(--status-success)]" />
|
||||
: <RiFileCopyLine className="size-3.5" />}
|
||||
{copied ? 'Copied' : 'Copy'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
<p className="typography-meta mt-1 text-muted-foreground/70">
|
||||
Expires: {tunnelInfo.bootstrapExpiresAt ? remainingText : 'Never'}
|
||||
@@ -1634,7 +1634,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
|
||||
<div className="pt-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="outline"
|
||||
onClick={handleStart}
|
||||
disabled={state === 'stopping' || isSavingMode || (tunnelMode === 'managed-local' && isManagedLocalConfigPathInvalid)}
|
||||
@@ -1642,9 +1642,9 @@ export const TunnelSettings: React.FC = () => {
|
||||
>
|
||||
<RiRestartLine className="size-3.5" />
|
||||
New connect link
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
onClick={handleStop}
|
||||
disabled={state === 'stopping' || isSavingMode}
|
||||
@@ -1653,7 +1653,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
{state === 'stopping'
|
||||
? <><RiLoader4Line className="size-3.5 animate-spin" /> Stopping...</>
|
||||
: 'Stop Tunnel'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1662,7 +1662,7 @@ export const TunnelSettings: React.FC = () => {
|
||||
{state === 'error' && errorMessage && (
|
||||
<section className="space-y-3 px-2 pb-2 pt-0">
|
||||
<p className="typography-meta text-[var(--status-error)]">{errorMessage}</p>
|
||||
<ButtonSmall variant="ghost" onClick={handleStart}>Retry</ButtonSmall>
|
||||
<Button size="sm" variant="ghost" onClick={handleStart}>Retry</Button>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { NumberInput } from '@/components/ui/number-input';
|
||||
import { RiPlayLine, RiStopLine, RiCloseLine, RiAppleLine, RiInformationLine } from '@remixicon/react';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
@@ -363,7 +363,7 @@ export const VoiceSettings: React.FC = () => {
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setVoiceProvider('browser')}
|
||||
@@ -375,8 +375,8 @@ export const VoiceSettings: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
Browser
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setVoiceProvider('openai')}
|
||||
@@ -388,9 +388,9 @@ export const VoiceSettings: React.FC = () => {
|
||||
)}
|
||||
>
|
||||
OpenAI
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
{isSayAvailable && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
onClick={() => setVoiceProvider('say')}
|
||||
@@ -403,7 +403,7 @@ export const VoiceSettings: React.FC = () => {
|
||||
>
|
||||
<RiAppleLine className="w-3.5 h-3.5 mr-0.5" />
|
||||
Say
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -455,9 +455,9 @@ export const VoiceSettings: React.FC = () => {
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<ButtonSmall variant="ghost" className="h-7 w-7 px-0" onClick={previewOpenAIVoice} title="Preview">
|
||||
<Button size="xs" variant="ghost" onClick={previewOpenAIVoice} title="Preview">
|
||||
{isOpenAIPreviewPlaying ? <RiStopLine className="w-3.5 h-3.5" /> : <RiPlayLine className="w-3.5 h-3.5" />}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -473,9 +473,9 @@ export const VoiceSettings: React.FC = () => {
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<ButtonSmall variant="ghost" className="h-7 w-7 px-0" onClick={previewVoice} title="Preview">
|
||||
<Button size="xs" variant="ghost" onClick={previewVoice} title="Preview">
|
||||
{isPreviewPlaying ? <RiStopLine className="w-3.5 h-3.5" /> : <RiPlayLine className="w-3.5 h-3.5" />}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -492,9 +492,9 @@ export const VoiceSettings: React.FC = () => {
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<ButtonSmall variant="ghost" className="h-7 w-7 px-0" onClick={previewBrowserVoice} title="Preview">
|
||||
<Button size="xs" variant="ghost" onClick={previewBrowserVoice} title="Preview">
|
||||
{isBrowserPreviewPlaying ? <RiStopLine className="w-3.5 h-3.5" /> : <RiPlayLine className="w-3.5 h-3.5" />}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { RiAddLine, RiCloseLine, RiDeleteBinLine, RiInformationLine } from '@remixicon/react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { useProjectsStore } from '@/stores/useProjectsStore';
|
||||
@@ -306,7 +306,7 @@ export const WorktreeSectionContent: React.FC<WorktreeSectionContentProps> = ({
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
@@ -315,7 +315,7 @@ export const WorktreeSectionContent: React.FC<WorktreeSectionContentProps> = ({
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
Add command
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
RiInformationLine,
|
||||
RiPlayLine,
|
||||
} from '@remixicon/react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import {
|
||||
Collapsible,
|
||||
@@ -198,10 +198,10 @@ export const ProjectActionsSection: React.FC<ProjectActionsSectionProps> = ({ pr
|
||||
<h3 className="typography-ui-header font-medium text-foreground">Actions</h3>
|
||||
<p className="typography-meta text-muted-foreground">Per-project commands shown in header next to project name.</p>
|
||||
</div>
|
||||
<ButtonSmall type="button" variant="outline" size="xs" className="!font-normal" onClick={handleAddAction}>
|
||||
<Button type="button" variant="outline" size="xs" className="!font-normal" onClick={handleAddAction}>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
Add action
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<section className="pb-2 pt-0 space-y-2">
|
||||
@@ -248,7 +248,7 @@ export const ProjectActionsSection: React.FC<ProjectActionsSectionProps> = ({ pr
|
||||
</div>
|
||||
</CollapsibleTrigger>
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
@@ -256,7 +256,7 @@ export const ProjectActionsSection: React.FC<ProjectActionsSectionProps> = ({ pr
|
||||
onClick={() => handleRemoveAction(action.id)}
|
||||
>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<CollapsibleContent className="pt-1.5">
|
||||
@@ -418,7 +418,7 @@ export const ProjectActionsSection: React.FC<ProjectActionsSectionProps> = ({ pr
|
||||
{validationError ? (
|
||||
<p className="typography-meta mb-2 text-[var(--status-warning)]">{validationError}</p>
|
||||
) : null}
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -426,7 +426,7 @@ export const ProjectActionsSection: React.FC<ProjectActionsSectionProps> = ({ pr
|
||||
disabled={!canSave}
|
||||
>
|
||||
{isSaving ? 'Saving...' : 'Save Actions'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { toast } from '@/components/ui';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -399,7 +399,7 @@ export const ProjectsPage: React.FC = () => {
|
||||
placeholder="#000000"
|
||||
className="h-7 w-[8rem]"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
size="xs"
|
||||
variant="outline"
|
||||
@@ -410,21 +410,21 @@ export const ProjectsPage: React.FC = () => {
|
||||
disabled={!iconBackground}
|
||||
>
|
||||
<RiCloseLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<div className="mt-2 flex flex-wrap items-center gap-2">
|
||||
{!hasCustomIcon && (
|
||||
<>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="h-6 !font-normal"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={isUploadingIcon}
|
||||
>
|
||||
{isUploadingIcon ? 'Uploading...' : 'Upload Icon'}
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
size="xs"
|
||||
className="h-6 !font-normal"
|
||||
variant="outline"
|
||||
@@ -432,11 +432,11 @@ export const ProjectsPage: React.FC = () => {
|
||||
disabled={isDiscoveringIcon}
|
||||
>
|
||||
{isDiscoveringIcon ? 'Discovering...' : 'Discover Favicon'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{hasRemovableImageIcon && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
variant="outline"
|
||||
@@ -444,10 +444,10 @@ export const ProjectsPage: React.FC = () => {
|
||||
disabled={isRemovingCustomIcon}
|
||||
>
|
||||
{isRemovingCustomIcon ? 'Removing...' : 'Remove Project Icon'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
{pendingRemoveImageIcon && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
variant="outline"
|
||||
@@ -455,7 +455,7 @@ export const ProjectsPage: React.FC = () => {
|
||||
disabled={isRemovingCustomIcon}
|
||||
>
|
||||
Undo Remove
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -463,14 +463,14 @@ export const ProjectsPage: React.FC = () => {
|
||||
</section>
|
||||
|
||||
<div className="mt-0.5 px-2 py-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={!hasChanges || name.trim().length === 0 || isUploadingIcon || isRemovingCustomIcon}
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
>
|
||||
Save Changes
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { useUIStore } from '@/stores/useUIStore';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import {
|
||||
DropdownMenu,
|
||||
@@ -653,14 +653,14 @@ export const ProvidersPage: React.FC = () => {
|
||||
placeholder="sk-..."
|
||||
className="flex-1 font-mono text-xs"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal shrink-0"
|
||||
onClick={() => handleSaveApiKey(candidateProviderId)}
|
||||
disabled={authBusyKey === `api:${candidateProviderId}`}
|
||||
>
|
||||
{authBusyKey === `api:${candidateProviderId}` ? 'Saving...' : 'Save Key'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -693,7 +693,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -701,7 +701,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
disabled={authBusyKey === `oauth:${candidateProviderId}:${index}`}
|
||||
>
|
||||
Connect
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{oauthDetails[codeKey]?.instructions && (
|
||||
@@ -713,7 +713,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
{oauthDetails[codeKey]?.userCode && (
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<Input value={oauthDetails[codeKey]?.userCode} readOnly className="font-mono text-center tracking-widest" />
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthCode(oauthDetails[codeKey]?.userCode ?? '')}>Copy Code</ButtonSmall>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthCode(oauthDetails[codeKey]?.userCode ?? '')}>Copy Code</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -721,8 +721,8 @@ export const ProvidersPage: React.FC = () => {
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<Input value={oauthDetails[codeKey]?.url} readOnly className="text-xs text-muted-foreground" />
|
||||
<div className="flex gap-1 shrink-0">
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => window.open(oauthDetails[codeKey]?.url, '_blank', 'noopener,noreferrer')}>Open</ButtonSmall>
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthLink(oauthDetails[codeKey]?.url ?? '')}>Copy</ButtonSmall>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => window.open(oauthDetails[codeKey]?.url, '_blank', 'noopener,noreferrer')}>Open</Button>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthLink(oauthDetails[codeKey]?.url ?? '')}>Copy</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -740,14 +740,14 @@ export const ProvidersPage: React.FC = () => {
|
||||
placeholder="Paste authorization code"
|
||||
className="font-mono text-xs"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
onClick={() => handleOAuthComplete(candidateProviderId, index)}
|
||||
disabled={authBusyKey === `oauth-complete:${candidateProviderId}:${index}`}
|
||||
>
|
||||
{authBusyKey === `oauth-complete:${candidateProviderId}:${index}` ? 'Saving...' : 'Complete'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -810,14 +810,14 @@ export const ProvidersPage: React.FC = () => {
|
||||
<div className="mb-8">
|
||||
<div className="mb-1 px-1 flex items-center justify-between gap-2">
|
||||
<h3 className="typography-ui-header font-medium text-foreground">Authentication</h3>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
onClick={() => setShowAuthPanel((prev) => !prev)}
|
||||
>
|
||||
{showAuthPanel ? 'Hide' : 'Reconnect'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<section className="px-2 pb-2 pt-0">
|
||||
@@ -856,14 +856,14 @@ export const ProvidersPage: React.FC = () => {
|
||||
placeholder="sk-..."
|
||||
className="flex-1 font-mono text-xs"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal shrink-0"
|
||||
onClick={() => handleSaveApiKey(selectedProvider.id)}
|
||||
disabled={authBusyKey === `api:${selectedProvider.id}`}
|
||||
>
|
||||
{authBusyKey === `api:${selectedProvider.id}` ? 'Saving...' : 'Save Key'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -886,7 +886,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -894,7 +894,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
disabled={authBusyKey === `oauth:${selectedProvider.id}:${index}`}
|
||||
>
|
||||
Connect
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{oauthDetails[codeKey]?.instructions && (
|
||||
@@ -906,7 +906,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
{oauthDetails[codeKey]?.userCode && (
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<Input value={oauthDetails[codeKey]?.userCode} readOnly className="font-mono text-center tracking-widest" />
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthCode(oauthDetails[codeKey]?.userCode ?? '')}>Copy Code</ButtonSmall>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthCode(oauthDetails[codeKey]?.userCode ?? '')}>Copy Code</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -914,8 +914,8 @@ export const ProvidersPage: React.FC = () => {
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<Input value={oauthDetails[codeKey]?.url} readOnly className="text-xs text-muted-foreground" />
|
||||
<div className="flex gap-1 shrink-0">
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => window.open(oauthDetails[codeKey]?.url, '_blank', 'noopener,noreferrer')}>Open</ButtonSmall>
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthLink(oauthDetails[codeKey]?.url ?? '')}>Copy</ButtonSmall>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => window.open(oauthDetails[codeKey]?.url, '_blank', 'noopener,noreferrer')}>Open</Button>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => handleCopyOAuthLink(oauthDetails[codeKey]?.url ?? '')}>Copy</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -933,14 +933,14 @@ export const ProvidersPage: React.FC = () => {
|
||||
placeholder="Paste authorization code"
|
||||
className="font-mono text-xs"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
onClick={() => handleOAuthComplete(selectedProvider.id, index)}
|
||||
disabled={authBusyKey === `oauth-complete:${selectedProvider.id}:${index}`}
|
||||
>
|
||||
{authBusyKey === `oauth-complete:${selectedProvider.id}:${index}` ? 'Saving...' : 'Complete'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -976,7 +976,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal text-[var(--status-error)] hover:text-[var(--status-error)]"
|
||||
@@ -984,7 +984,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
disabled={authBusyKey === `disconnect:${selectedProvider.id}`}
|
||||
>
|
||||
{authBusyKey === `disconnect:${selectedProvider.id}` ? 'Disconnecting...' : 'Disconnect'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1001,7 +1001,7 @@ export const ProvidersPage: React.FC = () => {
|
||||
)}
|
||||
</h3>
|
||||
<div className="flex items-center gap-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -1013,15 +1013,15 @@ export const ProvidersPage: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
Hide all
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
onClick={() => showAllModels(selectedProvider.id)}
|
||||
>
|
||||
Show all
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { useProjectsStore } from '@/stores/useProjectsStore';
|
||||
import { RiAddLine, RiStackLine } from '@remixicon/react';
|
||||
@@ -110,7 +110,7 @@ export const ProvidersSidebar: React.FC<ProvidersSidebarProps> = ({ onItemSelect
|
||||
<SettingsProjectSelector className="mb-3" />
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="typography-meta text-muted-foreground">Total {providers.length}</span>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 -my-1 text-muted-foreground"
|
||||
onClick={() => {
|
||||
@@ -121,7 +121,7 @@ export const ProvidersSidebar: React.FC<ProvidersSidebarProps> = ({ onItemSelect
|
||||
title="Connect provider"
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { NumberInput } from '@/components/ui/number-input';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
@@ -701,7 +701,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
</div>
|
||||
<div className="typography-micro text-muted-foreground">{candidate.source} config</div>
|
||||
</div>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -709,7 +709,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
onClick={() => void handleImportCandidate(candidate.host, candidate.pattern)}
|
||||
>
|
||||
Create
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -746,12 +746,12 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
autoFocus
|
||||
/>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<ButtonSmall type="button" variant="outline" size="xs" className="!font-normal" onClick={closePatternDialog} disabled={patternCreating}>
|
||||
<Button type="button" variant="outline" size="xs" className="!font-normal" onClick={closePatternDialog} disabled={patternCreating}>
|
||||
Cancel
|
||||
</ButtonSmall>
|
||||
<ButtonSmall type="submit" size="xs" className="!font-normal" disabled={patternCreating}>
|
||||
</Button>
|
||||
<Button type="submit" size="xs" className="!font-normal" disabled={patternCreating}>
|
||||
Create
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</DialogContent>
|
||||
@@ -782,7 +782,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
</div>
|
||||
<section className="px-2 pb-2 pt-0 space-y-3">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant={canDisconnect ? 'outline' : 'default'}
|
||||
size="xs"
|
||||
@@ -792,8 +792,8 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
{canDisconnect ? <RiStopLine className="h-3.5 w-3.5" /> : <RiPlug2Line className="h-3.5 w-3.5" />}
|
||||
{primaryButtonLabel}
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -803,8 +803,8 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiRefreshLine className={`h-3.5 w-3.5 ${isConnecting || (isReconnecting && !reconnectAppearsStuck) ? 'animate-spin' : ''}`} />
|
||||
{retryButtonLabel}
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -815,8 +815,8 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiTerminalWindowLine className="h-3.5 w-3.5" />
|
||||
Logs
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -838,7 +838,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
Remove
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
{status?.localUrl ? (
|
||||
<div className="flex flex-wrap items-center gap-2 typography-meta text-muted-foreground">
|
||||
@@ -1114,7 +1114,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
}}
|
||||
emptyLabel="Auto"
|
||||
/>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -1131,7 +1131,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
}
|
||||
>
|
||||
<RiShuffleLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1254,7 +1254,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch checked={forward.enabled} onCheckedChange={(checked) => updateForward((item) => ({ ...item, enabled: checked }))} aria-label="Enable forward" />
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
@@ -1267,7 +1267,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
}
|
||||
>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<CollapsibleContent className="pt-2">
|
||||
@@ -1416,7 +1416,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{canOpenLocalEndpoint ? (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -1431,7 +1431,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiExternalLinkLine className="h-3.5 w-3.5" />
|
||||
Open local
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1440,7 +1440,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
);
|
||||
})}
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -1459,7 +1459,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
Add forward
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -1486,7 +1486,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
</div>
|
||||
<div className="typography-micro text-muted-foreground truncate">{candidate.sshCommand}</div>
|
||||
</div>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -1494,7 +1494,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
onClick={() => void handleImportCandidate(candidate.host, candidate.pattern)}
|
||||
>
|
||||
Import
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -1504,12 +1504,12 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
|
||||
<div className="sticky bottom-0 z-10 -mx-3 sm:-mx-6 bg-[var(--surface-background)] border-t border-[var(--interactive-border)] px-3 sm:px-6 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<ButtonSmall type="button" size="xs" className="!font-normal" onClick={() => void handleSave()} disabled={!hasChanges || isSaving}>
|
||||
<Button type="button" size="xs" className="!font-normal" onClick={() => void handleSave()} disabled={!hasChanges || isSaving}>
|
||||
Save changes
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
{status?.localUrl ? (
|
||||
<>
|
||||
<ButtonSmall
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -1524,8 +1524,8 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiFileCopyLine className="h-3.5 w-3.5" />
|
||||
Copy local URL
|
||||
</ButtonSmall>
|
||||
<ButtonSmall
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
@@ -1536,7 +1536,7 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
>
|
||||
<RiExternalLinkLine className="h-3.5 w-3.5" />
|
||||
Open
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</>
|
||||
) : null}
|
||||
{error ? <div className="ml-auto typography-meta text-[var(--status-error)]">{error}</div> : null}
|
||||
@@ -1552,14 +1552,14 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<ButtonSmall type="button" variant="outline" size="xs" className="!font-normal" onClick={handleCopyAllLogs} disabled={logDialogLoading || !logLinesText.trim()}>
|
||||
<Button type="button" variant="outline" size="xs" className="!font-normal" onClick={handleCopyAllLogs} disabled={logDialogLoading || !logLinesText.trim()}>
|
||||
<RiFileCopyLine className="h-3.5 w-3.5" />
|
||||
Copy all
|
||||
</ButtonSmall>
|
||||
<ButtonSmall type="button" variant="outline" size="xs" className="!font-normal" onClick={() => void handleClearLogs()} disabled={logDialogLoading}>
|
||||
</Button>
|
||||
<Button type="button" variant="outline" size="xs" className="!font-normal" onClick={() => void handleClearLogs()} disabled={logDialogLoading}>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
Clear
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
{logDialogLoading ? (
|
||||
<div className="typography-meta text-muted-foreground">Loading logs...</div>
|
||||
@@ -1602,12 +1602,12 @@ export const RemoteInstancesPage: React.FC = () => {
|
||||
autoFocus
|
||||
/>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<ButtonSmall type="button" variant="outline" size="xs" className="!font-normal" onClick={closePatternDialog} disabled={patternCreating}>
|
||||
<Button type="button" variant="outline" size="xs" className="!font-normal" onClick={closePatternDialog} disabled={patternCreating}>
|
||||
Cancel
|
||||
</ButtonSmall>
|
||||
<ButtonSmall type="submit" size="xs" className="!font-normal" disabled={patternCreating}>
|
||||
</Button>
|
||||
<Button type="submit" size="xs" className="!font-normal" disabled={patternCreating}>
|
||||
Create
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</DialogContent>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { toast } from '@/components/ui';
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { SkillsCatalogPage } from './catalog/SkillsCatalogPage';
|
||||
import {
|
||||
SKILL_LOCATION_OPTIONS,
|
||||
@@ -459,9 +458,9 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
<h3 className="typography-ui-header font-medium text-foreground">
|
||||
Supporting Files
|
||||
</h3>
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal gap-1" onClick={handleAddFile}>
|
||||
<Button variant="outline" size="xs" className="!font-normal gap-1" onClick={handleAddFile}>
|
||||
<RiAddLine className="h-3.5 w-3.5" /> Add File
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<section className="px-2 pb-2 pt-0">
|
||||
@@ -491,7 +490,7 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
pending
|
||||
</span>
|
||||
)}
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-5 w-5 px-0 flex-shrink-0 text-muted-foreground hover:text-[var(--status-error)] opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
onClick={(e) => {
|
||||
@@ -500,7 +499,7 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className="h-3 w-3" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -511,14 +510,14 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
|
||||
{/* Save action */}
|
||||
<div className="px-2 py-1">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
disabled={isSaving || !hasSkillChanges}
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
>
|
||||
{isSaving ? 'Saving...' : isNewSkill ? 'Create Skill' : 'Save Changes'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -540,16 +539,17 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => setDeleteFilePath(null)}
|
||||
disabled={isDeletingFile}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleConfirmDeleteFile} disabled={isDeletingFile} className="bg-[var(--status-error)] hover:bg-[var(--status-error)]/90 text-white border-0">
|
||||
</Button>
|
||||
<Button size="sm" variant="destructive" onClick={handleConfirmDeleteFile} disabled={isDeletingFile}>
|
||||
Delete
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -603,7 +603,8 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
<DialogFooter className="mt-4">
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setIsFileDialogOpen(false);
|
||||
@@ -611,10 +612,10 @@ const SkillsInstalledPage: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleSaveFile} disabled={isLoadingFile || !hasFileChanges}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleSaveFile} disabled={isLoadingFile || !hasFileChanges}>
|
||||
{editingFilePath ? 'Save Changes' : 'Create File'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { toast } from '@/components/ui';
|
||||
import { isMobileDeviceViaCSS } from '@/lib/device';
|
||||
@@ -207,13 +206,13 @@ export const SkillsSidebar: React.FC<SkillsSidebarProps> = ({ onItemSelect }) =>
|
||||
<SettingsProjectSelector className="mb-3" />
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="typography-meta text-muted-foreground">Total {skills.length}</span>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 -my-1 text-muted-foreground"
|
||||
onClick={handleCreateNew}
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -347,17 +346,18 @@ export const SkillsSidebar: React.FC<SkillsSidebarProps> = ({ onItemSelect }) =>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
className="text-foreground hover:bg-interactive-hover hover:text-foreground"
|
||||
variant="ghost"
|
||||
onClick={() => setDeleteDialogSkill(null)}
|
||||
disabled={isDeletePending}
|
||||
className="text-foreground hover:bg-interactive-hover hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleConfirmDeleteSkill} disabled={isDeletePending}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleConfirmDeleteSkill} disabled={isDeletePending}>
|
||||
Delete
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -383,16 +383,17 @@ export const SkillsSidebar: React.FC<SkillsSidebarProps> = ({ onItemSelect }) =>
|
||||
}}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
className="text-foreground hover:bg-interactive-hover hover:text-foreground"
|
||||
variant="ghost"
|
||||
onClick={() => setRenameDialogSkill(null)}
|
||||
className="text-foreground hover:bg-interactive-hover hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge onClick={handleRenameSkill}>
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleRenameSkill}>
|
||||
Rename
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -461,12 +462,12 @@ const SkillListItem: React.FC<SkillListItemProps> = ({
|
||||
|
||||
<DropdownMenu open={isMenuOpen} onOpenChange={onMenuOpenChange}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-6 w-6 px-0 flex-shrink-0 -mr-1 opacity-100 transition-opacity md:opacity-0 md:group-hover:opacity-100"
|
||||
>
|
||||
<RiMore2Line className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit min-w-20">
|
||||
<DropdownMenuItem
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import {
|
||||
Select,
|
||||
@@ -311,24 +311,26 @@ export const AddCatalogDialog: React.FC<AddCatalogDialogProps> = ({ open, onOpen
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<ButtonLarge variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
<Button size="sm" variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
className="gap-2"
|
||||
variant="ghost"
|
||||
onClick={() => void handleScan()}
|
||||
disabled={isScanning || !source.trim()}
|
||||
className="gap-2"
|
||||
>
|
||||
<RiGitRepositoryLine className="h-4 w-4" />
|
||||
{isScanning ? 'Scanning...' : 'Scan'}
|
||||
</ButtonLarge>
|
||||
<ButtonLarge
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => void handleAdd()}
|
||||
disabled={!scanOk || isDuplicate || !label.trim() || !source.trim()}
|
||||
>
|
||||
Add catalog
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -73,8 +72,8 @@ export const InstallConflictsDialog: React.FC<InstallConflictsDialogProps> = ({
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="typography-meta text-muted-foreground">{conflicts.length} conflict(s)</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => setAll('skip')}>Skip all</ButtonSmall>
|
||||
<ButtonSmall variant="outline" size="xs" className="!font-normal" onClick={() => setAll('overwrite')}>Overwrite all</ButtonSmall>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => setAll('skip')}>Skip all</Button>
|
||||
<Button variant="outline" size="xs" className="!font-normal" onClick={() => setAll('overwrite')}>Overwrite all</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -113,15 +112,16 @@ export const InstallConflictsDialog: React.FC<InstallConflictsDialogProps> = ({
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<ButtonLarge variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
<Button size="sm" variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => onConfirm(decisions)}
|
||||
disabled={!canConfirm}
|
||||
>
|
||||
Continue
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
@@ -487,15 +486,16 @@ export const InstallFromRepoDialog: React.FC<InstallFromRepoDialogProps> = ({ op
|
||||
</div>
|
||||
|
||||
<DialogFooter className="flex-shrink-0">
|
||||
<ButtonLarge variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
<Button size="sm" variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={isInstalling || selectedDirs.length === 0 || !source.trim() || (scope === 'project' && !directoryOverride)}
|
||||
onClick={() => void doInstall({})}
|
||||
>
|
||||
{isInstalling ? 'Installing…' : 'Install selected'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -231,13 +231,15 @@ export const InstallSkillDialog: React.FC<InstallSkillDialogProps> = ({ open, on
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => onOpenChange(false)}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={isInstalling || !item.installable || (scope === 'project' && !directoryOverride)}
|
||||
onClick={() =>
|
||||
void doInstall({
|
||||
@@ -251,7 +253,7 @@ export const InstallSkillDialog: React.FC<InstallSkillDialogProps> = ({ open, on
|
||||
}
|
||||
>
|
||||
{isInstalling ? 'Installing...' : 'Install'}
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { SortableTabsStrip } from '@/components/ui/sortable-tabs-strip';
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { ButtonLarge } from '@/components/ui/button-large';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -195,7 +194,7 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal h-6 w-6 px-0"
|
||||
@@ -210,10 +209,10 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
title="Refresh"
|
||||
>
|
||||
<RiRefreshLine className={cn("h-3.5 w-3.5", (isLoadingCatalog || isLoadingSource) && "animate-spin")} />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
|
||||
{isCustomSource && (
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className="!font-normal h-6 w-6 px-0 text-[var(--status-error)] hover:text-[var(--status-error)]"
|
||||
@@ -222,16 +221,16 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
title="Remove Catalog"
|
||||
>
|
||||
<RiDeleteBinLine className="h-3.5 w-3.5" />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
size="xs"
|
||||
className="!font-normal gap-1"
|
||||
onClick={() => setAddCatalogOpen(true)}
|
||||
>
|
||||
<RiAddLine className="h-3.5 w-3.5" /> Add Catalog
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="py-1.5">
|
||||
@@ -328,7 +327,7 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal shrink-0"
|
||||
@@ -339,7 +338,7 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
}}
|
||||
>
|
||||
Install
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -350,7 +349,7 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
|
||||
{isClawdHubSource && hasMoreClawdHub && !isLoadingSource && filtered.length > 0 && (
|
||||
<div className="flex justify-center mt-2 px-2">
|
||||
<ButtonSmall
|
||||
<Button
|
||||
variant="outline"
|
||||
size="xs"
|
||||
className="!font-normal"
|
||||
@@ -358,7 +357,7 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
disabled={isLoadingMore}
|
||||
>
|
||||
{isLoadingMore ? 'Loading...' : 'Load More Skills'}
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -381,16 +380,17 @@ export const SkillsCatalogPage: React.FC<SkillsCatalogPageProps> = ({ mode, onMo
|
||||
<DialogDescription>Are you sure you want to remove this catalog?</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<ButtonLarge
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => setIsRemoveCatalogDialogOpen(false)}
|
||||
disabled={isRemovingCatalog}
|
||||
>
|
||||
Cancel
|
||||
</ButtonLarge>
|
||||
<ButtonLarge className="bg-[var(--status-error)] hover:bg-[var(--status-error)]/90 text-white" onClick={() => void removeSelectedCatalog()} disabled={isRemovingCatalog}>
|
||||
</Button>
|
||||
<Button size="sm" variant="destructive" onClick={() => void removeSelectedCatalog()} disabled={isRemovingCatalog}>
|
||||
Remove Catalog
|
||||
</ButtonLarge>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||
import { ButtonSmall } from '@/components/ui/button-small';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
@@ -111,7 +111,7 @@ export const UsageSidebar: React.FC<UsageSidebarProps> = ({ onItemSelect }) => {
|
||||
<SelectItem value="300000">5m</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<ButtonSmall
|
||||
<Button size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 px-0 text-muted-foreground"
|
||||
onClick={() => fetchAllQuotas()}
|
||||
@@ -120,7 +120,7 @@ export const UsageSidebar: React.FC<UsageSidebarProps> = ({ onItemSelect }) => {
|
||||
disabled={isLoading}
|
||||
>
|
||||
<RiRefreshLine className={cn('h-3.5 w-3.5', isLoading && 'animate-spin')} />
|
||||
</ButtonSmall>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center justify-between gap-2">
|
||||
|
||||
Reference in New Issue
Block a user