Repository navigation
Panel: actions and folding, striped panels, a dark board, header-sized buttons, steppers that fill - #67
Merged
Conversation
.github/FUNDING.yml names FourCourtJester on GitHub Sponsors and fourcourtjester on Ko-fi. GitHub reads it from the default branch only, so the button appears once this is on main and Sponsorships is ticked under Settings > General > Features. Checked: prettier and lint pass. Not checked: either link resolves -- this environment cannot reach ko-fi.com or github.com/sponsors -- and the button itself, which only shows once this is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
…e it templates/studio/.github/FUNDING.yml and templates/plugin/.github/FUNDING.yml are the same file as the repository's own. They have to live here rather than be pushed to the mirrors: a sync deletes everything in a mirror but .git and copies the template across, so a file added there directly is gone at the next one. The demo is left without, as asked. A project started from a template inherits the file, and with it a Sponsor button pointing at Single Studio. Each README now says to delete it or point it at your own accounts: the studio's beside its note about LICENSE, the plugin's as step 4 of building your own. Checked: lint passes; verify:template builds both templates and the demo against packed packages. Not checked: the mirrors themselves, which sync on merge; the links, which this environment cannot reach. Prettier flags templates/plugin/README.md, as it did before this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
The mirror job failed for both templates on #65, the first push that ever reached its install step: setup-node@v5 "Unable to locate executable file: pnpm". v5 turns on a package-manager cache by itself whenever the checked-out package.json has a "packageManager", and the root one names pnpm, which this job never installs -- it installs the mirror's copy with npm, from npm. Its only two runs before were the merge that added it, where nothing changed, and #63, which changed packages/ and so was left to the release. So the step had never run. package-manager-cache: false is setup-node's own switch for that (checked in its v5 action.yml: "Set to false to disable automatic caching based on the package manager field in package.json"). Nothing was pushed by the failed run, so the template repositories are still on their v0.12.0 sync. Checked: prettier and lint pass. Not checked: the job itself, which can only run on GitHub. This change touches only .github, so merging it does not mirror anything; Run workflow on the Mirror workflow, on main, is what will carry #65's FUNDING.yml across and prove the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
docs/internal/next.md gets a "Raise these first" section, for what the owner wants reminding of at the top of any "where are we at": - a right-aligned toolbar on a Panel's title line, for extra components, with the three questions to settle before building it; - Sequence in a real OBS, which 0.12.0 shipped without. AGENTS.md is what every session reads first, so it now says to start from next.md, and that section, when asked where things stand. Without that the note would only be found by somebody already looking for it. Checked: lint passes. Prettier flags next.md, as it did before this change (two *emphasis* spans and a table, all older than this section). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
A time input's clock icon is Chrome's to draw, and it draws it dark unless the page declares a dark theme, so on the board it all but disappeared. A studio fixed it with color-scheme: dark on its board in its own index.css, and found it also darkens the time picker's popup, the menus behind Select and the scrollbars. Every board is dark, so the line belongs in core's base.css, scoped to .ss-control as the board's cursors are, where it cannot reach a graphic. Queued, not done. The toolbar entry is renamed to the owner's word for it: an actions slot. Checked: lint passes. Not checked: anything in a browser; this only records the finding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
FourCourtJester
force-pushed
the
claude/repo-overview-bcfbgu
branch
from
October 21, 2026 19:03
56e74f8 to
db446ef
Compare
…at built one SS-Mercy-Riftbound-2v2 built a collapsible Panel with header actions in its own src/control, because core's Panel has nothing beside its title. Its notes go into next.md so core can take it over rather than rediscover it: - the behaviour: everything starts folded on every load, and the fold is component state only -- not the show, which would fold every operator's board, and not localStorage, so a reload is always the same board; - the markup: the button inside the h2, not the other way round; - what bit: .ss-panel-body's display: flex beats the hidden attribute, and a grid of panels needs items-start; - the API it asks for: collapsible, defaultOpen, exported useCollapsed and Chevron, an actions slot, and size="sm" on the four header buttons, none of which has a size today. It replaces the earlier actions-slot entry in "Raise these first", which now points here. Checked: lint passes. Not checked: the hidden-attribute finding, which is the studio's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
Two things a studio (SS-Mercy-Riftbound-2v2) built for itself because core's
Panel had nothing beside its title:
- `actions`: anything at all, right-aligned on the title line, or a function
given `{ open }` that returns it. They stay in the header and work while the
panel is folded, and in a slim dock take a line of their own under the
title rather than squeezing it.
- `collapsible`: the title becomes a button that folds the body away. A
collapsible panel starts folded on every load; `defaultOpen` starts one
open. The fold is component state only -- not the show, which would fold
every operator's board, and not storage, so a reload is the same board.
The body is hidden, not unmounted, so a draft in a folded panel survives.
Off unless asked for, so every existing panel renders as before, except that
its title now sits in a `.ss-panel-header` line. With no title, actions keep
their line and a collapsible panel gets a chevron of its own, named "Fold
panel" / "Open panel"; with nothing for a header to hold there is none. The
button sits inside the h2, never the reverse. `chevron` joins Icon.
Cross-checked against the studio's own Panel and collapse.jsx, and took its
header element and its larger title hit area. Not taken: its Tailwind
`hidden` class on the body. Its notes say `.ss-panel-body`'s display: flex
beats the hidden attribute, but Tailwind's preflight, which every studio
imports, has `[hidden] { display: none !important }`: a `[hidden]` rule
written into base.css for it changed nothing (the folded body measured 0px
tall without it), so it was taken out again rather than kept as code
nothing can catch.
Thirteen e2e checks, in their own section near the end. Placed after Rows
first, they wedged the asset library's folder upload a hundred lines later --
the stall AGENTS.md describes -- and moved, everything passed. Negative-tested
with nine breaks, each turning its check red: body not hidden; body unmounted
while folded; function actions not given the fold; a header with nothing in it;
collapsible by default; defaultOpen ignored; a header that does not wrap; a
header that toggles on any press inside it; a fold remembered in localStorage.
Docs: getting-started's Panel row and a paragraph with an example,
CHANGELOG Unreleased, api.md regenerated, and next.md now says what is built
and what the studio still wants: size="sm" on header buttons, useCollapsed and
Chevron exported for folding cards, and zebra striping.
Checked: test (core 603, every package passes), lint, typecheck,
verify:template, docs:build, and e2e 306 of 306 against a fresh build. Not
checked: in OBS's own browser, or in the studio itself, which still uses its
own Panel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
… buttons Four things from SS-Mercy-Riftbound-2v2 that every studio should have without writing them: - Striped panels, by default. Every other panel is a shade lighter, so a long board reads as blocks rather than one slab. The studio's own rule and colours: rgb(15 23 42 / 0.4) and rgb(30 41 59 / 0.7). The background moved from a class on the element into base.css, because the count -- nth-of-type among sibling panels -- can only be made in CSS; in the components layer, so a bg-* on one panel or a studio's own rule still wins. A panel wrapped in a <div> of its own never counts as even; documented rather than worked around. - color-scheme: dark on .ss-control. Chrome draws a time input's clock icon, its picker, a select's list and scrollbars in the page's scheme, and on the board they were black on slate. On the board only; a graphic stays normal. - size="sm" on Confirm, ResetButton, SwapButton and Toggle, for a button in a panel's header: text-xs, smaller padding, off the Row's input line, and a min-h-6 floor so it is never under the 24px pointer target WCAG 2.5.8 asks for. Replaces the studio's `min-h-0! px-2.5! py-1! text-xs!`, which had no floor. Measured: 24 or 26px against 40px on a row, 12px text. - useCollapsed and Chevron, exported from @single-studio/core/control, so a card folds the way a Panel does. Panel is now built on them, and both are in the API reference's list. Seven e2e checks, all near the end, and the small buttons mount only when those checks ask: mounted from the start, they gave earlier checks that find the board's one swap by class three to choose from. Negative-tested, each check red when broken for it: stripes removed; the scheme normal; the scheme on :root, reaching graphics; Toggle ignoring size; a confirming Reset not passing size on; the small size under 24px; useCollapsed starting open; the chevron never turning. Removing the min-h-6 floor at first changed nothing, because the padding alone makes 24px, so the fixture now squeezes one button's padding to zero and the floor is what holds it at 24. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 313 of 313 against a fresh build. The useCollapsed doc comment was reworded after that run; nothing else changed. Not checked: OBS's own browser, or the studio itself, which still uses its own Panel and CSS until core is released. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
…nels A stepper's number field stopped at 4rem, so a stepper was 160px in any cell and the rest of the cell sat empty -- the negative space at every breakpoint. Measured on the fixture: 170px of 330 in a 380px dock, 414px of 574 at 640px, 601px of 761 at 1600px. A stopwatch's readout did the same, up to 295px. Both now grow between their buttons (`grow`, not `flex-1`, so `w-16` is still the basis and a `col-auto` stepper keeps its own 160px). The same thing SS-Mercy-Riftbound-2v2's FillStepper did for itself, now for everyone. The demo, built against these packages: its two score steppers left 121-201px empty below 1024px on 0.12.0 and leave nothing now, measured at 380, 640, 800, 1024, 1280 and 1600px. Its panels are collapsible: the scoreboard starts open, the rest folded. Its Swap sides moved into the scoreboard's header at size="sm", where it works with the panel folded. The demo uses props 0.12.0 does not have, so it has to go out with the release; the mirror leaves a push that also changes packages/ to the release anyway. Nine e2e checks at 380, 800 and 1280px: every stepper on a Row reaches its cell's edge, so does a stopwatch, and a col-auto stepper is 160px. Negative- tested: the field not growing, the readout not growing, and the field sized to its cell (which loses col-auto its width) each turned their checks red. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 322 of 322 against a fresh build. Not checked: OBS's own browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
The API reference takes each component's opening paragraph, and the fill change only touched the markup and its comments, so docs/api.md still described a stepper as if it sat at 160px. One sentence in each opening paragraph, and api.md regenerated from the built types. Checked: lint, typecheck, test (core 603, every package passes), and `api-reference.mjs --check` says api.md matches the shipped types. Not run: e2e, since only doc comments changed; it passed, 322 of 322, on a3d3e31. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
FourCourtJester
pushed a commit
that referenced
this pull request
Oct 23, 2026
… out Every published package moves to 0.13.0 together, as the release workflow requires: core, provider-supabase and the four plugins. The plugins' peer range on core, both templates and the demo move to ^0.13.0 -- in 0.x a caret on 0.12.0 does not reach 0.13.0, and the demo now uses collapsible, defaultOpen and size="sm", which 0.12.0 does not have. A minor: a board looks different after upgrading without asking -- every other panel lighter, a dark scheme for native pickers, steppers and stopwatches that fill their cell -- though no prop changes meaning and nothing is removed. The CHANGELOG's Unreleased section becomes 0.13.0, with a paragraph saying why it is a minor. next.md's first reminder becomes moving SS-Mercy-Riftbound-2v2 onto it. Checked: `pnpm install --frozen-lockfile` needs no lockfile change. test (core 603, every package passes), lint and typecheck pass. verify:template packs the 0.13.0 tarballs and builds both templates and the demo against them. docs:build passes. Not run: the end-to-end suite, since nothing the fixture loads changed but version numbers; it passed, 322 of 322, on #67's code. Not checked: the publish itself, which happens on the tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
FourCourtJester
added a commit
that referenced
this pull request
Oct 23, 2026
… out (#68) * Add a Sponsor button: GitHub Sponsors and Ko-fi .github/FUNDING.yml names FourCourtJester on GitHub Sponsors and fourcourtjester on Ko-fi. GitHub reads it from the default branch only, so the button appears once this is on main and Sponsorships is ticked under Settings > General > Features. Checked: prettier and lint pass. Not checked: either link resolves -- this environment cannot reach ko-fi.com or github.com/sponsors -- and the button itself, which only shows once this is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Give both templates the Sponsor button, and tell their users to change it templates/studio/.github/FUNDING.yml and templates/plugin/.github/FUNDING.yml are the same file as the repository's own. They have to live here rather than be pushed to the mirrors: a sync deletes everything in a mirror but .git and copies the template across, so a file added there directly is gone at the next one. The demo is left without, as asked. A project started from a template inherits the file, and with it a Sponsor button pointing at Single Studio. Each README now says to delete it or point it at your own accounts: the studio's beside its note about LICENSE, the plugin's as step 4 of building your own. Checked: lint passes; verify:template builds both templates and the demo against packed packages. Not checked: the mirrors themselves, which sync on merge; the links, which this environment cannot reach. Prettier flags templates/plugin/README.md, as it did before this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Let the template mirror run: no pnpm cache in a job without pnpm The mirror job failed for both templates on #65, the first push that ever reached its install step: setup-node@v5 "Unable to locate executable file: pnpm". v5 turns on a package-manager cache by itself whenever the checked-out package.json has a "packageManager", and the root one names pnpm, which this job never installs -- it installs the mirror's copy with npm, from npm. Its only two runs before were the merge that added it, where nothing changed, and #63, which changed packages/ and so was left to the release. So the step had never run. package-manager-cache: false is setup-node's own switch for that (checked in its v5 action.yml: "Set to false to disable automatic caching based on the package manager field in package.json"). Nothing was pushed by the failed run, so the template repositories are still on their v0.12.0 sync. Checked: prettier and lint pass. Not checked: the job itself, which can only run on GitHub. This change touches only .github, so merging it does not mirror anything; Run workflow on the Mirror workflow, on main, is what will carry #65's FUNDING.yml across and prove the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue a toolbar for a control Panel, and say where to look first docs/internal/next.md gets a "Raise these first" section, for what the owner wants reminding of at the top of any "where are we at": - a right-aligned toolbar on a Panel's title line, for extra components, with the three questions to settle before building it; - Sequence in a real OBS, which 0.12.0 shipped without. AGENTS.md is what every session reads first, so it now says to start from next.md, and that section, when asked where things stand. Without that the note would only be found by somebody already looking for it. Checked: lint passes. Prettier flags next.md, as it did before this change (two *emphasis* spans and a table, all older than this section). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue color-scheme: dark for the board, alongside the Panel actions slot A time input's clock icon is Chrome's to draw, and it draws it dark unless the page declares a dark theme, so on the board it all but disappeared. A studio fixed it with color-scheme: dark on its board in its own index.css, and found it also darkens the time picker's popup, the menus behind Select and the scrollbars. Every board is dark, so the line belongs in core's base.css, scoped to .ss-control as the board's cursors are, where it cannot reach a graphic. Queued, not done. The toolbar entry is renamed to the owner's word for it: an actions slot. Checked: lint passes. Not checked: anything in a browser; this only records the finding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Rewrap the actions-slot reminder to the file's width Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue a Panel that folds and carries header actions, from a studio that built one SS-Mercy-Riftbound-2v2 built a collapsible Panel with header actions in its own src/control, because core's Panel has nothing beside its title. Its notes go into next.md so core can take it over rather than rediscover it: - the behaviour: everything starts folded on every load, and the fold is component state only -- not the show, which would fold every operator's board, and not localStorage, so a reload is always the same board; - the markup: the button inside the h2, not the other way round; - what bit: .ss-panel-body's display: flex beats the hidden attribute, and a grid of panels needs items-start; - the API it asks for: collapsible, defaultOpen, exported useCollapsed and Chevron, an actions slot, and size="sm" on the four header buttons, none of which has a size today. It replaces the earlier actions-slot entry in "Raise these first", which now points here. Checked: lint passes. Not checked: the hidden-attribute finding, which is the studio's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Give a Panel actions on its title line, and let it fold Two things a studio (SS-Mercy-Riftbound-2v2) built for itself because core's Panel had nothing beside its title: - `actions`: anything at all, right-aligned on the title line, or a function given `{ open }` that returns it. They stay in the header and work while the panel is folded, and in a slim dock take a line of their own under the title rather than squeezing it. - `collapsible`: the title becomes a button that folds the body away. A collapsible panel starts folded on every load; `defaultOpen` starts one open. The fold is component state only -- not the show, which would fold every operator's board, and not storage, so a reload is the same board. The body is hidden, not unmounted, so a draft in a folded panel survives. Off unless asked for, so every existing panel renders as before, except that its title now sits in a `.ss-panel-header` line. With no title, actions keep their line and a collapsible panel gets a chevron of its own, named "Fold panel" / "Open panel"; with nothing for a header to hold there is none. The button sits inside the h2, never the reverse. `chevron` joins Icon. Cross-checked against the studio's own Panel and collapse.jsx, and took its header element and its larger title hit area. Not taken: its Tailwind `hidden` class on the body. Its notes say `.ss-panel-body`'s display: flex beats the hidden attribute, but Tailwind's preflight, which every studio imports, has `[hidden] { display: none !important }`: a `[hidden]` rule written into base.css for it changed nothing (the folded body measured 0px tall without it), so it was taken out again rather than kept as code nothing can catch. Thirteen e2e checks, in their own section near the end. Placed after Rows first, they wedged the asset library's folder upload a hundred lines later -- the stall AGENTS.md describes -- and moved, everything passed. Negative-tested with nine breaks, each turning its check red: body not hidden; body unmounted while folded; function actions not given the fold; a header with nothing in it; collapsible by default; defaultOpen ignored; a header that does not wrap; a header that toggles on any press inside it; a fold remembered in localStorage. Docs: getting-started's Panel row and a paragraph with an example, CHANGELOG Unreleased, api.md regenerated, and next.md now says what is built and what the studio still wants: size="sm" on header buttons, useCollapsed and Chevron exported for folding cards, and zebra striping. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 306 of 306 against a fresh build. Not checked: in OBS's own browser, or in the studio itself, which still uses its own Panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Stripe the board's panels, darken its native pickers, and size header buttons Four things from SS-Mercy-Riftbound-2v2 that every studio should have without writing them: - Striped panels, by default. Every other panel is a shade lighter, so a long board reads as blocks rather than one slab. The studio's own rule and colours: rgb(15 23 42 / 0.4) and rgb(30 41 59 / 0.7). The background moved from a class on the element into base.css, because the count -- nth-of-type among sibling panels -- can only be made in CSS; in the components layer, so a bg-* on one panel or a studio's own rule still wins. A panel wrapped in a <div> of its own never counts as even; documented rather than worked around. - color-scheme: dark on .ss-control. Chrome draws a time input's clock icon, its picker, a select's list and scrollbars in the page's scheme, and on the board they were black on slate. On the board only; a graphic stays normal. - size="sm" on Confirm, ResetButton, SwapButton and Toggle, for a button in a panel's header: text-xs, smaller padding, off the Row's input line, and a min-h-6 floor so it is never under the 24px pointer target WCAG 2.5.8 asks for. Replaces the studio's `min-h-0! px-2.5! py-1! text-xs!`, which had no floor. Measured: 24 or 26px against 40px on a row, 12px text. - useCollapsed and Chevron, exported from @single-studio/core/control, so a card folds the way a Panel does. Panel is now built on them, and both are in the API reference's list. Seven e2e checks, all near the end, and the small buttons mount only when those checks ask: mounted from the start, they gave earlier checks that find the board's one swap by class three to choose from. Negative-tested, each check red when broken for it: stripes removed; the scheme normal; the scheme on :root, reaching graphics; Toggle ignoring size; a confirming Reset not passing size on; the small size under 24px; useCollapsed starting open; the chevron never turning. Removing the min-h-6 floor at first changed nothing, because the padding alone makes 24px, so the fixture now squeezes one button's padding to zero and the floor is what holds it at 24. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 313 of 313 against a fresh build. The useCollapsed doc comment was reworded after that run; nothing else changed. Not checked: OBS's own browser, or the studio itself, which still uses its own Panel and CSS until core is released. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Let a stepper and a stopwatch fill their cell, and fold the demo's panels A stepper's number field stopped at 4rem, so a stepper was 160px in any cell and the rest of the cell sat empty -- the negative space at every breakpoint. Measured on the fixture: 170px of 330 in a 380px dock, 414px of 574 at 640px, 601px of 761 at 1600px. A stopwatch's readout did the same, up to 295px. Both now grow between their buttons (`grow`, not `flex-1`, so `w-16` is still the basis and a `col-auto` stepper keeps its own 160px). The same thing SS-Mercy-Riftbound-2v2's FillStepper did for itself, now for everyone. The demo, built against these packages: its two score steppers left 121-201px empty below 1024px on 0.12.0 and leave nothing now, measured at 380, 640, 800, 1024, 1280 and 1600px. Its panels are collapsible: the scoreboard starts open, the rest folded. Its Swap sides moved into the scoreboard's header at size="sm", where it works with the panel folded. The demo uses props 0.12.0 does not have, so it has to go out with the release; the mirror leaves a push that also changes packages/ to the release anyway. Nine e2e checks at 380, 800 and 1280px: every stepper on a Row reaches its cell's edge, so does a stopwatch, and a col-auto stepper is 160px. Negative- tested: the field not growing, the readout not growing, and the field sized to its cell (which loses col-auto its width) each turned their checks red. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 322 of 322 against a fresh build. Not checked: OBS's own browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Say in the reference that a stepper and a stopwatch fill their cell The API reference takes each component's opening paragraph, and the fill change only touched the markup and its comments, so docs/api.md still described a stepper as if it sat at 160px. One sentence in each opening paragraph, and api.md regenerated from the built types. Checked: lint, typecheck, test (core 603, every package passes), and `api-reference.mjs --check` says api.md matches the shipped types. Not run: e2e, since only doc comments changed; it passed, 322 of 322, on a3d3e31. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Cut 0.13.0, so the folding Panel, the stripes and filling steppers go out Every published package moves to 0.13.0 together, as the release workflow requires: core, provider-supabase and the four plugins. The plugins' peer range on core, both templates and the demo move to ^0.13.0 -- in 0.x a caret on 0.12.0 does not reach 0.13.0, and the demo now uses collapsible, defaultOpen and size="sm", which 0.12.0 does not have. A minor: a board looks different after upgrading without asking -- every other panel lighter, a dark scheme for native pickers, steppers and stopwatches that fill their cell -- though no prop changes meaning and nothing is removed. The CHANGELOG's Unreleased section becomes 0.13.0, with a paragraph saying why it is a minor. next.md's first reminder becomes moving SS-Mercy-Riftbound-2v2 onto it. Checked: `pnpm install --frozen-lockfile` needs no lockfile change. test (core 603, every package passes), lint and typecheck pass. verify:template packs the 0.13.0 tarballs and builds both templates and the demo against them. docs:build passes. Not run: the end-to-end suite, since nothing the fixture loads changed but version numbers; it passed, 322 of 322, on #67's code. Not checked: the publish itself, which happens on the tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU --------- Co-authored-by: Claude <noreply@anthropic.com>
FourCourtJester
added a commit
that referenced
this pull request
Oct 23, 2026
…pickers (#69) * Add a Sponsor button: GitHub Sponsors and Ko-fi .github/FUNDING.yml names FourCourtJester on GitHub Sponsors and fourcourtjester on Ko-fi. GitHub reads it from the default branch only, so the button appears once this is on main and Sponsorships is ticked under Settings > General > Features. Checked: prettier and lint pass. Not checked: either link resolves -- this environment cannot reach ko-fi.com or github.com/sponsors -- and the button itself, which only shows once this is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Give both templates the Sponsor button, and tell their users to change it templates/studio/.github/FUNDING.yml and templates/plugin/.github/FUNDING.yml are the same file as the repository's own. They have to live here rather than be pushed to the mirrors: a sync deletes everything in a mirror but .git and copies the template across, so a file added there directly is gone at the next one. The demo is left without, as asked. A project started from a template inherits the file, and with it a Sponsor button pointing at Single Studio. Each README now says to delete it or point it at your own accounts: the studio's beside its note about LICENSE, the plugin's as step 4 of building your own. Checked: lint passes; verify:template builds both templates and the demo against packed packages. Not checked: the mirrors themselves, which sync on merge; the links, which this environment cannot reach. Prettier flags templates/plugin/README.md, as it did before this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Let the template mirror run: no pnpm cache in a job without pnpm The mirror job failed for both templates on #65, the first push that ever reached its install step: setup-node@v5 "Unable to locate executable file: pnpm". v5 turns on a package-manager cache by itself whenever the checked-out package.json has a "packageManager", and the root one names pnpm, which this job never installs -- it installs the mirror's copy with npm, from npm. Its only two runs before were the merge that added it, where nothing changed, and #63, which changed packages/ and so was left to the release. So the step had never run. package-manager-cache: false is setup-node's own switch for that (checked in its v5 action.yml: "Set to false to disable automatic caching based on the package manager field in package.json"). Nothing was pushed by the failed run, so the template repositories are still on their v0.12.0 sync. Checked: prettier and lint pass. Not checked: the job itself, which can only run on GitHub. This change touches only .github, so merging it does not mirror anything; Run workflow on the Mirror workflow, on main, is what will carry #65's FUNDING.yml across and prove the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue a toolbar for a control Panel, and say where to look first docs/internal/next.md gets a "Raise these first" section, for what the owner wants reminding of at the top of any "where are we at": - a right-aligned toolbar on a Panel's title line, for extra components, with the three questions to settle before building it; - Sequence in a real OBS, which 0.12.0 shipped without. AGENTS.md is what every session reads first, so it now says to start from next.md, and that section, when asked where things stand. Without that the note would only be found by somebody already looking for it. Checked: lint passes. Prettier flags next.md, as it did before this change (two *emphasis* spans and a table, all older than this section). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue color-scheme: dark for the board, alongside the Panel actions slot A time input's clock icon is Chrome's to draw, and it draws it dark unless the page declares a dark theme, so on the board it all but disappeared. A studio fixed it with color-scheme: dark on its board in its own index.css, and found it also darkens the time picker's popup, the menus behind Select and the scrollbars. Every board is dark, so the line belongs in core's base.css, scoped to .ss-control as the board's cursors are, where it cannot reach a graphic. Queued, not done. The toolbar entry is renamed to the owner's word for it: an actions slot. Checked: lint passes. Not checked: anything in a browser; this only records the finding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Rewrap the actions-slot reminder to the file's width Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue a Panel that folds and carries header actions, from a studio that built one SS-Mercy-Riftbound-2v2 built a collapsible Panel with header actions in its own src/control, because core's Panel has nothing beside its title. Its notes go into next.md so core can take it over rather than rediscover it: - the behaviour: everything starts folded on every load, and the fold is component state only -- not the show, which would fold every operator's board, and not localStorage, so a reload is always the same board; - the markup: the button inside the h2, not the other way round; - what bit: .ss-panel-body's display: flex beats the hidden attribute, and a grid of panels needs items-start; - the API it asks for: collapsible, defaultOpen, exported useCollapsed and Chevron, an actions slot, and size="sm" on the four header buttons, none of which has a size today. It replaces the earlier actions-slot entry in "Raise these first", which now points here. Checked: lint passes. Not checked: the hidden-attribute finding, which is the studio's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Give a Panel actions on its title line, and let it fold Two things a studio (SS-Mercy-Riftbound-2v2) built for itself because core's Panel had nothing beside its title: - `actions`: anything at all, right-aligned on the title line, or a function given `{ open }` that returns it. They stay in the header and work while the panel is folded, and in a slim dock take a line of their own under the title rather than squeezing it. - `collapsible`: the title becomes a button that folds the body away. A collapsible panel starts folded on every load; `defaultOpen` starts one open. The fold is component state only -- not the show, which would fold every operator's board, and not storage, so a reload is the same board. The body is hidden, not unmounted, so a draft in a folded panel survives. Off unless asked for, so every existing panel renders as before, except that its title now sits in a `.ss-panel-header` line. With no title, actions keep their line and a collapsible panel gets a chevron of its own, named "Fold panel" / "Open panel"; with nothing for a header to hold there is none. The button sits inside the h2, never the reverse. `chevron` joins Icon. Cross-checked against the studio's own Panel and collapse.jsx, and took its header element and its larger title hit area. Not taken: its Tailwind `hidden` class on the body. Its notes say `.ss-panel-body`'s display: flex beats the hidden attribute, but Tailwind's preflight, which every studio imports, has `[hidden] { display: none !important }`: a `[hidden]` rule written into base.css for it changed nothing (the folded body measured 0px tall without it), so it was taken out again rather than kept as code nothing can catch. Thirteen e2e checks, in their own section near the end. Placed after Rows first, they wedged the asset library's folder upload a hundred lines later -- the stall AGENTS.md describes -- and moved, everything passed. Negative-tested with nine breaks, each turning its check red: body not hidden; body unmounted while folded; function actions not given the fold; a header with nothing in it; collapsible by default; defaultOpen ignored; a header that does not wrap; a header that toggles on any press inside it; a fold remembered in localStorage. Docs: getting-started's Panel row and a paragraph with an example, CHANGELOG Unreleased, api.md regenerated, and next.md now says what is built and what the studio still wants: size="sm" on header buttons, useCollapsed and Chevron exported for folding cards, and zebra striping. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 306 of 306 against a fresh build. Not checked: in OBS's own browser, or in the studio itself, which still uses its own Panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Stripe the board's panels, darken its native pickers, and size header buttons Four things from SS-Mercy-Riftbound-2v2 that every studio should have without writing them: - Striped panels, by default. Every other panel is a shade lighter, so a long board reads as blocks rather than one slab. The studio's own rule and colours: rgb(15 23 42 / 0.4) and rgb(30 41 59 / 0.7). The background moved from a class on the element into base.css, because the count -- nth-of-type among sibling panels -- can only be made in CSS; in the components layer, so a bg-* on one panel or a studio's own rule still wins. A panel wrapped in a <div> of its own never counts as even; documented rather than worked around. - color-scheme: dark on .ss-control. Chrome draws a time input's clock icon, its picker, a select's list and scrollbars in the page's scheme, and on the board they were black on slate. On the board only; a graphic stays normal. - size="sm" on Confirm, ResetButton, SwapButton and Toggle, for a button in a panel's header: text-xs, smaller padding, off the Row's input line, and a min-h-6 floor so it is never under the 24px pointer target WCAG 2.5.8 asks for. Replaces the studio's `min-h-0! px-2.5! py-1! text-xs!`, which had no floor. Measured: 24 or 26px against 40px on a row, 12px text. - useCollapsed and Chevron, exported from @single-studio/core/control, so a card folds the way a Panel does. Panel is now built on them, and both are in the API reference's list. Seven e2e checks, all near the end, and the small buttons mount only when those checks ask: mounted from the start, they gave earlier checks that find the board's one swap by class three to choose from. Negative-tested, each check red when broken for it: stripes removed; the scheme normal; the scheme on :root, reaching graphics; Toggle ignoring size; a confirming Reset not passing size on; the small size under 24px; useCollapsed starting open; the chevron never turning. Removing the min-h-6 floor at first changed nothing, because the padding alone makes 24px, so the fixture now squeezes one button's padding to zero and the floor is what holds it at 24. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 313 of 313 against a fresh build. The useCollapsed doc comment was reworded after that run; nothing else changed. Not checked: OBS's own browser, or the studio itself, which still uses its own Panel and CSS until core is released. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Let a stepper and a stopwatch fill their cell, and fold the demo's panels A stepper's number field stopped at 4rem, so a stepper was 160px in any cell and the rest of the cell sat empty -- the negative space at every breakpoint. Measured on the fixture: 170px of 330 in a 380px dock, 414px of 574 at 640px, 601px of 761 at 1600px. A stopwatch's readout did the same, up to 295px. Both now grow between their buttons (`grow`, not `flex-1`, so `w-16` is still the basis and a `col-auto` stepper keeps its own 160px). The same thing SS-Mercy-Riftbound-2v2's FillStepper did for itself, now for everyone. The demo, built against these packages: its two score steppers left 121-201px empty below 1024px on 0.12.0 and leave nothing now, measured at 380, 640, 800, 1024, 1280 and 1600px. Its panels are collapsible: the scoreboard starts open, the rest folded. Its Swap sides moved into the scoreboard's header at size="sm", where it works with the panel folded. The demo uses props 0.12.0 does not have, so it has to go out with the release; the mirror leaves a push that also changes packages/ to the release anyway. Nine e2e checks at 380, 800 and 1280px: every stepper on a Row reaches its cell's edge, so does a stopwatch, and a col-auto stepper is 160px. Negative- tested: the field not growing, the readout not growing, and the field sized to its cell (which loses col-auto its width) each turned their checks red. Checked: test (core 603, every package passes), lint, typecheck, verify:template, docs:build, and e2e 322 of 322 against a fresh build. Not checked: OBS's own browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Say in the reference that a stepper and a stopwatch fill their cell The API reference takes each component's opening paragraph, and the fill change only touched the markup and its comments, so docs/api.md still described a stepper as if it sat at 160px. One sentence in each opening paragraph, and api.md regenerated from the built types. Checked: lint, typecheck, test (core 603, every package passes), and `api-reference.mjs --check` says api.md matches the shipped types. Not run: e2e, since only doc comments changed; it passed, 322 of 322, on a3d3e31. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Cut 0.13.0, so the folding Panel, the stripes and filling steppers go out Every published package moves to 0.13.0 together, as the release workflow requires: core, provider-supabase and the four plugins. The plugins' peer range on core, both templates and the demo move to ^0.13.0 -- in 0.x a caret on 0.12.0 does not reach 0.13.0, and the demo now uses collapsible, defaultOpen and size="sm", which 0.12.0 does not have. A minor: a board looks different after upgrading without asking -- every other panel lighter, a dark scheme for native pickers, steppers and stopwatches that fill their cell -- though no prop changes meaning and nothing is removed. The CHANGELOG's Unreleased section becomes 0.13.0, with a paragraph saying why it is a minor. next.md's first reminder becomes moving SS-Mercy-Riftbound-2v2 onto it. Checked: `pnpm install --frozen-lockfile` needs no lockfile change. test (core 603, every package passes), lint and typecheck pass. verify:template packs the 0.13.0 tarballs and builds both templates and the demo against them. docs:build passes. Not run: the end-to-end suite, since nothing the fixture loads changed but version numbers; it passed, 322 of 322, on #67's code. Not checked: the publish itself, which happens on the tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Queue three reports from client work: board padding, col-auto pickers, --ss-* docs A studio on 0.13.0 filed three findings, each measured on a live board; next.md now carries them with the measurements, each checked against the code here: - The board steps its padding at 640px through utilities in the markup: Panel's `p-3 sm:p-4`, and in pages/Control.jsx the <main>'s `gap-3 p-3 sm:gap-4 sm:p-4` and the bar's `px-3 py-2.5 sm:px-4 sm:py-3`. The <main> has no class of its own. The ask is custom properties with today's values as defaults, and an `ss-board` class. - `col-auto` is `flex: 0 0 auto` with no ceiling, and an ImagePicker is a <select> as wide as the longest library key: 136px for `x`, 365px for a descriptive logo name, leaving the Field beside it 25px. The ask is a cap inside the utility, which a studio cannot write for itself. - Docs only: read an --ss-* property with a fallback, and how to tell a half-applied dev-server stylesheet from broken code. Raised first, alongside the Mercy move and Sequence in OBS. Prettier also reformatted three older spots in the file it was already flagging. Checked: lint passes. Not checked: the studio's measurements, which are its own; only the code each one points at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Cut 0.14.0: the board's spacing as properties, a ceiling on col-auto pickers Three findings from a studio running 0.13.0 on client work, each measured on a live board there and checked against the code here. The board stepped its padding at 640px through utilities in the markup -- Panel's `p-3 sm:p-4`, the <main>'s `gap-3 p-3 sm:gap-4 sm:p-4`, the bar's `px-3 py-2.5 sm:px-4 sm:py-3` -- which a studio could only beat with CSS aimed at those classes, and the <main> had no class at all. They are now `--ss-panel-pad`, `--ss-board-pad`, `--ss-board-gap`, `--ss-bar-pad-x` and `--ss-bar-pad-y` on `.ss-control`, with the same values and the same step at 40rem by default (measured: 12/12/12/12/10px at 380px, 16/16/16/16/12px at 1280px, as before), and the <main> is `.ss-board`. A studio that sets them on `.ss-control` gets them at every width: 20px at 380px and at 1280px. `col-auto` was `flex: 0 0 auto` with no ceiling, and an ImagePicker is a <select> as wide as the longest library key: the studio measured 365px and a 25px Field beside it for a logo named northwind-esports-primary-logo-2026. The utility now caps a col-auto picker at `--ss-picker-max` (9.25rem), inside the utility so `sm:col-auto` caps only from `sm` up. With that name in the library here: 148px and the Field 798px of a 958px row at 1024px wide, and 330 of 330px at 380px, where the picker has its line to itself. Docs: getting-started gets the spacing properties, reading an --ss-* property with a fallback, and a Troubleshooting entry for a dev server serving half a stylesheet. releasing.md says renaming an --ss-* property is quietly breaking. Version: all six packages to 0.14.0; the plugins' peer range, both templates and the demo to ^0.14.0. A minor: a col-auto picker can render narrower, and the board's spacing moved out of the markup. Six e2e checks, negative-tested, each red when broken for it: no cap; the cap a studio could write by attribute selector (it caps below the breakpoint too); panel padding back as utilities (a studio's setting then loses); <main> without its class; the 640px step lost. Two fixes to the checks on the way: the cap measured at 700px, where a Row still stacks, proved nothing, so it is measured at 1024px with the field's width exact; and a missing .ss-board made the spacing measure throw rather than fail, so it now falls back and fails by name. The fixture's new picker took a panel of its own, because its library dialog brings an h2 into the panel it sits in. Checked: test (core 603, every package passes), lint, typecheck, verify:template (0.14.0 tarballs), docs:build, api.md current, and e2e 328 of 328 against a fresh build. Not checked: OBS's own browser; the studio itself, which still carries its overrides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU * Stop a stalled Chromium download holding CI: cache it, retry it, time-limit it On 2026-10-23 the "Install Chromium" step hung three times -- 7 to 10 minutes each against 20-27 seconds healthy -- and each held a pull request until somebody noticed and cancelled; a re-run on another runner always went straight through. The job had no timeout, so GitHub would have allowed 360 minutes. - The browser is cached (actions/cache@v5, the lowest major on Node 24, as every action here is), keyed on Playwright's version, so most runs do not download it at all. On a hit only `install-deps` runs, for the system packages, which are not in the cache. - Each install attempt gets two minutes and three tries. `timeout` signals the whole process group, so a hung apt-get under sudo dies with it rather than holding the dpkg lock for the retry. - `verify` has a 20-minute limit (healthy: about 4), and the Pages build and deploy 10 each (healthy: 19-28s and 9-13s). release.yml and mirror.yml already had theirs. Checked: the retry loop, against a fake installer at 3 seconds instead of 120: one that hangs twice then succeeds passes on attempt 3; one that always hangs fails after three, with each attempt's child process killed (state Z, not left running). Both workflow files parse as YAML and pass prettier. Not checked: any of it on GitHub, which only the run on this push can show -- including that the first run saves the cache and the next restores it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
Panelthat folds and carries header actions, striped panels, a dark board for the browser's own pickers, header-sized buttons, steppers that fill their cell, and a demo whose panels fold. All of it was built first in SS-Mercy-Riftbound-2v2 and is now in core, so every studio gets it.Panel
actionscan be anything, or a function given{ open }that returns it. It sits right-aligned on the title line and keeps working while the panel is folded; pressing an action never opens or folds the panel. In a narrow dock the actions move to their own line under the title.collapsiblemakes the title a button that folds the panel. It's off by default, so existing panels stay as they are.defaultOpenstarts one open.The board
<div>stays the darker shade. That's documented rather than worked around.color-scheme: darkon.ss-control. The clock icon on time inputs, the time picker,<select>lists and scrollbars now draw dark. Graphics are untouched.Buttons and folding helpers
size="sm"onConfirm,ResetButton,SwapButtonandToggle, for buttons in a panel's header. It has smaller text and padding and a 24px minimum height (WCAG 2.5.8), even when a studio squeezes the padding. It replaces the studio'smin-h-0! px-2.5! py-1! text-xs!.useCollapsedandChevron, exported from@single-studio/core/control, for folding cards and anything else the way aPanelfolds.Panelitself is built on them.Steppers and stopwatches fill their cell
col-autostill keeps a stepper at its own 160px.FillStepperunnecessary.Demo
size="sm", so it works with the panel folded.packages/.Also
docs/internal/next.mdgets a "Raise these first" list.AGENTS.mdnow points there when someone asks where things stand.display: flexbeats thehiddenattribute. Tailwind's base styles already force[hidden]todisplay: none !important, so a CSS rule written for it changed nothing. Core relies on the attribute.Verified
Not checked: OBS's own browser, or the studio itself, which keeps its own Panel until this is released.
Release: these are additions plus a visible default change (the stripes), so the next version would be 0.13.0. Nothing is bumped in this PR.
https://claude.ai/code/session_01TFGhv32jx1vxD7qxaMoFxU
Generated by Claude Code