feat(FN-779): make inline editor taller with 4-row default and mount-time resize

- Increase inline editor textarea default rows from 1 to 4 for better multi-line editing
- Add mount-time auto-resize to fit content on initial render
- Add regression tests for taller inline editor behavior
- Update documentation to reflect the new taller editor defaults
This commit is contained in:
gsxdsm
2026-04-03 11:23:53 -07:00
parent d55e6a4431
commit 18335ab2a5
4 changed files with 59 additions and 6 deletions

View File

@@ -161,10 +161,16 @@ function TaskCardComponent({
setEditDescription(task.description || "");
}, [task.id, task.description]);
// Auto-focus on description textarea when entering edit mode
// Auto-focus and auto-resize description textarea when entering edit mode
useEffect(() => {
if (isEditing) {
descTextareaRef.current?.focus();
if (isEditing && descTextareaRef.current) {
const el = descTextareaRef.current;
el.focus();
// Apply the same resize logic used in handleDescChange so the textarea
// opens at the correct height for existing long descriptions without
// requiring the user to type first.
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
}
}, [isEditing]);
@@ -511,7 +517,7 @@ function TaskCardComponent({
onKeyDown={handleDescKeyDown}
onBlur={handleBlur}
disabled={isSaving}
rows={1}
rows={4}
/>
{isSaving && (
<div className="card-edit-loading">

View File

@@ -1387,6 +1387,53 @@ describe("TaskCard inline editing", () => {
expect(screen.queryByPlaceholderText(/Task title/i)).toBeNull();
expect(screen.getByPlaceholderText(/Task description/i)).toBeDefined();
});
it("opens the description textarea with 4 visible rows", () => {
const task = makeEditableTask({ description: "Some text" });
render(
<TaskCard
task={task}
onOpenDetail={vi.fn()}
addToast={noopToast}
onUpdateTask={noopUpdateTask}
/>
);
// Enter edit mode
const card = document.querySelector('[data-id="FN-099"]');
fireEvent.doubleClick(card!);
const descTextarea = screen.getByPlaceholderText(/Task description/i) as HTMLTextAreaElement;
expect(descTextarea).toBeDefined();
expect(descTextarea.getAttribute("rows")).toBe("4");
});
it("applies mount-time auto-resize for existing long descriptions", () => {
// A multi-line description that would exceed the default 4-row height
const longDescription = Array(10).fill("This is a line of description text.").join("\n");
const task = makeEditableTask({ description: longDescription });
render(
<TaskCard
task={task}
onOpenDetail={vi.fn()}
addToast={noopToast}
onUpdateTask={noopUpdateTask}
/>
);
// Enter edit mode
const card = document.querySelector('[data-id="FN-099"]');
fireEvent.doubleClick(card!);
const descTextarea = screen.getByPlaceholderText(/Task description/i) as HTMLTextAreaElement;
// The mount-time resize effect sets height to scrollHeight + "px".
// In JSDOM, scrollHeight is 0 (no real layout), so the style ends up
// as "0px" — but the important thing is the effect *did* set the
// height property, proving the auto-resize logic runs on mount.
expect(descTextarea.style.height).not.toBe("");
});
});
/**