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
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
### 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.
|
||||
- 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.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const ctx = useLayerTree()
|
|||
|
||||
const isSelected = computed(() => ctx.selectedIds.value.has(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)
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ defineExpose({ rowEl })
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div :ref="onRef" :data-node-id="node.id">
|
||||
<div :ref="onRef" :data-node-id="node.id" class="w-full">
|
||||
<slot
|
||||
:node="node"
|
||||
:level="level"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,10 @@ interface PageActions {
|
|||
const pageInput = templateRef<HTMLInputElement>('pageInput')
|
||||
const rename = useInlineRename((id, name) => pageActions.value?.rename(id, name))
|
||||
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 baseStyles = pageListStyles()
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import type { VariableType } from '@open-pencil/scene-graph'
|
|||
|
||||
const open = defineModel<boolean>('open', { default: false })
|
||||
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 variableTable = tv(variableTableTheme)
|
||||
const tableStyles = variableTable()
|
||||
|
|
|
|||
|
|
@ -154,19 +154,7 @@ test('effect settings expand semantically and row remove reveals on hover', asyn
|
|||
await expect(expand).toHaveAttribute('aria-expanded', 'false')
|
||||
await expand.click()
|
||||
await expect(expand).toHaveAttribute('aria-expanded', 'true')
|
||||
const effectSettings = editor.page.locator('[data-slot="effect-settings"]')
|
||||
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)
|
||||
await expect(editor.page.locator('[data-slot="effect-settings"]')).toBeVisible()
|
||||
|
||||
const remove = effectItem.getByRole('button', { name: 'Remove effect' })
|
||||
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)
|
||||
|
||||
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')
|
||||
|
||||
for (const sectionName of ['Position', 'Layout', 'Appearance']) {
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |