Prevent workflow-enabled board surfaces from flashing the legacy layout during first paint. - Hydrate Board and ListView workflow metadata from a per-project session cache before async revalidation. - Gate legacy board/list rendering behind settings and workflow-lane metadata readiness, with neutral skeleton states for cold or empty workflow loads. - Add regression coverage for no-legacy-flash behavior and cache validation, plus docs and changeset notes. Files changed: .changeset/fn-6776-board-flash.md | 5 + docs/dashboard-guide.md | 1 + packages/dashboard/app/App.tsx | 4 + packages/dashboard/app/components/Board.css | 69 +++++ packages/dashboard/app/components/Board.tsx | 53 +++- packages/dashboard/app/components/ListView.css | 53 ++++ packages/dashboard/app/components/ListView.tsx | 52 +++- .../__tests__/board-no-legacy-flash.test.tsx | 326 +++++++++++++++++++++ .../utils/__tests__/boardWorkflowsCache.test.ts | 71 +++++ .../dashboard/app/utils/boardWorkflowsCache.ts | 49 ++++ 10 files changed, 676 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-6776 Fusion-Task-Lineage: caa8e53f-9b6d-49a6-94ca-b694550b43ef
70 lines
1.6 KiB
CSS
70 lines
1.6 KiB
CSS
/*
|
|
FNXC:BoardWorkflows 2026-06-20-09:02:
|
|
The board needs a neutral first-paint shell whenever workflow lanes are enabled but metadata is not ready, so users never see the legacy single-lane board flash before workflow lanes load.
|
|
*/
|
|
.board.board-workflows-skeleton {
|
|
display: flex;
|
|
align-items: stretch;
|
|
gap: var(--column-gap, var(--space-md));
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
padding: var(--board-padding, var(--space-md));
|
|
background: var(--bg);
|
|
}
|
|
|
|
.board-workflows-skeleton__column {
|
|
flex: 1 0 min(24rem, 85vw);
|
|
min-width: min(24rem, 85vw);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-md);
|
|
padding: var(--space-md);
|
|
border: 1px solid var(--border);
|
|
background: var(--surface);
|
|
}
|
|
|
|
.board-workflows-skeleton__header,
|
|
.board-workflows-skeleton__card {
|
|
border-radius: var(--radius-md);
|
|
background: color-mix(in srgb, var(--border) 70%, var(--surface));
|
|
animation: board-workflows-skeleton-pulse 1.4s ease-in-out infinite;
|
|
}
|
|
|
|
.board-workflows-skeleton__header {
|
|
block-size: var(--space-lg);
|
|
inline-size: 55%;
|
|
}
|
|
|
|
.board-workflows-skeleton__card {
|
|
block-size: calc(var(--space-2xl) * 2);
|
|
inline-size: 100%;
|
|
}
|
|
|
|
.board-workflows-skeleton__card--short {
|
|
inline-size: 75%;
|
|
}
|
|
|
|
@keyframes board-workflows-skeleton-pulse {
|
|
0%, 100% {
|
|
opacity: 0.55;
|
|
}
|
|
|
|
50% {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.board.board-workflows-skeleton {
|
|
gap: var(--space-sm);
|
|
padding: var(--space-sm);
|
|
scroll-snap-type: x proximity;
|
|
}
|
|
|
|
.board-workflows-skeleton__column {
|
|
flex-basis: 86vw;
|
|
min-width: 86vw;
|
|
scroll-snap-align: center;
|
|
}
|
|
}
|