Add Blueprint editor shortcut to the "Start a new Playground" panel#3723
Add Blueprint editor shortcut to the "Start a new Playground" panel#3723amitraj2203 wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a discoverable “Blueprint editor” shortcut to the “Start a new Playground” panel, enabling users to jump directly into the Blueprint tab in the Site Manager.
Changes:
- Adds a new “Blueprint editor” creation option that sets the preferred SiteInfoPanel tab to
blueprintand opens the site manager. - Introduces a Redux-driven remount key (
siteInfoPanelKey) and action to forceSiteInfoPanelremount when the site manager is already open. - Exposes
setSiteLastTabfor reuse so the overlay can write the tab preference consistently.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| packages/playground/website/src/lib/state/redux/slice-ui.ts | Adds siteInfoPanelKey to UI state and a remountSiteInfoPanel action to force panel remounts. |
| packages/playground/website/src/components/site-manager/site-info-panel/index.tsx | Exports setSiteLastTab for external callers. |
| packages/playground/website/src/components/site-manager/index.tsx | Uses siteInfoPanelKey in SiteInfoPanel’s React key to trigger remounts. |
| packages/playground/website/src/components/saved-playgrounds-overlay/index.tsx | Adds the “Blueprint editor” launch option and hooks it into Site Manager open/remount behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| setSiteSlugToSave, | ||
| remountSiteInfoPanel, | ||
| } from '../../lib/state/redux/slice-ui'; | ||
| import { setSiteLastTab } from '../site-manager/site-info-panel'; |
| onClick: () => { | ||
| if (activeSite) { | ||
| setSiteLastTab(activeSite.slug, 'blueprint'); | ||
| } | ||
| if (siteManagerIsOpen) { | ||
| dispatch(remountSiteInfoPanel()); | ||
| } | ||
| dispatch(setSiteManagerOpen(true)); | ||
| dispatch(setSiteManagerSection('site-details')); | ||
| onClose(); | ||
| }, | ||
| disabled: false, |
| offline: boolean; | ||
| siteManagerIsOpen: boolean; | ||
| siteManagerSection: SiteManagerSection; | ||
| siteInfoPanelKey: number; |
| remountSiteInfoPanel: (state) => { | ||
| state.siteInfoPanelKey++; | ||
| }, |
| fullScreenSections ? ( | ||
| <SiteInfoPanel | ||
| key={activeSite?.slug} | ||
| key={`${activeSite?.slug}-${siteInfoPanelKey}`} |
| }} | ||
| > | ||
| <SiteInfoPanel | ||
| key={`${activeSite?.slug}-${siteInfoPanelKey}`} |
|
Thanks for the PR @amitraj2203! I've taken a look at the new button, and it's displayed as a new line.
Let's explore some other options, like displaying all buttons in a single line or two lines.
|
| onClick: () => { | ||
| if (activeSite) { | ||
| setSiteLastTab(activeSite.slug, 'blueprint'); | ||
| } | ||
| if (siteManagerIsOpen) { | ||
| dispatch(remountSiteInfoPanel()); | ||
| } | ||
| dispatch(setSiteManagerOpen(true)); | ||
| dispatch(setSiteManagerSection('site-details')); | ||
| onClose(); | ||
| }, |
There was a problem hiding this comment.
This seems complex. What would it take to have just this?
dispatch(setSiteManagerOpen(true));
dispatch(setSiteManagerSection('blueprint'));
There was a problem hiding this comment.
Hey, totally agree it was overcomplicated! The issue was that TabPanel only reads initialTabName once on mount, so switching to the Blueprint tab externally was tricky. The old approach worked around this by writing to localStorage and force-remounting the panel via a counter which ended up touching way too many files.
Your suggestion made me rethink it. In 1bf3df9 I've added 'blueprint' as a new SiteManagerSection as it makes more sense, the panel remounts when the section changes, and SiteInfoPanel just reads initialTab as a prop. The onClick is now exactly those two dispatches.
Let me know if further changes are required.
|
With Playground autosaving enabled, Blueprints can't be edited anymore, so we will need to start a new temporary Playground to allow users to add Blueprints. It might be worth addressing this separately from this PR, but as-is autosaving is blocking users from editing Blueprints. |
| fullScreenSections ? ( | ||
| <SiteInfoPanel | ||
| key={activeSite?.slug} | ||
| key={`${activeSite?.slug}-${siteInfoPanelKey}`} |
There was a problem hiding this comment.
Why do we need siteInfoPanelKey? From what I could understand, it's used to force an update to the SiteInfo panel, but we shouldn't need this. React should always display the current site info. Is there an underlying bug that prevents React from updating site info?
There was a problem hiding this comment.
The SiteInfoPanel key is now ${activeSite.slug}-${activeSiteManagerSection}, so when the section changes from site-details to blueprint, React naturally remounts the panel with initialTab="blueprint"
| const initialTab = | ||
| activeSiteManagerSection === 'blueprint' | ||
| ? 'blueprint' | ||
| : undefined; |
There was a problem hiding this comment.
Why limit it just to blueprint? Could it work with other tabs without adding complexity?
There was a problem hiding this comment.
I flipped the logic now in 01dc267, defined the sections that are NOT tab names and anything outside that list is treated as a tab name.
| }) { | ||
| const offline = useAppSelector((state) => state.ui.offline); | ||
| const dispatch = useAppDispatch(); | ||
| // Load the last active tab for this site |
There was a problem hiding this comment.
We should update the comment
| fullScreenSections ? ( | ||
| <SiteInfoPanel | ||
| key={activeSite?.slug} | ||
| key={`${activeSite?.slug}-${activeSiteManagerSection}`} |
There was a problem hiding this comment.
Do we need the key still now that we have initialTab?
There was a problem hiding this comment.
Yes, I think we still need it. initialTab is only read once when the panel mounts (via useState/TabPanel's initialTabName), so if the panel is already open for the same site, changing the prop alone won't switch tabs. The section in the key forces a remount so initialTab actually takes effect for example when the manager is already open on Settings and we pick "Blueprint editor". With key={slug} only, the slug is unchanged so it'd stay on the old tab.
I've also tested this behaviour.
Screen.Recording.2026-06-03.at.6.33.21.PM.mov
bgrgicak
left a comment
There was a problem hiding this comment.
Thank you for simplifying the PR! I left a few more comments, but the PR seems mostly good now.
When you get a chance, please update the PR description to match the new implementation.
I've updated the PR description now |


Motivation for the change, related issues
Users who write blueprints (e.g. with external tools) had no quick way to reach the Blueprint editor from the "Start a new Playground" launch panel. This adds a dedicated shortcut so the editor is discoverable alongside the other launch options.
Closes #3171
Implementation details
< >code icon) as the last entry in thecreationOptionsarray inSavedPlaygroundsOverlay. Clicking it opens the site manager and sets the section to'blueprint'.'blueprint'as a newSiteManagerSectionvalue. InSiteManager, any section that isn't a standard panel (site-details,blueprints,sidebar) is passed toSiteInfoPanelas theinitialTab, so the panel opens directly on the matching tab.SiteInfoPanelaccepts an optionalinitialTabprop that takes precedence over the last-visited tab when choosing which tab to open on mount.SiteInfoPanelkey includes the active section (${slug}-${section}) so that changing the section remounts the panel — this is what letsinitialTabtake effect when the site manager is already open on another tab.createVanillaSite,previewBlueprint) reset the section back to'site-details'so a freshly created Playground doesn't inadvertently open on the Blueprint tab..creationRowlayout (flex: 1on buttons) so the launch options share rows evenly instead of orphaning the new 7th button on its own line.Testing Instructions (or ideally a Blueprint)
< >icon appears in the "Start a new Playground" row.