Repair outline rows and add split panels for drag & drop

Outline chevron buttons were matched by a generic `.cms-outline li
button { width: 100% }` rule, so each expand/collapse arrow took a full
row and the tree looked stacked and broken. Scope row styling to
`.cms-orow__main`, fix the chevron to 22px, add rotating chevrons to the
section headers, and turn the blocks palette from centered narrow cards
into left-aligned rows.

Add a split toggle to the panel header: outline stays visible in a left
column while Blocks/Nodes switch as tabs in a right column, so a drag
source and its outline drop gaps are on screen together. Choice and
library tab persist per profile; stacked mode is unchanged.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
mats committed 2026-11-07 13:37:45 +01:00
1 parent fc0eb2c6be
commit b7849c0359
3 files changed
+140 -44

No files matched your search

+33
View File
@@ -114,6 +114,39 @@ describe('rail sections', () => {
expect(q('.cms-dev__body').textContent).toContain('blockEditors')
})
it('split mode shows the outline beside blocks/nodes tabs for drag & drop', async () => {
h = await setup()
await h.settle()
await h.press('Panel')
await h.settle()
// stacked by default: single column, no tabs
expect(h.shadow.querySelector('.cms-rail.is-split')).toBeNull()
await act(async () => void q('button[aria-label="Split panels side by side"]').click())
await h.settle()
expect(q('.cms-rail.is-split')).not.toBeNull()
// outline and blocks visible at the same time: a drag source can reach a gap
expect(qa('.cms-outline').length).toBeGreaterThan(0)
expect(q('[aria-label="Search blocks"]')).not.toBeNull()
// switch the library tab to nodes: blocks hide, nodes show, outline stays
await act(async () => void q('button[aria-label="Show nodes panel"]').click())
await h.settle()
expect(h.shadow.querySelector('[aria-label="Search blocks"]')).toBeNull()
expect(q('[aria-label="Search nodes"]')).not.toBeNull()
expect(qa('.cms-outline').length).toBeGreaterThan(0)
// starting a palette drag reveals outline gaps while both columns stay visible
h.editor.ctrl.beginPaletteDrag({ type: 'text', label: 'text' })
await h.settle()
expect(qa('[data-ogap]').length).toBeGreaterThan(0)
expect(q('[aria-label="Search nodes"]')).not.toBeNull()
await act(async () => void h.editor.ctrl.cancelDrag())
await h.settle()
// stacking collapses back to one column and remembers the choice
await act(async () => void q('button[aria-label="Stack panels"]').click())
await h.settle()
expect(h.shadow.querySelector('.cms-rail.is-split')).toBeNull()
expect(localStorage.getItem('cms-onpage.railsplit')).toBe('false')
})
it('assistant sits beside the dev panel instead of stacking under it', async () => {
;(navigator as any).gpu = {} // aiSupported() checks for a WebGPU API
h = await setup()