refactor: streamline feature addition in BoardView and KanbanBoard

- Removed the add feature shortcut from BoardHeader and integrated the add feature functionality directly into the KanbanBoard and BoardView components.
- Added a floating action button for adding features in the KanbanBoard's backlog column.
- Updated KanbanColumn to support a footer action for enhanced UI consistency.
- Cleaned up unused imports and props related to feature addition.
This commit is contained in:
webdevcody
2026-01-10 13:19:21 -05:00
parent a67b8c6109
commit dd882139f3
4 changed files with 64 additions and 46 deletions

View File

@@ -1153,13 +1153,7 @@ export function BoardView() {
autoMode.stop(); autoMode.stop();
} }
}} }}
onAddFeature={() => setShowAddDialog(true)}
onOpenPlanDialog={() => setShowPlanDialog(true)} onOpenPlanDialog={() => setShowPlanDialog(true)}
addFeatureShortcut={{
key: shortcuts.addFeature,
action: () => setShowAddDialog(true),
description: 'Add new feature',
}}
isMounted={isMounted} isMounted={isMounted}
/> />
@@ -1252,6 +1246,7 @@ export function BoardView() {
featuresWithContext={featuresWithContext} featuresWithContext={featuresWithContext}
runningAutoTasks={runningAutoTasks} runningAutoTasks={runningAutoTasks}
onArchiveAllVerified={() => setShowArchiveAllVerifiedDialog(true)} onArchiveAllVerified={() => setShowArchiveAllVerifiedDialog(true)}
onAddFeature={() => setShowAddDialog(true)}
pipelineConfig={ pipelineConfig={
currentProject?.path ? pipelineConfigByProject[currentProject.path] || null : null currentProject?.path ? pipelineConfigByProject[currentProject.path] || null : null
} }

View File

@@ -1,11 +1,9 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import { HotkeyButton } from '@/components/ui/hotkey-button';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Slider } from '@/components/ui/slider'; import { Slider } from '@/components/ui/slider';
import { Switch } from '@/components/ui/switch'; import { Switch } from '@/components/ui/switch';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Plus, Bot, Wand2, Settings2, GitBranch } from 'lucide-react'; import { Bot, Wand2, Settings2, GitBranch } from 'lucide-react';
import { KeyboardShortcut } from '@/hooks/use-keyboard-shortcuts';
import { UsagePopover } from '@/components/usage-popover'; import { UsagePopover } from '@/components/usage-popover';
import { useAppStore } from '@/store/app-store'; import { useAppStore } from '@/store/app-store';
import { useSetupStore } from '@/store/setup-store'; import { useSetupStore } from '@/store/setup-store';
@@ -20,9 +18,7 @@ interface BoardHeaderProps {
onConcurrencyChange: (value: number) => void; onConcurrencyChange: (value: number) => void;
isAutoModeRunning: boolean; isAutoModeRunning: boolean;
onAutoModeToggle: (enabled: boolean) => void; onAutoModeToggle: (enabled: boolean) => void;
onAddFeature: () => void;
onOpenPlanDialog: () => void; onOpenPlanDialog: () => void;
addFeatureShortcut: KeyboardShortcut;
isMounted: boolean; isMounted: boolean;
} }
@@ -38,9 +34,7 @@ export function BoardHeader({
onConcurrencyChange, onConcurrencyChange,
isAutoModeRunning, isAutoModeRunning,
onAutoModeToggle, onAutoModeToggle,
onAddFeature,
onOpenPlanDialog, onOpenPlanDialog,
addFeatureShortcut,
isMounted, isMounted,
}: BoardHeaderProps) { }: BoardHeaderProps) {
const [showAutoModeSettings, setShowAutoModeSettings] = useState(false); const [showAutoModeSettings, setShowAutoModeSettings] = useState(false);
@@ -176,17 +170,6 @@ export function BoardHeader({
<Wand2 className="w-4 h-4 mr-2" /> <Wand2 className="w-4 h-4 mr-2" />
Plan Plan
</Button> </Button>
<HotkeyButton
size="sm"
onClick={onAddFeature}
hotkey={addFeatureShortcut}
hotkeyActive={false}
data-testid="add-feature-button"
>
<Plus className="w-4 h-4 mr-2" />
Add Feature
</HotkeyButton>
</div> </div>
</div> </div>
); );

View File

@@ -10,6 +10,8 @@ interface KanbanColumnProps {
count: number; count: number;
children: ReactNode; children: ReactNode;
headerAction?: ReactNode; headerAction?: ReactNode;
/** Floating action button at the bottom of the column */
footerAction?: ReactNode;
opacity?: number; opacity?: number;
showBorder?: boolean; showBorder?: boolean;
hideScrollbar?: boolean; hideScrollbar?: boolean;
@@ -24,6 +26,7 @@ export const KanbanColumn = memo(function KanbanColumn({
count, count,
children, children,
headerAction, headerAction,
footerAction,
opacity = 100, opacity = 100,
showBorder = true, showBorder = true,
hideScrollbar = false, hideScrollbar = false,
@@ -79,12 +82,21 @@ export const KanbanColumn = memo(function KanbanColumn({
hideScrollbar && hideScrollbar &&
'[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]', '[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]',
// Smooth scrolling // Smooth scrolling
'scroll-smooth' 'scroll-smooth',
// Add padding at bottom if there's a footer action
footerAction && 'pb-14'
)} )}
> >
{children} {children}
</div> </div>
{/* Floating Footer Action */}
{footerAction && (
<div className="absolute bottom-0 left-0 right-0 z-20 p-2 bg-gradient-to-t from-card/95 via-card/80 to-transparent pt-6">
{footerAction}
</div>
)}
{/* Drop zone indicator when dragging over */} {/* Drop zone indicator when dragging over */}
{isOver && ( {isOver && (
<div className="absolute inset-0 rounded-xl bg-primary/5 pointer-events-none z-5 border-2 border-dashed border-primary/20" /> <div className="absolute inset-0 rounded-xl bg-primary/5 pointer-events-none z-5 border-2 border-dashed border-primary/20" />

View File

@@ -4,7 +4,7 @@ import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { KanbanColumn, KanbanCard } from './components'; import { KanbanColumn, KanbanCard } from './components';
import { Feature } from '@/store/app-store'; import { Feature } from '@/store/app-store';
import { Archive, Settings2, CheckSquare, GripVertical } from 'lucide-react'; import { Archive, Settings2, CheckSquare, GripVertical, Plus } from 'lucide-react';
import { useResponsiveKanban } from '@/hooks/use-responsive-kanban'; import { useResponsiveKanban } from '@/hooks/use-responsive-kanban';
import { getColumnsWithPipeline, type ColumnId } from './constants'; import { getColumnsWithPipeline, type ColumnId } from './constants';
import type { PipelineConfig } from '@automaker/types'; import type { PipelineConfig } from '@automaker/types';
@@ -43,6 +43,7 @@ interface KanbanBoardProps {
featuresWithContext: Set<string>; featuresWithContext: Set<string>;
runningAutoTasks: string[]; runningAutoTasks: string[];
onArchiveAllVerified: () => void; onArchiveAllVerified: () => void;
onAddFeature: () => void;
pipelineConfig: PipelineConfig | null; pipelineConfig: PipelineConfig | null;
onOpenPipelineSettings?: () => void; onOpenPipelineSettings?: () => void;
// Selection mode props // Selection mode props
@@ -78,6 +79,7 @@ export function KanbanBoard({
featuresWithContext, featuresWithContext,
runningAutoTasks, runningAutoTasks,
onArchiveAllVerified, onArchiveAllVerified,
onAddFeature,
pipelineConfig, pipelineConfig,
onOpenPipelineSettings, onOpenPipelineSettings,
isSelectionMode = false, isSelectionMode = false,
@@ -127,6 +129,17 @@ export function KanbanBoard({
Complete All Complete All
</Button> </Button>
) : column.id === 'backlog' ? ( ) : column.id === 'backlog' ? (
<div className="flex items-center gap-1">
<Button
variant="default"
size="sm"
className="h-6 w-6 p-0"
onClick={onAddFeature}
title="Add Feature"
data-testid="add-feature-button"
>
<Plus className="w-3.5 h-3.5" />
</Button>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@@ -147,6 +160,7 @@ export function KanbanBoard({
</> </>
)} )}
</Button> </Button>
</div>
) : column.id === 'in_progress' ? ( ) : column.id === 'in_progress' ? (
<Button <Button
variant="ghost" variant="ghost"
@@ -171,6 +185,20 @@ export function KanbanBoard({
</Button> </Button>
) : undefined ) : undefined
} }
footerAction={
column.id === 'backlog' ? (
<Button
variant="default"
size="sm"
className="w-full h-9 text-sm"
onClick={onAddFeature}
data-testid="add-feature-floating-button"
>
<Plus className="w-4 h-4 mr-2" />
Add Feature
</Button>
) : undefined
}
> >
<SortableContext <SortableContext
items={columnFeatures.map((f) => f.id)} items={columnFeatures.map((f) => f.id)}