Add a reusable dashboard workflow picker that shows inline task status counts across board and list views. - Replace native workflow selects with a themed accessible dropdown component. - Share workflow status count calculation between board and list views. - Add styling, i18n labels, tests, and dashboard docs for the switcher behavior. Files changed: docs/dashboard-guide.md | 3 +- packages/dashboard/app/components/Board.tsx | 28 +-- packages/dashboard/app/components/Lane.css | 2 + .../dashboard/app/components/LeftSidebarNav.tsx | 2 +- packages/dashboard/app/components/ListView.css | 17 -- packages/dashboard/app/components/ListView.tsx | 31 ++- .../dashboard/app/components/WorkflowSwitcher.css | 186 ++++++++++++++ .../dashboard/app/components/WorkflowSwitcher.tsx | 270 +++++++++++++++++++++ .../app/components/__tests__/Board.test.tsx | 60 +++-- .../app/components/__tests__/ListView.test.tsx | 79 +++++- .../components/__tests__/WorkflowSwitcher.test.tsx | 92 +++++++ .../__tests__/workflowStatusCounts.test.ts | 122 ++++++++++ .../app/components/workflowStatusCounts.ts | 54 +++++ packages/i18n/locales/en/app.json | 9 + packages/i18n/locales/es/app.json | 9 + packages/i18n/locales/fr/app.json | 9 + packages/i18n/locales/ko/app.json | 9 + packages/i18n/locales/zh-CN/app.json | 9 + packages/i18n/locales/zh-TW/app.json | 9 + 19 files changed, 930 insertions(+), 70 deletions(-) Fusion-Task-Id: FN-6763 Fusion-Task-Lineage: 3503ea85-841a-4cd3-9960-1b22ef2cd4ea
194 lines
4.1 KiB
CSS
194 lines
4.1 KiB
CSS
/* Multi-lane board lane (U9). Each lane is a full-width vertical row whose
|
|
* columns scroll horizontally inside the lane. Tokens mirror .board/.column in
|
|
* app/styles.css; no monolith CSS is touched. */
|
|
|
|
.board-lanes {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--column-gap, 12px);
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
min-width: 0;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
padding: var(--board-padding, 12px);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.board-workflow-view {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1 1 auto;
|
|
width: 100%;
|
|
height: 100%;
|
|
max-height: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.board-workflow-toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: var(--space-md);
|
|
padding: var(--space-md) var(--space-xl);
|
|
border-bottom: 1px solid var(--border);
|
|
background: var(--surface);
|
|
}
|
|
|
|
.board-workflow-selector {
|
|
display: inline-flex;
|
|
margin-left: auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.board-workflow-create-btn,
|
|
.board-workflow-edit-btn {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.board.board-workflow-columns {
|
|
flex: 1 1 auto;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: stretch;
|
|
width: 100%;
|
|
height: 100%;
|
|
max-height: 100%;
|
|
min-height: 0;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-x: contain;
|
|
scroll-snap-type: x proximity;
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
|
|
.board.board-workflow-columns > .column {
|
|
flex: 1 0 300px;
|
|
min-width: 300px;
|
|
height: 100%;
|
|
min-height: 0;
|
|
scroll-snap-align: center;
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
|
|
.lane {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 0 0 auto;
|
|
width: 100%;
|
|
min-width: 0;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg, 10px);
|
|
background: var(--surface-muted, var(--surface));
|
|
}
|
|
|
|
.lane-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 8px 12px;
|
|
border-bottom: 1px solid var(--border);
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.lane-header:hover {
|
|
background: var(--surface-hover, var(--surface));
|
|
}
|
|
|
|
.lane-header:focus-visible {
|
|
outline: 2px solid var(--todo);
|
|
outline-offset: -2px;
|
|
}
|
|
|
|
.lane-name {
|
|
font-size: 0.95rem;
|
|
font-weight: 600;
|
|
margin: 0;
|
|
}
|
|
|
|
.lane-count {
|
|
font-variant-numeric: tabular-nums;
|
|
font-size: 0.8rem;
|
|
color: var(--text-muted, var(--text));
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm, 6px);
|
|
padding: 0 6px;
|
|
min-width: 1.5rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.lane-columns {
|
|
display: flex;
|
|
gap: var(--column-gap, 12px);
|
|
padding: 12px;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-x: contain;
|
|
scroll-snap-type: x proximity;
|
|
scrollbar-color: var(--border) transparent;
|
|
scrollbar-width: thin;
|
|
min-height: 0;
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
|
|
.lane-columns > .column {
|
|
flex: 0 0 clamp(280px, 28vw, 340px);
|
|
/* Repo convention (mobile-scroll-snap test): snap-align must be `center`. */
|
|
scroll-snap-align: center;
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
|
|
.lane-columns::-webkit-scrollbar {
|
|
height: 6px;
|
|
}
|
|
.lane-columns::-webkit-scrollbar-thumb {
|
|
background: var(--border);
|
|
border-radius: var(--radius-sm, 6px);
|
|
}
|
|
|
|
/* Inline column feedback (capacity-exhausted promote, deterministic drag
|
|
* rejection) — rendered in-column, not a toast (R17 / promote spec). */
|
|
.column-inline-feedback {
|
|
margin: 4px 12px 0;
|
|
padding: 6px 8px;
|
|
font-size: 0.8rem;
|
|
color: var(--color-error);
|
|
background: color-mix(in srgb, var(--color-error) 12%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--color-error) 35%, transparent);
|
|
border-radius: var(--radius-sm, 6px);
|
|
}
|
|
|
|
|
|
@media (max-width: 1024px) {
|
|
.board.board-lanes {
|
|
flex-direction: column;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
scroll-snap-type: none;
|
|
}
|
|
|
|
.board.board-lanes > .lane {
|
|
width: 100%;
|
|
min-width: 0;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.board.board-workflow-columns {
|
|
flex: 1 1 auto;
|
|
flex-direction: row;
|
|
align-items: stretch;
|
|
width: 100%;
|
|
height: 100%;
|
|
max-height: 100%;
|
|
min-height: 0;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
scroll-snap-type: x proximity;
|
|
}
|
|
}
|