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

View File

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

View File

@@ -10,6 +10,8 @@ interface KanbanColumnProps {
count: number;
children: ReactNode;
headerAction?: ReactNode;
/** Floating action button at the bottom of the column */
footerAction?: ReactNode;
opacity?: number;
showBorder?: boolean;
hideScrollbar?: boolean;
@@ -24,6 +26,7 @@ export const KanbanColumn = memo(function KanbanColumn({
count,
children,
headerAction,
footerAction,
opacity = 100,
showBorder = true,
hideScrollbar = false,
@@ -79,12 +82,21 @@ export const KanbanColumn = memo(function KanbanColumn({
hideScrollbar &&
'[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]',
// Smooth scrolling
'scroll-smooth'
'scroll-smooth',
// Add padding at bottom if there's a footer action
footerAction && 'pb-14'
)}
>
{children}
</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 */}
{isOver && (
<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 { KanbanColumn, KanbanCard } from './components';
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 { getColumnsWithPipeline, type ColumnId } from './constants';
import type { PipelineConfig } from '@automaker/types';
@@ -43,6 +43,7 @@ interface KanbanBoardProps {
featuresWithContext: Set<string>;
runningAutoTasks: string[];
onArchiveAllVerified: () => void;
onAddFeature: () => void;
pipelineConfig: PipelineConfig | null;
onOpenPipelineSettings?: () => void;
// Selection mode props
@@ -78,6 +79,7 @@ export function KanbanBoard({
featuresWithContext,
runningAutoTasks,
onArchiveAllVerified,
onAddFeature,
pipelineConfig,
onOpenPipelineSettings,
isSelectionMode = false,
@@ -127,26 +129,38 @@ export function KanbanBoard({
Complete All
</Button>
) : column.id === 'backlog' ? (
<Button
variant="ghost"
size="sm"
className={`h-6 px-2 text-xs ${isSelectionMode ? 'text-primary bg-primary/10' : 'text-muted-foreground hover:text-foreground'}`}
onClick={onToggleSelectionMode}
title={isSelectionMode ? 'Switch to Drag Mode' : 'Select Multiple'}
data-testid="selection-mode-button"
>
{isSelectionMode ? (
<>
<GripVertical className="w-3.5 h-3.5 mr-1" />
Drag
</>
) : (
<>
<CheckSquare className="w-3.5 h-3.5 mr-1" />
Select
</>
)}
</Button>
<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
variant="ghost"
size="sm"
className={`h-6 px-2 text-xs ${isSelectionMode ? 'text-primary bg-primary/10' : 'text-muted-foreground hover:text-foreground'}`}
onClick={onToggleSelectionMode}
title={isSelectionMode ? 'Switch to Drag Mode' : 'Select Multiple'}
data-testid="selection-mode-button"
>
{isSelectionMode ? (
<>
<GripVertical className="w-3.5 h-3.5 mr-1" />
Drag
</>
) : (
<>
<CheckSquare className="w-3.5 h-3.5 mr-1" />
Select
</>
)}
</Button>
</div>
) : column.id === 'in_progress' ? (
<Button
variant="ghost"
@@ -171,6 +185,20 @@ export function KanbanBoard({
</Button>
) : 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
items={columnFeatures.map((f) => f.id)}