fix(studio): pin synthesis controls below scrolling form

This commit is contained in:
Palash Debnath
2026-09-05 16:26:13 +05:30
parent aedca15f7e
commit 17df9210cd
5 changed files with 17 additions and 11 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ the frozen-backend fallback mirror it for their toolchains.
**Highlights**
- Voice modes now lead the workspace as full-width tabs, with the active engine above them and each workflow below (#1823)
- Voice modes now lead the workspace as full-width tabs, with the active engine above them and Synthesize pinned below the scrolling form (#1823)
- Voice cloning now starts with a clear upload-or-record choice, reveals recording and reference details only when needed, and keeps sampling controls under Production Overrides (#1817)
### Changed
+1 -1
View File
@@ -57,7 +57,7 @@
| **Storage** | Voices, projects, settings, and outputs stay on the machine by default |
| **License** | AGPL-3.0 application; downloaded models keep their upstream terms |
The Voice workspace starts with the active engine selector and three tabs: **From audio** for cloning, **By design** for creating a voice, and **Convert** for speech-to-speech conversion. Each tab displays its own workflow below.
The Voice workspace starts with the active engine selector and three tabs: **From audio** for cloning, **By design** for creating a voice, and **Convert** for speech-to-speech conversion. Each tab displays its own workflow below. In From audio and By design, Synthesize Audio stays at the bottom while the form scrolls above it.
<a id="install"></a>
+6 -1
View File
@@ -2148,6 +2148,11 @@ div[role="dialog"].audio-trimmer {
gap: 8px;
}
.studio-action-bar .override-content {
max-height: 40vh;
overflow-y: auto;
}
/* ═══════════════════════════════════════════════════════════
RESPONSIVE — make every component adapt to viewport width
════════════════════════════════════════════════════════════ */
@@ -4953,7 +4958,7 @@ button.dub-stepper__action:focus-visible {
.shell-narrow .studio-with-history__main,
.shell-mini .studio-with-history__main {
overflow: visible;
flex: 0 0 auto;
flex: 1 0 auto;
order: 1;
}
.shell-narrow .studio-with-history__main .studio-action-bar,
+2 -8
View File
@@ -443,14 +443,8 @@ export default function CloneDesignTab(props) {
</TabsList>
</div>
<TabsContent value={defineMethod} className="flex min-h-0 flex-col">
{/* #1771 follow-up (item 6): NOT flex-1 the old always-open 12-row
Design block was tall enough that this area routinely filled the
full column height on its own. Now that Details defaults collapsed,
forcing this to grow-fill would strand a dead gap between it and
ActionBar below. Sizing to content (min-h-0 + overflow-y-auto still
in play) lets it shrink for short content and still scroll when
content genuinely exceeds the available height. */}
<div className="flex flex-col gap-[6px] min-h-0 overflow-y-auto">
{/* The form owns the remaining height and scrolls above the action bar. */}
<div className="flex flex-1 flex-col gap-[6px] min-h-0 overflow-y-auto">
{/* SCRIPT what should it say
Hidden for Convert: the source clip IS the script (the backend
transcribes it), so a text panel would only mislead. */}
@@ -46,6 +46,13 @@ describe('workspace narrow-shell reflow (#476 CTA-clipping guard)', () => {
expect(css).toMatch(/\.studio-action-bar\s*\{[^}]*position:\s*sticky/s);
});
it('fills narrow workspaces and bounds expanded settings above the pinned action', () => {
expect(css).toMatch(/\.shell-mini\s+\.studio-with-history__main\s*\{[^}]*flex:\s*1 0 auto/s);
expect(indexRaw).toMatch(
/\.studio-action-bar\s+\.override-content\s*\{[^}]*max-height:\s*40vh;[^}]*overflow-y:\s*auto/s,
);
});
it('keeps saved voices in the left rail and generation history alone on the right', () => {
expect(app).toMatch(
/className="studio-voices">\s*<WorkspaceVoices[\s\S]*?<\/div>\s*<div className="studio-with-history__main">/,