feat: enhance feature dialogs with planning mode tooltips

- Integrated Tooltip components into AddFeatureDialog, EditFeatureDialog, and MassEditDialog to provide user guidance on planning mode availability.
- Updated the rendering logic for planning mode selection to conditionally display tooltips when planning modes are not supported.
- Improved user experience by clarifying the conditions under which planning modes can be utilized.
This commit is contained in:
Kacper
2026-01-10 20:08:17 +01:00
parent 555523df38
commit e64a850f57
3 changed files with 179 additions and 91 deletions

View File

@@ -53,6 +53,7 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'; } from '@/components/ui/dropdown-menu';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { import {
getAncestors, getAncestors,
formatAncestorContextForPrompt, formatAncestorContextForPrompt,
@@ -492,23 +493,44 @@ export function AddFeatureDialog({
/> />
</div> </div>
<div <div className="grid gap-3 grid-cols-2">
className={cn( <div className="space-y-1.5">
'grid gap-3', <Label
modelSupportsPlanningMode ? 'grid-cols-2' : 'grid-cols-1' className={cn(
)} 'text-xs text-muted-foreground',
> !modelSupportsPlanningMode && 'opacity-50'
{modelSupportsPlanningMode && ( )}
<div className="space-y-1.5"> >
<Label className="text-xs text-muted-foreground">Planning</Label> Planning
</Label>
{modelSupportsPlanningMode ? (
<PlanningModeSelect <PlanningModeSelect
mode={planningMode} mode={planningMode}
onModeChange={setPlanningMode} onModeChange={setPlanningMode}
testIdPrefix="add-feature-planning" testIdPrefix="add-feature-planning"
compact compact
/> />
</div> ) : (
)} <TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div>
<PlanningModeSelect
mode="skip"
onModeChange={() => {}}
testIdPrefix="add-feature-planning"
compact
disabled
/>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Planning modes are only available for Claude Provider</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
</div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<Label className="text-xs text-muted-foreground">Options</Label> <Label className="text-xs text-muted-foreground">Options</Label>
<div className="flex flex-col gap-2 pt-1"> <div className="flex flex-col gap-2 pt-1">
@@ -526,28 +548,32 @@ export function AddFeatureDialog({
Run tests Run tests
</Label> </Label>
</div> </div>
{modelSupportsPlanningMode && ( <div className="flex items-center gap-2">
<div className="flex items-center gap-2"> <Checkbox
<Checkbox id="add-feature-require-approval"
id="add-feature-require-approval" checked={requirePlanApproval}
checked={requirePlanApproval} onCheckedChange={(checked) => setRequirePlanApproval(!!checked)}
onCheckedChange={(checked) => setRequirePlanApproval(!!checked)} disabled={
disabled={planningMode === 'skip' || planningMode === 'lite'} !modelSupportsPlanningMode ||
data-testid="add-feature-require-approval-checkbox" planningMode === 'skip' ||
/> planningMode === 'lite'
<Label }
htmlFor="add-feature-require-approval" data-testid="add-feature-require-approval-checkbox"
className={cn( />
'text-xs font-normal', <Label
planningMode === 'skip' || planningMode === 'lite' htmlFor="add-feature-require-approval"
? 'cursor-not-allowed text-muted-foreground' className={cn(
: 'cursor-pointer' 'text-xs font-normal',
)} !modelSupportsPlanningMode ||
> planningMode === 'skip' ||
Require approval planningMode === 'lite'
</Label> ? 'cursor-not-allowed text-muted-foreground'
</div> : 'cursor-pointer'
)} )}
>
Require approval
</Label>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -52,6 +52,7 @@ import {
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'; } from '@/components/ui/dropdown-menu';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { DependencyTreeDialog } from './dependency-tree-dialog'; import { DependencyTreeDialog } from './dependency-tree-dialog';
import { isClaudeModel, supportsReasoningEffort } from '@automaker/types'; import { isClaudeModel, supportsReasoningEffort } from '@automaker/types';
@@ -516,23 +517,44 @@ export function EditFeatureDialog({
/> />
</div> </div>
<div <div className="grid gap-3 grid-cols-2">
className={cn( <div className="space-y-1.5">
'grid gap-3', <Label
modelSupportsPlanningMode ? 'grid-cols-2' : 'grid-cols-1' className={cn(
)} 'text-xs text-muted-foreground',
> !modelSupportsPlanningMode && 'opacity-50'
{modelSupportsPlanningMode && ( )}
<div className="space-y-1.5"> >
<Label className="text-xs text-muted-foreground">Planning</Label> Planning
</Label>
{modelSupportsPlanningMode ? (
<PlanningModeSelect <PlanningModeSelect
mode={planningMode} mode={planningMode}
onModeChange={setPlanningMode} onModeChange={setPlanningMode}
testIdPrefix="edit-feature-planning" testIdPrefix="edit-feature-planning"
compact compact
/> />
</div> ) : (
)} <TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div>
<PlanningModeSelect
mode="skip"
onModeChange={() => {}}
testIdPrefix="edit-feature-planning"
compact
disabled
/>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Planning modes are only available for Claude Provider</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
</div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<Label className="text-xs text-muted-foreground">Options</Label> <Label className="text-xs text-muted-foreground">Options</Label>
<div className="flex flex-col gap-2 pt-1"> <div className="flex flex-col gap-2 pt-1">
@@ -552,28 +574,32 @@ export function EditFeatureDialog({
Run tests Run tests
</Label> </Label>
</div> </div>
{modelSupportsPlanningMode && ( <div className="flex items-center gap-2">
<div className="flex items-center gap-2"> <Checkbox
<Checkbox id="edit-feature-require-approval"
id="edit-feature-require-approval" checked={requirePlanApproval}
checked={requirePlanApproval} onCheckedChange={(checked) => setRequirePlanApproval(!!checked)}
onCheckedChange={(checked) => setRequirePlanApproval(!!checked)} disabled={
disabled={planningMode === 'skip' || planningMode === 'lite'} !modelSupportsPlanningMode ||
data-testid="edit-feature-require-approval-checkbox" planningMode === 'skip' ||
/> planningMode === 'lite'
<Label }
htmlFor="edit-feature-require-approval" data-testid="edit-feature-require-approval-checkbox"
className={cn( />
'text-xs font-normal', <Label
planningMode === 'skip' || planningMode === 'lite' htmlFor="edit-feature-require-approval"
? 'cursor-not-allowed text-muted-foreground' className={cn(
: 'cursor-pointer' 'text-xs font-normal',
)} !modelSupportsPlanningMode ||
> planningMode === 'skip' ||
Require approval planningMode === 'lite'
</Label> ? 'cursor-not-allowed text-muted-foreground'
</div> : 'cursor-pointer'
)} )}
>
Require approval
</Label>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -15,8 +15,9 @@ import { modelSupportsThinking } from '@/lib/utils';
import { Feature, ModelAlias, ThinkingLevel, PlanningMode } from '@/store/app-store'; import { Feature, ModelAlias, ThinkingLevel, PlanningMode } from '@/store/app-store';
import { TestingTabContent, PrioritySelect, PlanningModeSelect } from '../shared'; import { TestingTabContent, PrioritySelect, PlanningModeSelect } from '../shared';
import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector'; import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector';
import { isCursorModel, type PhaseModelEntry } from '@automaker/types'; import { isCursorModel, isClaudeModel, type PhaseModelEntry } from '@automaker/types';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
interface MassEditDialogProps { interface MassEditDialogProps {
open: boolean; open: boolean;
@@ -167,6 +168,7 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
const hasAnyApply = Object.values(applyState).some(Boolean); const hasAnyApply = Object.values(applyState).some(Boolean);
const isCurrentModelCursor = isCursorModel(model); const isCurrentModelCursor = isCursorModel(model);
const modelAllowsThinking = !isCurrentModelCursor && modelSupportsThinking(model); const modelAllowsThinking = !isCurrentModelCursor && modelSupportsThinking(model);
const modelSupportsPlanningMode = isClaudeModel(model);
return ( return (
<Dialog open={open} onOpenChange={(open) => !open && onClose()}> <Dialog open={open} onOpenChange={(open) => !open && onClose()}>
@@ -205,30 +207,64 @@ export function MassEditDialog({ open, onClose, selectedFeatures, onApply }: Mas
<div className="border-t border-border" /> <div className="border-t border-border" />
{/* Planning Mode */} {/* Planning Mode */}
<FieldWrapper {modelSupportsPlanningMode ? (
label="Planning Mode" <FieldWrapper
isMixed={mixedValues.planningMode || mixedValues.requirePlanApproval} label="Planning Mode"
willApply={applyState.planningMode || applyState.requirePlanApproval} isMixed={mixedValues.planningMode || mixedValues.requirePlanApproval}
onApplyChange={(apply) => willApply={applyState.planningMode || applyState.requirePlanApproval}
setApplyState((prev) => ({ onApplyChange={(apply) =>
...prev, setApplyState((prev) => ({
planningMode: apply, ...prev,
requirePlanApproval: apply, planningMode: apply,
})) requirePlanApproval: apply,
} }))
> }
<PlanningModeSelect >
mode={planningMode} <PlanningModeSelect
onModeChange={(newMode) => { mode={planningMode}
setPlanningMode(newMode); onModeChange={(newMode) => {
// Auto-suggest approval based on mode, but user can override setPlanningMode(newMode);
setRequirePlanApproval(newMode === 'spec' || newMode === 'full'); // Auto-suggest approval based on mode, but user can override
}} setRequirePlanApproval(newMode === 'spec' || newMode === 'full');
requireApproval={requirePlanApproval} }}
onRequireApprovalChange={setRequirePlanApproval} requireApproval={requirePlanApproval}
testIdPrefix="mass-edit-planning" onRequireApprovalChange={setRequirePlanApproval}
/> testIdPrefix="mass-edit-planning"
</FieldWrapper> />
</FieldWrapper>
) : (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div
className={cn(
'p-3 rounded-lg border transition-colors border-border bg-muted/20 opacity-50 cursor-not-allowed'
)}
>
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<Checkbox checked={false} disabled className="opacity-50" />
<Label className="text-sm font-medium text-muted-foreground">
Planning Mode
</Label>
</div>
</div>
<div className="opacity-50 pointer-events-none">
<PlanningModeSelect
mode="skip"
onModeChange={() => {}}
testIdPrefix="mass-edit-planning"
disabled
/>
</div>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Planning modes are only available for Claude Provider</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{/* Priority */} {/* Priority */}
<FieldWrapper <FieldWrapper