Skip to content
Core

Widget clipping and layering ​

Loading interactive example…Open in new tab ↗
Opening the live canvas…

The controls card extends beyond its clipping frame. A higher element covers part of the live controls. Hidden and covered controls must not receive pointer input; the visible foreground element owns that space.

ActionPublic APIExpected result
Move framemove(delta, ids: ['frame'])Moves the child once with its owner; the independent cover stays in place.
Remove coverdelete(ids: ['cover'])Reveals controls beneath it.
Release contentsunframe(ids: ['frame'])Removes the frame, retaining the widget and its world position.
Undoundo()Restores the prior ownership, clipping or cover.

Try dragging the cover, clicking the visible slider, and releasing the contents to reveal the bottom of the widget. Pan and zoom through the normal canvas controls. The example supplies canonical ownership and z-order; the framework owns widget mounting, clipping, hit testing and transforms.

The bottom Count button is fully outside the frame and is omitted from the accessibility tree. Releasing the contents exposes it again. Partially visible controls retain their accessibility nodes; clipping follows the resolved path's bounding rectangle for native semantics, while pointer clipping uses the path.

Source ​

dart
DiagramController widgetLayersController() {
  final seed = createControlsExample();
  try {
    return DiagramController(
      configuration: DiagramConfiguration(extensions: seed.diagram.extensions),
      document: DiagramDocument(
        id: 'widget-layers',
        revision: 0,
        elements: [
          ShapeElement(
            id: 'frame',
            type: Shapes.frame,
            frame: const DiagramRect.fromLTWH(0, 0, 340, 180),
            clipContent: true,
          ),
          seed.document
              .shapeById('controls')!
              .copyWith(
                parentId: 'frame',
                frame: const DiagramRect.fromLTWH(60, 0, 300, 280),
                zIndex: 1,
              ),
          ShapeElement(
            id: 'cover',
            type: Shapes.rectangle,
            zIndex: 2,
            frame: const DiagramRect.fromLTWH(180, 80, 170, 80),
            style: const ShapeStyle(
              fill: DiagramColor(0xFFE4E4E7),
              cornerRadius: 8,
            ),
            textStory: TextStory.paragraph(
              id: 'cover-story',
              blockId: 'cover-text',
              text: 'On top of the controls',
            ),
          ),
        ],
      ),
    );
  } finally {
    seed.dispose();
  }
}