feat: move feature action buttons to pending column header

Move the "Add Feature" (+) and "Expand Project" (sparkles) buttons from
the top navigation bar to the Pending column header in the Kanban board.

Changes:
- KanbanColumn: Add optional onAddFeature, onExpandProject, and
  showExpandButton props; render action buttons in column header
- KanbanBoard: Accept and pass action handlers to the Pending column
- App: Remove buttons from header, pass handlers to KanbanBoard

This improves UX by placing feature creation actions contextually near
the pending features they affect. Keyboard shortcuts (N, E) still work.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Auto
2026-01-10 20:26:57 +02:00
parent 117ca89f08
commit 334b655472
3 changed files with 46 additions and 31 deletions

View File

@@ -19,7 +19,7 @@ import { AssistantFAB } from './components/AssistantFAB'
import { AssistantPanel } from './components/AssistantPanel'
import { ExpandProjectModal } from './components/ExpandProjectModal'
import { SettingsModal } from './components/SettingsModal'
import { Plus, Loader2, Sparkles, Settings } from 'lucide-react'
import { Loader2, Settings } from 'lucide-react'
import type { Feature } from './lib/types'
function App() {
@@ -171,31 +171,6 @@ function App() {
{selectedProject && (
<>
<button
onClick={() => setShowAddFeature(true)}
className="neo-btn neo-btn-primary text-sm"
title="Add new feature"
>
<Plus size={18} />
<kbd className="ml-1.5 px-1.5 py-0.5 text-xs bg-black/20 rounded font-mono">
N
</kbd>
</button>
{/* Expand Project - only show if project has features */}
{features && (features.pending.length + features.in_progress.length + features.done.length) > 0 && (
<button
onClick={() => setShowExpandProject(true)}
className="neo-btn bg-[var(--color-neo-progress)] text-black text-sm"
title="Expand project with AI"
>
<Sparkles size={18} />
<kbd className="ml-1.5 px-1.5 py-0.5 text-xs bg-black/20 rounded font-mono">
E
</kbd>
</button>
)}
<AgentControl
projectName={selectedProject}
status={wsState.agentStatus}
@@ -267,6 +242,8 @@ function App() {
<KanbanBoard
features={features}
onFeatureClick={setSelectedFeature}
onAddFeature={() => setShowAddFeature(true)}
onExpandProject={() => setShowExpandProject(true)}
/>
</div>
)}

View File

@@ -4,9 +4,13 @@ import type { Feature, FeatureListResponse } from '../lib/types'
interface KanbanBoardProps {
features: FeatureListResponse | undefined
onFeatureClick: (feature: Feature) => void
onAddFeature?: () => void
onExpandProject?: () => void
}
export function KanbanBoard({ features, onFeatureClick }: KanbanBoardProps) {
export function KanbanBoard({ features, onFeatureClick, onAddFeature, onExpandProject }: KanbanBoardProps) {
const hasFeatures = features && (features.pending.length + features.in_progress.length + features.done.length) > 0
if (!features) {
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
@@ -32,6 +36,9 @@ export function KanbanBoard({ features, onFeatureClick }: KanbanBoardProps) {
features={features.pending}
color="pending"
onFeatureClick={onFeatureClick}
onAddFeature={onAddFeature}
onExpandProject={onExpandProject}
showExpandButton={hasFeatures}
/>
<KanbanColumn
title="In Progress"

View File

@@ -1,4 +1,5 @@
import { FeatureCard } from './FeatureCard'
import { Plus, Sparkles } from 'lucide-react'
import type { Feature } from '../lib/types'
interface KanbanColumnProps {
@@ -7,6 +8,9 @@ interface KanbanColumnProps {
features: Feature[]
color: 'pending' | 'progress' | 'done'
onFeatureClick: (feature: Feature) => void
onAddFeature?: () => void
onExpandProject?: () => void
showExpandButton?: boolean
}
const colorMap = {
@@ -21,6 +25,9 @@ export function KanbanColumn({
features,
color,
onFeatureClick,
onAddFeature,
onExpandProject,
showExpandButton,
}: KanbanColumnProps) {
return (
<div
@@ -32,10 +39,34 @@ export function KanbanColumn({
className="px-4 py-3 border-b-3 border-[var(--color-neo-border)]"
style={{ backgroundColor: colorMap[color] }}
>
<h2 className="font-display text-lg font-bold uppercase flex items-center justify-between text-[var(--color-neo-text)]">
{title}
<span className="neo-badge bg-white text-[var(--color-neo-text)]">{count}</span>
</h2>
<div className="flex items-center justify-between">
<h2 className="font-display text-lg font-bold uppercase flex items-center gap-2 text-[var(--color-neo-text)]">
{title}
<span className="neo-badge bg-white text-[var(--color-neo-text)]">{count}</span>
</h2>
{(onAddFeature || onExpandProject) && (
<div className="flex items-center gap-2">
{onAddFeature && (
<button
onClick={onAddFeature}
className="neo-btn neo-btn-primary text-sm py-1.5 px-2"
title="Add new feature (N)"
>
<Plus size={16} />
</button>
)}
{onExpandProject && showExpandButton && (
<button
onClick={onExpandProject}
className="neo-btn bg-[var(--color-neo-progress)] text-black text-sm py-1.5 px-2"
title="Expand project with AI (E)"
>
<Sparkles size={16} />
</button>
)}
</div>
)}
</div>
</div>
{/* Cards */}