feat(kanban): wrap card text and support multi-line editing #66
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard!66
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "development_kanban_card_multiline_text"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Kanban cards now wrap long text across multiple lines and auto-grow to fit, and the inline editor supports multi-line input. Base
cardHeightin state remains the slider/transformer-controlled minimum; per-card actual heights are re-derived each render fromcard.text,textFs, andcolW - 50, never persisted.Related Issue
Closes #52
Changes
crates/hero_whiteboard_ui/static/web/js/whiteboard/kanban.jscardTextswitched towrap: 'word'andellipsisremoved. Text width unchanged atcolW - 50.renderKanbannow does a two-pass layout: for every column it measures all cards and stores{heights[], offsets[]}in a module-levelWeakMap<col, layout>.totalHis derived from the tallest stack.renderColumnandrenderCardread the layout back from the WeakMap.renderCardsignature extended withcardYLocal, actualCardH;cardRect.heightandmenuHit.heightuse the per-card actual height.cardGroup.on('dragend')computes per-card midpoints from the target column's layout, so reordering and cross-column drops work with variable-height cards. Defensive fallback to the uniform formula on cache miss.editInlinegains amultilineflag. Multi-line branch:<textarea>, auto-grow oninput,Shift+Enterfor newlines,Enter/blurcommit,Escapecancel. Single-line<input>path preserved unchanged for board-title and column-title edits.multiline: true.Preserved behaviors
textFs/menuFsstill derive from the basecardH.cardRect.on('click tap')still mutates stroke/strokeWidth directly, preserving Konva dblclick identity.state.cardHeightfrom livesy; downstreamrenderKanbanre-measures wrapped text and re-stacks.showCardMenustill passescardTextdirectly; Edit call now includes the newmultiline: true.Out of scope
card.textremains a plain string;\nround-trips through JSON.shortcuts.js,tools.js,properties.js, or CSS. The whiteboard's global key handler already short-circuits on INPUT/TEXTAREA targets, so Delete/Backspace/Enter shortcuts don't fire while typing.colWidth,cardHeight) — no per-card height in the wire format.Test Results
cargo check --workspace: passcargo test --workspace --lib: passcargo clippy --workspace -- -D warnings: passcargo fmt --check: passManual QA required: wrap rendering, stacking under tall cards, drag-drop into variable-height columns, textarea editing (Enter commit, Shift+Enter newline, Escape cancel), persistence across reload, and all preserved behaviors.
Card text now word-wraps instead of truncating with an ellipsis, and cards auto-grow vertically to fit wrapped or explicitly multi-line content. Base cardHeight in state remains the slider/transformer- controlled minimum and is not affected by the new auto-grow; per-card actual heights are re-derived every render from the text, font size, and text width. renderKanban now does a two-pass layout: it measures every column's cards up-front, stores {heights[], offsets[]} per column in a module- level WeakMap, and computes the column-background height from the tallest stack. renderColumn and renderCard read the layout back, and the dragend slot calculation uses per-card midpoints so reordering works correctly when cards have different heights. editInline gains a multiline flag. When true it renders a <textarea> with auto-grow on input, Shift+Enter for newlines, Enter/blur to commit, and Escape to cancel. Single-line <input> path is preserved for board and column titles. Both card edit entry points (double-click and the 3-dots menu Edit item) now pass multiline: true. #52