Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/mobile/src/app/(app)/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const TAB_BAR_ICON_STYLE = {
} satisfies ViewStyle;
const TAB_BAR_LABEL_STYLE = {
fontFamily: 'JetBrainsMono_500Medium',
fontSize: 10,
letterSpacing: 0,
fontSize: 11,
letterSpacing: 0.2,
marginTop: 2,
minWidth: TAB_BAR_ITEM_CONTENT_WIDTH,
textAlign: 'center',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,17 @@ export default function ModelListScreen() {
<Text className="text-xs text-muted-foreground">{item.id}</Text>
</View>
{item.supportsVision && <Eye size={14} color={colors.mutedForeground} />}
{selected && <Check size={16} color="#3b82f6" />}
{selected && <Check size={16} color={colors.primary} />}
</Pressable>
);
},
[currentModel, handleSelect, mutations.updateModel.isPending, colors.mutedForeground]
[
currentModel,
handleSelect,
mutations.updateModel.isPending,
colors.mutedForeground,
colors.primary,
]
);

const sections = [
Expand Down
8 changes: 8 additions & 0 deletions apps/mobile/src/components/agents/chat-composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ export function ChatComposer({
<Pressable
onPress={handleStop}
disabled={disabled}
hitSlop={6}
accessibilityRole="button"
accessibilityLabel="Stop generating"
accessibilityState={{ disabled }}
className="h-8 w-8 items-center justify-center rounded-full bg-neutral-400 active:opacity-70 dark:bg-neutral-500"
>
<Square size={14} color="white" fill="white" />
Expand All @@ -174,6 +178,10 @@ export function ChatComposer({
<Pressable
onPress={handleSend}
disabled={!canSend}
hitSlop={6}
accessibilityRole="button"
accessibilityLabel="Send message"
accessibilityState={{ disabled: !canSend }}
className={`h-8 w-8 items-center justify-center rounded-full active:opacity-70 ${
canSend ? 'bg-accent-soft' : 'bg-muted'
}`}
Expand Down
20 changes: 12 additions & 8 deletions apps/mobile/src/components/agents/child-session-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Animated, { FadeIn, LinearTransition } from 'react-native-reanimated';
import { type Part, type StoredMessage, type ToolPart } from 'cloud-agent-sdk';

import { Text } from '@/components/ui/text';
import { useThemeColors } from '@/lib/hooks/use-theme-colors';
import { type ThemeColors, useThemeColors } from '@/lib/hooks/use-theme-colors';

import { MessageErrorBoundary } from './message-error-boundary';
import { isToolPart } from './part-types';
Expand Down Expand Up @@ -116,7 +116,7 @@ export function ChildSessionSection({

const currentTool = isRunning ? getCurrentRunningTool(childMessages) : undefined;

const borderColor = getStatusBorderColor(status, colors.destructive);
const borderColor = getStatusBorderColor(status, colors);

const handlePress = useCallback(() => {
setIsExpanded(prev => !prev);
Expand All @@ -142,15 +142,19 @@ export function ChildSessionSection({
style={{ transform: [{ rotate: isExpanded ? '90deg' : '0deg' }] }}
/>

{isRunning ? <Loader2 size={16} color="#3b82f6" /> : <Bot size={16} color="#3b82f6" />}
{isRunning ? (
<Loader2 size={16} color={colors.agentSky} />
) : (
<Bot size={16} color={colors.agentSky} />
)}

<View className="flex-1">
<Text className="text-sm text-foreground" numberOfLines={1}>
{subtitle}
</Text>
{currentTool ? (
<Text className="text-xs text-muted-foreground" numberOfLines={1}>
<Text className="text-xs text-blue-500">{currentTool.tool}</Text>
<Text className="text-xs text-agent-sky">{currentTool.tool}</Text>
{currentTool.context ? ` ${currentTool.context}` : ''}
</Text>
) : null}
Expand Down Expand Up @@ -261,14 +265,14 @@ function ChildSessionMessage({
);
}

function getStatusBorderColor(status: string, destructiveColor: string): string {
function getStatusBorderColor(status: string, colors: ThemeColors): string {
if (status === 'error') {
return destructiveColor;
return colors.destructive;
}
if (status === 'completed') {
return '#22c55e';
return colors.good;
}
return '#3b82f6';
return colors.agentSky;
}

function StatusBadge({ status }: Readonly<{ status: string }>) {
Expand Down
9 changes: 7 additions & 2 deletions apps/mobile/src/components/agents/session-list-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,22 @@ export function AgentSessionListScreen() {
onPress={() => {
router.push(getNewAgentSessionPath(organizationId) as Href);
}}
hitSlop={8}
// right slop capped so the expanded targets don't overlap inside the 16px gap
hitSlop={{ top: 11, bottom: 11, left: 11, right: 8 }}
accessibilityRole="button"
accessibilityLabel="New session"
className="active:opacity-70"
>
<Plus size={22} color={colors.foreground} />
</Pressable>
<Pressable
onPress={() => {
setShowFilterModal(true);
}}
hitSlop={8}
hitSlop={{ top: 12, bottom: 12, left: 8, right: 12 }}
accessibilityRole="button"
accessibilityLabel="Filter sessions"
className="active:opacity-70"
>
<SlidersHorizontal
size={20}
Expand Down
29 changes: 20 additions & 9 deletions apps/mobile/src/components/kiloclaw/model-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Skeleton } from '@/components/ui/skeleton';
import { Text } from '@/components/ui/text';
import { useInstanceContext } from '@/lib/hooks/use-instance-context';
import { useKiloClawConfig, useKiloClawMutations } from '@/lib/hooks/use-kiloclaw-queries';
import { useThemeColors } from '@/lib/hooks/use-theme-colors';
import { addModelPrefix, stripModelPrefix } from '@/lib/model-id';

type AutoModelCard = {
Expand All @@ -14,7 +15,7 @@ type AutoModelCard = {
description: string;
icon: LucideIcon;
iconBg: string;
iconColor: string;
iconColorKey: 'agentSky' | 'agentYuki';
cost: number;
performance: number;
performanceDotColor: string;
Expand All @@ -26,8 +27,8 @@ const AUTO_MODEL_CARDS: AutoModelCard[] = [
label: 'Frontier',
description: 'Highest performance. Routes to frontier models with reasoning.',
icon: Zap,
iconBg: 'bg-purple-500/20',
iconColor: '#a855f7',
iconBg: 'bg-agent-yuki-tile-bg',
iconColorKey: 'agentYuki',
cost: 3,
performance: 3,
performanceDotColor: 'bg-purple-400',
Expand All @@ -37,8 +38,8 @@ const AUTO_MODEL_CARDS: AutoModelCard[] = [
label: 'Balanced',
description: 'Smart balance of speed and capability at lower cost.',
icon: Scale,
iconBg: 'bg-blue-500/20',
iconColor: '#3b82f6',
iconBg: 'bg-agent-sky-tile-bg',
iconColorKey: 'agentSky',
cost: 2,
performance: 2,
performanceDotColor: 'bg-blue-400',
Expand Down Expand Up @@ -87,6 +88,7 @@ export function ModelPicker() {
const { organizationId } = useInstanceContext(instanceId);
const { data: config, isLoading } = useKiloClawConfig(organizationId);
const mutations = useKiloClawMutations(organizationId);
const colors = useThemeColors();

const currentModel = stripModelPrefix(config?.kilocodeDefaultModel);
const isAutoModel = AUTO_MODEL_IDS.has(currentModel);
Expand Down Expand Up @@ -119,19 +121,26 @@ export function ModelPicker() {
return (
<Pressable
key={card.id}
className={`relative gap-3 rounded-lg border p-4 ${selected ? 'border-blue-500 bg-blue-500/5' : 'border-border bg-secondary'}`}
className={`relative gap-3 rounded-lg border p-4 active:opacity-80 ${
selected
? 'border-primary bg-neutral-100 dark:bg-neutral-800'
: 'border-border bg-secondary'
}`}
disabled={mutations.updateModel.isPending}
onPress={() => {
handleSelectAutoModel(card.id);
}}
accessibilityRole="button"
accessibilityState={{ selected, disabled: mutations.updateModel.isPending }}
accessibilityLabel={`${card.label} auto model`}
>
{selected && (
<View className="absolute right-3 top-3">
<CheckCircle2 size={20} color="#3b82f6" />
<CheckCircle2 size={20} color={colors.primary} />
</View>
)}
<View className={`h-9 w-9 items-center justify-center rounded-lg ${card.iconBg}`}>
<Icon size={20} color={card.iconColor} />
<Icon size={20} color={colors[card.iconColorKey]} />
</View>
<View className="gap-1">
<Text className="font-semibold">{card.label}</Text>
Expand Down Expand Up @@ -161,10 +170,12 @@ export function ModelPicker() {

{/* Navigate to full model list */}
<Pressable
className="items-center py-2 active:opacity-70"
className="min-h-11 items-center justify-center py-2 active:opacity-70"
onPress={() => {
router.push(`/(app)/kiloclaw/${instanceId}/settings/model-list` as Href);
}}
accessibilityRole="link"
accessibilityLabel="Browse all 500+ models"
>
<Text className="text-sm text-muted-foreground">or select from 500+ models</Text>
</Pressable>
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/src/components/profile-avatar-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function ProfileAvatarButton() {
}}
accessibilityRole="button"
accessibilityLabel="Open profile"
className="h-11 w-11 items-center justify-center rounded-full active:opacity-70"
>
<CircleUserRound size={22} color={colors.foreground} />
</Pressable>
Expand Down
5 changes: 4 additions & 1 deletion apps/mobile/src/components/screen-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ export function ScreenHeader({
titleNode = onTitlePress ? (
<Pressable
onPress={onTitlePress}
hitSlop={8}
hitSlop={13}
accessibilityRole="button"
accessibilityLabel={title ? `Open menu for ${title}` : 'Open menu'}
className="flex-row items-center gap-1 active:opacity-70"
>
{titleText}
Expand All @@ -89,6 +91,7 @@ export function ScreenHeader({
}
}}
hitSlop={12}
accessibilityRole="button"
accessibilityLabel="Go back"
className="-ml-1 mr-1 active:opacity-70"
>
Expand Down
6 changes: 2 additions & 4 deletions apps/mobile/src/components/ui/configure-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,8 @@ export function ConfigureRow({
<Icon size={16} color={iconColor} />
</View>
<View className="flex-1">
<Text className="text-[14px] font-medium text-foreground">{title}</Text>
{subtitle ? (
<Text className="mt-0.5 text-[11.5px] text-muted-foreground">{subtitle}</Text>
) : null}
<Text className="text-sm font-medium text-foreground">{title}</Text>
{subtitle ? <Text className="mt-0.5 text-xs text-muted-foreground">{subtitle}</Text> : null}
</View>
{trailing ?? <ChevronRight size={14} color={colors.mutedForeground} />}
</View>
Expand Down
9 changes: 3 additions & 6 deletions apps/mobile/src/components/ui/session-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,18 @@ export function SessionRow({
<Eyebrow className={color.hueTextClass}>{agentLabel}</Eyebrow>
{live && <StatusDot tone="good" glow />}
{!live && meta && (
<Text variant="mono" className="text-[10.5px] text-ink2">
<Text variant="mono" className="text-xs text-ink2">
{meta}
</Text>
)}
</View>
<Text
className="text-[14.5px] font-medium tracking-tight leading-[19px] text-foreground"
numberOfLines={1}
>
<Text className="text-sm font-medium tracking-tight text-foreground" numberOfLines={1}>
{title}
</Text>
{subtitle ? (
<Text
variant="mono"
className="mt-1 text-[10.5px] tracking-[0.3px] text-muted-soft"
className="mt-1 text-xs tracking-[0.3px] text-muted-soft"
numberOfLines={1}
>
{subtitle}
Expand Down