Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 42 additions & 44 deletions src/renderer/components/shared/settings/SettingsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
Expand Down Expand Up @@ -67,65 +66,64 @@ export const SettingsModal = () => {
<FiSettings className="ml-2 text-xl" />
</DialogTrigger>

<DialogContent className="flex h-[80vh] max-w-4xl flex-col p-0 lg:max-w-5xl">
<div className="flex h-full flex-col">
<DialogContent className="border-border bg-background-secondary text-foreground flex h-[82vh] max-w-5xl flex-col overflow-hidden border p-0 shadow-lg">
<Tabs defaultValue="variables" className="flex min-h-0 flex-1 flex-col">
{/* Header - Fixed */}
<div className="shrink-0 px-4 pt-4">
<div className="border-border bg-background-secondary shrink-0 border-b px-6 pt-5 pb-3">
<DialogHeader>
<DialogTitle className="font-bold">Collection Settings</DialogTitle>
<DialogTitle className="text-foreground text-[20px] font-bold">
Collection Settings
</DialogTitle>
</DialogHeader>
<TabsList className="mt-5 flex gap-3 bg-transparent p-0">
<TabsTrigger
value="variables"
className="text-muted-foreground data-[state=active]:bg-accent-tertiary data-[state=active]:text-accent-primary rounded-full px-4 py-2.5 text-[14px] font-medium transition-all data-[state=active]:shadow-none"
>
Variables
</TabsTrigger>
<TabsTrigger
value="environments"
className="text-muted-foreground data-[state=active]:bg-accent-tertiary data-[state=active]:text-accent-primary rounded-full px-4 py-2.5 text-[14px] font-medium transition-all data-[state=active]:shadow-none"
>
Environments
</TabsTrigger>
</TabsList>
</div>

{/* Tabs - Takes remaining space */}
<Tabs defaultValue="variables" className="flex min-h-0 flex-1 flex-col">
<div className="shrink-0 px-4 py-4">
<TabsList className="bg-background">
<TabsTrigger value="variables" className="font-light!">
Variables
</TabsTrigger>
<TabsTrigger value="environments" className="font-light!">
Environments
</TabsTrigger>
</TabsList>
</div>

<TabsContent value="variables" className="m-0 min-h-0 flex-1 p-0">
<div className="h-full overflow-y-auto p-4">
<VariableEditor
variables={editorVariables}
onValidChange={setValid}
onVariablesChange={setEditorVariables}
/>
</div>
</TabsContent>
<TabsContent value="variables" className="m-0 min-h-0 flex-1 p-0">
<div className="bg-background-primary h-full overflow-x-hidden overflow-y-auto px-6 pt-4 pb-6">
<VariableEditor
variables={editorVariables}
onValidChange={setValid}
onVariablesChange={setEditorVariables}
/>
</div>
</TabsContent>

<TabsContent value="environments" className="m-0 min-h-0 flex-1 p-0">
<TabsContent value="environments" className="m-0 min-h-0 flex-1 p-0">
<div className="bg-background-primary h-full overflow-x-hidden overflow-y-auto px-6 pt-4 pb-6">
<EnvironmentEditor
environments={editorEnvironments}
selectedEnvironment={editorSelectedEnvironment}
onEnvironmentsChange={setEditorEnvironments}
onEnvironmentSelect={setEditorSelectedEnvironment}
onValidChange={setEnvironmentValid}
/>
</TabsContent>
</Tabs>

{/* Footer - Fixed */}
<DialogFooter className="shrink-0 p-4">
<div className="flex gap-2">
<Button onClick={() => setOpen(false)} variant="outline">
<span className="leading-4 font-bold">Cancel</span>
</Button>
<Button
onClick={save}
disabled={!isOverallValid}
variant={isOverallValid ? 'default' : 'defaultDisable'}
>
<span className="leading-4 font-bold">Save</span>
</Button>
</div>
</DialogFooter>
</div>
</TabsContent>
<div className="bg-background-primary flex shrink-0 justify-end px-6 pt-4 pb-6">
<Button
onClick={save}
disabled={!isOverallValid}
className="h-12.5 px-5 text-[14px] font-semibold transition-all active:scale-[0.98]"
>
Save
</Button>
</div>
</Tabs>
</DialogContent>
</Dialog>
);
Expand Down
148 changes: 81 additions & 67 deletions src/renderer/components/shared/settings/VariableTab/VariableEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,83 +76,97 @@ export const VariableEditor = memo<VariableEditorProps>(
};

return (
<>
<div className="w-full min-w-0">
<Button
className="h-fit gap-1 pl-0 hover:bg-transparent"
className="text-text-primary hover:text-text-secondary flex h-9 items-center gap-2 pl-0 hover:bg-transparent"
size="sm"
variant="ghost"
onClick={add}
>
<AddIcon /> Add Variable
<AddIcon className="h-4 w-4" />
<span className="text-[15px] font-medium">Add Variable</span>
</Button>

<Divider className="mb-4" />

<Table className="w-full table-auto">
<TableHeader>
<TableRow>
<TableHead className="w-1/5">Key</TableHead>
<TableHead className="w-1/4">Value</TableHead>
<TableHead className="w-auto">Description</TableHead>
<TableHead className="w-20">Secret</TableHead>
<TableHead className="w-16">{/* Action Column */}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{variables.map((variable, index) => (
<TableRow key={index}>
<TableCell className="break-all">
<input
type="text"
value={variable.key}
className={cn('w-full bg-transparent outline-hidden', {
'text-danger': invalidVariableKeys.has(variable.key),
})}
placeholder="Enter variable key"
onChange={(e) => update(index, { key: e.target.value })}
/>
</TableCell>
<TableCell className="break-all">
<SecretInput
secret={variable.secret}
value={variable.value}
className={cn('w-full border-none bg-transparent outline-hidden', {
'text-danger': invalidVariableKeys.has(variable.key),
})}
placeholder="Enter variable value"
onChange={(e) => update(index, { value: e.target.value })}
/>
</TableCell>
<TableCell className="break-all">
<input
type="text"
value={variable.description}
className="w-full bg-transparent outline-hidden"
placeholder="Enter variable description"
onChange={(e) => update(index, { description: e.target.value })}
/>
</TableCell>
<TableCell className="text-center">
<Checkbox
checked={variable.secret}
onCheckedChange={(checked) => update(index, { secret: Boolean(checked) })}
/>
</TableCell>
<TableCell className="py-2 text-center">
<Button
variant="ghost"
size="icon"
className="hover:text-accent-primary active:text-accent-secondary w-5 hover:bg-transparent"
onClick={() => remove(index)}
>
<Trash2 />
</Button>
</TableCell>
<div className="border-border bg-background mt-1 overflow-hidden rounded-xl border">
<Table className="w-full table-auto border-collapse">
<TableHeader className="[&_tr]:border-0">
<TableRow className="hover:bg-background">
<TableHead className="text-text-primary w-1/5 border-r border-b py-3 text-[14px] font-medium">
Key
</TableHead>
<TableHead className="text-text-primary w-1/4 border-r border-b text-[14px] font-medium">
Value
</TableHead>
<TableHead className="text-text-primary w-auto border-r border-b text-[14px] font-medium">
Description
</TableHead>
<TableHead className="text-text-primary w-24 border-r border-b text-center text-[14px] font-medium">
Secret
</TableHead>
<TableHead className="w-14 border-b">{/* Action Column */}</TableHead>
</TableRow>
))}
</TableBody>
</Table>
</>
</TableHeader>
<TableBody>
{variables.map((variable, index) => (
<TableRow
key={index}
className="hover:bg-background-secondary border-b transition-colors last:border-0"
>
<TableCell className="border-r px-4">
<input
type="text"
value={variable.key}
className={cn(
'placeholder:text-text-secondary text-text-primary w-full bg-transparent py-3 text-[14px] outline-none',
invalidVariableKeys.has(variable.key) && 'text-destructive'
)}
placeholder="Enter variable key"
onChange={(e) => update(index, { key: e.target.value })}
/>
</TableCell>
<TableCell className="border-r px-4">
<SecretInput
secret={variable.secret}
value={variable.value}
className="placeholder:text-text-secondary text-text-primary w-full border-none bg-transparent py-3 text-[14px] outline-none"
placeholder="Enter variable value"
onChange={(e) => update(index, { value: e.target.value })}
/>
</TableCell>
<TableCell className="border-r px-4">
<input
type="text"
value={variable.description}
className="text-text-primary placeholder:text-text-secondary w-full bg-transparent py-3 text-[14px] outline-none"
placeholder="Enter variable description"
onChange={(e) => update(index, { description: e.target.value })}
/>
</TableCell>
<TableCell className="border-r py-3 text-center">
<Checkbox
className="border-text-secondary hover:border-text-primary data-[state=checked]:border-text-secondary data-[state=checked]:bg-text-secondary cursor-pointer transition-colors"
checked={variable.secret}
onCheckedChange={(checked) => update(index, { secret: Boolean(checked) })}
/>
</TableCell>
<TableCell className="text-center">
<Button
variant="ghost"
size="icon"
className="text-text-secondary hover:text-destructive transition-colors hover:bg-transparent"
onClick={() => remove(index)}
>
<Trash2 size={18} />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
}
);
27 changes: 19 additions & 8 deletions src/renderer/components/ui/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import { cn } from '@/lib/utils';

const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
({ className, ...props }, ref) => (
<div className={`relative rounded-(--radius) border`}>
<table ref={ref} className={cn('w-full caption-bottom text-sm', className)} {...props} />
<div className="relative w-full overflow-hidden">
<table
ref={ref}
className={cn('w-full caption-bottom border-collapse text-sm', className)}
{...props}
/>
</div>
)
);
Expand All @@ -15,15 +19,19 @@ const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />
<thead ref={ref} className={cn('[&_tr]:border-none', className)} {...props} />
));
TableHeader.displayName = 'TableHeader';

const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />
<tbody
ref={ref}
className={cn('bg-background [&_tr:last-child]:border-0', className)}
{...props}
/>
));
TableBody.displayName = 'TableBody';

Expand All @@ -33,7 +41,10 @@ const TableFooter = React.forwardRef<
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn('bg-muted/50 border-t font-medium last:[&>tr]:border-b-0', className)}
className={cn(
'border-border bg-background-primary border-t font-medium last:[&>tr]:border-b-0',
className
)}
{...props}
/>
));
Expand All @@ -44,7 +55,7 @@ const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTML
<tr
ref={ref}
className={cn(
'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
'bg-background hover:bg-background-secondary data-[state=selected]:bg-background-secondary transition-colors duration-100',
className
)}
{...props}
Expand All @@ -60,7 +71,7 @@ const TableHead = React.forwardRef<
<th
ref={ref}
className={cn(
'border-border text-muted-foreground h-12 px-4 text-left align-middle font-medium not-last:border-r [&:has([role=checkbox])]:pr-0',
'border-border bg-background text-foreground h-11 border-b px-4 text-left align-middle font-semibold',
className
)}
{...props}
Expand All @@ -75,7 +86,7 @@ const TableCell = React.forwardRef<
<td
ref={ref}
className={cn(
'overflow-wrap break-word border-border p-4 align-middle break-all not-last:border-r',
'border-border bg-background text-secondary border-r-border border-b px-4 py-3 align-middle break-all not-last:border-r',
className
)}
{...props}
Expand Down