-import { computed, ref } from 'vue'
+import { computed } from 'vue'
-import { MIXED, useAppearance, useI18n } from '@open-pencil/vue'
+import { AppearanceControlsRoot, MIXED, useI18n } from '@open-pencil/vue'
import NumberField from '@/components/inputs/NumberField.vue'
import VariableNumberField from '@/components/properties/VariableNumberField.vue'
import AppSelect from '@/components/ui/AppSelect.vue'
import IconButton from '@/components/ui/IconButton.vue'
+import PanelFieldGroup from '@/components/ui/panel/PanelFieldGroup.vue'
+import PanelGrid from '@/components/ui/panel/PanelGrid.vue'
+import PanelRail from '@/components/ui/panel/PanelRail.vue'
import PanelSection from '@/components/ui/panel/PanelSection.vue'
-import Tip from '@/components/ui/Tip.vue'
import type { BlendMode } from '@open-pencil/scene-graph'
const { panels } = useI18n()
-
type BlendModeSelectValue = BlendMode | 'MIXED'
-const blendModeOptions = computed
>(() => {
- const options: Array<{ value: BlendModeSelectValue; label: string }> = [
- { value: 'PASS_THROUGH', label: panels.value.blendModePassThrough },
- { value: 'NORMAL', label: panels.value.blendModeNormal },
- { value: 'DARKEN', label: panels.value.blendModeDarken },
- { value: 'MULTIPLY', label: panels.value.blendModeMultiply },
- { value: 'COLOR_BURN', label: panels.value.blendModeColorBurn },
- { value: 'LIGHTEN', label: panels.value.blendModeLighten },
- { value: 'SCREEN', label: panels.value.blendModeScreen },
- { value: 'COLOR_DODGE', label: panels.value.blendModeColorDodge },
- { value: 'OVERLAY', label: panels.value.blendModeOverlay },
- { value: 'SOFT_LIGHT', label: panels.value.blendModeSoftLight },
- { value: 'HARD_LIGHT', label: panels.value.blendModeHardLight },
- { value: 'DIFFERENCE', label: panels.value.blendModeDifference },
- { value: 'EXCLUSION', label: panels.value.blendModeExclusion },
- { value: 'HUE', label: panels.value.blendModeHue },
- { value: 'SATURATION', label: panels.value.blendModeSaturation },
- { value: 'COLOR', label: panels.value.blendModeColor },
- { value: 'LUMINOSITY', label: panels.value.blendModeLuminosity }
- ]
- return blendModeValue.value === MIXED
- ? [{ value: 'MIXED', label: panels.value.mixed }, ...options]
- : options
-})
-const {
- node,
- isMulti,
- active,
- hasCornerRadius,
- independentCorners,
- cornerRadiusValue,
- opacityPercent,
- blendModeValue,
- visibilityState,
- setBlendMode,
- updateProp,
- commitProp,
- toggleVisibility,
- toggleIndependentCorners,
- updateCornerProp,
- commitCornerProp
-} = useAppearance()
+const baseBlendModeOptions = computed>(() => [
+ { value: 'PASS_THROUGH', label: panels.value.blendModePassThrough },
+ { value: 'NORMAL', label: panels.value.blendModeNormal },
+ { value: 'DARKEN', label: panels.value.blendModeDarken },
+ { value: 'MULTIPLY', label: panels.value.blendModeMultiply },
+ { value: 'COLOR_BURN', label: panels.value.blendModeColorBurn },
+ { value: 'LIGHTEN', label: panels.value.blendModeLighten },
+ { value: 'SCREEN', label: panels.value.blendModeScreen },
+ { value: 'COLOR_DODGE', label: panels.value.blendModeColorDodge },
+ { value: 'OVERLAY', label: panels.value.blendModeOverlay },
+ { value: 'SOFT_LIGHT', label: panels.value.blendModeSoftLight },
+ { value: 'HARD_LIGHT', label: panels.value.blendModeHardLight },
+ { value: 'DIFFERENCE', label: panels.value.blendModeDifference },
+ { value: 'EXCLUSION', label: panels.value.blendModeExclusion },
+ { value: 'HUE', label: panels.value.blendModeHue },
+ { value: 'SATURATION', label: panels.value.blendModeSaturation },
+ { value: 'COLOR', label: panels.value.blendModeColor },
+ { value: 'LUMINOSITY', label: panels.value.blendModeLuminosity }
+])
-const manualExpanded = ref(null)
-
-const showIndependentCorners = computed(() => {
- if (manualExpanded.value !== null) return manualExpanded.value
- if (independentCorners.value === true) return true
- const n = node.value
- if (!n) return false
- return !(
- n.topLeftRadius === n.topRightRadius &&
- n.topLeftRadius === n.bottomRightRadius &&
- n.topLeftRadius === n.bottomLeftRadius
- )
-})
-
-function onToggleCorners() {
- manualExpanded.value = !showIndependentCorners.value
- toggleIndependentCorners()
+function blendModeOptions(value: BlendMode | typeof MIXED) {
+ return value === MIXED
+ ? [{ value: 'MIXED' as const, label: panels.value.mixed }, ...baseBlendModeOptions.value]
+ : baseBlendModeOptions.value
}
-
-const blendModeSelectValue = computed({
- get: () => (blendModeValue.value === MIXED ? 'MIXED' : blendModeValue.value),
- set: (value) => {
- if (value !== 'MIXED') setBlendMode(value)
- }
-})
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+ value !== 'MIXED' && actions.setBlendMode(value)
+ "
+ />
+
+
+
+ actions.commitProp('opacity', v / 100, p / 100)"
+ >
+
+
+
+
+ actions.commitProp('opacity', v / 100, p / 100)"
+ >
+
+
+
+
+
+
+
+
+
+ actions.commitProp('cornerRadius', v, p)"
+ >
+
+
+
+
+ actions.commitProp('cornerRadius', v, p)"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ actions.commitCornerProp('topLeftRadius', v, p)"
/>
-
-
-
commitProp('opacity', v / 100, p / 100)"
- >
-
-
-
-
- commitProp('opacity', v / 100, p / 100)"
- >
-
-
-
-
-
-
-
-
-
- commitProp('cornerRadius', v, p)"
- >
-
+ binding-path="topRightRadius"
+ @update:model-value="actions.updateCornerProp('topRightRadius', $event)"
+ @commit="(v: number, p: number) => actions.commitCornerProp('topRightRadius', v, p)"
+ />
+
+
-
-
-
+
+ commitProp('cornerRadius', v, p)"
- >
-
-
-
-
-
-
-
-
-
-
-
-
- commitCornerProp('topLeftRadius', v, p)"
- />
- commitCornerProp('topRightRadius', v, p)"
- />
- commitCornerProp('bottomLeftRadius', v, p)"
- />
- commitCornerProp('bottomRightRadius', v, p)"
- />
-
-
+ :node-id="node.id"
+ binding-path="bottomLeftRadius"
+ @update:model-value="actions.updateCornerProp('bottomLeftRadius', $event)"
+ @commit="(v: number, p: number) => actions.commitCornerProp('bottomLeftRadius', v, p)"
+ />
+ actions.commitCornerProp('bottomRightRadius', v, p)"
+ />
+
+
+
+
diff --git a/src/components/properties/PositionSection.vue b/src/components/properties/PositionSection.vue
index c8b9bcea5..dbea41fe6 100644
--- a/src/components/properties/PositionSection.vue
+++ b/src/components/properties/PositionSection.vue
@@ -1,11 +1,12 @@
+
+
+
+
+
+
diff --git a/src/components/ui/panel/index.ts b/src/components/ui/panel/index.ts
index e9b7fafcd..16988854e 100644
--- a/src/components/ui/panel/index.ts
+++ b/src/components/ui/panel/index.ts
@@ -1,5 +1,6 @@
export { default as PanelFieldGroup } from './PanelFieldGroup.vue'
export { default as PanelGrid } from './PanelGrid.vue'
+export { default as PanelHeader } from './PanelHeader.vue'
export { default as PanelRail } from './PanelRail.vue'
export { default as PanelRow } from './PanelRow.vue'
export { default as PanelSection } from './PanelSection.vue'
diff --git a/src/theme/panel/header.ts b/src/theme/panel/header.ts
new file mode 100644
index 000000000..ffdc63e5c
--- /dev/null
+++ b/src/theme/panel/header.ts
@@ -0,0 +1,24 @@
+const panelHeaderTheme = {
+ slots: {
+ root: 'grid min-w-0 grid-cols-[var(--spacing-panel-icon)_minmax(0,1fr)_auto] items-center gap-panel border-b border-border px-panel-x py-panel-y text-surface',
+ icon: 'flex size-panel-icon items-center justify-center text-muted',
+ title: 'min-w-0 truncate text-xs font-semibold text-surface',
+ actions:
+ 'flex min-w-0 items-center justify-end gap-0.5 [&_[data-slot=icon-button]]:size-control [&_[data-slot=icon-button]]:rounded-panel'
+ },
+ variants: {
+ component: {
+ true: {
+ icon: 'text-component',
+ title: 'text-component'
+ },
+ false: {}
+ }
+ },
+ defaultVariants: {
+ component: false
+ }
+}
+
+export type PanelHeaderTheme = typeof panelHeaderTheme
+export default panelHeaderTheme
diff --git a/tests/e2e/color-picker/demo-card.spec.ts b/tests/e2e/color-picker/demo-card.spec.ts
index af759f849..d0ac8fc2a 100644
--- a/tests/e2e/color-picker/demo-card.spec.ts
+++ b/tests/e2e/color-picker/demo-card.spec.ts
@@ -43,8 +43,9 @@ async function selectDemoCard(page: Parameters[0]['page'], canvas:
})
await canvas.waitForRender()
- await expect(page.getByTestId('design-panel-single')).toBeVisible()
- await expect(page.getByTestId('design-node-header')).toContainText('Card')
+ const designPanel = page.getByTestId('design-panel-single')
+ await expect(designPanel).toBeVisible()
+ await expect(designPanel.getByRole('heading', { name: 'Card' })).toBeVisible()
}
async function getSelectedFill(page: Parameters[0]['page']) {
diff --git a/tests/e2e/components.spec.ts b/tests/e2e/components.spec.ts
index 06fe8ac27..99fa7c56d 100644
--- a/tests/e2e/components.spec.ts
+++ b/tests/e2e/components.spec.ts
@@ -52,9 +52,8 @@ test('create component from selection (⌘⌥K)', async () => {
componentId = selectedId
})
-test('component shows purple label in design panel', async () => {
- const header = editor.page.getByTestId('design-node-header')
- await expect(header).toContainText('COMPONENT')
+test('component shows its type icon in the design panel', async () => {
+ await expect(editor.page.getByRole('img', { name: 'COMPONENT' })).toBeVisible()
})
test('component visible in layers panel', async () => {
@@ -103,8 +102,7 @@ test('instance shows INSTANCE type in design panel', async () => {
}, instance.id)
await editor.canvas.waitForRender()
- const header = editor.page.getByTestId('design-node-header')
- await expect(header).toContainText('INSTANCE')
+ await expect(editor.page.getByRole('img', { name: 'INSTANCE' })).toBeVisible()
})
test('instance has "Go to Main Component" button', async () => {
diff --git a/tests/e2e/design/panel.spec.ts b/tests/e2e/design/panel.spec.ts
index 93ae2b39c..02ffe7f46 100644
--- a/tests/e2e/design/panel.spec.ts
+++ b/tests/e2e/design/panel.spec.ts
@@ -8,10 +8,6 @@ function designPanel() {
return editor.page.getByTestId('design-panel-single')
}
-function nodeHeader() {
- return editor.page.getByTestId('design-node-header')
-}
-
function fillSection() {
return editor.page.getByTestId('fill-section')
}
@@ -21,7 +17,7 @@ function strokeSection() {
}
function positionSection() {
- return editor.page.getByTestId('position-section')
+ return propertySection(editor.page, 'Position')
}
function effectsSection() {
@@ -73,8 +69,9 @@ test('selecting a rectangle shows design panel with type and name', async () =>
await editor.canvas.waitForRender()
await expect(designPanel()).toBeVisible()
- await expect(nodeHeader()).toContainText('RECTANGLE')
- await expect(nodeHeader()).toContainText('Rectangle')
+ await expect(designPanel().getByRole('img', { name: 'RECTANGLE' })).toBeVisible()
+ await expect(designPanel().getByRole('heading', { name: 'Rectangle' })).toBeVisible()
+ await expect(designPanel()).toHaveScreenshot('design-panel-position-appearance.png')
})
test('position section shows X, Y, rotation inputs', async () => {
@@ -246,7 +243,9 @@ test('mask action toggles mask section and mask type control', async () => {
})
test('visibility toggle in appearance section works', async () => {
- const visBtn = editor.page.getByTestId('appearance-visibility')
+ const visBtn = propertySection(editor.page, 'Appearance').getByRole('button', {
+ name: 'Toggle visibility'
+ })
await expect(visBtn).toBeVisible()
const id = await getSelectedId()
@@ -393,10 +392,10 @@ test('multi-select shows mixed header and boolean operations', async () => {
await editor.canvas.selectAll()
await editor.canvas.waitForRender()
- const multiHeader = editor.page.getByTestId('design-multi-header')
+ const multiHeader = editor.page
+ .getByTestId('design-panel-multi')
+ .getByRole('heading', { name: /layers/ })
await expect(multiHeader).toBeVisible()
- await expect(multiHeader).toContainText('Mixed')
- await expect(multiHeader).toContainText('layers')
const booleanOperations = editor.page.getByTestId('boolean-operations-trigger')
await booleanOperations.hover()
diff --git a/tests/e2e/design/panel.spec.ts-snapshots/design-panel-position-appearance-openpencil-darwin.png b/tests/e2e/design/panel.spec.ts-snapshots/design-panel-position-appearance-openpencil-darwin.png
new file mode 100644
index 000000000..0c0cf5d08
Binary files /dev/null and b/tests/e2e/design/panel.spec.ts-snapshots/design-panel-position-appearance-openpencil-darwin.png differ
diff --git a/tests/e2e/properties/corner-stroke-toggles.spec.ts b/tests/e2e/properties/corner-stroke-toggles.spec.ts
index c6da11128..70aed46bb 100644
--- a/tests/e2e/properties/corner-stroke-toggles.spec.ts
+++ b/tests/e2e/properties/corner-stroke-toggles.spec.ts
@@ -1,6 +1,7 @@
import { expect, test, type Page } from '@playwright/test'
import { CanvasHelper } from '#tests/helpers/canvas'
+import { propertySection } from '#tests/helpers/properties'
let page: Page
let canvas: CanvasHelper
@@ -48,14 +49,16 @@ test('independent corners toggle shows per-corner inputs', async () => {
expect(flags?.type).toBe('FRAME')
expect(flags?.independentCorners).toBe(false)
- const toggle = page.getByTestId('independent-corners-toggle')
+ const toggle = propertySection(page, 'Appearance').getByRole('button', {
+ name: 'Independent corner radii'
+ })
await expect(toggle).toBeVisible()
await toggle.click()
await canvas.waitForRender()
expect((await getSelectedNodeFlags())?.independentCorners).toBe(true)
- const grid = page.getByTestId('independent-corners-grid')
+ const grid = page.locator('[data-corner-grid]')
await expect(grid).toBeVisible()
const cornerInputs = grid.getByRole('spinbutton')
expect(await cornerInputs.count()).toBe(4)
@@ -65,6 +68,34 @@ test('independent corners toggle shows per-corner inputs', async () => {
await expect(grid).not.toBeVisible()
})
+test('multi-selection independent corners toggle is one undo step', async () => {
+ await canvas.clearCanvas()
+ await drawFrame(80, 80, 100, 70)
+ await drawFrame(240, 80, 100, 70)
+ await canvas.pressKey('Meta+a')
+ await canvas.waitForRender()
+
+ const independentStates = () =>
+ page.evaluate(() => {
+ const store = window.openPencil?.getStore?.()
+ if (!store) throw new Error('OpenPencil store not initialized')
+ return [...store.state.selectedIds].map(
+ (id) => store.graph.getNode(id)?.independentCorners ?? null
+ )
+ })
+
+ const toggle = propertySection(page, 'Appearance').getByRole('button', {
+ name: 'Independent corner radii'
+ })
+ await toggle.click()
+ await canvas.waitForRender()
+ expect(await independentStates()).toEqual([true, true])
+
+ await canvas.pressKey('Meta+z')
+ await canvas.waitForRender()
+ expect(await independentStates()).toEqual([false, false])
+})
+
test('stroke sides toggle shows per-side weight inputs', async () => {
await drawFrame(300, 50, 120, 80)
await canvas.waitForRender()
diff --git a/tests/e2e/properties/number-field.spec.ts b/tests/e2e/properties/number-field.spec.ts
index a70448e19..2f0caa28f 100644
--- a/tests/e2e/properties/number-field.spec.ts
+++ b/tests/e2e/properties/number-field.spec.ts
@@ -11,7 +11,7 @@ function xField() {
async function editField(field: ReturnType) {
await field.click()
- return field.getByRole('spinbutton', { name: 'X' })
+ return field.getByRole('spinbutton', { name: 'X Axis' })
}
async function numericFieldValue(field: ReturnType): Promise {
@@ -30,7 +30,7 @@ test('NumberField commits arithmetic and relative expressions', async () => {
let input = await editField(field)
await expect(field).not.toHaveAttribute('role')
await expect(input).toHaveAttribute('role', 'spinbutton')
- await expect(input).toHaveAttribute('aria-label', 'X')
+ await expect(input).toHaveAttribute('aria-label', 'X Axis')
await expect(field.getByRole('spinbutton')).toHaveCount(1)
await input.fill('*2')
await input.press('Enter')
diff --git a/tests/e2e/properties/panel.spec.ts b/tests/e2e/properties/panel.spec.ts
index 80fae4816..3e915bacf 100644
--- a/tests/e2e/properties/panel.spec.ts
+++ b/tests/e2e/properties/panel.spec.ts
@@ -41,7 +41,7 @@ test('corner radius uniform sets cornerRadius', async () => {
const scrubContainer = propertyField(editor.page, 'cornerRadius')
await scrubContainer.click()
await editor.canvas.waitForRender()
- const input = scrubContainer.getByRole('spinbutton', { name: 'cornerRadius' })
+ const input = scrubContainer.getByRole('spinbutton', { name: 'Radius' })
await input.fill('12')
await input.press('Enter')
await editor.canvas.waitForRender()
@@ -52,13 +52,15 @@ test('corner radius uniform sets cornerRadius', async () => {
})
test('independent corners toggle shows four corner inputs', async () => {
- await editor.page.getByTestId('independent-corners-toggle').click()
+ await propertySection(editor.page, 'Appearance')
+ .getByRole('button', { name: 'Independent corner radii' })
+ .click()
await editor.canvas.waitForRender()
- await expect(editor.page.getByTestId('corner-tl-input')).toBeVisible()
- await expect(editor.page.getByTestId('corner-tr-input')).toBeVisible()
- await expect(editor.page.getByTestId('corner-br-input')).toBeVisible()
- await expect(editor.page.getByTestId('corner-bl-input')).toBeVisible()
+ await expect(propertyField(editor.page, 'topLeftRadius')).toBeVisible()
+ await expect(propertyField(editor.page, 'topRightRadius')).toBeVisible()
+ await expect(propertyField(editor.page, 'bottomRightRadius')).toBeVisible()
+ await expect(propertyField(editor.page, 'bottomLeftRadius')).toBeVisible()
editor.canvas.assertNoErrors()
})
@@ -246,7 +248,7 @@ test('bound NumberField detach edit is one undo step', async () => {
})
await field.click({ position: { x: 40, y: 13 } })
- const input = field.getByRole('spinbutton', { name: 'cornerRadius' })
+ const input = field.getByRole('spinbutton', { name: 'Radius' })
await input.press('Tab')
expect(await readState()).toEqual({ radius: 0, binding: 'Radius/default' })
await editor.canvas.pressKey('Meta+z')
@@ -285,7 +287,7 @@ test('alignment buttons align nodes to same X', async () => {
await editor.canvas.pressKey('Meta+a')
await editor.canvas.waitForRender()
- await editor.page.getByTestId('position-align-left').click()
+ await propertySection(editor.page, 'Position').getByRole('button', { name: 'Align left' }).click()
await editor.canvas.waitForRender()
const children = await getPageChildren(editor.page)
@@ -298,7 +300,9 @@ test('flip horizontal sets flipX', async () => {
await editor.canvas.clearCanvas()
await editor.canvas.drawRect(200, 200, 80, 80)
- await editor.page.getByTestId('position-flip-horizontal').click()
+ await propertySection(editor.page, 'Position')
+ .getByRole('button', { name: 'Flip horizontal' })
+ .click()
await editor.canvas.waitForRender()
const node = await getSelectedNode(editor.page)
diff --git a/tests/e2e/properties/visibility.spec.ts b/tests/e2e/properties/visibility.spec.ts
index a7bd98fb1..2a2a2b8eb 100644
--- a/tests/e2e/properties/visibility.spec.ts
+++ b/tests/e2e/properties/visibility.spec.ts
@@ -1,5 +1,6 @@
import { expect, test, useEditorSetup } from '#tests/e2e/fixtures'
import { expectDefined } from '#tests/helpers/assert'
+import { propertySection } from '#tests/helpers/properties'
import { getSelectedNode } from '#tests/helpers/store'
const editor = useEditorSetup()
@@ -92,7 +93,9 @@ test('multi-selection list add is one undo step', async () => {
})
test('appearance visibility supports repeat click and undo redo in one step', async () => {
- const visibilityButton = editor.page.getByTestId('appearance-visibility')
+ const visibilityButton = propertySection(editor.page, 'Appearance').getByRole('button', {
+ name: 'Toggle visibility'
+ })
await expect(visibilityButton).toBeVisible()
expect(expectDefined(await getSelectedNode(editor.page), 'selected node').visible).toBe(true)
diff --git a/tests/e2e/tools/section.spec.ts b/tests/e2e/tools/section.spec.ts
index c80ef6ed6..2dfad9a85 100644
--- a/tests/e2e/tools/section.spec.ts
+++ b/tests/e2e/tools/section.spec.ts
@@ -5,7 +5,7 @@ const editor = useEditorSetupWithClear('/?test')
test('draw section in full editor without browser errors', async () => {
await editor.canvas.drawSection(100, 100, 240, 160)
- await expect(editor.page.getByTestId('design-node-header')).toContainText('SECTION')
+ await expect(editor.page.getByRole('img', { name: 'SECTION' })).toBeVisible()
await expect
.poll(async () => {
return editor.page.evaluate(() => {
diff --git a/tests/engine/vue/controls/appearance.test.ts b/tests/engine/vue/controls/appearance.test.ts
new file mode 100644
index 000000000..c7f89bb85
--- /dev/null
+++ b/tests/engine/vue/controls/appearance.test.ts
@@ -0,0 +1,64 @@
+import { describe, expect, test } from 'bun:test'
+
+import { computed, ref } from 'vue'
+
+import type { SceneNode } from '@open-pencil/scene-graph'
+import type { MixedValue } from '@open-pencil/vue'
+
+import { createAppearanceState } from '#vue/controls/appearance/helpers'
+
+import { createRect, firstPageId, makeSceneGraph } from '#tests/helpers/scene'
+
+function appearanceState(node: SceneNode, multi = false) {
+ const selected = ref(node)
+ const nodes = ref([node])
+ const isMulti = ref(multi)
+
+ function merged(key: K): MixedValue {
+ const current = selected.value
+ if (!current) throw new Error('Expected selected node')
+ return current[key]
+ }
+
+ return createAppearanceState({
+ node: computed(() => selected.value),
+ nodes: computed(() => nodes.value),
+ isMulti: computed(() => isMulti.value),
+ merged
+ })
+}
+
+function rectangle() {
+ const graph = makeSceneGraph()
+ return createRect(graph, firstPageId(graph))
+}
+
+describe('appearance control state', () => {
+ test('keeps equal uniform corners collapsed', () => {
+ const state = appearanceState(rectangle())
+ expect(state.showIndependentCorners.value).toBe(false)
+ })
+
+ test('expands corners when the explicit independent flag is set', () => {
+ const node = rectangle()
+ node.independentCorners = true
+ const state = appearanceState(node)
+ expect(state.showIndependentCorners.value).toBe(true)
+ })
+
+ test('expands imported unequal corners when the explicit flag is stale', () => {
+ const node = rectangle()
+ node.independentCorners = false
+ node.topLeftRadius = 4
+ node.topRightRadius = 12
+ const state = appearanceState(node)
+ expect(state.showIndependentCorners.value).toBe(true)
+ })
+
+ test('leaves the per-corner editor collapsed for multi-selection', () => {
+ const node = rectangle()
+ node.independentCorners = true
+ const state = appearanceState(node, true)
+ expect(state.showIndependentCorners.value).toBe(false)
+ })
+})