Device preview + responsive spacing in the Style panel
Style panel gets a real-viewport iframe preview (390/820/1280px) tied to the breakpoint tab, reloaded after each edit, and spacing/gap controls per breakpoint. The editor does not boot inside the preview frame. Mock and tests mirror the new k6n layout template. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cb7a7a1fab
commit
ec4212c113
7 files changed
+136
-9
No files matched your search
@@ -84,7 +84,6 @@ describe('Style panel (schema-driven)', () => {
|
||||
await select('l1')
|
||||
await h.press('Style')
|
||||
await act(async () => void [...h.shadow.querySelectorAll<HTMLElement>('[role=tab]')].find((t) => t.textContent === 'Tablet')!.click())
|
||||
expect(h.shadow.querySelector('[data-style-field="gap"]')).toBeNull() // spacing has no per-breakpoint form
|
||||
await act(async () => void chip('flow', 'Stack').click())
|
||||
await h.settle()
|
||||
expect(data('l1').responsive).toEqual({ tablet: { flow: 'stack' } })
|
||||
@@ -95,6 +94,33 @@ describe('Style panel (schema-driven)', () => {
|
||||
expect('responsive' in data('l1')).toBe(false)
|
||||
})
|
||||
|
||||
it('breakpoints can override gap, which renders as a k6n-<bp>-gap class', async () => {
|
||||
h = await setup()
|
||||
await h.settle()
|
||||
await select('l1')
|
||||
await h.press('Style')
|
||||
await act(async () => void [...h.shadow.querySelectorAll<HTMLElement>('[role=tab]')].find((t) => t.textContent === 'Mobile')!.click())
|
||||
await act(async () => void chip('gap', 'xs').click())
|
||||
await h.settle()
|
||||
expect(data('l1').responsive).toEqual({ mobile: { gap: 'xs' } })
|
||||
expect(data('l1').gap).not.toBe('xs')
|
||||
expect(byId('l1').className).toContain('k6n-m-gap-xs')
|
||||
})
|
||||
|
||||
it('the device preview is an iframe named so the editor does not boot inside it', async () => {
|
||||
h = await setup()
|
||||
await h.settle()
|
||||
await select('l1')
|
||||
await h.press('Style')
|
||||
await act(async () => void [...h.shadow.querySelectorAll<HTMLElement>('[role=tab]')].find((t) => t.textContent === 'Mobile')!.click())
|
||||
await act(async () => void [...h.shadow.querySelectorAll<HTMLElement>('.cms-style__preview .cms-chip')][0].click())
|
||||
const f = h.shadow.querySelector('iframe')!
|
||||
expect(f.name).toBe('cms-device-preview')
|
||||
expect(f.style.width).toBe('390px')
|
||||
await act(async () => void h.shadow.querySelector<HTMLElement>('[aria-label="Close preview"]')!.click())
|
||||
expect(h.shadow.querySelector('iframe')).toBeNull()
|
||||
})
|
||||
|
||||
it('rapid clicks on one field coalesce into a single undo step', async () => {
|
||||
h = await setup()
|
||||
await h.settle()
|
||||
|
||||
+2
-1
@@ -25,7 +25,8 @@ describe('describeStyle', () => {
|
||||
expect(byName('paddingTop')).toMatchObject({ kind: 'spacing', box: 'padding', side: 'top', overrides: 'padding', token: '--k6n-sp-{value}', inferred: false })
|
||||
expect(byName('gap')).toMatchObject({ kind: 'gap', inferred: false })
|
||||
expect(byName('flow').responsive).toEqual(['mobile', 'tablet', 'desktop'])
|
||||
expect(byName('gap').responsive).toEqual([]) // spacing is not a breakpoint override (the template has no classes for it)
|
||||
expect(byName('gap').responsive).toEqual(['mobile', 'tablet', 'desktop'])
|
||||
expect(byName('padding').responsive).toEqual([]) // only declared per-side in the breakpoint def
|
||||
expect(isWrapperSchema(layout)).toBe(true)
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user