Skip to content

LayrzSelectionToolbar

Kenny Mochizuki Escalona edited this page Aug 21, 2026 · 2 revisions

LayrzSelectionToolbar

A Material-free text selection toolbar displaying action buttons for copy, cut, paste, select all, and custom operations.

Metadata
Domain: Selection
Phase: M2 (Selection framework)
Primitive: TextSelectionToolbar, CustomSingleChildLayout
Status: Shipped in 0.0.12.


Overview

LayrzSelectionToolbar renders a horizontal action button bar for text selection operations. The toolbar is shown above the selected text and automatically repositions below if insufficient space is available above.

Surface Treatment

The toolbar uses a dark overlay surface treatment (matching LayrzTooltip):

  • Background fill: tokens.colors.fg1 (dark foreground color)
  • Content color: tokens.colors.sf1 (light surface text)
  • Text style: tokens.typography.label (14px, w400)
  • Border radius: tokens.radius.r2 (8 logical pixels)
  • Elevation: elevation2 shadow for visual separation

This dark-on-light treatment establishes the general rule: page surfaces are light with dark text; overlay surfaces are dark with light text. This is deliberate and not to be "corrected" to a light fill — the contrast ensures the toolbar is readable above any background.

Sizing and Positioning

  • Content-based sizing: The toolbar sizes to fit its action buttons rather than expanding to fill the overlay width
  • Horizontal scrolling: Enabled only when content exceeds available width (rare; typical toolbars have 3–5 buttons)
  • Automatic positioning: Via CustomSingleChildLayout with TextSelectionToolbarLayoutDelegate, the toolbar automatically positions above the selection and flips below when necessary

API Reference

class LayrzSelectionToolbar extends StatelessWidget {
  /// The set of actions to display as buttons in the toolbar.
  final Set<LayrzSelectableAction> actions;

  /// The anchor offset where the toolbar should be positioned above the selection.
  final Offset anchorAbove;

  /// The anchor offset where the toolbar should be positioned below the selection.
  /// Used when there is not enough space above to render the toolbar.
  final Offset? anchorBelow;

  /// Design system tokens for colors, spacing, radius, and typography.
  final LayrzTokens tokens;

  /// Callback to invoke when a button action is pressed.
  /// Called with the action's `type` field (e.g., 'copy', 'cut', 'paste', 'selectAll').
  final Function(String actionType) onActionPressed;

  const LayrzSelectionToolbar({
    super.key,
    required this.actions,
    required this.anchorAbove,
    this.anchorBelow,
    required this.tokens,
    required this.onActionPressed,
  });
}

Parameters

  • actions (Set<LayrzSelectableAction), required) — The action buttons to display. Set is automatically sorted by type for consistent ordering.
  • anchorAbove (Offset, required) — The position where the toolbar should appear above the selection. Typically the top-left corner of the selection.
  • anchorBelow (Offset?, optional) — The position where the toolbar should appear below the selection if there is insufficient space above. If null, the toolbar flips below and may extend off-screen.
  • tokens (LayrzTokens, required) — Design system tokens for rendering. Typically obtained from context.tokens.
  • onActionPressed (Function(String), required) — Callback fired when an action button is pressed. The action's type is passed (e.g., 'copy', 'cut', 'paste', 'selectAll', or a custom action's identifier).

Usage

In most cases, LayrzSelectionToolbar is not directly instantiated. Instead, it is rendered by LayrzTextSelectionControls via EditableText.contextMenuBuilder:

EditableText(
  selectionControls: LayrzTextSelectionControls.instance,
  // ... other parameters
)

Direct Usage (Advanced)

To manually integrate the toolbar into a custom overlay or popover:

LayrzSelectionToolbar(
  actions: {
    LayrzSelectableAction.copy(),
    LayrzSelectableAction.paste(),
  },
  anchorAbove: Offset(selection.dx, selection.dy),
  anchorBelow: Offset(selection.dx, selection.dy + 50),
  tokens: context.tokens,
  onActionPressed: (type) {
    if (type == 'copy') {
      _copySelectedText();
    } else if (type == 'paste') {
      _pasteText();
    }
  },
)

Action Button Styling

Each button in the toolbar is styled as a compact button with:

  • Padding: sp1 (4px) horizontally, consistent spacing between buttons
  • Text color: Inherits sf1 from the container
  • Hover state: Subtle background color change to provide feedback (specific color derived from tokens)
  • Press state: Elevated feedback via shadow/opacity change (D15: geometry remains constant)

The buttons are rendered in the order determined by the set's natural ordering, but the toolbar internally sorts them by type for consistency.


Technical Notes

  • Singleton integration: This widget is used internally by LayrzTextSelectionControls.instance, which is itself a singleton to prevent overlay disposal on rebuild
  • Context-driven theming: All visual properties (colors, spacing, radius, typography) are resolved from LayrzTokens passed at construction time, allowing theme changes to be reflected without recreating this instance
  • Localization: Action labels are localized via LayrzSelectableAction, which provides localized button text based on BuildContext
  • Accessibility: Buttons are rendered as semantic actions; screen readers announce button labels and states

Related Components


Last updated: 2026-08-20
Related documents: LayrzSelectableAction, LayrzTextSelectionControls, Selection (D50)

Clone this wiki locally