Bottom and top bar refinement (#2303)

Co-authored-by: Nahiyan Khan <nahiyan@squareup.com>
This commit is contained in:
Zane
2025-05-05 08:48:43 -07:00
committed by GitHub
parent 8ba40bdccc
commit a812d6ff79
26 changed files with 221 additions and 219 deletions

View File

@@ -37,7 +37,7 @@
"express": "^4.21.1",
"framer-motion": "^11.11.11",
"lodash": "^4.17.21",
"lucide-react": "^0.454.0",
"lucide-react": "^0.475.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
@@ -11454,12 +11454,12 @@
}
},
"node_modules/lucide-react": {
"version": "0.454.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.454.0.tgz",
"integrity": "sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==",
"version": "0.475.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.475.0.tgz",
"integrity": "sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/magic-string": {

View File

@@ -109,7 +109,7 @@
"express": "^4.21.1",
"framer-motion": "^11.11.11",
"lodash": "^4.17.21",
"lucide-react": "^0.454.0",
"lucide-react": "^0.475.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",

View File

@@ -1,8 +1,10 @@
import React, { useRef, useState, useEffect, useCallback } from 'react';
import { Button } from './ui/button';
import type { View } from '../App';
import Stop from './ui/Stop';
import { Attach, Send } from './icons';
import { debounce } from 'lodash';
import BottomMenu from './bottom_menu/BottomMenu';
interface InputProps {
handleSubmit: (e: React.FormEvent) => void;
@@ -11,6 +13,8 @@ interface InputProps {
commandHistory?: string[];
initialValue?: string;
droppedFiles?: string[];
setView: (view: View) => void;
numTokens?: number;
}
export default function Input({
@@ -19,10 +23,13 @@ export default function Input({
onStop,
commandHistory = [],
initialValue = '',
setView,
numTokens,
droppedFiles = [],
}: InputProps) {
const [_value, setValue] = useState(initialValue);
const [displayValue, setDisplayValue] = useState(initialValue); // For immediate visual feedback
const [isFocused, setIsFocused] = useState(false);
// Update internal value when initialValue changes
useEffect(() => {
@@ -205,10 +212,14 @@ export default function Input({
};
return (
<form
onSubmit={onFormSubmit}
className="flex relative h-auto px-[16px] pr-[68px] py-[1rem] border-t border-borderSubtle"
<div
className={`flex flex-col relative h-auto border rounded-lg transition-colors ${
isFocused
? 'border-borderProminent hover:border-borderProminent'
: 'border-borderSubtle hover:border-borderStandard'
} bg-bgApp z-10`}
>
<form onSubmit={onFormSubmit}>
<textarea
data-testid="chat-input"
autoFocus
@@ -219,6 +230,8 @@ export default function Input({
onCompositionStart={handleCompositionStart}
onCompositionEnd={handleCompositionEnd}
onKeyDown={handleKeyDown}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
ref={textAreaRef}
rows={1}
style={{
@@ -226,17 +239,9 @@ export default function Input({
maxHeight: `${maxHeight}px`,
overflowY: 'auto',
}}
className="w-full outline-none border-none focus:ring-0 bg-transparent p-0 text-base resize-none text-textStandard"
className="w-full pl-4 pr-[68px] outline-none border-none focus:ring-0 bg-transparent pt-3 pb-1.5 text-sm resize-none text-textStandard"
/>
<Button
type="button"
size="icon"
variant="ghost"
onClick={handleFileSelect}
className="absolute right-[40px] top-1/2 -translate-y-1/2 text-textSubtle hover:text-textStandard"
>
<Attach />
</Button>
{isLoading ? (
<Button
type="button"
@@ -247,7 +252,7 @@ export default function Input({
e.stopPropagation();
onStop?.();
}}
className="absolute right-2 top-1/2 -translate-y-1/2 [&_svg]:size-5 text-textSubtle hover:text-textStandard"
className="absolute right-3 top-2 text-textSubtle rounded-full border border-borderSubtle hover:border-borderStandard hover:text-textStandard w-7 h-7 [&_svg]:size-4"
>
<Stop size={24} />
</Button>
@@ -257,13 +262,32 @@ export default function Input({
size="icon"
variant="ghost"
disabled={!displayValue.trim()}
className={`absolute right-2 top-1/2 -translate-y-1/2 text-textSubtle hover:text-textStandard ${
!displayValue.trim() ? 'text-textSubtle cursor-not-allowed' : ''
className={`absolute right-3 top-2 transition-colors rounded-full hover:cursor w-7 h-7 [&_svg]:size-4 ${
!displayValue.trim()
? 'text-textSubtle cursor-not-allowed'
: 'bg-bgAppInverse text-white'
}`}
>
<Send />
</Button>
)}
</form>
<div className="flex items-center transition-colors text-textSubtle relative text-xs p-2 pr-3 border-t border-borderSubtle gap-2">
<div className="gap-1 flex items-center justify-between w-full">
<Button
type="button"
size="icon"
variant="ghost"
onClick={handleFileSelect}
className="text-textSubtle hover:text-textStandard w-7 h-7 [&_svg]:size-4"
>
<Attach />
</Button>
<BottomMenu setView={setView} numTokens={numTokens} />
</div>
</div>
</div>
);
}

View File

@@ -1,9 +1,7 @@
import React, { useEffect, useRef, useState, useMemo } from 'react';
import { getApiUrl } from '../config';
import BottomMenu from './bottom_menu/BottomMenu';
import FlappyGoose from './FlappyGoose';
import GooseMessage from './GooseMessage';
import Input from './Input';
import { type View, ViewOptions } from '../App';
import LoadingGoose from './LoadingGoose';
import MoreMenuLayout from './more_menu/MoreMenuLayout';
@@ -34,6 +32,7 @@ import {
ToolResponseMessageContent,
ToolConfirmationRequestMessageContent,
} from '../types/message';
import ChatInput from './ChatInput';
export interface ChatType {
id: string;
@@ -469,9 +468,11 @@ function ChatContent({
<div className="flex flex-col w-full h-screen items-center justify-center">
{/* Loader when generating recipe */}
{isGeneratingRecipe && <LayingEggLoader />}
<div className="relative flex items-center h-[36px] w-full">
<MoreMenuLayout setView={setView} setIsGoosehintsModalOpen={setIsGoosehintsModalOpen} />
</div>
<MoreMenuLayout
hasMessages={hasMessages}
setView={setView}
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
/>
<Card
className="flex flex-col flex-1 rounded-none h-[calc(100vh-95px)] w-full bg-bgApp mt-0 border-none relative"
@@ -559,21 +560,23 @@ function ChatContent({
</div>
</div>
)}
<div className="block h-16" />
<div className="block h-8" />
</ScrollArea>
)}
<div className="relative">
<div className="relative p-4 pt-0 z-10 animate-[fadein_400ms_ease-in_forwards]">
{isLoading && <LoadingGoose />}
<Input
<ChatInput
handleSubmit={handleSubmit}
isLoading={isLoading}
onStop={onStopGoose}
commandHistory={commandHistory}
initialValue={_input}
setView={setView}
hasMessages={hasMessages}
numTokens={sessionTokenCount}
droppedFiles={droppedFiles}
/>
<BottomMenu hasMessages={hasMessages} setView={setView} numTokens={sessionTokenCount} />
</div>
</Card>

View File

@@ -6,7 +6,7 @@ const LoadingGoose = () => {
<div className="w-full pb-[2px]">
<div
data-testid="loading-indicator"
className="flex items-center text-xs text-textStandard mb-2 mt-2 pl-4 animate-[appear_250ms_ease-in_forwards]"
className="flex items-center text-xs text-textStandard mb-2 mt-2 animate-[appear_250ms_ease-in_forwards]"
>
<GooseLogo className="mr-2" size="small" hover={false} />
goose is working on it

View File

@@ -3,6 +3,7 @@ import { ProviderGrid } from './ProviderGrid';
import { ScrollArea } from './ui/scroll-area';
import { Button } from './ui/button';
import WelcomeGooseLogo from './WelcomeGooseLogo';
import MoreMenuLayout from './more_menu/MoreMenuLayout';
// Extending React CSSProperties to include custom webkit property
declare module 'react' {
@@ -18,11 +19,7 @@ interface WelcomeScreenProps {
export default function WelcomeScreen({ onSubmit }: WelcomeScreenProps) {
return (
<div className="h-screen w-full select-none bg-white dark:bg-black">
{/* Draggable title bar region */}
<div
className="relative flex items-center h-[36px] w-full bg-bgSubtle"
style={{ WebkitAppRegion: 'drag' }}
></div>
<MoreMenuLayout showMenu={false} />
{/* Content area - explicitly set as non-draggable */}
<div

View File

@@ -5,25 +5,22 @@ import { AlertType, useAlerts } from '../alerts';
import { useToolCount } from '../alerts/useToolCount';
import BottomMenuAlertPopover from './BottomMenuAlertPopover';
import { ModelRadioList } from '../settings/models/ModelRadioList';
import { Document, ChevronUp, ChevronDown } from '../icons';
import { ChevronUp, ChevronDown } from '../icons';
import type { View, ViewOptions } from '../../App';
import { settingsV2Enabled } from '../../flags';
import { BottomMenuModeSelection } from './BottomMenuModeSelection';
import ModelsBottomBar from '../settings_v2/models/bottom_bar/ModelsBottomBar';
import { useConfig } from '../ConfigContext';
import { getCurrentModelAndProvider } from '../settings_v2/models';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/Tooltip';
const TOKEN_LIMIT_DEFAULT = 128000; // fallback for custom models that the backend doesn't know about
const TOKEN_WARNING_THRESHOLD = 0.8; // warning shows at 80% of the token limit
const TOOLS_MAX_SUGGESTED = 60; // max number of tools before we show a warning
export default function BottomMenu({
hasMessages,
setView,
numTokens = 0,
}: {
hasMessages: boolean;
setView: (view: View, viewOptions?: ViewOptions) => void;
numTokens?: number;
}) {
@@ -34,10 +31,6 @@ export default function BottomMenu({
const toolCount = useToolCount();
const { getProviders, read } = useConfig();
const [tokenLimit, setTokenLimit] = useState<number>(TOKEN_LIMIT_DEFAULT);
const [isDirTruncated, setIsDirTruncated] = useState(false);
// eslint-disable-next-line no-undef
const dirRef = useRef<HTMLSpanElement>(null);
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
// Load providers and get current model's token limit
const loadProviderDetails = async () => {
@@ -142,62 +135,12 @@ export default function BottomMenu({
};
}, [isModelMenuOpen]);
useEffect(() => {
const checkTruncation = () => {
if (dirRef.current) {
setIsDirTruncated(dirRef.current.scrollWidth > dirRef.current.clientWidth);
}
};
checkTruncation();
window.addEventListener('resize', checkTruncation);
return () => window.removeEventListener('resize', checkTruncation);
}, []);
useEffect(() => {
setIsTooltipOpen(false);
}, [isDirTruncated]);
return (
<div className="flex justify-between items-center text-textSubtle relative bg-bgSubtle border-t border-borderSubtle text-xs pl-4 h-[40px] pb-1 align-middle">
{/* Directory Chooser - Always visible */}
<span
className="cursor-pointer flex items-center [&>svg]:size-4"
onClick={async () => {
if (hasMessages) {
window.electron.directoryChooser();
} else {
window.electron.directoryChooser(true);
}
}}
>
<Document className="mr-1" />
<TooltipProvider>
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
<TooltipTrigger asChild>
<span
ref={dirRef}
className="max-w-[170px] md:max-w-[200px] lg:max-w-[380px] min-w-0 block overflow-hidden text-ellipsis whitespace-nowrap [direction:rtl] text-left"
>
{window.appConfig.get('GOOSE_WORKING_DIR') as string}
</span>
</TooltipTrigger>
{isDirTruncated && (
<TooltipContent className="max-w-96 overflow-auto scrollbar-thin" side="top">
{window.appConfig.get('GOOSE_WORKING_DIR') as string}
</TooltipContent>
)}
</Tooltip>
</TooltipProvider>
<ChevronUp className="ml-1" />
</span>
{/* Goose Mode Selector Dropdown */}
<BottomMenuModeSelection setView={setView} />
{/* Right-side section with ToolCount and Model Selector together */}
<div className="flex items-center mr-4 space-x-1">
<div className="flex justify-between items-center transition-colors text-textSubtle relative text-xs align-middle">
<div className="flex items-center pl-2">
{/* Tool and Token count */}
{<BottomMenuAlertPopover alerts={alerts} />}
{/* Model Selector Dropdown */}
{settingsV2Enabled ? (
<ModelsBottomBar dropdownRef={dropdownRef} setView={setView} />
@@ -262,13 +205,19 @@ export default function BottomMenu({
}}
>
<span className="text-sm">Tools and Settings</span>
<Sliders className="w-5 h-5 ml-2 rotate-90" />
<Sliders className="w-4 h-4 ml-2 rotate-90" />
</div>
</div>
</div>
)}
</div>
)}
{/* Separator */}
<div className="w-[1px] h-4 bg-borderSubtle mx-2" />
{/* Goose Mode Selector Dropdown */}
<BottomMenuModeSelection setView={setView} />
</div>
</div>
);

View File

@@ -1,10 +1,10 @@
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { getApiUrl, getSecretKey } from '../../config';
import { ChevronDown, ChevronUp } from '../icons';
import { all_goose_modes, ModeSelectionItem } from '../settings_v2/mode/ModeSelectionItem';
import { useConfig } from '../ConfigContext';
import { settingsV2Enabled } from '../../flags';
import { View, ViewOptions } from '../App';
import { View, ViewOptions } from '../../App';
import { Orbit } from 'lucide-react';
interface BottomMenuModeSelectionProps {
setView: (view: View, viewOptions?: ViewOptions) => void;
@@ -119,23 +119,25 @@ export const BottomMenuModeSelection = ({ setView }: BottomMenuModeSelectionProp
return (
<div className="relative flex items-center" ref={gooseModeDropdownRef}>
<div
className="flex items-center cursor-pointer"
<button
className="flex items-center justify-center text-textSubtle hover:text-textStandard h-6 [&_svg]:size-4"
onClick={() => setIsGooseModeMenuOpen(!isGooseModeMenuOpen)}
>
<span className="truncate max-w-[170px] md:max-w-[200px] lg:max-w-[380px]">
Goose Mode: {getValueByKey(gooseMode)}
</span>
{isGooseModeMenuOpen ? (
<ChevronDown className="w-4 h-4 ml-1" />
) : (
<ChevronUp className="w-4 h-4 ml-1" />
)}
</div>
<span className="pr-1.5">{getValueByKey(gooseMode).toLowerCase()}</span>
<Orbit />
{/*<span className="truncate max-w-[170px] md:max-w-[200px] lg:max-w-[380px]">*/}
{/* Goose Mode: {getValueByKey(gooseMode)}*/}
{/*</span>*/}
{/*{isGooseModeMenuOpen ? (*/}
{/* <ChevronDown className="w-4 h-4 ml-1" />*/}
{/*) : (*/}
{/* <ChevronUp className="w-4 h-4 ml-1" />*/}
{/*)}*/}
</button>
{/* Dropdown Menu */}
{isGooseModeMenuOpen && (
<div className="absolute bottom-[24px] pl-4 pt-2 right-0 w-[240px] bg-bgApp rounded-lg border border-borderSubtle">
<div className="absolute bottom-[24px] right-0 w-[240px] py-2 bg-bgApp rounded-lg border border-borderSubtle">
<div>
{all_goose_modes.map((mode) => (
<ModeSelectionItem

View File

@@ -1,6 +1,6 @@
import { Popover, PopoverContent, PopoverPortal, PopoverTrigger } from '../ui/popover';
import React, { useEffect, useState } from 'react';
import { ChatSmart, Idea, More, Refresh, Time, Send } from '../icons';
import { ChatSmart, Idea, Refresh, Time, Send, Settings } from '../icons';
import { FolderOpen, Moon, Sliders, Sun } from 'lucide-react';
import { useConfig } from '../ConfigContext';
import { settingsV2Enabled } from '../../flags';
@@ -169,10 +169,10 @@ export default function MoreMenu({
<PopoverTrigger asChild>
<button
data-testid="more-options-button"
className={`z-[100] absolute top-2 right-4 w-[20px] h-[20px] transition-colors cursor-pointer no-drag hover:text-textProminent ${open ? 'text-textProminent' : 'text-textSubtle'}`}
className={`z-[100] w-7 h-7 p-1 rounded-full border border-borderSubtle transition-colors cursor-pointer no-drag hover:text-textStandard hover:border-borderStandard ${open ? 'text-textStandard' : 'text-textSubtle'}`}
role="button"
>
<More />
<Settings />
</button>
</PopoverTrigger>

View File

@@ -1,22 +1,56 @@
import { useState } from 'react';
import MoreMenu from './MoreMenu';
import React from 'react';
import { View, ViewOptions } from '../../App';
import type { View, ViewOptions } from '../../App';
import { Document } from '../icons';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/Tooltip';
export default function MoreMenuLayout({
hasMessages,
showMenu = true,
setView,
setIsGoosehintsModalOpen,
}: {
setView: (view: View, viewOptions?: ViewOptions) => void;
setIsGoosehintsModalOpen: (isOpen: boolean) => void;
hasMessages?: boolean;
showMenu?: boolean;
setView?: (view: View, viewOptions?: ViewOptions) => void;
setIsGoosehintsModalOpen?: (isOpen: boolean) => void;
}) {
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
return (
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle border-b border-borderSubtle">
<div className="flex-1"></div>
<div className="flex items-center h-full">
<div className="flex items-center justify-center h-full px-2 mr-2">
<div
className="relative flex items-center h-14 border-b border-borderSubtle w-full"
style={{ WebkitAppRegion: 'drag' }}
>
{showMenu && (
<div className="flex items-center justify-between w-full h-full pl-[86px] pr-4">
<TooltipProvider>
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
<TooltipTrigger asChild>
<button
className="z-[100] no-drag hover:cursor-pointer border border-subtle hover:border-borderStandard rounded-lg p-2 pr-3 text-textSubtle hover:text-textStandard text-sm flex items-center transition-colors [&>svg]:size-4 "
onClick={async () => {
if (hasMessages) {
window.electron.directoryChooser();
} else {
window.electron.directoryChooser(true);
}
}}
>
<Document className="mr-1" />
<div className="max-w-[200px] truncate [direction:rtl]">
{window.appConfig.get('GOOSE_WORKING_DIR')}
</div>
</button>
</TooltipTrigger>
<TooltipContent className="max-w-96 overflow-auto scrollbar-thin" side="top">
{window.appConfig.get('GOOSE_WORKING_DIR') as string}
</TooltipContent>
</Tooltip>
</TooltipProvider>
<MoreMenu setView={setView} setIsGoosehintsModalOpen={setIsGoosehintsModalOpen} />
</div>
</div>
)}
</div>
);
}

View File

@@ -17,6 +17,7 @@ import { createSharedSession } from '../../sharedSessions';
import { Modal, ModalContent } from '../ui/modal';
import { Button } from '../ui/button';
import { toast } from 'react-toastify';
import MoreMenuLayout from '../more_menu/MoreMenuLayout';
interface SessionHistoryViewProps {
session: SessionDetails;
@@ -109,7 +110,7 @@ const SessionHistoryView: React.FC<SessionHistoryViewProps> = ({
return (
<div className="h-screen w-full flex flex-col">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<MoreMenuLayout showMenu={false} />
{/* Top Row - back, info, reopen thread (fixed) */}
<SessionHeaderCard onBack={onBack}>

View File

@@ -15,6 +15,7 @@ import BackButton from '../ui/BackButton';
import { ScrollArea } from '../ui/scroll-area';
import { View, ViewOptions } from '../../App';
import { formatMessageTimestamp } from '../../utils/timeUtils';
import MoreMenuLayout from '../more_menu/MoreMenuLayout';
interface SessionListViewProps {
setView: (view: View, viewOptions?: ViewOptions) => void;
@@ -48,7 +49,7 @@ const SessionListView: React.FC<SessionListViewProps> = ({ setView, onSelectSess
return (
<div className="h-screen w-full">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="h-full w-full">
<div className="flex flex-col pb-24">

View File

@@ -18,6 +18,7 @@ import { View, ViewOptions } from '../../App';
import { ModeSelection } from './basic/ModeSelection';
import SessionSharingSection from './session/SessionSharingSection';
import { toastSuccess } from '../../toasts';
import MoreMenuLayout from '../more_menu/MoreMenuLayout';
const EXTENSIONS_DESCRIPTION =
'The Model Context Protocol (MCP) is a system that allows AI models to securely connect with local or remote resources using standard server setups. It works like a client-server setup and expands AI capabilities using three main components: Prompts, Resources, and Tools.';
@@ -190,7 +191,7 @@ export default function SettingsView({
return (
<div className="h-screen w-full">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="h-full w-full">
<div className="flex flex-col pb-24">

View File

@@ -11,7 +11,7 @@ export interface GooseMode {
export const all_goose_modes: GooseMode[] = [
{
key: 'auto',
label: 'Completely Autonomous',
label: 'Autonomous',
description: 'Full file modification capabilities, edit, create, and delete files freely.',
},
{
@@ -90,18 +90,15 @@ export function ModeSelectionItem({
return (
<div>
<div
className="flex items-center justify-between p-2 text-textStandard hover:bg-bgSubtle transition-colors"
onClick={() => handleModeChange(mode.key)}
>
<div>
<h3 className="text-sm font-light text-textStandard dark:text-gray-200">{mode.label}</h3>
<div className="group hover:cursor-pointer" onClick={() => handleModeChange(mode.key)}>
<div className="flex items-center justify-between text-textStandard mb-4">
<div className="flex">
<h3 className="text-textStandard">{mode.label}</h3>
{showDescription && (
<p className="text-xs text-textSubtle dark:text-gray-400 mt-[2px]">
{mode.description}
</p>
<p className="text-xs text-textSubtle mt-[2px]">{mode.description}</p>
)}
</div>
</div>
<div className="relative flex items-center gap-3">
{!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && (
<button

View File

@@ -6,6 +6,7 @@ import { SearchBar } from './Search';
import { AddModelInline } from './AddModelInline';
import { ScrollArea } from '../../ui/scroll-area';
import type { View } from '../../../App';
import MoreMenuLayout from '../../more_menu/MoreMenuLayout';
export default function MoreModelsView({
onClose,
@@ -16,7 +17,7 @@ export default function MoreModelsView({
}) {
return (
<div className="h-screen w-full">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="h-full w-full">
<div className="px-8 pt-6 pb-4">

View File

@@ -2,11 +2,12 @@ import React from 'react';
import { ScrollArea } from '../../ui/scroll-area';
import BackButton from '../../ui/BackButton';
import { ConfigureProvidersGrid } from './ConfigureProvidersGrid';
import MoreMenuLayout from '../../more_menu/MoreMenuLayout';
export default function ConfigureProvidersView({ onClose }: { onClose: () => void }) {
return (
<div className="h-screen w-full">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="h-full w-full">
<div className="px-8 pt-6 pb-4">

View File

@@ -6,6 +6,7 @@ import ModelsSection from './models/ModelsSection';
import { ModeSection } from './mode/ModeSection';
import SessionSharingSection from './sessions/SessionSharingSection';
import { ExtensionConfig } from '../../api';
import MoreMenuLayout from '../more_menu/MoreMenuLayout';
export type SettingsViewOptions = {
deepLinkConfig?: ExtensionConfig;
@@ -23,7 +24,7 @@ export default function SettingsView({
}) {
return (
<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>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="h-full w-full">
<div className="flex flex-col pb-24">

View File

@@ -1,6 +1,5 @@
import { Input } from '../../../ui/input';
import { Select } from '../../../ui/Select';
import React from 'react';
interface ExtensionInfoFieldsProps {
name: string;

View File

@@ -12,17 +12,17 @@ export interface GooseMode {
export const all_goose_modes: GooseMode[] = [
{
key: 'auto',
label: 'Completely autonomous',
label: 'Autonomous',
description: 'Full file modification capabilities, edit, create, and delete files freely.',
},
{
key: 'approve',
label: 'Manual approval',
label: 'Manual',
description: 'All tools, extensions and file modifications will require human approval',
},
{
key: 'smart_approve',
label: 'Smart approval',
label: 'Smart',
description: 'Intelligently determine which actions need approval based on risk level ',
},
{
@@ -61,21 +61,19 @@ export function ModeSelectionItem({
return (
<div className="group hover:cursor-pointer">
<div
className="flex items-center justify-between text-textStandard mb-4"
className="flex items-center justify-between text-textStandard py-2 px-4 hover:bg-bgSubtle"
onClick={() => handleModeChange(mode.key)}
>
<div className="flex">
<div>
<h3 className="text-textStandard dark:text-gray-200">{mode.label}</h3>
<h3 className="text-textStandard">{mode.label}</h3>
{showDescription && (
<p className="text-xs text-textSubtle dark:text-gray-400 mt-[2px]">
{mode.description}
</p>
<p className="text-xs text-textSubtle mt-[2px]">{mode.description}</p>
)}
</div>
</div>
<div className="relative flex items-center gap-3 mr-4">
<div className="relative flex items-center gap-2">
{!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && (
<button
onClick={() => {
@@ -84,7 +82,7 @@ export function ModeSelectionItem({
});
}}
>
<Gear className="w-5 h-5 text-textSubtle hover:text-textStandard" />
<Gear className="w-4 h-4 text-textSubtle hover:text-textStandard" />
</button>
)}
<input

View File

@@ -1,4 +1,3 @@
import { ChevronDown, ChevronUp } from '../../../icons';
import { Sliders } from 'lucide-react';
import React, { useEffect, useState, useRef } from 'react';
import { useConfig } from '../../../ConfigContext';
@@ -69,10 +68,10 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
}, [isModelMenuOpen]);
return (
<div className="relative flex items-center ml-auto mr-4" ref={dropdownRef}>
<div className="relative flex items-center" ref={dropdownRef}>
<div ref={menuRef} className="relative">
<div
className="flex items-center cursor-pointer max-w-[180px] md:max-w-[200px] lg:max-w-[380px] min-w-0 group"
className="flex items-center hover:cursor-pointer max-w-[180px] md:max-w-[200px] lg:max-w-[380px] min-w-0 group hover:text-textStandard transition-colors"
onClick={() => setIsModelMenuOpen(!isModelMenuOpen)}
>
<TooltipProvider>
@@ -92,23 +91,18 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
)}
</Tooltip>
</TooltipProvider>
{isModelMenuOpen ? (
<ChevronDown className="w-4 h-4 ml-1 flex-shrink-0" />
) : (
<ChevronUp className="w-4 h-4 ml-1 flex-shrink-0" />
)}
</div>
{/* Dropdown Menu */}
{isModelMenuOpen && (
<div className="absolute bottom-[24px] right-0 w-[300px] bg-bgApp rounded-lg border border-borderSubtle">
<div className="absolute bottom-[24px] right-[-55px] w-[300px] bg-bgApp rounded-lg border border-borderSubtle">
<div className="">
<div className="text-sm text-textProminent mt-3 ml-2">Current:</div>
<div className="text-sm text-textProminent mt-2 ml-2">Current:</div>
<div className="flex items-center justify-between text-sm ml-2">
{model} -- {provider}
</div>
<div
className="flex items-center justify-between text-textStandard p-2 cursor-pointer hover:bg-bgStandard
className="flex items-center justify-between text-textStandard p-2 cursor-pointer transition-colors hover:bg-bgStandard
border-t border-borderSubtle mt-2"
onClick={() => {
setIsModelMenuOpen(false);
@@ -116,7 +110,7 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
}}
>
<span className="text-sm">Change Model</span>
<Sliders className="w-5 h-5 ml-2 rotate-90" />
<Sliders className="w-4 h-4 ml-2 rotate-90" />
</div>
</div>
</div>

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState, useCallback } from 'react';
import { useEffect, useState, useCallback } from 'react';
import { ArrowLeftRight, ExternalLink } from 'lucide-react';
import Modal from '../../../Modal';

View File

@@ -4,6 +4,7 @@ import BackButton from '../../ui/BackButton';
import { FixedExtensionEntry, useConfig } from '../../ConfigContext';
import { ChevronRight } from 'lucide-react';
import PermissionModal from './PermissionModal';
import MoreMenuLayout from '../../more_menu/MoreMenuLayout';
function RuleItem({ title, description }: { title: string; description: string }) {
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -76,7 +77,7 @@ export default function PermissionSettingsView({ onClose }: { onClose: () => voi
return (
<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>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="h-full w-full">
<div className="flex flex-col pb-24">

View File

@@ -173,7 +173,8 @@ export const PROVIDER_REGISTRY: ProviderRegistry[] = [
details: {
id: 'azure_openai',
name: 'Azure OpenAI',
description: 'Access Azure OpenAI models using API key or Azure credentials. If no API key is provided, Azure credential chain will be used.',
description:
'Access Azure OpenAI models using API key or Azure credentials. If no API key is provided, Azure credential chain will be used.',
parameters: [
{
name: 'AZURE_OPENAI_API_KEY',

View File

@@ -7,6 +7,7 @@ import { ProviderDetails } from '../../../api/types.gen';
import { initializeSystem } from '../../../utils/providerUtils';
import WelcomeGooseLogo from '../../WelcomeGooseLogo';
import { toastService } from '../../../toasts';
import MoreMenuLayout from '../../more_menu/MoreMenuLayout';
interface ProviderSettingsProps {
onClose: () => void;
@@ -88,7 +89,8 @@ export default function ProviderSettings({ onClose, isOnboarding }: ProviderSett
return (
<div className="h-screen w-full flex flex-col">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
<MoreMenuLayout showMenu={false} />
<ScrollArea className="flex-1 w-full">
{isOnboarding && (
<div className="group/logo flex justify-left pl-8">

View File

@@ -97,12 +97,7 @@ const ScrollArea = React.forwardRef<ScrollAreaHandle, ScrollAreaProps>(
data-scrolled={isScrolled}
{...props}
>
<div
className={cn(
'absolute top-0 left-0 right-0 z-10 transition-all duration-200',
isScrolled ? 'border-t border-borderSubtle' : 'border-t border-transparent'
)}
/>
<div className={cn('absolute top-0 left-0 right-0 z-10 transition-all duration-200')} />
<ScrollAreaPrimitive.Viewport
ref={viewportRef}
className="h-full w-full rounded-[inherit] [&>div]:!block"

View File

@@ -334,7 +334,7 @@ const createChat = async (
const mainWindow = new BrowserWindow({
titleBarStyle: process.platform === 'darwin' ? 'hidden' : 'default',
trafficLightPosition: process.platform === 'darwin' ? { x: 16, y: 10 } : undefined,
trafficLightPosition: process.platform === 'darwin' ? { x: 16, y: 20 } : undefined,
vibrancy: process.platform === 'darwin' ? 'window' : undefined,
frame: process.platform === 'darwin' ? false : true,
width: 750,