diff --git a/.changeset/petite-spoons-flash.md b/.changeset/petite-spoons-flash.md
new file mode 100644
index 0000000000..806704f196
--- /dev/null
+++ b/.changeset/petite-spoons-flash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': minor
+---
+
+Add resizable panels width for the editor and preview panels in the template editor and template form playground layouts. Users can now resize these panels by dragging the divider between the two areas.
diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt
index 5eba84e61d..4682640f90 100644
--- a/.github/vale/config/vocabularies/Backstage/accept.txt
+++ b/.github/vale/config/vocabularies/Backstage/accept.txt
@@ -552,3 +552,4 @@ zod
Zolotusky
zoomable
zsh
+resizable
diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json
index 4432b15d3a..73e6474e5a 100644
--- a/plugins/scaffolder/package.json
+++ b/plugins/scaffolder/package.json
@@ -96,6 +96,7 @@
"luxon": "^3.0.0",
"qs": "^6.9.4",
"react-resizable": "^3.0.5",
+ "react-resizable-panels": "^3.0.4",
"react-use": "^17.2.4",
"react-window": "^1.8.10",
"yaml": "^2.0.0",
diff --git a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditor.tsx
index b339be18e3..f845f1ca8d 100644
--- a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditor.tsx
+++ b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditor.tsx
@@ -34,6 +34,7 @@ import {
TemplateEditorLayoutFiles,
TemplateEditorLayoutPreview,
TemplateEditorLayoutConsole,
+ TemplateEditorPanels,
} from './TemplateEditorLayout';
import { TemplateEditorToolbar } from './TemplateEditorToolbar';
import { TemplateEditorToolbarFileMenu } from './TemplateEditorToolbarFileMenu';
@@ -88,17 +89,24 @@ export const TemplateEditor = (props: {
-
-
-
-
-
-
+
+
+
+ }
+ preview={
+
+
+
+ }
+ />
diff --git a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorLayout.tsx b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorLayout.tsx
index 242befe2b4..8b72b96b20 100644
--- a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorLayout.tsx
+++ b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorLayout.tsx
@@ -14,8 +14,11 @@
* limitations under the License.
*/
-import { PropsWithChildren } from 'react';
+import { PropsWithChildren, ReactNode } from 'react';
import { WithStyles, withStyles } from '@material-ui/core/styles';
+import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels';
+import { useTheme } from '@material-ui/core/styles';
+import useMediaQuery from '@material-ui/core/useMediaQuery';
export const TemplateEditorLayout = withStyles(
theme => ({
@@ -36,7 +39,7 @@ export const TemplateEditorLayout = withStyles(
"browser editor preview"
"results results results"
`,
- gridTemplateColumns: '1fr 3fr 2fr',
+ gridTemplateColumns: '1fr 5fr',
gridTemplateRows: 'auto 1fr auto',
},
},
@@ -73,12 +76,15 @@ export const TemplateEditorLayoutBrowser = withStyles(
));
export const TemplateEditorLayoutFiles = withStyles(
- {
+ theme => ({
root: {
gridArea: 'editor',
overflow: 'auto',
+ [theme.breakpoints.up('md')]: {
+ height: '100%',
+ },
},
- },
+ }),
{ name: 'ScaffolderTemplateEditorLayoutFiles' },
)(({ children, classes }: PropsWithChildren) => (
@@ -91,7 +97,7 @@ export const TemplateEditorLayoutPreview = withStyles(
position: 'relative',
backgroundColor: theme.palette.background.default,
[theme.breakpoints.up('md')]: {
- borderLeft: `1px solid ${theme.palette.divider}`,
+ height: '100%',
},
},
scroll: {
@@ -124,3 +130,50 @@ export const TemplateEditorLayoutConsole = withStyles(
)(({ children, classes }: PropsWithChildren) => (
));
+
+export const TemplateEditorPanelResizeHandle = withStyles(
+ {
+ root: {
+ width: 8,
+ cursor: 'col-resize',
+ background: 'rgba(0,0,0,0.04)',
+ },
+ },
+ { name: 'ScaffolderTemplateEditorPanelResizeHandle' },
+)(({ classes }: { classes: WithStyles['classes'] }) => (
+
+));
+
+export function TemplateEditorPanels({
+ files,
+ preview,
+ autoSaveId = 'template-editor-panels',
+}: {
+ files: ReactNode;
+ preview: ReactNode;
+ autoSaveId?: string;
+}) {
+ const theme = useTheme();
+ const isMdUp = useMediaQuery(theme.breakpoints.up('md'));
+
+ if (isMdUp) {
+ return (
+
+
+ {files}
+
+
+
+ {preview}
+
+
+ );
+ }
+ // Stack as rows for small screens, just render children in a plain block
+ return (
+ <>
+ {files}
+ {preview}
+ >
+ );
+}
diff --git a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx
index 0d31f2ebe2..cb40ff2766 100644
--- a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx
+++ b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx
@@ -39,6 +39,7 @@ import {
TemplateEditorLayoutToolbar,
TemplateEditorLayoutFiles,
TemplateEditorLayoutPreview,
+ TemplateEditorPanels,
} from './TemplateEditorLayout';
import { TemplateEditorToolbar } from './TemplateEditorToolbar';
import { TemplateEditorToolbarFileMenu } from './TemplateEditorToolbarFileMenu';
@@ -113,7 +114,7 @@ const useStyles = makeStyles(
"textArea preview"
`,
gridTemplateRows: 'auto 1fr',
- gridTemplateColumns: '1fr 1fr',
+ gridTemplateColumns: '1fr',
},
},
files: {
@@ -207,23 +208,30 @@ export const TemplateFormPreviewer = ({
/>
-
-
-
-
-
-
+
+
+
+ }
+ preview={
+
+
+
+ }
+ />
);
};
diff --git a/yarn.lock b/yarn.lock
index 42bf210419..3f9a5af805 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7675,6 +7675,7 @@ __metadata:
react: "npm:^18.0.2"
react-dom: "npm:^18.0.2"
react-resizable: "npm:^3.0.5"
+ react-resizable-panels: "npm:^3.0.4"
react-router-dom: "npm:^6.3.0"
react-use: "npm:^17.2.4"
react-window: "npm:^1.8.10"
@@ -44498,6 +44499,16 @@ __metadata:
languageName: node
linkType: hard
+"react-resizable-panels@npm:^3.0.4":
+ version: 3.0.4
+ resolution: "react-resizable-panels@npm:3.0.4"
+ peerDependencies:
+ react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ checksum: 10/92b8ac224d3c60c7c8ea0d80f712d9cd719afad76d4f1a5b8c8cc7c886b77f1d5058fa622ea057f28f5f7fc1a2c86e38e14d7b0f33722c30bff02e37f9fba705
+ languageName: node
+ linkType: hard
+
"react-resizable@npm:^3.0.4, react-resizable@npm:^3.0.5":
version: 3.0.5
resolution: "react-resizable@npm:3.0.5"