fix(webui): smooth kanban detail panel animation and column alignment#42
Open
jimpablo wants to merge 4 commits into
Open
fix(webui): smooth kanban detail panel animation and column alignment#42jimpablo wants to merge 4 commits into
jimpablo wants to merge 4 commits into
Conversation
Signed-off-by: jimpablo <194239734+jimpablo@users.noreply.github.com>
Signed-off-by: jimpablo <194239734+jimpablo@users.noreply.github.com>
Signed-off-by: jimpablo <194239734+jimpablo@users.noreply.github.com>
Signed-off-by: jimpablo <194239734+jimpablo@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the WebUI Kanban inbox layout/animation so opening the detail panel no longer causes flex reflow/jitter, and so the panel aligns correctly regardless of which column is active. It also improves timestamp robustness and ensures the detail panel closes when changing sidebar filters/views.
Changes:
- Reworks Kanban board column/panel layout using measured widths and an absolutely positioned sliding detail panel.
- Makes
formatRelativeTimetolerate empty/invalid timestamps, and usesmetadata.created_atas a preferred timestamp for cards. - Clears the selected envelope when switching sidebar view/source/group/prefix.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| loom/webui/frontend/src/lib/utils.ts | Makes relative-time formatting robust to empty/invalid date strings. |
| loom/webui/frontend/src/components/KanbanBoard.tsx | Implements the new column freezing + absolute detail panel animation/layout logic. |
| loom/webui/frontend/src/components/EnvelopeCard.tsx | Displays relative time based on metadata.created_at with fallback to received_at. |
| loom/webui/frontend/src/App.tsx | Clears selection when navigation/filter context changes. |
| loom/webui/frontend/package-lock.json | Lockfile normalization (removes peer: true entries). |
Files not reviewed (1)
- loom/webui/frontend/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)
loom/webui/frontend/src/components/KanbanBoard.tsx:33
onCloseDetailis declared inKanbanBoardPropsand destructured in the component props, but it is no longer used. WithnoUnusedParameters: truein the frontend tsconfig, this will failtsc. Either removeonCloseDetailfrom the props/interface and stop passing it fromApp, or call it from the detail panel close handler.
interface KanbanBoardProps {
envelopes: Envelope[]
showArchived: boolean
selectedId: string | null
onSelect: (id: string | null) => void
onCloseDetail: () => void
}
export function KanbanBoard({
envelopes,
showArchived,
selectedId,
onSelect,
onCloseDetail,
}: KanbanBoardProps) {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+9
to
+11
| if (!iso) return "" | ||
| const date = new Date(iso) | ||
| if (isNaN(date.getTime())) return "" |
Comment on lines
192
to
+206
| <div | ||
| className={cn( | ||
| "flex-none overflow-hidden rounded-lg border-l border-border transition-all duration-300 ease-in-out", | ||
| isOpen | ||
| ? "ml-3 min-w-[480px] flex-[3] opacity-100" | ||
| : "min-w-0 w-0 flex-none opacity-0" | ||
| "absolute inset-y-3 right-0 overflow-hidden rounded-lg border-l border-border", | ||
| isOpen ? "opacity-100" : "opacity-0 pointer-events-none", | ||
| )} | ||
| style={{ | ||
| left: panelLeft ?? "100%", | ||
| transition: isPanelSnapping | ||
| ? "opacity 300ms ease-in-out" | ||
| : "opacity 300ms ease-in-out, left 300ms ease-in-out", | ||
| }} | ||
| > | ||
| {isOpen && <DetailPanel envelopeId={selectedId} onClose={onCloseDetail} />} | ||
| {(isOpen || frozenStatus != null) && ( | ||
| <DetailPanel envelopeId={selectedId} onClose={() => handleSelect(null)} /> | ||
| )} |
Comment on lines
160
to
+179
| return ( | ||
| <div className="flex h-full px-4 py-3"> | ||
| {orderedColumns.map((colDef, idx) => { | ||
| const isHidden = isOpen && idx > 0 | ||
| <div ref={containerRef} className="relative flex h-full overflow-hidden px-4 py-3"> | ||
| {COLUMN_DEFS.map((colDef) => { | ||
| const isActive = effectiveStatus === colDef.status && frozenWidth != null | ||
| const isHidden = isOpen && effectiveStatus != null && effectiveStatus !== colDef.status | ||
| return ( | ||
| <div | ||
| key={colDef.status} | ||
| ref={(el) => { colRefs.current[colDef.status] = el }} | ||
| className={cn( | ||
| "transition-all duration-300 ease-in-out", | ||
| isHidden | ||
| ? "w-0 min-w-0 flex-none overflow-hidden opacity-0" | ||
| : "flex h-full min-w-[260px] flex-1 flex-col rounded-lg p-2" | ||
| "flex-none h-full flex-col overflow-hidden rounded-lg p-2", | ||
| isHidden && "opacity-0 pointer-events-none select-none", | ||
| )} | ||
| style={isHidden ? { marginLeft: 0, marginRight: 0 } : undefined} | ||
| style={{ | ||
| width: isActive ? frozenWidth! : isHidden ? 0 : "25%", | ||
| ...(isHidden ? { padding: 0 } : {}), | ||
| transition: isActive || isSnapping | ||
| ? "none" | ||
| : "width 300ms ease-in-out, padding 300ms ease-in-out, opacity 300ms ease-in-out", | ||
| }} |
| { title: "Done", status: "done" as const }, | ||
| ] as const | ||
|
|
||
| const ANIM_MS = 300 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
width+padding+opacity(no flex-grow transitions) to eliminate reflow and jitterlefttransition, ensuring correct alignment for all 4 columns (not just Queue)width:0due tobox-sizing: border-box+padding— clears padding on hidden columns to ensure true 0px widthisSnappingflag suppresses transitions on close so columns snap back invisibly under the still-opaque panel before it fades out