feat(ui): add profiles-only mode to simplify model selection

Adds a new setting to show only AI profiles by default, hiding advanced
model tweaking options (Claude SDK, thinking levels, Codex) for a cleaner
UI. Users can toggle advanced options when needed via "Show Advanced" button.

- Added showProfilesOnly setting in app store and settings view
- Modified board-view dialogs to conditionally hide advanced options
- Added toggle buttons to temporarily show advanced options in both
  add and edit feature modals
- Enhanced settings view with proper icons and descriptions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
This commit is contained in:
Kacper
2025-12-10 14:12:13 +01:00
parent 55b8e6858e
commit 1ea18b779e
4 changed files with 141 additions and 11 deletions

View File

@@ -185,6 +185,7 @@ export function BoardView() {
setMaxConcurrency,
defaultSkipTests,
useWorktrees,
showProfilesOnly,
aiProfiles,
} = useAppStore();
const [activeFeature, setActiveFeature] = useState<Feature | null>(null);
@@ -223,6 +224,9 @@ export function BoardView() {
const [followUpPreviewMap, setFollowUpPreviewMap] = useState<ImagePreviewMap>(
() => new Map()
);
// Local state to temporarily show advanced options when profiles-only mode is enabled
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
const [showEditAdvancedOptions, setShowEditAdvancedOptions] = useState(false);
// Make current project available globally for modal
useEffect(() => {
@@ -1619,9 +1623,10 @@ export function BoardView() {
{/* Add Feature Dialog */}
<Dialog open={showAddDialog} onOpenChange={(open) => {
setShowAddDialog(open);
// Clear preview map when dialog closes
// Clear preview map and reset advanced options when dialog closes
if (!open) {
setNewFeaturePreviewMap(new Map());
setShowAdvancedOptions(false);
}
}}>
<DialogContent
@@ -1694,6 +1699,29 @@ export function BoardView() {
{/* Model Tab */}
<TabsContent value="model" className="space-y-4 overflow-y-auto">
{/* Show Advanced Options Toggle - only when profiles-only mode is enabled */}
{showProfilesOnly && (
<div className="flex items-center justify-between p-3 bg-muted/30 rounded-lg border border-border">
<div className="space-y-1">
<p className="text-sm font-medium text-foreground">
Simple Mode Active
</p>
<p className="text-xs text-muted-foreground">
Only showing AI profiles. Advanced model tweaking is hidden.
</p>
</div>
<Button
variant="outline"
size="sm"
onClick={() => setShowAdvancedOptions(!showAdvancedOptions)}
data-testid="show-advanced-options-toggle"
>
<Settings2 className="w-4 h-4 mr-2" />
{showAdvancedOptions ? 'Hide' : 'Show'} Advanced
</Button>
</div>
)}
{/* Quick Select Profile Section */}
{aiProfiles.length > 0 && (
<div className="space-y-3">
@@ -1775,9 +1803,10 @@ export function BoardView() {
)}
{/* Separator */}
{aiProfiles.length > 0 && <div className="border-t border-border" />}
{aiProfiles.length > 0 && (!showProfilesOnly || showAdvancedOptions) && <div className="border-t border-border" />}
{/* Claude Models Section */}
{/* Claude Models Section - Hidden when showProfilesOnly is true and showAdvancedOptions is false */}
{(!showProfilesOnly || showAdvancedOptions) && (
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="flex items-center gap-2">
@@ -1844,11 +1873,13 @@ export function BoardView() {
</div>
)}
</div>
)}
{/* Separator */}
<div className="border-t border-border" />
{(!showProfilesOnly || showAdvancedOptions) && <div className="border-t border-border" />}
{/* Codex Models Section */}
{/* Codex Models Section - Hidden when showProfilesOnly is true and showAdvancedOptions is false */}
{(!showProfilesOnly || showAdvancedOptions) && (
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="flex items-center gap-2">
@@ -1873,6 +1904,7 @@ export function BoardView() {
Codex models do not support thinking levels.
</p>
</div>
)}
</TabsContent>
{/* Testing Tab */}
@@ -1960,7 +1992,12 @@ export function BoardView() {
{/* Edit Feature Dialog */}
<Dialog
open={!!editingFeature}
onOpenChange={() => setEditingFeature(null)}
onOpenChange={(open) => {
if (!open) {
setEditingFeature(null);
setShowEditAdvancedOptions(false);
}
}}
>
<DialogContent compact={!isMaximized} data-testid="edit-feature-dialog">
<DialogHeader>
@@ -2020,6 +2057,29 @@ export function BoardView() {
{/* Model Tab */}
<TabsContent value="model" className="space-y-4 overflow-y-auto">
{/* Show Advanced Options Toggle - only when profiles-only mode is enabled */}
{showProfilesOnly && (
<div className="flex items-center justify-between p-3 bg-muted/30 rounded-lg border border-border">
<div className="space-y-1">
<p className="text-sm font-medium text-foreground">
Simple Mode Active
</p>
<p className="text-xs text-muted-foreground">
Only showing AI profiles. Advanced model tweaking is hidden.
</p>
</div>
<Button
variant="outline"
size="sm"
onClick={() => setShowEditAdvancedOptions(!showEditAdvancedOptions)}
data-testid="edit-show-advanced-options-toggle"
>
<Settings2 className="w-4 h-4 mr-2" />
{showEditAdvancedOptions ? 'Hide' : 'Show'} Advanced
</Button>
</div>
)}
{/* Quick Select Profile Section */}
{aiProfiles.length > 0 && (
<div className="space-y-3">
@@ -2091,9 +2151,10 @@ export function BoardView() {
)}
{/* Separator */}
{aiProfiles.length > 0 && <div className="border-t border-border" />}
{aiProfiles.length > 0 && (!showProfilesOnly || showEditAdvancedOptions) && <div className="border-t border-border" />}
{/* Claude Models Section */}
{/* Claude Models Section - Hidden when showProfilesOnly is true and showEditAdvancedOptions is false */}
{(!showProfilesOnly || showEditAdvancedOptions) && (
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="flex items-center gap-2">
@@ -2161,11 +2222,13 @@ export function BoardView() {
</div>
)}
</div>
)}
{/* Separator */}
<div className="border-t border-border" />
{(!showProfilesOnly || showEditAdvancedOptions) && <div className="border-t border-border" />}
{/* Codex Models Section */}
{/* Codex Models Section - Hidden when showProfilesOnly is true and showEditAdvancedOptions is false */}
{(!showProfilesOnly || showEditAdvancedOptions) && (
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="flex items-center gap-2">
@@ -2191,6 +2254,7 @@ export function BoardView() {
Codex models do not support thinking levels.
</p>
</div>
)}
</TabsContent>
{/* Testing Tab */}

View File

@@ -37,6 +37,7 @@ import {
Folder,
GitBranch,
TestTube,
Settings2,
} from "lucide-react";
import { getElectronAPI } from "@/lib/electron";
import { Checkbox } from "@/components/ui/checkbox";
@@ -73,6 +74,8 @@ export function SettingsView() {
setDefaultSkipTests,
useWorktrees,
setUseWorktrees,
showProfilesOnly,
setShowProfilesOnly,
currentProject,
moveProjectToTrash,
} = useAppStore();
@@ -1283,6 +1286,40 @@ export function SettingsView() {
</p>
</div>
<div className="p-6 space-y-4">
{/* Profiles Only Setting */}
<div className="space-y-3">
<div className="flex items-start space-x-3">
<Checkbox
id="show-profiles-only"
checked={showProfilesOnly}
onCheckedChange={(checked) =>
setShowProfilesOnly(checked === true)
}
className="mt-0.5"
data-testid="show-profiles-only-checkbox"
/>
<div className="space-y-1">
<Label
htmlFor="show-profiles-only"
className="text-foreground cursor-pointer font-medium flex items-center gap-2"
>
<Settings2 className="w-4 h-4 text-brand-500" />
Show profiles only by default
</Label>
<p className="text-xs text-muted-foreground">
When enabled, the Add Feature dialog will show only AI profiles
and hide advanced model tweaking options (Claude SDK, thinking levels,
and OpenAI Codex CLI). This creates a cleaner, less overwhelming UI.
You can always disable this to access advanced settings.
</p>
</div>
</div>
</div>
{/* Separator */}
<div className="border-t border-border" />
{/* Skip Tests Setting */}
<div className="space-y-3">
<div className="flex items-start space-x-3">
<Checkbox
@@ -1297,7 +1334,7 @@ export function SettingsView() {
<div className="space-y-1">
<Label
htmlFor="default-skip-tests"
className="text-foreground cursor-pointer font-medium"
className="text-foreground cursor-pointer font-medium flex items-center gap-2"
>
<TestTube className="w-4 h-4 text-brand-500" />
Skip automated testing by default

View File

@@ -192,6 +192,9 @@ export interface AppState {
// AI Profiles
aiProfiles: AIProfile[];
// Profile Display Settings
showProfilesOnly: boolean; // When true, hide model tweaking options and show only profile selection
// Project Analysis
projectAnalysis: ProjectAnalysis | null;
isAnalyzing: boolean;
@@ -283,6 +286,9 @@ export interface AppActions {
// Worktree Settings actions
setUseWorktrees: (enabled: boolean) => void;
// Profile Display Settings actions
setShowProfilesOnly: (enabled: boolean) => void;
// AI Profile actions
addAIProfile: (profile: Omit<AIProfile, "id">) => void;
updateAIProfile: (id: string, updates: Partial<AIProfile>) => void;
@@ -377,6 +383,7 @@ const initialState: AppState = {
kanbanCardDetailLevel: "standard", // Default to standard detail level
defaultSkipTests: false, // Default to TDD mode (tests enabled)
useWorktrees: false, // Default to disabled (worktree feature is experimental)
showProfilesOnly: false, // Default to showing all options (not profiles only)
aiProfiles: DEFAULT_AI_PROFILES,
projectAnalysis: null,
isAnalyzing: false,
@@ -711,6 +718,9 @@ export const useAppStore = create<AppState & AppActions>()(
// Worktree Settings actions
setUseWorktrees: (enabled) => set({ useWorktrees: enabled }),
// Profile Display Settings actions
setShowProfilesOnly: (enabled) => set({ showProfilesOnly: enabled }),
// AI Profile actions
addAIProfile: (profile) => {
const id = `profile-${Date.now()}-${Math.random()
@@ -766,6 +776,7 @@ export const useAppStore = create<AppState & AppActions>()(
kanbanCardDetailLevel: state.kanbanCardDetailLevel,
defaultSkipTests: state.defaultSkipTests,
useWorktrees: state.useWorktrees,
showProfilesOnly: state.showProfilesOnly,
aiProfiles: state.aiProfiles,
}),
}