v0.113.0 — Sidebar tabs
Merged 2026-10-02 (f11eb2dc) — built on version/0.113.0; the tag is in
the changelog. With system8 0.19.0 and dnd5e 0.20.0 (Module API 1.41.0).
Sidebar tabs: the play bar's side columns become tab buttons and each sidebar holds exactly one context, its tab's content, without the context chrome (header, collapse, undock, padding) stacked under the bar. Plus the Mini-Me overlay for the impersonated character or token, and a positivity on TimedEffects. Desktop only; the MobileShell is unchanged.
Decisions carried from the spec's questions: an old persisted stack keeps its first context and drops the rest; the active tab and its sidebar are one continuous shape and one colour; Timeline and Chat Settings are always on the bar; Chat Settings autosaves; conditions are not given a positivity (all render as negative), TimedEffects are, per instance, default neutral; clicking Mini-Me's portrait does nothing.
- [x] ST.1 — one context per side:
layoutStoreholds at most one docked context on each side (opening one on a side replaces what was there), collapse is gone, a persisted stack migrates to its first context; a docked tab closed by its button stays closed (the chat is opened on a first visit, not reopened on every render); popping a tab out leaves its side empty - [x] ST.2 — tab buttons: the play bar's columns are tab strips — the active tab extends to the bar's bottom edge, square-cornered there, with no rule under it, in the same colour as its sidebar; a popped-out tab has its own, detached highlight; a tooltip on each; Left: Me, System, Library, Map, Campaign, Wiki; Right (right to left): Transcript, Combat Log, Initiative, Chat Settings, Chat, Timeline (a toggle for the strip, shown popped-out while expanded)
- [x] ST.3 — tab content: the context header is gone; a title row at the top of the content (per the spec's table: none for System, Wiki, Chat, Initiative, Combat Log, Transcript) carries the content's own actions plus Undock and Close, ordered by priority (Close rightmost, then Edit, Focus Camera, Settings, History, Share, Refresh, Undock, others), the lowest collapsing into a … menu at the row's left when they do not fit
- [x] ST.4 — Chat: the old view dropdown, the Timeline toggle, the record button and the gear leave the header; Chat Settings is a tab whose content is the settings form, autosaving; the ChannelBar heads Chat, Combat Log and Transcript (not Initiative); the Transcript has a fixed record / stop button at its foot
- [x] ST.5 — the Character context in a tab: the Build Mode toggle becomes an Edit action; its actions (focus, refresh, share, history, validation, linked tokens, sheet view) join the title row; the sheet-view action toggles between the original sheet and the new one
- [x] ST.6 — Me: the character context for an impersonated character, the impersonated-token context for an unlinked token, and with nothing impersonated a list of what the user may impersonate (as the phone's Me chooser), a click impersonating
- [x] ST.7 — TimedEffect positivity:
positive | neutral | negativeon the shared type, apositivitycolumn (defaultneutral) indbSchema.ts, the sqlite DDL and a generated pg migration, through the service, the routes and Action API'sapi.timeline, and a picker in the effect dialogue - [x] ST.8 — Mini-Me: pinned at the map's top left (below the play bar, beside the left sidebar or the rail, following a resize), above the map and below modals, sidebars and the nub; the portrait (falling back to token art) at 120px, the name with an × that stops impersonating, and every bar the user can see as a labelled 14px bar
- [x] ST.9 — Mini-Me's status row: conditions (red), TimedEffects coloured by positivity, and Concentration (green), each with its tooltip
- [x] ST.10 — Mini-Me's action menus: icon buttons opening 15rem popovers of action buttons (each with its … menu — Info, Edit, Delete), grouped one per power or spell, and Full Character Sheet (opens Me) rightmost on every system. Which menus a system gets is the module's: Module API 1.41.0
SystemModule.actionMenus(sources: abilities, saves, attacks, powers, spells, skills, actions), filled by the platform from the token's actions; none declared — every module today — is one menu of every action. The platform names no system (CC-1). Spells show the slots above them, read-only: casting from Mini-Me runs the action through the map's executor, which (as the map's token bar always has) does not spend a slot - [x] ST.11 — the modules declare their menus: system8 —
actionMenus: [abilities, attacks, powers]; dnd5e —[abilities, saves, attacks, spells, skills];modules.hosted.jsonpins bumped- vtt-modules main, tagged:
dnd5e/v0.19.0(the Figma-styled sheet, fromexperiment/dnd5e-figma-sheet),dnd5e/v0.20.0andsystem8/v0.19.0— the menus spread from anobject(the campaign configuration's pattern), so they compile against GitHub's platform main and publish ahead of this release; an older host ignores the field. system8 0.19.0 folds in the never-tagged 0.18.2 (system8 8.19.0's reorganized docs) and commits the 8.19.0 content snapshot;content-source.jsonstill namesmain, so the publish job ships main's content. modules.hosted.json: system8 0.19.0, dnd5e 0.20.0. Publishing is CI's, on the tags' push — confirm both published before this release merges.
- vtt-modules main, tagged:
Open question (from the spec, not in scope until answered): Combat Log entries and transcript rows post into whatever channel the acting client has open. Should they always post to and read from the Campaign channel, dropping the picker there?