feat(app): expose wrap cross axis gap
This commit is contained in:
parent
806c512a86
commit
84124721ff
|
|
@ -199,6 +199,8 @@ export const panelMessages = i18n('panels', {
|
|||
direction: 'Direction',
|
||||
flow: 'Flow',
|
||||
gapAuto: 'Auto gap',
|
||||
horizontalGap: 'Horizontal gap',
|
||||
verticalGap: 'Vertical gap',
|
||||
auto: 'Auto',
|
||||
columns: 'Columns',
|
||||
rows: 'Rows',
|
||||
|
|
|
|||
|
|
@ -26,36 +26,62 @@ const { panels } = useI18n()
|
|||
</div>
|
||||
|
||||
<div class="mt-2 flex items-center gap-1.5">
|
||||
<button
|
||||
v-if="ctx.gapAuto"
|
||||
data-test-id="layout-gap-input"
|
||||
class="group flex h-[26px] min-w-0 flex-1 cursor-pointer items-center rounded border border-accent/50 bg-accent/10 text-xs text-accent hover:bg-accent/15"
|
||||
@click="ctx.setGapAuto(false)"
|
||||
>
|
||||
<span class="flex shrink-0 items-center justify-center self-stretch px-[5px] text-accent/80">
|
||||
{{ ctx.node.layoutMode === 'VERTICAL' ? '↕' : '↔' }}
|
||||
</span>
|
||||
<span class="flex-1 truncate text-left">{{ panels.auto }}</span>
|
||||
</button>
|
||||
<ScrubInput
|
||||
v-else
|
||||
data-test-id="layout-gap-input"
|
||||
class="flex-1"
|
||||
:icon="ctx.node.layoutMode === 'VERTICAL' ? '↕' : '↔'"
|
||||
:model-value="Math.round(ctx.node.itemSpacing)"
|
||||
:min="0"
|
||||
@update:model-value="ctx.updateProp('itemSpacing', $event)"
|
||||
@commit="(v: number, p: number) => ctx.commitProp('itemSpacing', v, p)"
|
||||
/>
|
||||
<button
|
||||
data-test-id="layout-gap-auto-toggle"
|
||||
:title="panels.gapAuto"
|
||||
class="flex size-7 shrink-0 cursor-pointer items-center justify-center rounded border border-border bg-transparent text-[10px] text-muted hover:bg-hover hover:text-surface"
|
||||
:class="ctx.gapAuto ? 'border-accent bg-accent/10 text-accent' : ''"
|
||||
@click="ctx.setGapAuto(!ctx.gapAuto)"
|
||||
>
|
||||
A
|
||||
</button>
|
||||
<template v-if="ctx.node.layoutWrap === 'WRAP'">
|
||||
<ScrubInput
|
||||
data-test-id="layout-gap-input"
|
||||
class="min-w-0 flex-1"
|
||||
:icon="ctx.node.layoutMode === 'VERTICAL' ? '↕' : '↔'"
|
||||
:label="ctx.node.layoutMode === 'VERTICAL' ? panels.verticalGap : panels.horizontalGap"
|
||||
:model-value="Math.round(ctx.node.itemSpacing)"
|
||||
:min="0"
|
||||
@update:model-value="ctx.updateProp('itemSpacing', $event)"
|
||||
@commit="(v: number, p: number) => ctx.commitProp('itemSpacing', v, p)"
|
||||
/>
|
||||
<ScrubInput
|
||||
data-test-id="layout-cross-gap-input"
|
||||
class="min-w-0 flex-1"
|
||||
:icon="ctx.node.layoutMode === 'VERTICAL' ? '↔' : '↕'"
|
||||
:label="ctx.node.layoutMode === 'VERTICAL' ? panels.horizontalGap : panels.verticalGap"
|
||||
:model-value="Math.round(ctx.node.counterAxisSpacing)"
|
||||
:min="0"
|
||||
@update:model-value="ctx.updateProp('counterAxisSpacing', $event)"
|
||||
@commit="(v: number, p: number) => ctx.commitProp('counterAxisSpacing', v, p)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button
|
||||
v-if="ctx.gapAuto"
|
||||
data-test-id="layout-gap-input"
|
||||
class="group flex h-[26px] min-w-0 flex-1 cursor-pointer items-center rounded border border-accent/50 bg-accent/10 text-xs text-accent hover:bg-accent/15"
|
||||
@click="ctx.setGapAuto(false)"
|
||||
>
|
||||
<span
|
||||
class="flex shrink-0 items-center justify-center self-stretch px-[5px] text-accent/80"
|
||||
>
|
||||
{{ ctx.node.layoutMode === 'VERTICAL' ? '↕' : '↔' }}
|
||||
</span>
|
||||
<span class="flex-1 truncate text-left">{{ panels.auto }}</span>
|
||||
</button>
|
||||
<ScrubInput
|
||||
v-else
|
||||
data-test-id="layout-gap-input"
|
||||
class="flex-1"
|
||||
:icon="ctx.node.layoutMode === 'VERTICAL' ? '↕' : '↔'"
|
||||
:model-value="Math.round(ctx.node.itemSpacing)"
|
||||
:min="0"
|
||||
@update:model-value="ctx.updateProp('itemSpacing', $event)"
|
||||
@commit="(v: number, p: number) => ctx.commitProp('itemSpacing', v, p)"
|
||||
/>
|
||||
<button
|
||||
data-test-id="layout-gap-auto-toggle"
|
||||
:title="panels.gapAuto"
|
||||
class="flex size-7 shrink-0 cursor-pointer items-center justify-center rounded border border-border bg-transparent text-[10px] text-muted hover:bg-hover hover:text-surface"
|
||||
:class="ctx.gapAuto ? 'border-accent bg-accent/10 text-accent' : ''"
|
||||
@click="ctx.setGapAuto(!ctx.gapAuto)"
|
||||
>
|
||||
A
|
||||
</button>
|
||||
</template>
|
||||
<button
|
||||
class="flex size-7 shrink-0 cursor-pointer items-center justify-center rounded border border-border bg-transparent text-muted hover:bg-hover hover:text-surface"
|
||||
@click="ctx.toggleIndividualPadding"
|
||||
|
|
|
|||
|
|
@ -91,6 +91,22 @@ test('gap auto toggle sets space-between alignment', async () => {
|
|||
canvas.assertNoErrors()
|
||||
})
|
||||
|
||||
test('wrap mode exposes cross-axis gap control', async () => {
|
||||
await selectFrame()
|
||||
|
||||
await page.locator('[data-test-id="layout-direction-wrap"]').click()
|
||||
await canvas.waitForRender()
|
||||
|
||||
const before = await getNodeById(page, frameId)
|
||||
const initialSpacing = before!.counterAxisSpacing
|
||||
await canvas.dragScrubInput(page.locator('[data-test-id="layout-cross-gap-input"]'), 40)
|
||||
|
||||
const after = await getNodeById(page, frameId)
|
||||
expect(after!.layoutWrap).toBe('WRAP')
|
||||
expect(after!.counterAxisSpacing).toBeGreaterThan(initialSpacing + 5)
|
||||
canvas.assertNoErrors()
|
||||
})
|
||||
|
||||
test('uniform padding ScrubInput sets all four padding sides', async () => {
|
||||
await selectFrame()
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ export function getNodeById(page: Page, id: string) {
|
|||
primaryAxisAlign: n.primaryAxisAlign,
|
||||
counterAxisAlign: n.counterAxisAlign,
|
||||
itemSpacing: n.itemSpacing,
|
||||
counterAxisSpacing: n.counterAxisSpacing,
|
||||
layoutWrap: n.layoutWrap,
|
||||
paddingTop: n.paddingTop,
|
||||
paddingRight: n.paddingRight,
|
||||
paddingBottom: n.paddingBottom,
|
||||
|
|
|
|||
Loading…
Reference in a new issue