Add a persistent New Task entry to the left sidebar so task creation is available from project views. - Wire the left sidebar to the existing New Task dialog trigger from App. - Render an accessible, token-styled New Task CTA above sidebar navigation with collapsed rail support. - Cover the new sidebar affordance behavior and document it in the dashboard guide. Files changed: docs/dashboard-guide.md | 2 +- packages/dashboard/app/App.tsx | 1 + .../dashboard/app/components/LeftSidebarNav.css | 27 +++++++ .../dashboard/app/components/LeftSidebarNav.tsx | 18 +++++ .../components/__tests__/LeftSidebarNav.test.tsx | 83 ++++++++++++++++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-6880 Fusion-Task-Lineage: 7d9cffd4-c216-4250-9615-51e7c16438c2
219 lines
5.9 KiB
CSS
219 lines
5.9 KiB
CSS
/*
|
|
FNXC:Navigation 2026-06-19-00:00:
|
|
The experimental sidebar is a persistent desktop/tablet navigation replacement for the Header view-toggle row. It uses the same tokenized visual rhythm as Header navigation so the flag can be toggled without changing dashboard information architecture.
|
|
*/
|
|
.left-sidebar-nav {
|
|
--left-sidebar-nav-width: calc(var(--space-2xl) * 7);
|
|
--left-sidebar-nav-rail-width: calc(var(--space-2xl) * 2);
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
box-sizing: border-box;
|
|
width: var(--left-sidebar-nav-width);
|
|
min-width: var(--left-sidebar-nav-width);
|
|
min-height: 0;
|
|
background: var(--surface);
|
|
border-right: 1px solid var(--border);
|
|
color: var(--text);
|
|
}
|
|
|
|
/*
|
|
FNXC:Navigation 2026-06-20-00:00:
|
|
The left sidebar is a sibling of project-content, so it does not inherit project-content footer padding. When the fixed executor status bar is rendered, reserve the shared --executor-footer-height on the aside so the bottom Settings button remains visible and clickable above the footer.
|
|
*/
|
|
.left-sidebar-nav--with-footer {
|
|
padding-bottom: var(--executor-footer-height);
|
|
}
|
|
|
|
/*
|
|
FNXC:Navigation 2026-06-21-00:00:
|
|
The collapse toggle lives in the footer above Settings instead of floating on the resize border. It reuses the tokenized row-item styling so expanded mode can show the Collapse label and rail mode can hide that label consistently with other sidebar items.
|
|
*/
|
|
.left-sidebar-nav__collapse-toggle {
|
|
flex-shrink: 0;
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
/*
|
|
FNXC:Navigation 2026-06-21-20:45:
|
|
The persistent desktop/tablet sidebar needs a centered New Task CTA at the top so task creation is reachable from any project screen. It uses the shared row label and rail hiding behavior so expanded mode shows icon plus text while collapsed mode remains an icon-only button with the same global dialog trigger.
|
|
*/
|
|
.left-sidebar-nav__new-task {
|
|
flex-shrink: 0;
|
|
justify-content: center;
|
|
align-self: stretch;
|
|
width: auto;
|
|
margin: var(--space-sm) var(--space-sm) 0;
|
|
border-radius: var(--radius-md);
|
|
background: var(--accent);
|
|
color: var(--accent-text);
|
|
font-weight: 600;
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.left-sidebar-nav__new-task:hover,
|
|
.left-sidebar-nav__new-task:focus-visible {
|
|
background: color-mix(in srgb, var(--accent) 88%, var(--surface));
|
|
color: var(--accent-text);
|
|
}
|
|
|
|
.left-sidebar-nav__list {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
padding: var(--space-sm);
|
|
}
|
|
|
|
.left-sidebar-nav__section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.left-sidebar-nav__section--secondary {
|
|
padding-top: var(--space-sm);
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.left-sidebar-nav__item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
width: 100%;
|
|
min-height: calc(var(--space-xl) + var(--space-sm));
|
|
padding: 0 var(--space-sm);
|
|
background: transparent;
|
|
border: none;
|
|
border-radius: var(--radius-md);
|
|
color: var(--text-muted);
|
|
font: inherit;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
transition:
|
|
background var(--transition-fast),
|
|
color var(--transition-fast),
|
|
box-shadow var(--transition-fast);
|
|
}
|
|
|
|
.left-sidebar-nav__item:hover,
|
|
.left-sidebar-nav__item:focus-visible {
|
|
background: var(--card);
|
|
color: var(--text);
|
|
outline: none;
|
|
}
|
|
|
|
.left-sidebar-nav__item:focus-visible {
|
|
box-shadow: var(--focus-ring);
|
|
}
|
|
|
|
/*
|
|
FNXC:DashboardStyling 2026-06-21-11:16:
|
|
The left sidebar active highlight and resize accent must use the per-theme --accent token so the selected state reflects the active color theme instead of the workflow todo-status blue. FN-6830 keeps this requirement in the base sidebar rules so every theme inherits it without per-theme overrides.
|
|
*/
|
|
.left-sidebar-nav__item--active {
|
|
background: color-mix(in srgb, var(--accent) 15%, transparent);
|
|
color: var(--accent);
|
|
}
|
|
|
|
.left-sidebar-nav__icon-wrap {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
color: currentColor;
|
|
}
|
|
|
|
.left-sidebar-nav__dot {
|
|
position: absolute;
|
|
top: calc(var(--space-xs) * -1);
|
|
right: calc(var(--space-xs) * -1);
|
|
}
|
|
|
|
/*
|
|
FNXC:Navigation 2026-06-21-00:00:
|
|
The narrower resizable sidebar must preserve row rhythm by truncating labels instead of wrapping or pushing badges/toggles out of place. Rail mode still hides labels entirely through the collapsed sidebar rule.
|
|
*/
|
|
.left-sidebar-nav__label {
|
|
flex: 1;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.left-sidebar-nav__badge {
|
|
position: static;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.left-sidebar-nav__footer {
|
|
margin-top: auto;
|
|
padding: var(--space-sm);
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.left-sidebar-nav__settings {
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
.left-sidebar-nav__resize-handle {
|
|
position: absolute;
|
|
top: 0;
|
|
right: calc(var(--space-xs) * -1 / 2);
|
|
bottom: 0;
|
|
width: var(--space-xs);
|
|
cursor: col-resize;
|
|
touch-action: none;
|
|
z-index: 1;
|
|
}
|
|
|
|
.left-sidebar-nav__resize-handle::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
right: calc(var(--space-xs) / 2);
|
|
bottom: 0;
|
|
width: 1px;
|
|
background: transparent;
|
|
transition: background var(--transition-fast);
|
|
}
|
|
|
|
.left-sidebar-nav__resize-handle:hover::after,
|
|
.left-sidebar-nav__resize-handle:focus-visible::after {
|
|
background: var(--accent);
|
|
}
|
|
|
|
.left-sidebar-nav__resize-handle:focus-visible {
|
|
outline: none;
|
|
}
|
|
|
|
.left-sidebar-nav--collapsed {
|
|
width: var(--left-sidebar-nav-rail-width);
|
|
min-width: var(--left-sidebar-nav-rail-width);
|
|
}
|
|
|
|
.left-sidebar-nav--collapsed .left-sidebar-nav__label,
|
|
.left-sidebar-nav--collapsed .left-sidebar-nav__badge {
|
|
display: none;
|
|
}
|
|
|
|
.left-sidebar-nav--collapsed .left-sidebar-nav__item {
|
|
justify-content: center;
|
|
padding-right: 0;
|
|
padding-left: 0;
|
|
}
|
|
|
|
.left-sidebar-nav--collapsed .left-sidebar-nav__new-task {
|
|
justify-content: center;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.left-sidebar-nav {
|
|
display: none;
|
|
}
|
|
}
|