Files
fusion/packages/dashboard/app/components/EngineControlMenu.css
gsxdsm 1d860ec310 feat: global concurrency slider (footer + dashboard) and scoped settings
Add a "Global Max Concurrent" slider to the footer engine menu and the
Command Center Concurrency card, and group the Scheduling settings by
Global vs Project scope so the global cap isn't mistaken for a per-project
setting (clearer on mobile).

Both sliders are backed by a single shared `useGlobalConcurrency` hook
(module-level store) so they read/write one source of truth and revalidate
after every PUT /api/global-concurrency — fixing the last-writer-wins and
stale-clobber races a per-component cache would cause. The hook treats a
fetch error as non-interactive (slider disabled, not stuck at 1), surfaces
a save-state indicator, and flushes a pending edit on menu close / unmount
so a quick drag-then-dismiss is never silently dropped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:19:24 -07:00

133 lines
3.1 KiB
CSS

.engine-control-menu {
position: relative;
display: inline-flex;
align-items: center;
}
.engine-control-menu__trigger {
color: var(--text-muted);
}
.engine-control-menu__trigger:hover {
color: var(--text);
}
.engine-control-menu__popover {
position: absolute;
right: 0;
bottom: calc(100% + var(--space-xs));
z-index: 70;
width: min(24rem, calc(100vw - (var(--space-lg) * 2)));
max-height: min(32rem, calc(100vh - var(--space-2xl)));
overflow: auto;
padding: var(--space-md);
display: flex;
flex-direction: column;
gap: var(--space-md);
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg);
color: var(--text);
}
.engine-control-menu__section {
display: flex;
flex-direction: column;
gap: var(--space-sm);
}
.engine-control-menu__section--actions {
gap: var(--space-xs);
}
.engine-control-menu__action {
width: 100%;
justify-content: flex-start;
gap: var(--space-sm);
}
.engine-control-menu__action:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.engine-control-menu__section-header,
.engine-control-menu__slider-label {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-md);
}
.engine-control-menu__section-header {
color: var(--text);
font-weight: 600;
}
.engine-control-menu__save-state {
color: var(--text-muted);
font-size: var(--font-size-xs);
font-weight: 500;
}
/* FNXC:GlobalConcurrencyControls 2026-06-25-22:45: "All projects" scope caption sits between the global-cap title and its save-state indicator; muted so the save-state remains the emphasized signal. */
.engine-control-menu__scope-caption {
margin-inline-start: auto;
color: var(--text-muted);
font-size: var(--font-size-xs);
font-weight: 500;
}
.engine-control-menu__save-state--saving {
color: var(--color-warning);
}
.engine-control-menu__save-state--saved {
color: var(--color-success);
}
.engine-control-menu__save-state--error,
.engine-control-menu__error {
color: var(--color-error);
}
/* FNXC:GlobalConcurrencyControls 2026-06-25-14:10: The global cap is a cross-project setting; separate it visually from the per-project sliders below with a divider and an "All projects" caption. */
.engine-control-menu__section--global {
padding-bottom: var(--space-sm);
border-bottom: 1px solid var(--border);
}
.engine-control-menu__slider {
display: flex;
flex-direction: column;
gap: var(--space-xs);
color: var(--text-muted);
}
.engine-control-menu__slider-label strong {
color: var(--text);
font-family: var(--font-mono);
}
.engine-control-menu__range {
width: 100%;
accent-color: var(--accent);
}
.engine-control-menu__error {
margin: 0;
font-size: var(--font-size-xs);
}
@media (max-width: 768px) {
.engine-control-menu__popover {
position: fixed;
left: var(--space-sm);
right: var(--space-sm);
bottom: calc(var(--mobile-nav-height) + max(env(safe-area-inset-bottom, 0px), var(--space-md)) + var(--space-2xl));
width: auto;
max-height: min(28rem, calc(100vh - var(--mobile-nav-height) - var(--space-2xl) - var(--space-lg)));
}
}