feat: new workspace screen with sticky search combobox design

- Replace workspace setup dialog with full-screen new workspace route
- Restyle Combobox SearchInput to match CombinedModelSelector Level 2 design:
  borderless sticky search bar above scroll area instead of inline bordered box
- CombinedModelSelector now uses shared SearchInput, removing duplicate ProviderSearchInput
- Fix TooltipTrigger children type to accept render functions (remove PropsWithChildren wrapper)
- Fix empty rightControls View causing gap between dictation and send buttons
- Add branch picker with searchable Combobox and GitBranch icons
- Muted icon buttons (attachment, dictation, voice mode) that brighten on hover
This commit is contained in:
Mohamed Boudra
2026-04-06 08:31:28 +07:00
parent c6e87744f1
commit 6362d429c7
10 changed files with 526 additions and 168 deletions
+38 -34
View File
@@ -610,40 +610,44 @@ export function Composer({
</Tooltip>
) : null;
const rightContent = (
<View style={styles.rightControls}>
{!isVoiceModeForAgent && hasAgent ? (
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
<TooltipTrigger
onPress={handleToggleRealtimeVoice}
disabled={!isConnected || voice?.isVoiceSwitching}
accessibilityLabel="Enable Voice mode"
accessibilityRole="button"
style={({ hovered }) => [
styles.realtimeVoiceButton as any,
(hovered ? styles.iconButtonHovered : undefined) as any,
(!isConnected || voice?.isVoiceSwitching ? styles.buttonDisabled : undefined) as any,
]}
>
{voice?.isVoiceSwitching ? (
<ActivityIndicator size="small" color="white" />
) : (
<AudioLines size={buttonIconSize} color={theme.colors.foreground} />
)}
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<View style={styles.tooltipRow}>
<Text style={styles.tooltipText}>Voice mode</Text>
{voiceToggleKeys ? (
<Shortcut chord={voiceToggleKeys} style={styles.tooltipShortcut} />
) : null}
</View>
</TooltipContent>
</Tooltip>
) : null}
{cancelButton}
</View>
);
const showVoiceModeButton = !isVoiceModeForAgent && hasAgent;
const rightContent =
showVoiceModeButton || cancelButton ? (
<View style={styles.rightControls}>
{showVoiceModeButton ? (
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
<TooltipTrigger
onPress={handleToggleRealtimeVoice}
disabled={!isConnected || voice?.isVoiceSwitching}
accessibilityLabel="Enable Voice mode"
accessibilityRole="button"
style={({ hovered }) => [
styles.realtimeVoiceButton as any,
(hovered ? styles.iconButtonHovered : undefined) as any,
(!isConnected || voice?.isVoiceSwitching ? styles.buttonDisabled : undefined) as any,
]}
>
{({ hovered }) =>
voice?.isVoiceSwitching ? (
<ActivityIndicator size="small" color="white" />
) : (
<AudioLines size={buttonIconSize} color={hovered ? theme.colors.foreground : theme.colors.foregroundMuted} />
)
}
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<View style={styles.tooltipRow}>
<Text style={styles.tooltipText}>Voice mode</Text>
{voiceToggleKeys ? (
<Shortcut chord={voiceToggleKeys} style={styles.tooltipShortcut} />
) : null}
</View>
</TooltipContent>
</Tooltip>
) : null}
{cancelButton}
</View>
) : null;
const leftContent =
resolveStatusControlMode(statusControls) === "draft" && statusControls ? (