-
Notifications
You must be signed in to change notification settings - Fork 0
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.
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.
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:
elevation2shadow 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.
- 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
CustomSingleChildLayoutwithTextSelectionToolbarLayoutDelegate, the toolbar automatically positions above the selection and flips below when necessary
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,
});
}-
actions (Set<LayrzSelectableAction), required) — The action buttons to display. Set is automatically sorted by
typefor 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
typeis passed (e.g.,'copy','cut','paste','selectAll', or a custom action's identifier).
In most cases, LayrzSelectionToolbar is not directly instantiated. Instead, it is rendered by LayrzTextSelectionControls via EditableText.contextMenuBuilder:
EditableText(
selectionControls: LayrzTextSelectionControls.instance,
// ... other parameters
)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();
}
},
)Each button in the toolbar is styled as a compact button with:
-
Padding:
sp1(4px) horizontally, consistent spacing between buttons -
Text color: Inherits
sf1from 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.
- 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
LayrzTokenspassed 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
- LayrzSelectableAction — defines the action buttons displayed in the toolbar
- LayrzTextSelectionControls — singleton that owns the toolbar and renders it via context menu builder
- LayrzTooltip — provides similar dark overlay surface treatment for persistent hints
Last updated: 2026-08-20
Related documents: LayrzSelectableAction, LayrzTextSelectionControls, Selection (D50)
Made with ❤️ by Golden M, Inc.
- LayrzTextInput
- LayrzSelectableAction
- LayrzSelectionToolbar
- LayrzTextSelectionControls
- LayrzSelectionMagnifier
- LayrzSelectionHandlePainter
- LayrzTextAreaInput
- LayrzComboBoxInput
- LayrzNumberInput
- LayrzPasswordInput
- LayrzCheckboxInput
- LayrzRadioInput
- LayrzSelectInput
- LayrzMultiSelectInput
- LayrzSearchInput
- LayrzDualListInput
- LayrzDurationInput