diff --git a/manifold/ONBOARDING.md b/manifold/ONBOARDING.md index ac4696d..abcda42 100644 --- a/manifold/ONBOARDING.md +++ b/manifold/ONBOARDING.md @@ -122,7 +122,8 @@ double-click exits). `OutputStage.tsx` is the output columns; drag a bar to set defines `OUTPUT_MODES` = **particles** (default) / midi / osc / cv / synth / editor, each mapping to a `BackendId`. `DEFAULT_OUTPUT_MODE='particles'`. `outputDisplayCount()` is the shared presentation boundary for the stage and routing rows: MIDI uses its configured CC count, while backends without - a separate count present the full mode parameter set. This does not reshape the MLP or clear examples. + a separate count present the full mode parameter set. The condensed Outputs panel reports this as an + `N outputs` chip. This does not reshape the MLP or clear examples. - `src/console/output-mode.ts`, `types.ts`, `model.ts` are the shared vocabulary — read these first when touching anything cross-cutting: - `types.ts`: `Focus`, `OutputMode`, `DrawerKey`, `DrawerDepth`, `FeedbackModeUI`, `SoloMode`, diff --git a/manifold/src/console/Drawers.tsx b/manifold/src/console/Drawers.tsx index b8fed14..bfe8112 100644 --- a/manifold/src/console/Drawers.tsx +++ b/manifold/src/console/Drawers.tsx @@ -624,6 +624,7 @@ function RoutingDrawer(ctx: ConsoleCtx, depth: DrawerDepth) { <>
{modeDesc.label} + {activeParams.length} output{activeParams.length === 1 ? '' : 's'} live {counts.live || 0} fixed {counts.fixed || 0} off {counts.off || 0} diff --git a/manifold/tests/e2e/output-display-count.spec.ts b/manifold/tests/e2e/output-display-count.spec.ts index cef0785..fea7fbd 100644 --- a/manifold/tests/e2e/output-display-count.spec.ts +++ b/manifold/tests/e2e/output-display-count.spec.ts @@ -11,18 +11,25 @@ declare global { test('output sliders follow the active backend output count', async ({ page }) => { await loadProbe(page); - await page.evaluate(() => { - window.__mf!.setOutputMode('midi'); - window.__mf!.setMidiCcCount(3); - }); - await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', '3'); + // Drive the real UI path: output target → Outputs drawer → expanded MIDI + // config. This deliberately does not use the debug setters; the regression + // covers the same interaction an operator performs. + await page.getByTitle(/^Mode:/).click(); + await page.getByRole('button', { name: 'MIDI', exact: true }).click(); + await page.getByTitle('Outputs').click(); + await page.getByTitle('Expand').click(); + await page.getByLabel('CCs').fill('2'); - await page.evaluate(() => window.__mf!.setMidiCcCount(7)); - await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', '7'); + // The count remains visible in condensed chrome after leaving the advanced + // config, and closing the drawer reveals the same number of stage columns. + await page.getByTitle('Condense').click(); + await expect(page.getByText('2 outputs', { exact: true })).toBeVisible(); + await page.getByTitle('Close').click(); + await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', '2'); - const fullCount = await page.evaluate(() => { - window.__mf!.setOutputMode('osc'); - return window.__mf!.paramCount(); - }); + // Backends without a configured count present the full mode output set. + const fullCount = await page.evaluate(() => window.__mf!.paramCount()); + await page.getByTitle(/^Mode:/).click(); + await page.getByRole('button', { name: 'OSC', exact: true }).click(); await expect(page.getByTestId('output-stage')).toHaveAttribute('data-output-count', String(fullCount)); });