+
-
-
-
-
-
-
@@ -667,11 +727,27 @@ onMounted(loadStudioGraph);
+
+
+
+
+
+
.self-serve-studio {
+ container-type: inline-size;
min-height: calc(100vh - 160px);
}
+.self-serve-studio.is-studio-fullscreen,
+.self-serve-studio:fullscreen {
+ background: #ffffff;
+ inset: 0;
+ min-height: 100vh;
+ overflow: auto;
+ padding: 24px;
+ position: fixed;
+ z-index: 10000;
+}
+
.studio-page-actions {
align-items: center;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+}
+
+.studio-page-actions.buttons .button {
+ margin-bottom: 0.5rem;
}
.studio-shell {
display: grid;
- grid-template-columns: 168px minmax(0, 1fr) 360px;
+ grid-template-columns: 168px minmax(620px, 1fr) minmax(300px, 340px);
gap: 14px;
- min-height: 760px;
+ min-height: min(760px, calc(100vh - 230px));
+}
+
+.self-serve-studio.is-studio-fullscreen .studio-shell,
+.self-serve-studio:fullscreen .studio-shell {
+ grid-template-columns: 190px minmax(760px, 1fr) minmax(340px, 420px);
+ min-height: calc(100vh - 132px);
}
.studio-sidebar,
@@ -1054,7 +1154,7 @@ onMounted(loadStudioGraph);
.studio-toolbar {
align-items: center;
display: grid;
- grid-template-columns: minmax(180px, 1fr) repeat(3, minmax(132px, 170px)) auto;
+ grid-template-columns: minmax(220px, 1fr) repeat(3, minmax(142px, 184px));
gap: 8px;
}
@@ -1074,11 +1174,21 @@ onMounted(loadStudioGraph);
padding-left: 36px;
}
+.studio-toolbar .select,
+.studio-toolbar .select select {
+ width: 100%;
+}
+
.studio-workspace {
display: grid;
- grid-template-columns: 132px minmax(0, 1fr);
+ grid-template-columns: 132px minmax(460px, 1fr);
gap: 10px;
- min-height: 700px;
+ min-height: min(700px, calc(100vh - 290px));
+}
+
+.self-serve-studio.is-studio-fullscreen .studio-workspace,
+.self-serve-studio:fullscreen .studio-workspace {
+ min-height: calc(100vh - 196px);
}
.studio-palette {
@@ -1113,15 +1223,47 @@ onMounted(loadStudioGraph);
linear-gradient(135deg, #dbeafe, #ddd6fe) border-box;
border: 1px solid transparent;
border-radius: 8px;
- min-height: 700px;
+ min-height: min(700px, calc(100vh - 290px));
overflow: hidden;
position: relative;
}
+.self-serve-studio.is-studio-fullscreen .studio-flow-surface,
+.self-serve-studio:fullscreen .studio-flow-surface {
+ min-height: calc(100vh - 196px);
+}
+
.studio-flow-surface :deep(.vue-flow) {
background-color: #f8fafc;
}
+.studio-flow-surface :deep(.vue-flow__controls) {
+ display: none;
+}
+
+.studio-flow-actions {
+ align-items: center;
+ background: rgba(255, 255, 255, 0.9);
+ border: 1px solid #e2e8f0;
+ border-radius: 7px;
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
+ display: flex;
+ flex-wrap: nowrap;
+ gap: 4px;
+ margin: 0;
+ padding: 4px;
+ position: absolute;
+ right: 12px;
+ top: 12px;
+ z-index: 4;
+}
+
+.studio-flow-actions.buttons .button {
+ height: 30px;
+ margin: 0;
+ min-width: 30px;
+}
+
.studio-flow-node {
background: #ffffff;
border: 1px solid #cbd5e1;
@@ -1187,11 +1329,16 @@ onMounted(loadStudioGraph);
display: flex;
flex-direction: column;
gap: 14px;
- max-height: 760px;
+ max-height: min(760px, calc(100vh - 230px));
overflow: auto;
padding-left: 14px;
}
+.self-serve-studio.is-studio-fullscreen .studio-details,
+.self-serve-studio:fullscreen .studio-details {
+ max-height: calc(100vh - 132px);
+}
+
.studio-details-header {
align-items: center;
display: flex;
@@ -1377,6 +1524,29 @@ onMounted(loadStudioGraph);
min-height: 160px;
}
+@container (max-width: 1120px) {
+ .studio-shell {
+ grid-template-columns: 64px minmax(0, 1fr);
+ }
+
+ .studio-sidebar .studio-panel-button span:last-child {
+ display: none;
+ }
+
+ .studio-workspace {
+ grid-template-columns: 128px minmax(0, 1fr);
+ }
+
+ .studio-details {
+ border-left: 0;
+ border-top: 1px solid #e2e8f0;
+ grid-column: 1 / -1;
+ max-height: none;
+ padding-left: 0;
+ padding-top: 12px;
+ }
+}
+
@media (max-width: 1280px) {
.studio-shell {
grid-template-columns: 64px minmax(0, 1fr);
diff --git a/tests/e2e/self-serve-studio-flow.spec.js b/tests/e2e/self-serve-studio-flow.spec.js
index f132cfa5..8d498da1 100644
--- a/tests/e2e/self-serve-studio-flow.spec.js
+++ b/tests/e2e/self-serve-studio-flow.spec.js
@@ -249,9 +249,31 @@ test.describe("All-in-one self-serve studio", () => {
await expect(page.getByTestId("self-serve-studio")).toBeVisible();
await expect(page.getByTestId("self-serve-studio-flow")).toBeVisible();
+ await expect(page.getByTestId("studio-flow-actions")).toBeVisible();
await expect(page.getByText("Are mirrors folded?").first()).toBeVisible();
await expect(page.getByText("Roskilde Edge 01").first()).toBeVisible();
+ const controlsDoNotCoverDetails = await page.evaluate(() => {
+ const controls = document.querySelector('[data-testid="studio-flow-actions"]')?.getBoundingClientRect();
+ const details = document.querySelector(".studio-details")?.getBoundingClientRect();
+ if (!controls || !details) {
+ return false;
+ }
+ return (
+ controls.right <= details.left ||
+ controls.bottom <= details.top ||
+ controls.left >= details.right ||
+ controls.top >= details.bottom
+ );
+ });
+ expect(controlsDoNotCoverDetails).toBe(true);
+
+ await page.getByTestId("studio-fullscreen-toggle").click();
+ await expect(page.getByTestId("self-serve-studio")).toHaveClass(/is-studio-fullscreen/);
+ await expect(page.getByTestId("studio-fullscreen-toggle")).toContainText("Exit fullscreen");
+ await page.getByTestId("studio-fullscreen-toggle").click();
+ await expect(page.getByTestId("self-serve-studio")).not.toHaveClass(/is-studio-fullscreen/);
+
await page.getByText("Are mirrors folded?").first().click();
await expect(page.getByRole("heading", { name: "Inspector" })).toBeVisible();
await page.getByRole("textbox", { name: "Question", exact: true }).fill("Are loose straps secured?");