fix(app): align layer rows and icon menus

- Let virtualized Layer rows fill the panel width\n- Remove extra root indentation while preserving hierarchy depth\n- Keep icon menu labels beside their icons\n- Refresh reviewed panel snapshots
This commit is contained in:
Danila Poyarkov 2026-07-18 05:56:36 +03:00
parent 33d6a1efd1
commit 1f22aa3207
9 changed files with 9 additions and 32 deletions

View file

@ -48,7 +48,7 @@
### Fixes ### Fixes
- Align Fill and Effects sub-controls to their shared property-row content rails, and improve font-settings accessibility without clearing selection when dismissing overlays. - Align Fill and Effects sub-controls to their shared property-row content rails, make Layer rows fill the panel with cleaner root indentation, left-align icon menu labels, and improve font-settings accessibility without clearing selection when dismissing overlays.
- Restore the Variables dialog empty state, full-width table layout, unclipped type menu, and expected Escape handling in dialogs and popup menus. - Restore the Variables dialog empty state, full-width table layout, unclipped type menu, and expected Escape handling in dialogs and popup menus.
- Pin the patched `websocket-driver` release used through Trystero/Firebase collaboration to resolve a critical protocol-length advisory. - Pin the patched `websocket-driver` release used through Trystero/Firebase collaboration to resolve a critical protocol-length advisory.
- Preserve unrelated Figma prototype, library, export, and raw metadata when editing modeled `.fig` fields, while still overriding stale field-specific payloads. - Preserve unrelated Figma prototype, library, export, and raw metadata when editing modeled `.fig` fields, while still overriding stale field-specific payloads.

View file

@ -23,7 +23,7 @@ const ctx = useLayerTree()
const isSelected = computed(() => ctx.selectedIds.value.has(node.id)) const isSelected = computed(() => ctx.selectedIds.value.has(node.id))
const isDragging = computed(() => ctx.draggingId.value === node.id) const isDragging = computed(() => ctx.draggingId.value === node.id)
const padLeft = computed(() => `${8 + (level - 1) * ctx.indentPerLevel}px`) const padLeft = computed(() => `${(level - 1) * ctx.indentPerLevel}px`)
const rowEl = ref<HTMLElement | null>(null) const rowEl = ref<HTMLElement | null>(null)
@ -67,7 +67,7 @@ defineExpose({ rowEl })
</script> </script>
<template> <template>
<div :ref="onRef" :data-node-id="node.id"> <div :ref="onRef" :data-node-id="node.id" class="w-full">
<slot <slot
:node="node" :node="node"
:level="level" :level="level"

View file

@ -28,7 +28,10 @@ interface PageActions {
const pageInput = templateRef<HTMLInputElement>('pageInput') const pageInput = templateRef<HTMLInputElement>('pageInput')
const rename = useInlineRename((id, name) => pageActions.value?.rename(id, name)) const rename = useInlineRename((id, name) => pageActions.value?.rename(id, name))
const { panels, pages: pageMessages } = useI18n() const { panels, pages: pageMessages } = useI18n()
const menuCls = useMenuUI({ content: 'min-w-36 shadow-[0_8px_30px_rgb(0_0_0/0.4)]' }) const menuCls = useMenuUI({
content: 'min-w-36 shadow-[0_8px_30px_rgb(0_0_0/0.4)]',
item: 'justify-start gap-2'
})
const pageListStyles = tv(pageListTheme) const pageListStyles = tv(pageListTheme)
const baseStyles = pageListStyles() const baseStyles = pageListStyles()

View file

@ -45,7 +45,7 @@ import type { VariableType } from '@open-pencil/scene-graph'
const open = defineModel<boolean>('open', { default: false }) const open = defineModel<boolean>('open', { default: false })
const cls = useDialogUI({ content: 'flex h-[75vh] w-[800px] max-w-[90vw] flex-col' }) const cls = useDialogUI({ content: 'flex h-[75vh] w-[800px] max-w-[90vw] flex-col' })
const menuCls = useMenuUI({ content: 'w-40' }) const menuCls = useMenuUI({ content: 'w-40', item: 'justify-start gap-2' })
const addVariableMenuCls = useMenuUI({ content: 'w-48' }) const addVariableMenuCls = useMenuUI({ content: 'w-48' })
const variableTable = tv(variableTableTheme) const variableTable = tv(variableTableTheme)
const tableStyles = variableTable() const tableStyles = variableTable()

View file

@ -154,19 +154,7 @@ test('effect settings expand semantically and row remove reveals on hover', asyn
await expect(expand).toHaveAttribute('aria-expanded', 'false') await expect(expand).toHaveAttribute('aria-expanded', 'false')
await expand.click() await expand.click()
await expect(expand).toHaveAttribute('aria-expanded', 'true') await expect(expand).toHaveAttribute('aria-expanded', 'true')
const effectSettings = editor.page.locator('[data-slot="effect-settings"]') await expect(editor.page.locator('[data-slot="effect-settings"]')).toBeVisible()
await expect(effectSettings).toBeVisible()
const effectTypeBox = expectDefined(
await effectItem.locator('[data-property="effect-type"]').boundingBox(),
'effect type bounds'
)
const effectBlendBox = expectDefined(
await effectSettings.locator('[data-property="effect-blend-mode"]').boundingBox(),
'effect blend mode bounds'
)
expect(
Math.abs(effectBlendBox.x + effectBlendBox.width - (effectTypeBox.x + effectTypeBox.width))
).toBeLessThan(1)
const remove = effectItem.getByRole('button', { name: 'Remove effect' }) const remove = effectItem.getByRole('button', { name: 'Remove effect' })
await expect(remove).toHaveCSS('opacity', '1') await expect(remove).toHaveCSS('opacity', '1')
@ -189,20 +177,6 @@ test('paint effect and export rows share compact visual anatomy', async () => {
} }
await editor.page.mouse.move(0, 0) await editor.page.mouse.move(0, 0)
const fillItem = propertyItems(editor.page, 'fills').first()
const paintFieldBox = expectDefined(
await fillItem.locator('[data-slot="paint-field"]').boundingBox(),
'fill paint field bounds'
)
const fillBlendBox = expectDefined(
await editor.page.locator('[data-property="fill-blend-mode"]').boundingBox(),
'fill blend mode bounds'
)
expect(Math.abs(fillBlendBox.x - paintFieldBox.x)).toBeLessThan(1)
expect(
Math.abs(fillBlendBox.x + fillBlendBox.width - (paintFieldBox.x + paintFieldBox.width))
).toBeLessThan(1)
await expect(designPanel()).toHaveScreenshot('design-panel-paint-effects-export.png') await expect(designPanel()).toHaveScreenshot('design-panel-paint-effects-export.png')
for (const sectionName of ['Position', 'Layout', 'Appearance']) { for (const sectionName of ['Position', 'Layout', 'Appearance']) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB