styles: settings v2 (#2103)

This commit is contained in:
Nahiyan Khan
2025-04-09 10:09:00 -04:00
committed by GitHub
parent 2c483a8146
commit 4b86900f47
23 changed files with 154 additions and 153 deletions

View File

@@ -62,7 +62,7 @@ export default function Modal({
return ( return (
<div <div
className="fixed inset-0 bg-black/20 dark:bg-white/20 backdrop-blur-sm transition-colors animate-[fadein_200ms_ease-in_forwards] flex items-center justify-center p-4 z-[9999]" className="fixed inset-0 bg-black/30 dark:bg-white/20 transition-colors animate-[fadein_200ms_ease-in_forwards] flex items-center justify-center p-4 z-[9999]"
onClick={handleBackdropClick} onClick={handleBackdropClick}
style={{ isolation: 'isolate' }} /* Creates a new stacking context */ style={{ isolation: 'isolate' }} /* Creates a new stacking context */
> >

View File

@@ -3,8 +3,7 @@ import { Card } from '../../ui/card';
import { Button } from '../../ui/button'; import { Button } from '../../ui/button';
import { Input } from '../../ui/input'; import { Input } from '../../ui/input';
import { FullExtensionConfig, DEFAULT_EXTENSION_TIMEOUT } from '../../../extensions'; import { FullExtensionConfig, DEFAULT_EXTENSION_TIMEOUT } from '../../../extensions';
import { toast } from 'react-toastify'; import { Select } from '../../ui/Select';
import Select from 'react-select';
import { createDarkSelectStyles, darkSelectTheme } from '../../ui/select-styles'; import { createDarkSelectStyles, darkSelectTheme } from '../../ui/select-styles';
import { getApiUrl, getSecretKey } from '../../../config'; import { getApiUrl, getSecretKey } from '../../../config';
import { toastError } from '../../../toasts'; import { toastError } from '../../../toasts';
@@ -147,8 +146,6 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
onChange={(option) => onChange={(option) =>
setFormData({ ...formData, type: option?.value as FullExtensionConfig['type'] }) setFormData({ ...formData, type: option?.value as FullExtensionConfig['type'] })
} }
styles={createDarkSelectStyles()}
theme={darkSelectTheme}
/> />
</div> </div>

View File

@@ -22,13 +22,14 @@ export default function SettingsView({
viewOptions: SettingsViewOptions; viewOptions: SettingsViewOptions;
}) { }) {
return ( return (
<div className="h-screen w-full"> <div className="h-screen w-full animate-[fadein_200ms_ease-in_forwards]">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div> <div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<ScrollArea className="h-full w-full"> <ScrollArea className="h-full w-full">
<div className="flex flex-col pb-24"> <div className="flex flex-col pb-24">
<div className="px-8 pt-6 pb-4"> <div className="px-8 pt-6 pb-4">
<BackButton onClick={() => onClose()} /> <BackButton onClick={() => onClose()} />
<h1 className="text-3xl font-medium text-textStandard mt-1">Settings</h1>
</div> </div>
{/* Content Area */} {/* Content Area */}

View File

@@ -113,11 +113,11 @@ export default function ExtensionsSection() {
}; };
return ( return (
<section id="extensions"> <section id="extensions" className="px-8">
<div className="flex justify-between items-center mb-6 px-8"> <div className="flex justify-between items-center mb-2">
<h1 className="text-3xl font-medium text-textStandard">Extensions</h1> <h2 className="text-xl font-medium text-textStandard">Extensions</h2>
</div> </div>
<div className="px-8"> <div className="border-b border-borderSubtle pb-8">
<p className="text-sm text-textStandard mb-6"> <p className="text-sm text-textStandard mb-6">
These extensions use the Model Context Protocol (MCP). They can expand Goose's These extensions use the Model Context Protocol (MCP). They can expand Goose's
capabilities using three main components: Prompts, Resources, and Tools. capabilities using three main components: Prompts, Resources, and Tools.
@@ -131,46 +131,46 @@ export default function ExtensionsSection() {
<div className="flex gap-4 pt-4 w-full"> <div className="flex gap-4 pt-4 w-full">
<Button <Button
className="flex items-center gap-2 flex-1 justify-center text-white dark:text-textSubtle bg-black dark:bg-white hover:bg-subtle" className="flex items-center gap-2 justify-center text-white dark:text-textSubtle bg-bgAppInverse hover:bg-bgStandardInverse [&>svg]:!size-4"
onClick={() => setIsAddModalOpen(true)} onClick={() => setIsAddModalOpen(true)}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
Add custom extension Add custom extension
</Button> </Button>
<Button <Button
className="flex items-center gap-2 flex-1 justify-center text-textSubtle bg-white dark:bg-black hover:bg-subtle dark:border dark:border-gray-500 dark:hover:border-gray-400" className="flex items-center gap-2 justify-center text-textStandard bg-bgApp border border-borderSubtle hover:border-borderProminent hover:bg-bgApp [&>svg]:!size-4"
onClick={() => window.open('https://block.github.io/goose/v1/extensions/', '_blank')} onClick={() => window.open('https://block.github.io/goose/v1/extensions/', '_blank')}
> >
<GPSIcon size={18} /> <GPSIcon size={12} />
Visit Extensions Browse extensions
</Button> </Button>
</div> </div>
{/* Modal for updating an existing extension */}
{isModalOpen && selectedExtension && (
<ExtensionModal
title="Update Extension"
initialData={extensionToFormData(selectedExtension)}
onClose={handleModalClose}
onSubmit={handleUpdateExtension}
onDelete={handleDeleteExtension}
submitLabel="Save Changes"
modalType={'edit'}
/>
)}
{/* Modal for adding a new extension */}
{isAddModalOpen && (
<ExtensionModal
title="Add custom extension"
initialData={getDefaultFormData()}
onClose={handleModalClose}
onSubmit={handleAddExtension}
submitLabel="Add Extension"
modalType={'add'}
/>
)}
</div> </div>
{/* Modal for updating an existing extension */}
{isModalOpen && selectedExtension && (
<ExtensionModal
title="Update Extension"
initialData={extensionToFormData(selectedExtension)}
onClose={handleModalClose}
onSubmit={handleUpdateExtension}
onDelete={handleDeleteExtension}
submitLabel="Save Changes"
modalType={'edit'}
/>
)}
{/* Modal for adding a new extension */}
{isAddModalOpen && (
<ExtensionModal
title="Add New Extension"
initialData={getDefaultFormData()}
onClose={handleModalClose}
onSubmit={handleAddExtension}
submitLabel="Add Extension"
modalType={'add'}
/>
)}
</section> </section>
); );
} }

View File

@@ -74,7 +74,7 @@ export default function EnvVarsSection({
<label className="text-sm font-medium text-textStandard mb-2 block"> <label className="text-sm font-medium text-textStandard mb-2 block">
Environment Variables Environment Variables
</label> </label>
<p className="text-xs text-textSubtle mb-2"> <p className="text-xs text-textSubtle mb-4">
Add key-value pairs for environment variables. Click the "+" button to add after filling Add key-value pairs for environment variables. Click the "+" button to add after filling
both fields. both fields.
</p> </p>
@@ -89,7 +89,7 @@ export default function EnvVarsSection({
onChange={(e) => onChange(index, 'key', e.target.value)} onChange={(e) => onChange(index, 'key', e.target.value)}
placeholder="Variable name" placeholder="Variable name"
className={cn( className={cn(
'w-full border-borderSubtle text-textStandard', 'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
isFieldInvalid(index, 'key') && 'border-red-500 focus:border-red-500' isFieldInvalid(index, 'key') && 'border-red-500 focus:border-red-500'
)} )}
/> />
@@ -100,7 +100,7 @@ export default function EnvVarsSection({
onChange={(e) => onChange(index, 'value', e.target.value)} onChange={(e) => onChange(index, 'value', e.target.value)}
placeholder="Value" placeholder="Value"
className={cn( className={cn(
'w-full border-borderSubtle text-textStandard', 'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
isFieldInvalid(index, 'value') && 'border-red-500 focus:border-red-500' isFieldInvalid(index, 'value') && 'border-red-500 focus:border-red-500'
)} )}
/> />
@@ -124,7 +124,7 @@ export default function EnvVarsSection({
}} }}
placeholder="Variable name" placeholder="Variable name"
className={cn( className={cn(
'w-full border-borderStandard text-textStandard', 'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
invalidFields.key && 'border-red-500 focus:border-red-500' invalidFields.key && 'border-red-500 focus:border-red-500'
)} )}
/> />
@@ -136,16 +136,16 @@ export default function EnvVarsSection({
}} }}
placeholder="Value" placeholder="Value"
className={cn( className={cn(
'w-full border-borderStandard text-textStandard', 'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
invalidFields.value && 'border-red-500 focus:border-red-500' invalidFields.value && 'border-red-500 focus:border-red-500'
)} )}
/> />
<Button <Button
onClick={handleAdd} onClick={handleAdd}
variant="ghost" variant="ghost"
className="flex items-center justify-start gap-1 px-2 pr-4 text-s font-medium rounded-full dark:bg-slate-400 dark:text-gray-300 bg-gray-300 dark:bg-slate text-slate-400 dark:hover:bg-slate-300 hover:bg-gray-500 hover:text-white dark:hover:text-gray-900 transition-colors min-w-[60px] h-9" className="flex items-center justify-start gap-1 px-2 pr-4 text-sm rounded-full text-textStandard bg-bgApp border border-borderSubtle hover:border-borderStandard transition-colors min-w-[60px] h-9 [&>svg]:!size-4"
> >
<Plus className="h-3 w-3" /> Add <Plus /> Add
</Button> </Button>
</div> </div>
{validationError && <div className="mt-2 text-red-500 text-sm">{validationError}</div>} {validationError && <div className="mt-2 text-red-500 text-sm">{validationError}</div>}

View File

@@ -1,5 +1,5 @@
import { Input } from '../../../ui/input'; import { Input } from '../../../ui/input';
import Select from 'react-select'; import { Select } from '../../../ui/Select';
import React, { useState } from 'react'; import React, { useState } from 'react';
interface ExtensionInfoFieldsProps { interface ExtensionInfoFieldsProps {

View File

@@ -131,7 +131,7 @@ export default function ExtensionModal({
<> <>
<div className="w-full px-6 py-4 bg-red-900/20 border-t border-red-500/30"> <div className="w-full px-6 py-4 bg-red-900/20 border-t border-red-500/30">
<p className="text-red-400 text-sm mb-2"> <p className="text-red-400 text-sm mb-2">
Are you sure you want to delete "{formData.name}"? This action cannot be undone. Are you sure you want to remove "{formData.name}"? This action cannot be undone.
</p> </p>
</div> </div>
<Button <Button
@@ -143,7 +143,7 @@ export default function ExtensionModal({
}} }}
className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-red-900/20 text-red-500 font-medium text-md" className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-red-900/20 text-red-500 font-medium text-md"
> >
<Trash2 className="h-4 w-4 mr-2" /> Confirm Delete <Trash2 className="h-4 w-4 mr-2" /> Confirm removal
</Button> </Button>
<Button <Button
onClick={() => setShowDeleteConfirmation(false)} onClick={() => setShowDeleteConfirmation(false)}
@@ -159,9 +159,9 @@ export default function ExtensionModal({
{modalType === 'edit' && onDelete && ( {modalType === 'edit' && onDelete && (
<Button <Button
onClick={() => setShowDeleteConfirmation(true)} onClick={() => setShowDeleteConfirmation(true)}
className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-bgSubtle text-red-500 font-medium text-md" className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-bgSubtle text-red-500 font-medium text-md [&>svg]:!size-4"
> >
<Trash2 className="h-4 w-4 mr-2" /> Delete Extension <Trash2 className="h-4 w-4 mr-2" /> Remove extension
</Button> </Button>
)} )}
<Button <Button

View File

@@ -29,25 +29,20 @@ export default function ExtensionTimeoutField({
return ( return (
<div className="flex flex-col gap-4 mb-6"> <div className="flex flex-col gap-4 mb-6">
{/* Row with Timeout and timeout input side by side */} {/* Row with Timeout and timeout input side by side */}
<div className="flex justify-between gap-4"> <div className="flex flex-col">
<div className="flex-1"> <div className="flex-1">
<label className="text-sm font-medium mb-2 block text-textStandard">Timeout</label> <label className="text-sm font-medium mb-2 block text-textStandard">Timeout</label>
</div> </div>
{/* Type Dropdown */} <Input
<div className="w-[200px]"> value={timeout}
<div className="relative"> onChange={(e) => onChange('timeout', e.target.value)}
<Input defaultValue={300}
value={timeout} className={`${!submitAttempted || isTimeoutValid() ? 'border-borderSubtle' : 'border-red-500'} text-textStandard focus:border-borderStandard`}
onChange={(e) => onChange('timeout', e.target.value)} />
defaultValue={300} {submitAttempted && !isTimeoutValid() && (
className={`${!submitAttempted || isTimeoutValid() ? 'border-borderSubtle' : 'border-red-500'} text-textStandard focus:border-borderStandard`} <div className="absolute text-xs text-red-500 mt-1">Timeout </div>
/> )}
{submitAttempted && !isTimeoutValid() && (
<div className="absolute text-xs text-red-500 mt-1">Timeout </div>
)}
</div>
</div>
</div> </div>
</div> </div>
); );

View File

@@ -57,27 +57,34 @@ export default function ExtensionItem({ extension, onToggle, onConfigure }: Exte
}; };
return ( return (
<div className="rounded-lg border border-borderSubtle p-4 mb-2"> <div
<div className="flex items-center justify-between mb-2"> className="flex justify-between rounded-lg transition-colors border border-borderSubtle p-4 pt-3 hover:border-borderProminent hover:cursor-pointer"
<h3 className="font-medium text-textStandard">{getFriendlyTitle(extension)}</h3> onClick={() => handleToggle(extension)}
<div className="flex items-center gap-2"> >
{/* Only show config button for non-builtin extensions */} <div className="flex flex-col w-max-[90%]">
{extension.type !== 'builtin' && ( <h3 className="text-textStandard">{getFriendlyTitle(extension)}</h3>
<button <p className="text-xs text-textSubtle">{renderFormattedSubtitle()}</p>
className="text-textSubtle hover:text-textStandard" </div>
onClick={() => onConfigure(extension)}
> <div
<Gear className="h-4 w-4" /> className="flex items-center justify-end gap-2 w-max-[10%]"
</button> onClick={(e) => e.stopPropagation()}
)} >
<Switch {/* Only show config button for non-builtin extensions */}
checked={(isToggling && visuallyEnabled) || extension.enabled} {extension.type !== 'builtin' && (
onCheckedChange={() => handleToggle(extension)} <button
variant="mono" className="text-textSubtle hover:text-textStandard"
/> onClick={() => onConfigure(extension)}
</div> >
<Gear className="h-4 w-4" />
</button>
)}
<Switch
checked={(isToggling && visuallyEnabled) || extension.enabled}
onCheckedChange={() => handleToggle(extension)}
variant="mono"
/>
</div> </div>
<p className="text-sm text-textSubtle">{renderFormattedSubtitle()}</p>
</div> </div>
); );
} }

View File

@@ -13,7 +13,7 @@ interface ExtensionListProps {
export default function ExtensionList({ extensions, onToggle, onConfigure }: ExtensionListProps) { export default function ExtensionList({ extensions, onToggle, onConfigure }: ExtensionListProps) {
return ( return (
<div className="grid grid-cols-2 gap-6"> <div className="grid grid-cols-2 gap-2 mb-2">
{extensions.map((extension) => ( {extensions.map((extension) => (
<ExtensionItem <ExtensionItem
key={extension.name} key={extension.name}

View File

@@ -17,12 +17,12 @@ export function ConfigureApproveMode({
const approveModes: GooseMode[] = [ const approveModes: GooseMode[] = [
{ {
key: 'approve', key: 'approve',
label: 'Manual Approval', label: 'Manual approval',
description: 'All tools, extensions and file modifications will require human approval', description: 'All tools, extensions and file modifications will require human approval',
}, },
{ {
key: 'smart_approve', key: 'smart_approve',
label: 'Smart Approval', label: 'Smart approval',
description: 'Intelligently determine which actions need approval based on risk level ', description: 'Intelligently determine which actions need approval based on risk level ',
}, },
]; ];
@@ -49,18 +49,16 @@ export function ConfigureApproveMode({
}; };
return ( return (
<div className="fixed inset-0 bg-black/20 backdrop-blur-sm"> <div className="fixed inset-0 bg-black/30">
<Card className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[440px] bg-white dark:bg-gray-800 rounded-xl shadow-xl overflow-hidden p-[16px] pt-[24px] pb-0"> <Card className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[440px] bg-bgApp rounded-xl overflow-hidden p-[16px] pt-[24px] pb-0">
<div className="px-4 pb-0 space-y-6"> <div className="px-4 pb-0 space-y-6">
{/* Header */} {/* Header */}
<div className="flex"> <div className="flex">
<h2 className="text-2xl font-regular dark:text-white text-gray-900"> <h2 className="text-2xl font-regular text-textStandard">Configure approve mode</h2>
Configure Approve Mode
</h2>
</div> </div>
<div className="mt-[24px]"> <div className="mt-[24px]">
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6"> <p className="text-sm text-textSubtle mb-6">
Approve requests can either be given to all tool requests or determine which actions Approve requests can either be given to all tool requests or determine which actions
may need integration may need integration
</p> </p>
@@ -81,22 +79,22 @@ export function ConfigureApproveMode({
</div> </div>
{/* Actions */} {/* Actions */}
<div className="mt-[8px] ml-[-24px] mr-[-24px] pt-[16px]"> <div className="mt-[8px] ml-[-32px] mr-[-32px] pt-[16px]">
<Button <Button
type="submit" type="submit"
variant="ghost" variant="ghost"
disabled={isSubmitting} disabled={isSubmitting}
onClick={handleModeSubmit} onClick={handleModeSubmit}
className="w-full h-[60px] rounded-none border-t dark:border-gray-600 text-lg hover:bg-gray-50 hover:dark:text-black dark:text-white dark:border-gray-600 font-regular" className="w-full h-[60px] rounded-none border-t border-borderSubtle hover:bg-bgSubtle text-textStandard dark:border-gray-600 text-base font-regular"
> >
{isSubmitting ? 'Saving...' : 'Save Mode'} {isSubmitting ? 'Saving...' : 'Save'}
</Button> </Button>
<Button <Button
type="button" type="button"
variant="ghost" variant="ghost"
disabled={isSubmitting} disabled={isSubmitting}
onClick={onClose} onClick={onClose}
className="w-full h-[60px] rounded-none border-t dark:border-gray-600 text-gray-400 hover:bg-gray-50 dark:border-gray-600 text-lg font-regular" className="w-full h-[60px] rounded-none border-t border-borderSubtle text-textSubtle hover:bg-bgSubtle dark:border-gray-600 text-base font-regular"
> >
Cancel Cancel
</Button> </Button>

View File

@@ -62,11 +62,11 @@ export const ModeSection = () => {
}, []); }, []);
return ( return (
<section id="mode"> <section id="mode" className="px-8">
<div className="flex justify-between items-center mb-6 px-8"> <div className="flex justify-between items-center mb-2">
<h1 className="text-3xl font-medium text-textStandard">Mode</h1> <h2 className="text-xl font-medium text-textStandard">Mode</h2>
</div> </div>
<div className="px-8"> <div className="border-b border-borderSubtle pb-8">
<p className="text-sm text-textStandard mb-6"> <p className="text-sm text-textStandard mb-6">
Configure how Goose interacts with tools and extensions Configure how Goose interacts with tools and extensions
</p> </p>

View File

@@ -11,22 +11,22 @@ export interface GooseMode {
export const all_goose_modes: GooseMode[] = [ export const all_goose_modes: GooseMode[] = [
{ {
key: 'auto', key: 'auto',
label: 'Completely Autonomous', label: 'Completely autonomous',
description: 'Full file modification capabilities, edit, create, and delete files freely.', description: 'Full file modification capabilities, edit, create, and delete files freely.',
}, },
{ {
key: 'approve', key: 'approve',
label: 'Manual Approval', label: 'Manual approval',
description: 'All tools, extensions and file modifications will require human approval', description: 'All tools, extensions and file modifications will require human approval',
}, },
{ {
key: 'smart_approve', key: 'smart_approve',
label: 'Smart Approval', label: 'Smart approval',
description: 'Intelligently determine which actions need approval based on risk level ', description: 'Intelligently determine which actions need approval based on risk level ',
}, },
{ {
key: 'chat', key: 'chat',
label: 'Chat Only', label: 'Chat only',
description: 'Engage with the selected provider without using tools or extensions.', description: 'Engage with the selected provider without using tools or extensions.',
}, },
]; ];
@@ -89,20 +89,23 @@ export function ModeSelectionItem({
}, [currentMode, mode.key]); }, [currentMode, mode.key]);
return ( return (
<div> <div className="group hover:cursor-pointer">
<div <div
className="flex items-center justify-between p-2 text-textStandard hover:bg-bgSubtle transition-colors" className="flex items-center justify-between text-textStandard mb-4"
onClick={() => handleModeChange(mode.key)} onClick={() => handleModeChange(mode.key)}
> >
<div> <div className="flex">
<h3 className="text-sm font-light text-textStandard dark:text-gray-200">{mode.label}</h3> <div>
{showDescription && ( <h3 className="text-textStandard dark:text-gray-200">{mode.label}</h3>
<p className="text-xs text-textSubtle dark:text-gray-400 mt-[2px]"> {showDescription && (
{mode.description} <p className="text-xs text-textSubtle dark:text-gray-400 mt-[2px]">
</p> {mode.description}
)} </p>
)}
</div>
</div> </div>
<div className="relative flex items-center gap-3">
<div className="relative flex items-center gap-3 mr-4">
{!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && ( {!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && (
<button <button
onClick={() => { onClick={() => {
@@ -121,10 +124,10 @@ export function ModeSelectionItem({
className="peer sr-only" className="peer sr-only"
/> />
<div <div
className="h-4 w-4 rounded-full border border-gray-400 dark:border-gray-500 className="h-4 w-4 rounded-full border border-borderStandard
peer-checked:border-[6px] peer-checked:border-black dark:peer-checked:border-white peer-checked:border-[6px] peer-checked:border-black dark:peer-checked:border-white
peer-checked:bg-white dark:peer-checked:bg-black peer-checked:bg-white dark:peer-checked:bg-black
transition-all duration-200 ease-in-out" transition-all duration-200 ease-in-out group-hover:border-borderProminent"
></div> ></div>
</div> </div>
</div> </div>

View File

@@ -58,14 +58,14 @@ export default function ModelsSection({ setView }: ModelsSectionProps) {
}, []); }, []);
return ( return (
<section id="models"> <section id="models" className="px-8">
<div className="flex justify-between items-center mb-6 px-8"> <div className="flex justify-between items-center mb-4">
<h1 className="text-3xl font-medium text-textStandard">Models</h1> <h2 className="text-xl font-medium text-textStandard">Models</h2>
</div> </div>
<div className="px-8"> <div className="border-b border-borderSubtle pb-8">
<div className="space-y-2"> <div className="">
<h3 className="font-medium text-textStandard">{model}</h3> <h3 className="text-textStandard">{model}</h3>
<h4 className="font-medium text-textSubtle">{provider}</h4> <h4 className="text-xs text-textSubtle">{provider}</h4>
</div> </div>
<ModelSettingsButtons setView={setView} /> <ModelSettingsButtons setView={setView} />
</div> </div>

View File

@@ -1,8 +1,8 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Button } from '../../../ui/button'; import { Button } from '../../../ui/button';
import { AddModelModal } from './AddModelModal'; import { AddModelModal } from './AddModelModal';
import { Gear } from '../../../icons';
import type { View } from '../../../../App'; import type { View } from '../../../../App';
import { ArrowLeftRight } from 'lucide-react';
interface AddModelButtonProps { interface AddModelButtonProps {
setView: (view: View) => void; setView: (view: View) => void;
@@ -14,11 +14,11 @@ export const AddModelButton = ({ setView }: AddModelButtonProps) => {
return ( return (
<> <>
<Button <Button
className="flex items-center gap-2 flex-1 justify-center text-white dark:text-textSubtle bg-black dark:bg-white hover:bg-subtle" className="flex items-center gap-2 justify-center text-white dark:text-textSubtle bg-bgAppInverse hover:bg-bgStandardInverse [&>svg]:!size-4"
onClick={() => setIsAddModelModalOpen(true)} onClick={() => setIsAddModelModalOpen(true)}
> >
<Gear className="h-4 w-4" /> <ArrowLeftRight />
Switch Models Switch models
</Button> </Button>
{isAddModelModalOpen ? ( {isAddModelModalOpen ? (
<AddModelModal setView={setView} onClose={() => setIsAddModelModalOpen(false)} /> <AddModelModal setView={setView} onClose={() => setIsAddModelModalOpen(false)} />

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ExternalLink, Plus } from 'lucide-react'; import { ArrowLeftRight, ExternalLink, Plus } from 'lucide-react';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import { Button } from '../../../ui/button'; import { Button } from '../../../ui/button';
@@ -221,10 +221,10 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
} }
> >
<div className="flex flex-col items-center gap-8"> <div className="flex flex-col items-center gap-8">
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col gap-3">
<Plus size={24} className="text-textStandard" /> <ArrowLeftRight size={24} className="text-textStandard" />
<div className="text-textStandard font-medium text-base">Switch models</div> <div className="text-textStandard font-medium text-base">Switch models</div>
<div className="text-textSubtle text-center text-md"> <div className="text-textSubtle text-md">
Configure your AI model providers by adding their API keys. Your keys are stored Configure your AI model providers by adding their API keys. Your keys are stored
securely and encrypted locally. securely and encrypted locally.
</div> </div>
@@ -233,7 +233,7 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
href={QUICKSTART_GUIDE_URL} href={QUICKSTART_GUIDE_URL}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="flex items-center justify-center text-textStandard font-medium text-sm" className="flex items-center text-textStandard font-medium text-sm"
> >
<ExternalLink size={16} className="mr-1" /> <ExternalLink size={16} className="mr-1" />
View quick start guide View quick start guide

View File

@@ -10,16 +10,16 @@ interface ConfigureModelButtonsProps {
export default function ModelSettingsButtons({ setView }: ConfigureModelButtonsProps) { export default function ModelSettingsButtons({ setView }: ConfigureModelButtonsProps) {
return ( return (
<div className="flex gap-4 pt-4 w-full"> <div className="flex gap-4 pt-4 ">
<AddModelButton setView={setView} /> <AddModelButton setView={setView} />
<Button <Button
className="flex items-center gap-2 flex-1 justify-center text-textSubtle bg-white dark:bg-black hover:bg-subtle dark:border dark:border-gray-500 dark:hover:border-gray-400" className="flex items-center gap-2 justify-center text-textStandard bg-bgApp border border-borderSubtle hover:border-borderProminent hover:bg-bgApp [&>svg]:!size-4"
onClick={() => { onClick={() => {
setView('ConfigureProviders'); setView('ConfigureProviders');
}} }}
> >
<Sliders className="h-4 w-4 rotate-90" /> <Sliders className="rotate-90" />
Configure Providers Configure providers
</Button> </Button>
</div> </div>
); );

View File

@@ -34,7 +34,7 @@ export default function CardContainer({
}: CardContainerProps) { }: CardContainerProps) {
return ( return (
<div <div
className={`relative h-full p-[2px] overflow-hidden rounded-[9px] group/card className={`relative h-full p-[1px] overflow-hidden rounded-[9px] group/card
${ ${
grayedOut grayedOut
? 'bg-borderSubtle hover:bg-gray-700' ? 'bg-borderSubtle hover:bg-gray-700'

View File

@@ -82,8 +82,8 @@ export default function SessionSharingSection() {
return ( return (
<section id="session-sharing"> <section id="session-sharing">
{/*Title*/} {/*Title*/}
<div className="flex justify-between items-center mb-6 px-8"> <div className="flex justify-between items-center mb-2 px-8">
<h1 className="text-3xl font-medium text-textStandard">Session sharing</h1> <h2 className="text-xl font-medium text-textStandard">Session sharing</h2>
</div> </div>
<div className="px-8"> <div className="px-8">
@@ -103,7 +103,7 @@ export default function SessionSharingSection() {
<div className="space-y-4"> <div className="space-y-4">
{/* Toggle for enabling session sharing */} {/* Toggle for enabling session sharing */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<label className="text-sm font-medium text-textStandard cursor-pointer"> <label className="text-textStandard cursor-pointer">
{envBaseUrlShare {envBaseUrlShare
? 'Session sharing has already been configured' ? 'Session sharing has already been configured'
: 'Enable session sharing'} : 'Enable session sharing'}

View File

@@ -32,7 +32,7 @@ const BackButton: React.FC<BackButtonProps> = ({
className={`flex items-center text-${textSize} text-textSubtle group hover:text-textStandard ${className}`} className={`flex items-center text-${textSize} text-textSubtle group hover:text-textStandard ${className}`}
> >
<Back className={`${iconSize} group-hover:-translate-x-1 transition-all mr-1`} /> <Back className={`${iconSize} group-hover:-translate-x-1 transition-all mr-1`} />
{showText && <span>Exit</span>} {showText && <span>Back</span>}
</button> </button>
); );
}; };

View File

@@ -10,12 +10,11 @@ export const Select = (props) => {
container: () => 'w-full cursor-pointer relative z-[99999]', container: () => 'w-full cursor-pointer relative z-[99999]',
indicatorSeparator: () => 'h-0', indicatorSeparator: () => 'h-0',
control: ({ isFocused }) => control: ({ isFocused }) =>
`border-2 ${isFocused ? 'border-borderStandard' : 'border-borderSubtle'} focus:border-borderStandard hover:border-borderStandard rounded-md w-full px-4 py-2.5 text-sm text-textSubtle`, `border ${isFocused ? 'border-borderStandard' : 'border-borderSubtle'} focus:border-borderStandard hover:border-borderStandard rounded-md w-full px-4 py-2 text-sm text-textSubtle hover:cursor-pointer`,
menu: () => menu: () =>
'mt-3 bg-bgStandard shadow-xl rounded-md text-textSubtle overflow-hidden relative z-[99999] select__menu', 'mt-1 bg-bgApp border border-borderStandard rounded-md text-textSubtle overflow-hidden relative z-[99999] select__menu',
menuPortal: () => 'z-[99999] select__menu', menuPortal: () => 'z-[99999] select__menu',
option: () => option: () => 'py-2 px-4 hover:cursor-pointer hover:bg-bgSubtle text-textStandard text-sm',
'py-4 px-4 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 text-textProminent font-medium',
}} }}
menuPortalTarget={document.body} menuPortalTarget={document.body}
styles={{ styles={{

View File

@@ -5,15 +5,15 @@ import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '../../utils'; import { cn } from '../../utils';
const buttonVariants = cva( const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-6 [&_svg]:shrink-0', 'inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-6 [&_svg]:shrink-0',
{ {
variants: { variants: {
variant: { variant: {
default: 'bg-gray-800 text-white rounded-full px-6 py-2 shadow hover:bg-gray-700', default: 'bg-gray-800 text-white rounded-full px-6 py-2 hover:bg-gray-700',
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: outline:
'border border-gray-300 bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', 'border border-gray-300 bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground', ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline', link: 'text-primary underline-offset-4 hover:underline',
}, },

View File

@@ -59,6 +59,7 @@ export default {
borderSubtle: 'var(--border-subtle)', borderSubtle: 'var(--border-subtle)',
borderStandard: 'var(--border-standard)', borderStandard: 'var(--border-standard)',
borderProminent: 'var(--border-prominent)',
textProminent: 'var(--text-prominent)', textProminent: 'var(--text-prominent)',
textStandard: 'var(--text-standard)', textStandard: 'var(--text-standard)',