feat(dashboard): Planning embedded view is a real two-pane like Missions
Left becomes a full-height .planning-sidebar (Missions-matched surface/border/width) with a scrolling list and a bottom-pinned footer; New Session moves to that footer using btn btn-primary (same CTA tokens as the Missions create button — size/color match). Right .planning-detail fills remaining width + full height, so it reads as a true two-pane view. Non-embedded modal presentation unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -136,29 +136,33 @@ The embedded planning title must read like other embedded-view titles (Command C
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
/*
|
||||
FNXC:Planning 2026-06-23-01:15:
|
||||
Embedded Planning is a real two-pane view mirroring Missions (mission-manager__split): the left sidebar is a full-height flex column (list scrolls, footer pinned to bottom) and the right detail pane fills the remaining width AND height. The sidebar surface/border/width treatment matches mission-manager__sidebar — var(--surface) background, a single border-right divider — so the two views read consistently. The flex chain planning-view -> planning-modal--embedded -> planning-modal-body keeps the whole layout filling the main-content pane to the bottom.
|
||||
*/
|
||||
.planning-sidebar {
|
||||
width: 260px;
|
||||
width: calc(var(--space-lg) * 18.75);
|
||||
flex-shrink: 0;
|
||||
border-right: 1px solid var(--border);
|
||||
background: var(--card);
|
||||
border-right: var(--btn-border-width) solid var(--border);
|
||||
background: var(--surface);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.planning-sidebar-header {
|
||||
padding: var(--space-md);
|
||||
border-bottom: 1px solid var(--border);
|
||||
flex-shrink: 0;
|
||||
/*
|
||||
FNXC:Planning 2026-06-23-01:15:
|
||||
The sidebar footer pins the primary "New session" action to the bottom (parity with mission-manager__sidebar-footer) with the show/hide-archived link beneath it. A top border separates it from the scrolling list.
|
||||
*/
|
||||
.planning-sidebar-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.planning-sidebar-footer {
|
||||
padding: var(--space-sm) var(--space-md) var(--space-md);
|
||||
padding: var(--space-md);
|
||||
border-top: var(--btn-border-width) solid var(--border);
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -181,37 +185,18 @@ The embedded planning title must read like other embedded-view titles (Command C
|
||||
box-shadow: var(--focus-ring-strong);
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:Planning 2026-06-23-01:15:
|
||||
The New session button carries the shared "btn btn-primary" classes so its size/color match Missions' primary sidebar CTA (mission-manager__sidebar-cta) exactly; this local rule only stretches it full-width and centers the icon+label. The .active state (no session selected) keeps the primary fill and adds an inset ring so the user can tell they're on the new-session view without losing the Missions color match.
|
||||
*/
|
||||
.planning-sidebar-new {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
gap: var(--space-sm);
|
||||
width: 100%;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--text);
|
||||
font-size: calc(var(--space-sm) + var(--space-xs) * 1.25);
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.planning-sidebar-new:hover {
|
||||
background: var(--card-hover);
|
||||
border-color: var(--todo);
|
||||
}
|
||||
|
||||
.planning-sidebar-new.active {
|
||||
background: color-mix(in srgb, var(--todo) 15%, transparent);
|
||||
border-color: var(--todo);
|
||||
color: var(--todo);
|
||||
}
|
||||
|
||||
.planning-sidebar-new:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: var(--focus-ring-strong);
|
||||
box-shadow: inset 0 0 0 var(--btn-border-width) var(--cta-text);
|
||||
}
|
||||
|
||||
.planning-sidebar-list {
|
||||
|
||||
@@ -3156,17 +3156,10 @@ function PlanningSessionList({
|
||||
const { t } = useTranslation("app");
|
||||
return (
|
||||
<aside className="planning-sidebar" aria-label={t("planning.planningSessions", "Planning sessions")}>
|
||||
<div className="planning-sidebar-header">
|
||||
<button
|
||||
className={`planning-sidebar-new ${selectedSessionId === null ? "active" : ""}`}
|
||||
onClick={onNewSession}
|
||||
type="button"
|
||||
>
|
||||
<MessageSquarePlus size={16} />
|
||||
<span>{t("planning.newSession", "New session")}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/*
|
||||
FNXC:Planning 2026-06-23-01:15:
|
||||
The embedded Planning view reads as a real two-pane layout matching Missions: the left sidebar is a full-height flex column whose session list scrolls and whose primary action ("New session") is pinned to a bottom footer (parity with MissionManager's mission-manager__sidebar-footer + sidebar-cta). The header that previously held the New session button is removed so the list owns the top of the sidebar like the Missions list.
|
||||
*/}
|
||||
<div className="planning-sidebar-list">
|
||||
{sessions.length === 0 && !loading && (
|
||||
<div className="planning-sidebar-empty text-muted">
|
||||
@@ -3266,6 +3259,18 @@ function PlanningSessionList({
|
||||
})}
|
||||
</div>
|
||||
<div className="planning-sidebar-footer">
|
||||
{/*
|
||||
FNXC:Planning 2026-06-23-01:15:
|
||||
The New session CTA mirrors Missions' primary sidebar action: it reuses the shared "btn btn-primary" look (same base button class MissionManager pairs with mission-manager__sidebar-cta) so size and color match the Missions create button exactly, full-width and bottom-anchored. The "active" state (no session selected) keeps a subtle accent so the user can tell they're on the new-session view.
|
||||
*/}
|
||||
<button
|
||||
className={`btn btn-primary planning-sidebar-new ${selectedSessionId === null ? "active" : ""}`}
|
||||
onClick={onNewSession}
|
||||
type="button"
|
||||
>
|
||||
<MessageSquarePlus size={16} />
|
||||
<span>{t("planning.newSession", "New session")}</span>
|
||||
</button>
|
||||
<a
|
||||
href="#"
|
||||
className="planning-sidebar-toggle-archived-link"
|
||||
|
||||
Reference in New Issue
Block a user