Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/26737-studio-selection-unfolds-panel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'@object-ui/app-shell': patch
---

fix(app-shell): in Studio, selecting an element while the right panel is hidden unfolds the panel on its properties

Clause-②: no
Metadata-protocol: none

With the right panel hidden from the top bar, selecting a flow node in Automations (or a block in Interfaces, or a field in Data) showed its configuration nowhere on a desktop-width screen: only a phone reopened the panel. A builder had to find the toggle again before they could edit the selected step.

What changes:

- A new selection now unfolds a hidden panel at every width, on the selected element's properties, the way `⌘.` unfolds it. The panel's shown state is remembered as when you show it from the toggle.
- Hiding the panel again while the same element stays selected keeps it hidden. Only another selection unfolds it.

What to do: nothing. Nothing a flow, page or object declares changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
* returns it to the flow's Configuration. A row too narrow for the classic
* aside opens no drawer (objectui#11795's fold is the classic layout's).
* - While 属性 shows, the copilot strip stays at the slot's foot.
* - A hidden slot stays hidden on a selection, as on Interfaces.
* - A hidden slot unfolds on a new selection (objectstack#26737); hidden again
* over the same selection, it stays hidden.
* - CONTROL: the Access pillar claims nothing — the slot shows the copilot
* alone; the Interfaces pillar's own pins live in `rightSlot-12725`.
*
Expand Down Expand Up @@ -383,19 +384,39 @@ describe('Automations: the Configuration is in the right slot (objectui#12725)',
}
});

it('a hidden slot stays hidden on a selection, as on Interfaces', async () => {
window.sessionStorage.setItem(DOCK_STUDIO_EXPANDED_STORAGE_KEY, '0');
// objectstack#26737 — at a desktop width (no `md` match), a node selected
// while the panel is hidden unfolds it on that node's configuration.
it('a hidden slot unfolds on a selection, on the selected node’s configuration', async () => {
await openFlow();
fireEvent.click(screen.getByTestId('studio-slot-toggle'));
expect(slot()).not.toBeVisible();
expect(window.sessionStorage.getItem(DOCK_STUDIO_EXPANDED_STORAGE_KEY)).toBe('0');

fireEvent.click(screen.getByTestId('pick-node'));
await act(async () => {});
expect(slot()).not.toBeVisible();
await waitFor(() => expect(slot()).toBeVisible());
expect(slot()).toHaveAttribute('data-mode', 'props');
expect(within(slotProps()).getByLabelText('Node start')).toBeVisible();
expect(screen.getByTestId('studio-slot-toggle')).toHaveAttribute('aria-pressed', 'true');
expect(window.sessionStorage.getItem(DOCK_STUDIO_EXPANDED_STORAGE_KEY)).toBe('1');
expect(screen.queryByTestId('auto-config-drawer')).toBeNull();
// Shown again, it opens on the selection's properties.
});

it('hidden again over the same selection, it stays hidden until another node is selected', async () => {
await openFlow();
fireEvent.click(screen.getByTestId('pick-node'));
await waitFor(() => expect(within(slotProps()).getByTestId('stub-flow-inspector')).toBeVisible());

fireEvent.click(screen.getByTestId('studio-slot-toggle'));
expect(slot()).toHaveAttribute('data-mode', 'props');
expect(within(slotProps()).getByTestId('stub-flow-inspector')).toBeVisible();
await act(async () => {});
expect(slot()).not.toBeVisible();
// The same node again is no new selection.
fireEvent.click(screen.getByTestId('pick-node'));
await act(async () => {});
expect(slot()).not.toBeVisible();

fireEvent.click(screen.getByTestId('pick-other-node'));
await waitFor(() => expect(slot()).toBeVisible());
expect(within(slotProps()).getByLabelText('Node end')).toBeVisible();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,19 @@ describe('Studio right slot: properties OR the copilot (objectui#12725)', () =>
expect(window.sessionStorage.getItem(DOCK_STUDIO_EXPANDED_STORAGE_KEY)).toBe('1');
});

// objectstack#26737 — a selection is never drawn nowhere: at a desktop width
// it unfolds a hidden slot on the selected block's properties.
it('selecting a block while the slot is hidden unfolds it on the properties', async () => {
await openDashboard();
fireEvent.click(screen.getByTestId('studio-slot-toggle'));
expect(slot()).not.toBeVisible();

fireEvent.click(screen.getByTestId('pick-block'));
await waitFor(() => expect(slot()).toBeVisible());
expect(slot()).toHaveAttribute('data-mode', 'props');
expect(within(slotProps()).getByTestId('stub-inspector')).toBeVisible();
});

it('the copilot tab and strip mark a plan that awaits approval', async () => {
copilot.planPending = true;
await openDashboard();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1807,10 +1807,19 @@ export function StudioDesignSurface({ aiSlot }: StudioDesignSurfaceProps): React
setSlotPropsClaims((n) => n + 1);
return () => setSlotPropsClaims((n) => n - 1);
}, []);
const showSlotProps = React.useCallback(() => {
// objectstack#26737 — a selection shows its properties at every width: a
// hidden slot unfolds, as `⌘.` unfolds it, so a builder who hid the panel is
// never left with a selection whose properties are drawn nowhere. One
// function for the surface's life (state, not a memo — AGENTS.md #10): the
// pillars ask on a new selection only, never because this was re-created.
const setSlotOpenRef = React.useRef(setSlotOpen);
React.useLayoutEffect(() => {
setSlotOpenRef.current = setSlotOpen;
});
const [showSlotProps] = React.useState(() => () => {
setSlotMode('props');
if (isMobile) setSlotOpenMobile(true);
}, [isMobile]);
setSlotOpenRef.current(true);
});
const slotHandle = React.useMemo<StudioRightSlotHandle | null>(
() =>
slotHost
Expand Down
Loading