diff --git a/ui/bun.lock b/ui/bun.lock
index 4d5fd5d2..59c1bef1 100644
--- a/ui/bun.lock
+++ b/ui/bun.lock
@@ -10,8 +10,10 @@
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8",
+ "@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
+ "@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-query": "^5.90.12",
"@tanstack/react-table": "^8.21.3",
@@ -184,6 +186,8 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+ "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
+
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
"@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw=="],
@@ -226,10 +230,14 @@
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
+ "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
+
"@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
+ "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
+
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
diff --git a/ui/package.json b/ui/package.json
index fef4ae5e..ef229add 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -21,8 +21,10 @@
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8",
+ "@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
+ "@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-query": "^5.90.12",
"@tanstack/react-table": "^8.21.3",
diff --git a/ui/src/components/accounts-table.tsx b/ui/src/components/accounts-table.tsx
index 434c6cbe..65865f03 100644
--- a/ui/src/components/accounts-table.tsx
+++ b/ui/src/components/accounts-table.tsx
@@ -29,11 +29,12 @@ export function AccountsTable({ data, defaultAccount }: AccountsTableProps) {
{
accessorKey: 'name',
header: 'Name',
+ size: 200,
cell: ({ row }) => (
- {row.original.name}
+
{row.original.name}
{row.original.name === defaultAccount && (
-
+
default
)}
@@ -43,39 +44,46 @@ export function AccountsTable({ data, defaultAccount }: AccountsTableProps) {
{
accessorKey: 'type',
header: 'Type',
- cell: ({ row }) => row.original.type || 'oauth',
+ size: 100,
+ cell: ({ row }) => (
+ {row.original.type || 'oauth'}
+ ),
},
{
accessorKey: 'created',
header: 'Created',
+ size: 150,
cell: ({ row }) => {
const date = new Date(row.original.created);
- return date.toLocaleDateString();
+ return {date.toLocaleDateString()};
},
},
{
accessorKey: 'last_used',
header: 'Last Used',
+ size: 150,
cell: ({ row }) => {
- if (!row.original.last_used) return '-';
+ if (!row.original.last_used) return -;
const date = new Date(row.original.last_used);
- return date.toLocaleDateString();
+ return {date.toLocaleDateString()};
},
},
{
id: 'actions',
header: 'Actions',
+ size: 100,
cell: ({ row }) => {
const isDefault = row.original.name === defaultAccount;
return (
);
},
@@ -111,7 +119,7 @@ export function AccountsTable({ data, defaultAccount }: AccountsTableProps) {
type: 'w-[100px]',
created: 'w-[150px]',
last_used: 'w-[150px]',
- actions: 'w-[120px]',
+ actions: 'w-[100px]',
}[header.id] || 'w-auto';
return (
diff --git a/ui/src/components/profiles-table.tsx b/ui/src/components/profiles-table.tsx
index 91f50048..c09ef990 100644
--- a/ui/src/components/profiles-table.tsx
+++ b/ui/src/components/profiles-table.tsx
@@ -20,17 +20,16 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
-import { MoreHorizontal, Trash2, Edit, Settings } from 'lucide-react';
+import { MoreHorizontal, Trash2, Edit } from 'lucide-react';
import { useDeleteProfile } from '@/hooks/use-profiles';
import type { Profile } from '@/lib/api-client';
interface ProfilesTableProps {
data: Profile[];
- onEdit?: (profile: Profile) => void;
onEditSettings?: (profile: Profile) => void;
}
-export function ProfilesTable({ data, onEdit, onEditSettings }: ProfilesTableProps) {
+export function ProfilesTable({ data, onEditSettings }: ProfilesTableProps) {
const deleteMutation = useDeleteProfile();
const columns: ColumnDef[] = [
@@ -64,22 +63,16 @@ export function ProfilesTable({ data, onEdit, onEditSettings }: ProfilesTablePro
-
- {onEdit && (
- onEdit(row.original)}>
-
- Edit Profile
-
- )}
+
{onEditSettings && (
onEditSettings(row.original)}>
-
- Edit Settings
+
+ Edit
)}
deleteMutation.mutate(row.original.name)}
>
diff --git a/ui/src/components/settings-dialog.tsx b/ui/src/components/settings-dialog.tsx
index 4142850c..1e87683c 100644
--- a/ui/src/components/settings-dialog.tsx
+++ b/ui/src/components/settings-dialog.tsx
@@ -42,6 +42,10 @@ interface SettingsDialogProps {
* Inner component that manages local edits state
* Gets unmounted/remounted via key prop when dialog closes/opens
*/
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
+import { ScrollArea } from '@/components/ui/scroll-area';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+
function SettingsDialogContent({
profileName,
onClose,
@@ -147,42 +151,94 @@ function SettingsDialogContent({
return (
<>
- Environment Settings: {profileName}
+ Edit Profile: {profileName}
- Edit environment variables for this profile. Sensitive keys are masked.
+ Configure environment variables and settings for this profile.
{isLoading ? (
-
-
-
Loading settings...
+
+
+ Loading settings...
- ) : currentSettings?.env && Object.keys(currentSettings.env).length > 0 ? (
-
- {Object.entries(currentSettings.env).map(([key, value]) => (
-
-
- {isSensitiveKey(key) ? (
- updateEnvValue(key, e.target.value)} />
- ) : (
- updateEnvValue(key, e.target.value)}
- className="font-mono"
- />
- )}
-
- ))}
+ ) : (
+
+
+
+
+ Environment
+
+
+ General
+
+
- {data && (
-
-
Path: {data.path}
-
Last modified: {new Date(data.mtime).toLocaleString()}
-
- )}
+
+
+ {currentSettings?.env && Object.keys(currentSettings.env).length > 0 ? (
+
+ {Object.entries(currentSettings.env).map(([key, value]) => (
+
+
+ {isSensitiveKey(key) ? (
+ updateEnvValue(key, e.target.value)}
+ className="font-mono text-sm"
+ />
+ ) : (
+ updateEnvValue(key, e.target.value)}
+ className="font-mono text-sm"
+ />
+ )}
+
+ ))}
+
+ ) : (
+
+
No environment variables configured.
+
Add variables in your settings.json file.
+
+ )}
+
+
-
+
+
+
+ Profile Information
+ Details about this configuration file.
+
+
+ {data && (
+ <>
+
+ Path
+
+ {data.path}
+
+
+
+ Last Modified
+ {new Date(data.mtime).toLocaleString()}
+
+ >
+ )}
+
+
+
+
+
+
@@ -193,16 +249,12 @@ function SettingsDialogContent({
>
) : (
<>
- Save
+ Save Changes
>
)}
- ) : (
-
- No environment variables configured for this profile.
-
)}
-
+
{/* Key prop ensures fresh state on each open */}
{open && profileName && (
,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+ {children}
+
+
+
+
+));
+ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
+
+const ScrollBar = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, orientation = 'vertical', ...props }, ref) => (
+
+
+
+));
+ScrollBar.displayName = ScrollAreaPrimitive.Scrollbar.displayName;
+
+export { ScrollArea, ScrollBar };
diff --git a/ui/src/components/ui/tabs.tsx b/ui/src/components/ui/tabs.tsx
new file mode 100644
index 00000000..afd72a42
--- /dev/null
+++ b/ui/src/components/ui/tabs.tsx
@@ -0,0 +1,53 @@
+import * as React from 'react';
+import * as TabsPrimitive from '@radix-ui/react-tabs';
+
+import { cn } from '@/lib/utils';
+
+const Tabs = TabsPrimitive.Root;
+
+const TabsList = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsList.displayName = TabsPrimitive.List.displayName;
+
+const TabsTrigger = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+
+const TabsContent = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/ui/src/index.css b/ui/src/index.css
index 6cae9b14..62db957d 100644
--- a/ui/src/index.css
+++ b/ui/src/index.css
@@ -27,6 +27,9 @@
--ring: oklch(0.2 0.02 40); /* Match primary */
--radius: 0.5rem;
+ --popover: oklch(0.9635 0.0067 97.35); /* Match background */
+ --popover-foreground: oklch(0.2 0.02 40); /* Match foreground */
+
/* Sidebar colors - Light */
--sidebar: oklch(0.9635 0.0067 97.35); /* Pampas */
--sidebar-foreground: oklch(0.2 0.02 40);
@@ -63,6 +66,9 @@
--ring: oklch(0.9635 0.0067 97.35);
+ --popover: oklch(0.21 0.006 100); /* Match dark bg */
+ --popover-foreground: oklch(0.9635 0.0067 97.35); /* Match dark fg */
+
/* Sidebar Dark Theme */
--sidebar: oklch(0.21 0.006 100); /* Match bg */
--sidebar-foreground: oklch(0.9635 0.0067 97.35);
diff --git a/ui/src/pages/api.tsx b/ui/src/pages/api.tsx
index a68df835..101586a5 100644
--- a/ui/src/pages/api.tsx
+++ b/ui/src/pages/api.tsx
@@ -19,11 +19,6 @@ export function ApiPage() {
const [settingsProfileName, setSettingsProfileName] = useState(null);
const { data, isLoading } = useProfiles();
- const handleEdit = (profile: Profile) => {
- setEditingProfile(profile);
- setDialogOpen(true);
- };
-
const handleEditSettings = (profile: Profile) => {
setSettingsProfileName(profile.name);
setSettingsDialogOpen(true);
@@ -57,11 +52,7 @@ export function ApiPage() {
{isLoading ? (
Loading profiles...
) : (
-
+
)}