Skip to content

Commit 3714cad

Browse files
committed
fix: address additional PR review feedback
- Fix Textarea controlled/uncontrolled warning with default value - Preserve IDs in useEffect sync to avoid unnecessary remounts - Consolidate lucide-react imports - Add JSDoc note about tag attributes limitation in xml-utils.ts - Remove redundant disabled prop from SpecModeTabs
1 parent e9bffb9 commit 3714cad

3 files changed

Lines changed: 22 additions & 10 deletions

File tree

apps/ui/src/components/views/spec-view.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,7 @@ export function SpecView() {
200200
{/* Mode tabs bar - inside the content area, centered */}
201201
{!isProcessing && (
202202
<div className="flex items-center justify-center px-4 py-2 border-b border-border bg-muted/30 relative">
203-
<SpecModeTabs
204-
mode={mode}
205-
onModeChange={handleModeChange}
206-
isParseValid={isParseValid}
207-
disabled={isProcessing}
208-
/>
203+
<SpecModeTabs mode={mode} onModeChange={handleModeChange} isParseValid={isParseValid} />
209204
{/* Show parse error indicator - positioned to the right */}
210205
{!isParseValid && parseErrors.length > 0 && (
211206
<span className="absolute right-4 text-xs text-destructive">

apps/ui/src/components/views/spec-view/components/edit-mode/roadmap-section.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Plus, X } from 'lucide-react';
1+
import { Plus, X, Map as MapIcon } from 'lucide-react';
22
import { useState, useRef, useEffect } from 'react';
33
import { Button } from '@/components/ui/button';
44
import { Input } from '@/components/ui/input';
@@ -12,7 +12,6 @@ import {
1212
SelectTrigger,
1313
SelectValue,
1414
} from '@/components/ui/select';
15-
import { Map as MapIcon } from 'lucide-react';
1615
import type { SpecOutput } from '@automaker/spec-parser';
1716

1817
type RoadmapPhase = NonNullable<SpecOutput['implementation_roadmap']>[number];
@@ -90,7 +89,7 @@ function PhaseCard({ phase, onChange, onRemove }: PhaseCardProps) {
9089
<div>
9190
<Label className="sr-only">Description</Label>
9291
<Textarea
93-
value={phase.description}
92+
value={phase.description ?? ''}
9493
onChange={(e) => handleDescriptionChange(e.target.value)}
9594
placeholder="Describe what this phase involves..."
9695
rows={2}
@@ -120,12 +119,24 @@ export function RoadmapSection({ phases, onChange }: RoadmapSectionProps) {
120119
const isInternalChange = useRef(false);
121120

122121
// Sync external phases to internal items when phases change externally
122+
// Preserve existing IDs where possible to avoid unnecessary remounts
123123
useEffect(() => {
124124
if (isInternalChange.current) {
125125
isInternalChange.current = false;
126126
return;
127127
}
128-
setItems(phases.map(phaseToInternal));
128+
setItems((currentItems) => {
129+
return phases.map((phase, index) => {
130+
// Try to find existing item by index (positional matching)
131+
const existingItem = currentItems[index];
132+
if (existingItem) {
133+
// Reuse the existing ID, update the phase data
134+
return { ...phase, _id: existingItem._id };
135+
}
136+
// New phase - generate new ID
137+
return phaseToInternal(phase);
138+
});
139+
});
129140
}, [phases]);
130141

131142
const handleAdd = () => {

libs/spec-parser/src/xml-utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ function escapeRegExp(value: string): string {
4141
/**
4242
* Extract the content of a specific XML section.
4343
*
44+
* Note: This function only matches bare tags without attributes.
45+
* Tags with attributes (e.g., `<tag id="1">`) are not supported.
46+
*
4447
* @param xmlContent - The full XML content
4548
* @param tagName - The tag name to extract (e.g., 'implemented_features')
4649
* @returns The content between the tags, or null if not found
@@ -55,6 +58,9 @@ export function extractXmlSection(xmlContent: string, tagName: string): string |
5558
/**
5659
* Extract all values from repeated XML elements.
5760
*
61+
* Note: This function only matches bare tags without attributes.
62+
* Tags with attributes (e.g., `<tag id="1">`) are not supported.
63+
*
5864
* @param xmlContent - The XML content to search
5965
* @param tagName - The tag name to extract values from
6066
* @returns Array of extracted values (unescaped and trimmed)

0 commit comments

Comments
 (0)