Add shared trigger components and horizontal desktop workspace arguments

- Add DropdownTrigger and ComboboxTrigger with an overridable chevron slot and a 1 px translateY caret nudge for consistent vertical alignment.

- Convert text-based dropdown/combobox triggers across model selector, agent controls, mode control, settings, and new workspace to use the shared components.

- Lay out New Workspace arguments horizontally on desktop without labels while keeping the mobile vertical stack; align the project icon left edge with the title.
This commit is contained in:
Mohamed Boudra
2026-06-16 14:56:07 +07:00
parent c464c2bcb4
commit 36a136d811
8 changed files with 365 additions and 258 deletions
@@ -20,7 +20,9 @@ import {
} from "react-native";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { useShallow } from "zustand/shallow";
import { Brain, ChevronDown, ListTodo, Settings2, ShieldCheck, Zap } from "lucide-react-native";
import { Brain, ListTodo, Settings2, ShieldCheck, Zap } from "lucide-react-native";
import { DropdownTrigger } from "@/components/ui/dropdown-trigger";
import { ComboboxTrigger } from "@/components/ui/combobox-trigger";
import { getProviderIcon } from "@/components/provider-icons";
import { CombinedModelSelector } from "@/components/combined-model-selector";
import {
@@ -37,12 +39,7 @@ import {
toggleFavoriteModel,
useFormPreferences,
} from "@/hooks/use-form-preferences";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { Combobox, ComboboxItem, type ComboboxOption } from "@/components/ui/combobox";
import { DraftAgentModeControl, AgentModeControl } from "@/composer/agent-controls/mode-control";
import { AdaptiveModalSheet, type SheetHeader } from "@/components/adaptive-modal-sheet";
@@ -764,7 +761,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
<>
{providerOptions && providerOptions.length > 0 ? (
<>
<Pressable
<ComboboxTrigger
ref={providerAnchorRef}
collapsable={false}
disabled={disabled || !canSelectProvider}
@@ -775,8 +772,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
testID="agent-provider-selector"
>
<Text style={styles.modeBadgeText}>{displayProvider}</Text>
<ChevronDown size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</Pressable>
</ComboboxTrigger>
<Combobox
options={comboboxProviderOptions}
value={selectedProviderId ?? ""}
@@ -821,7 +817,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
<>
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
<TooltipTrigger asChild triggerRefProp="ref">
<Pressable
<ComboboxTrigger
ref={thinkingAnchorRef}
collapsable={false}
disabled={disabled || !canSelectThinking}
@@ -835,8 +831,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
>
<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>
</ComboboxTrigger>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<Text style={styles.tooltipText}>{t(getAgentControlHintKey("thinking"))}</Text>
@@ -1173,7 +1168,7 @@ function DesktopFeatureItem({
<DropdownMenu open={openSelector === featureSelector} onOpenChange={handleFeatureOpenChange}>
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
<TooltipTrigger asChild triggerRefProp="ref">
<DropdownMenuTrigger
<DropdownTrigger
disabled={disabled}
style={selectPressableStyle}
accessibilityRole="button"
@@ -1182,8 +1177,7 @@ function DesktopFeatureItem({
>
<FeatureIcon size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
<Text style={styles.modeBadgeText}>{selectedOption?.label ?? feature.label}</Text>
<ChevronDown size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</DropdownMenuTrigger>
</DropdownTrigger>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<Text style={styles.tooltipText}>{getFeatureTooltip(feature)}</Text>
@@ -1288,7 +1282,7 @@ function SheetFeatureItem({
open={openSelector === featureSelector}
onOpenChange={handleFeatureOpenChange}
>
<DropdownMenuTrigger
<DropdownTrigger
disabled={disabled}
style={togglePressableStyle}
accessibilityRole="button"
@@ -1296,8 +1290,7 @@ function SheetFeatureItem({
testID={`agent-feature-${feature.id}`}
>
<Text style={styles.sheetSelectText}>{selectedOption?.label ?? feature.label}</Text>
<ChevronDown size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
</DropdownMenuTrigger>
</DropdownTrigger>
<DropdownMenuContent side="top" align="start">
{feature.options.map((option) => (
<FeatureOptionMenuItem
@@ -8,18 +8,12 @@ import {
type ReactElement,
} from "react";
import { useTranslation } from "react-i18next";
import { Pressable, Text, View, type PressableStateCallbackType } from "react-native";
import { Text, View, type PressableStateCallbackType } from "react-native";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { useShallow } from "zustand/shallow";
import { useStoreWithEqualityFn } from "zustand/traditional";
import {
Bot,
ChevronDown,
ShieldAlert,
ShieldCheck,
ShieldOff,
ShieldQuestionMark,
} from "lucide-react-native";
import { Bot, ShieldAlert, ShieldCheck, ShieldOff, ShieldQuestionMark } from "lucide-react-native";
import { ComboboxTrigger } from "@/components/ui/combobox-trigger";
import { type SheetHeader } from "@/components/adaptive-modal-sheet";
import { Combobox, ComboboxItem, type ComboboxOption } from "@/components/ui/combobox";
import { useSessionStore } from "@/stores/session-store";
@@ -198,7 +192,7 @@ function AgentModeControlView({
return (
<>
<Pressable
<ComboboxTrigger
ref={anchorRef}
collapsable={false}
disabled={disabled}
@@ -212,8 +206,7 @@ function AgentModeControlView({
>
{Icon ? <Icon size={theme.iconSize.md} color={iconColor} /> : null}
<Text style={labelStyle}>{selectedModeLabel}</Text>
<ChevronDown size={theme.iconSize.sm} color={iconColor} />
</Pressable>
</ComboboxTrigger>
<Combobox
options={options}
value={selectedMode.id}