Refactor project opening and add status bar tooltips

This commit is contained in:
Mohamed Boudra
2026-03-19 19:04:01 +07:00
parent efb3df8233
commit 3d4ac57bd0
15 changed files with 420 additions and 167 deletions
+130 -64
View File
@@ -22,6 +22,7 @@ import {
} from '@/components/ui/dropdown-menu'
import { Combobox, ComboboxItem, type ComboboxOption } from '@/components/ui/combobox'
import { AdaptiveModalSheet } from '@/components/adaptive-modal-sheet'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import type {
AgentMode,
AgentModelDefinition,
@@ -33,13 +34,18 @@ import {
type AgentModeColorTier,
type AgentModeIcon,
} from '@server/server/agent/provider-manifest'
import { normalizeModelId, resolveAgentModelSelection } from '@/components/agent-status-bar.utils'
import {
getStatusSelectorHint,
resolveAgentModelSelection,
} from '@/components/agent-status-bar.utils'
type StatusOption = {
id: string
label: string
}
type StatusSelector = 'provider' | 'mode' | 'model' | 'thinking'
type ControlledAgentStatusBarProps = {
provider: string
providerOptions?: StatusOption[]
@@ -139,7 +145,7 @@ function ControlledStatusBar({
const { theme } = useUnistyles()
const isWeb = Platform.OS === 'web'
const [prefsOpen, setPrefsOpen] = useState(false)
const [openSelector, setOpenSelector] = useState<'provider' | 'mode' | 'model' | 'thinking' | null>(null)
const [openSelector, setOpenSelector] = useState<StatusSelector | null>(null)
const providerAnchorRef = useRef<View>(null)
const modeAnchorRef = useRef<View>(null)
@@ -215,12 +221,19 @@ function ControlledStatusBar({
)
const handleOpenChange = useCallback(
(selector: 'provider' | 'mode' | 'model' | 'thinking') => (nextOpen: boolean) => {
(selector: StatusSelector) => (nextOpen: boolean) => {
setOpenSelector(nextOpen ? selector : null)
},
[]
)
const handleSelectorPress = useCallback(
(selector: StatusSelector) => {
handleOpenChange(selector)(openSelector !== selector)
},
[handleOpenChange, openSelector]
)
return (
<View style={styles.container}>
{isWeb ? (
@@ -231,7 +244,7 @@ function ControlledStatusBar({
ref={providerAnchorRef}
collapsable={false}
disabled={disabled || !canSelectProvider}
onPress={() => setOpenSelector(openSelector === 'provider' ? null : 'provider')}
onPress={() => handleSelectorPress('provider')}
style={({ pressed, hovered }) => [
styles.modeBadge,
hovered && styles.modeBadgeHovered,
@@ -260,27 +273,39 @@ function ControlledStatusBar({
{modeOptions && modeOptions.length > 0 ? (
<>
<Pressable
ref={modeAnchorRef}
collapsable={false}
disabled={disabled || !canSelectMode}
onPress={() => setOpenSelector(openSelector === 'mode' ? null : 'mode')}
style={({ pressed, hovered }) => [
styles.modeIconBadge,
hovered && styles.modeBadgeHovered,
(pressed || openSelector === 'mode') && styles.modeBadgePressed,
(disabled || !canSelectMode) && styles.disabledBadge,
]}
accessibilityRole="button"
accessibilityLabel={`Select agent mode (${displayMode})`}
testID="agent-mode-selector"
<Tooltip
key={`mode-${openSelector === 'mode' ? 'open' : 'closed'}`}
delayDuration={0}
enabledOnDesktop
enabledOnMobile={false}
>
{ModeIconComponent ? (
<ModeIconComponent size={theme.iconSize.md} color={modeIconColor} />
) : (
<ShieldCheck size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
)}
</Pressable>
<TooltipTrigger asChild triggerRefProp="ref">
<Pressable
ref={modeAnchorRef}
collapsable={false}
disabled={disabled || !canSelectMode}
onPress={() => handleSelectorPress('mode')}
style={({ pressed, hovered }) => [
styles.modeIconBadge,
hovered && styles.modeBadgeHovered,
(pressed || openSelector === 'mode') && styles.modeBadgePressed,
(disabled || !canSelectMode) && styles.disabledBadge,
]}
accessibilityRole="button"
accessibilityLabel={`Select agent mode (${displayMode})`}
testID="agent-mode-selector"
>
{ModeIconComponent ? (
<ModeIconComponent size={theme.iconSize.md} color={modeIconColor} />
) : (
<ShieldCheck size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
)}
</Pressable>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<Text style={styles.tooltipText}>{getStatusSelectorHint('mode')}</Text>
</TooltipContent>
</Tooltip>
<Combobox
options={comboboxModeOptions}
value={selectedModeId ?? ''}
@@ -297,25 +322,37 @@ function ControlledStatusBar({
{canSelectModel ? (
<>
<Pressable
ref={modelAnchorRef}
collapsable={false}
disabled={modelDisabled}
onPress={() => setOpenSelector(openSelector === 'model' ? null : 'model')}
style={({ pressed, hovered }) => [
styles.modeBadge,
hovered && styles.modeBadgeHovered,
(pressed || openSelector === 'model') && styles.modeBadgePressed,
modelDisabled && styles.disabledBadge,
]}
accessibilityRole="button"
accessibilityLabel="Select agent model"
testID="agent-model-selector"
<Tooltip
key={`model-${openSelector === 'model' ? 'open' : 'closed'}`}
delayDuration={0}
enabledOnDesktop
enabledOnMobile={false}
>
<ProviderIcon size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
<Text style={styles.modeBadgeText}>{displayModel}</Text>
<ChevronDown size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</Pressable>
<TooltipTrigger asChild triggerRefProp="ref">
<Pressable
ref={modelAnchorRef}
collapsable={false}
disabled={modelDisabled}
onPress={() => handleSelectorPress('model')}
style={({ pressed, hovered }) => [
styles.modeBadge,
hovered && styles.modeBadgeHovered,
(pressed || openSelector === 'model') && styles.modeBadgePressed,
modelDisabled && styles.disabledBadge,
]}
accessibilityRole="button"
accessibilityLabel="Select agent model"
testID="agent-model-selector"
>
<ProviderIcon size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
<Text style={styles.modeBadgeText}>{displayModel}</Text>
<ChevronDown size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</Pressable>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<Text style={styles.tooltipText}>{getStatusSelectorHint('model')}</Text>
</TooltipContent>
</Tooltip>
<Combobox
options={comboboxModelOptions}
value={selectedModelId ?? ''}
@@ -331,25 +368,37 @@ function ControlledStatusBar({
{thinkingOptions && thinkingOptions.length > 0 ? (
<>
<Pressable
ref={thinkingAnchorRef}
collapsable={false}
disabled={disabled || !canSelectThinking}
onPress={() => setOpenSelector(openSelector === 'thinking' ? null : 'thinking')}
style={({ pressed, hovered }) => [
styles.modeBadge,
hovered && styles.modeBadgeHovered,
(pressed || openSelector === 'thinking') && styles.modeBadgePressed,
(disabled || !canSelectThinking) && styles.disabledBadge,
]}
accessibilityRole="button"
accessibilityLabel={`Select thinking option (${displayThinking})`}
testID="agent-thinking-selector"
<Tooltip
key={`thinking-${openSelector === 'thinking' ? 'open' : 'closed'}`}
delayDuration={0}
enabledOnDesktop
enabledOnMobile={false}
>
<Brain size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
<Text style={styles.modeBadgeText}>{displayThinking}</Text>
<ChevronDown size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</Pressable>
<TooltipTrigger asChild triggerRefProp="ref">
<Pressable
ref={thinkingAnchorRef}
collapsable={false}
disabled={disabled || !canSelectThinking}
onPress={() => handleSelectorPress('thinking')}
style={({ pressed, hovered }) => [
styles.modeBadge,
hovered && styles.modeBadgeHovered,
(pressed || openSelector === 'thinking') && styles.modeBadgePressed,
(disabled || !canSelectThinking) && styles.disabledBadge,
]}
accessibilityRole="button"
accessibilityLabel={`Select thinking option (${displayThinking})`}
testID="agent-thinking-selector"
>
<Brain size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
<Text style={styles.modeBadgeText}>{displayThinking}</Text>
<ChevronDown size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</Pressable>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<Text style={styles.tooltipText}>{getStatusSelectorHint('thinking')}</Text>
</TooltipContent>
</Tooltip>
<Combobox
options={comboboxThinkingOptions}
value={selectedThinkingOptionId ?? ''}
@@ -386,7 +435,10 @@ function ControlledStatusBar({
>
{providerOptions && providerOptions.length > 0 ? (
<View style={styles.sheetSection}>
<DropdownMenu>
<DropdownMenu
open={openSelector === 'provider'}
onOpenChange={handleOpenChange('provider')}
>
<DropdownMenuTrigger
disabled={disabled || !canSelectProvider}
style={({ pressed }) => [
@@ -418,7 +470,10 @@ function ControlledStatusBar({
{modeOptions && modeOptions.length > 0 ? (
<View style={styles.sheetSection}>
<DropdownMenu>
<DropdownMenu
open={openSelector === 'mode'}
onOpenChange={handleOpenChange('mode')}
>
<DropdownMenuTrigger
disabled={disabled || !canSelectMode}
style={({ pressed }) => [
@@ -458,7 +513,10 @@ function ControlledStatusBar({
{canSelectModel ? (
<View style={styles.sheetSection}>
<DropdownMenu>
<DropdownMenu
open={openSelector === 'model'}
onOpenChange={handleOpenChange('model')}
>
<DropdownMenuTrigger
disabled={modelDisabled}
style={({ pressed }) => [
@@ -490,7 +548,10 @@ function ControlledStatusBar({
{thinkingOptions && thinkingOptions.length > 0 ? (
<View style={styles.sheetSection}>
<DropdownMenu>
<DropdownMenu
open={openSelector === 'thinking'}
onOpenChange={handleOpenChange('thinking')}
>
<DropdownMenuTrigger
disabled={disabled || !canSelectThinking}
style={({ pressed }) => [
@@ -763,6 +824,11 @@ const styles = StyleSheet.create((theme) => ({
fontSize: theme.fontSize.sm,
fontWeight: theme.fontWeight.normal,
},
tooltipText: {
color: theme.colors.foreground,
fontSize: theme.fontSize.sm,
lineHeight: theme.fontSize.sm * 1.4,
},
prefsButton: {
width: 28,
height: 28,