mirror of
https://github.com/voideditor/void
synced 2026-05-23 17:38:23 +00:00
lots of ux
This commit is contained in:
parent
d67cfb5b33
commit
c52a754076
3 changed files with 49 additions and 16 deletions
|
|
@ -1422,7 +1422,7 @@ const ToolRequestAcceptRejectButtons = ({ toolName }: { toolName: ToolName }) =>
|
|||
<ToolApprovalTypeSwitch size='xs' approvalType={approvalType} desc='Auto-approve' />
|
||||
</div> : null
|
||||
|
||||
return <div className="flex gap-2 mx-4 items-center">
|
||||
return <div className="flex gap-2 items-center">
|
||||
{approveButton}
|
||||
{cancelButton}
|
||||
{approvalToggle}
|
||||
|
|
@ -2714,15 +2714,15 @@ export const SidebarChat = () => {
|
|||
const sidebarRef = useRef<HTMLDivElement>(null)
|
||||
const scrollContainerRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const onSubmit = useCallback(async () => {
|
||||
const onSubmit = useCallback(async (_forceSubmit?: string) => {
|
||||
|
||||
if (isDisabled) return
|
||||
if (isDisabled && !_forceSubmit) return
|
||||
if (isRunning) return
|
||||
|
||||
const threadId = chatThreadsService.state.currentThreadId
|
||||
|
||||
// send message to LLM
|
||||
const userMessage = textAreaRef.current?.value ?? ''
|
||||
const userMessage = _forceSubmit || textAreaRef.current?.value || ''
|
||||
|
||||
try {
|
||||
await chatThreadsService.addUserMessageAndStreamResponse({ userMessage, threadId })
|
||||
|
|
@ -2884,6 +2884,26 @@ export const SidebarChat = () => {
|
|||
const isLandingPage = previousMessages.length === 0
|
||||
|
||||
|
||||
const initiallySuggestedPromptsHTML = <div className='flex flex-col gap-2 w-full text-nowrap text-void-fg-3 select-none'>
|
||||
{[
|
||||
'Summarize my codebase',
|
||||
'How do types work in Rust?',
|
||||
'Create a .voidrules file for me'
|
||||
].map((text, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className='py-1 px-2 rounded text-sm bg-zinc-700/5 hover:bg-zinc-700/10 dark:bg-zinc-300/5 dark:hover:bg-zinc-300/10 cursor-pointer opacity-80 hover:opacity-100'
|
||||
onClick={() => onSubmit(text)}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
console.log('!!!', Object.keys(chatThreadsState.allThreads).length)
|
||||
|
||||
|
||||
const threadPageInput = <div key={'input' + chatThreadsState.currentThreadId}>
|
||||
<div className='px-4'>
|
||||
<CommandBarInChat />
|
||||
|
|
@ -2907,11 +2927,16 @@ export const SidebarChat = () => {
|
|||
{landingPageInput}
|
||||
</ErrorBoundary>
|
||||
|
||||
{Object.values(chatThreadsState.allThreads).length > 0 && // show if there are threads
|
||||
{Object.keys(chatThreadsState.allThreads).length > 1 ? // show if there are threads
|
||||
<ErrorBoundary>
|
||||
<div className='pt-8 mb-2 text-void-fg-1 text-root'>Previous Threads</div>
|
||||
<PastThreadsList />
|
||||
</ErrorBoundary>
|
||||
:
|
||||
<ErrorBoundary>
|
||||
<div className='pt-8 mb-2 text-void-fg-1 text-root'>Suggestions</div>
|
||||
{initiallySuggestedPromptsHTML}
|
||||
</ErrorBoundary>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -176,8 +176,8 @@ export const PastThreadsList = ({ className = '' }: { className?: string }) => {
|
|||
|
||||
return (
|
||||
<div className={`flex flex-col mb-2 gap-2 w-full text-nowrap text-void-fg-3 select-none relative ${className}`}>
|
||||
{displayThreads.length === 0
|
||||
? <></> // No chats yet... Suggestion: Tell me about my codebase Suggestion: Create a new .voidrules file in the root of my repo
|
||||
{displayThreads.length === 0 // this should never happen
|
||||
? <></>
|
||||
: displayThreads.map((threadId, i) => {
|
||||
const pastThread = allThreads[threadId];
|
||||
if (!pastThread) {
|
||||
|
|
@ -199,7 +199,7 @@ export const PastThreadsList = ({ className = '' }: { className?: string }) => {
|
|||
|
||||
{hasMoreThreads && !showAll && (
|
||||
<div
|
||||
className="text-void-fg-3 opacity-60 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
|
||||
className="text-void-fg-3 opacity-80 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
|
||||
onClick={() => setShowAll(true)}
|
||||
>
|
||||
Show {sortedThreadIds.length - numInitialThreads} more...
|
||||
|
|
@ -207,7 +207,7 @@ export const PastThreadsList = ({ className = '' }: { className?: string }) => {
|
|||
)}
|
||||
{hasMoreThreads && showAll && (
|
||||
<div
|
||||
className="text-void-fg-3 opacity-60 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
|
||||
className="text-void-fg-3 opacity-80 hover:opacity-100 hover:brightness-115 cursor-pointer p-1 text-xs"
|
||||
onClick={() => setShowAll(false)}
|
||||
>
|
||||
Show less
|
||||
|
|
|
|||
|
|
@ -131,16 +131,25 @@ const FadeIn = ({ children, className, delayMs = 0, durationMs, ...props }: { ch
|
|||
// prev/next
|
||||
|
||||
const NextButton = ({ onClick, ...props }: { onClick: () => void } & React.ButtonHTMLAttributes<HTMLButtonElement>) => {
|
||||
|
||||
// Create a new props object without the disabled attribute
|
||||
const { disabled, ...buttonProps } = props;
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className="px-6 py-2 bg-zinc-100 enabled:hover:bg-zinc-100 disabled:bg-zinc-100/40 disabled:cursor-not-allowed rounded text-black duration-600 transition-all"
|
||||
{...props.disabled && {
|
||||
onClick={disabled ? undefined : onClick}
|
||||
onDoubleClick={onClick}
|
||||
className={`px-6 py-2 bg-zinc-100 ${disabled
|
||||
? 'bg-zinc-100/40 cursor-not-allowed'
|
||||
: 'hover:bg-zinc-100'
|
||||
} rounded text-black duration-600 transition-all
|
||||
`}
|
||||
{...disabled && {
|
||||
'data-tooltip-id': 'void-tooltip',
|
||||
'data-tooltip-content': 'Please enter all required fields or choose another provider',
|
||||
'data-tooltip-place': 'top',
|
||||
"data-tooltip-content": 'Please enter all required fields or choose another provider', // (double-click to proceed anyway, can come back in Settings)
|
||||
"data-tooltip-place": 'top',
|
||||
}}
|
||||
{...props}
|
||||
{...buttonProps}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
|
|
@ -481,7 +490,6 @@ const VoidOnboardingContent = () => {
|
|||
const [selectedPrivateProvider, setSelectedPrivateProvider] = useState<ProviderName>('ollama');
|
||||
const [selectedAffordableProvider, setSelectedAffordableProvider] = useState<ProviderName>('gemini');
|
||||
const [selectedAllProvider, setSelectedAllProvider] = useState<ProviderName>('anthropic');
|
||||
const [didDoubleClickSkip, setDidDoubleClickSkip] = useState(false)
|
||||
|
||||
// Helper function to get the current selected provider based on active tab
|
||||
const getSelectedProvider = (): ProviderName => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue