Add a Group action to the floating selection toolbar when multiple items are selected #206

Closed
opened 2026-05-20 11:06:36 +00:00 by AhmedHanafy725 · 2 comments

Summary

When the user selects two or more items, the floating selection toolbar should expose a Group action so creating a group is a one-click operation, like the existing Ungroup action shown when a group is selected. Today, grouping is only reachable via the right-click context menu or the Ctrl+G shortcut, which is inconsistent with the toolbar's role as the primary in-canvas action surface.

Scope

In the floating selection toolbar, when the current selection contains 2 or more selectable items, add a Group button:

  • Shows only for multi-selections (selection count >= 2).
  • Hidden when the selection is a single object (including a single group), a comment, or a locked-only selection where grouping doesn't make sense (mirror whatever guards the toolbar already applies for its other actions).
  • Clicking the button opens the existing themed group-name modal (WhiteboardPromptModal.open) pre-filled with Group, then on confirm calls WhiteboardGroups.createGroup(capturedNodes, name) with the SAME selection snapshot used by Ctrl+G and the context-menu action — so changing the selection between click and confirm does not affect the resulting group.
  • Tooltip should hint the keyboard shortcut (Ctrl+G).
  • Visually consistent with the other floating-toolbar actions (e.g. the Ungroup button); reuses the same button helper / icon style.

Acceptance Criteria

  • Selecting 2+ objects shows a Group button in the floating selection toolbar.
  • Selecting a single object (group or not) does not show the Group button.
  • Clicking Group opens the themed name modal; on confirm the selection is grouped with the entered name; Cancel/Escape/backdrop closes without grouping.
  • The grouped result matches what Ctrl+G or right-click → Group Selected produces (same name fallback to Group, same captured nodes).
  • No new code path duplicates the group-name modal; the existing WhiteboardPromptModal is reused.
  • Tooltip text shows the Ctrl+G shortcut.

Notes

The selection toolbar lives in crates/hero_whiteboard_admin/static/web/js/whiteboard/selection_toolbar.js. The existing Ungroup action and the toolbar's button helpers are good references. The Group + modal flow already exists in contextmenu.js and shortcuts.js; the toolbar should mirror that exact flow so the three entry points stay consistent. Frontend assets are embedded via rust-embed; rebuild required for visibility.

## Summary When the user selects two or more items, the floating selection toolbar should expose a **Group** action so creating a group is a one-click operation, like the existing **Ungroup** action shown when a group is selected. Today, grouping is only reachable via the right-click context menu or the Ctrl+G shortcut, which is inconsistent with the toolbar's role as the primary in-canvas action surface. ## Scope In the floating selection toolbar, when the current selection contains 2 or more selectable items, add a Group button: - Shows only for multi-selections (selection count >= 2). - Hidden when the selection is a single object (including a single group), a comment, or a locked-only selection where grouping doesn't make sense (mirror whatever guards the toolbar already applies for its other actions). - Clicking the button opens the existing themed group-name modal (`WhiteboardPromptModal.open`) pre-filled with `Group`, then on confirm calls `WhiteboardGroups.createGroup(capturedNodes, name)` with the SAME selection snapshot used by Ctrl+G and the context-menu action — so changing the selection between click and confirm does not affect the resulting group. - Tooltip should hint the keyboard shortcut (Ctrl+G). - Visually consistent with the other floating-toolbar actions (e.g. the Ungroup button); reuses the same button helper / icon style. ## Acceptance Criteria - Selecting 2+ objects shows a **Group** button in the floating selection toolbar. - Selecting a single object (group or not) does not show the Group button. - Clicking Group opens the themed name modal; on confirm the selection is grouped with the entered name; Cancel/Escape/backdrop closes without grouping. - The grouped result matches what Ctrl+G or right-click → Group Selected produces (same name fallback to `Group`, same captured nodes). - No new code path duplicates the group-name modal; the existing `WhiteboardPromptModal` is reused. - Tooltip text shows the Ctrl+G shortcut. ## Notes The selection toolbar lives in `crates/hero_whiteboard_admin/static/web/js/whiteboard/selection_toolbar.js`. The existing Ungroup action and the toolbar's button helpers are good references. The Group + modal flow already exists in `contextmenu.js` and `shortcuts.js`; the toolbar should mirror that exact flow so the three entry points stay consistent. Frontend assets are embedded via rust-embed; rebuild required for visibility.
Author
Owner

Implementation Spec for Issue #206

Objective

Add a Group label button to the floating selection toolbar that appears whenever the current selection contains 2 or more items (and is not all comments). Clicking it opens the themed WhiteboardPromptModal for a group name and then calls WhiteboardGroups.createGroup(capturedNodes, name) against a snapshot taken at click time. Mirrors the existing Ungroup button at selection_toolbar.js:1605 and exposes the Ctrl+G shortcut as a discoverable toolbar action.

Requirements

  • Visible only when cachedNodes.length >= 2.
  • Hidden for single-node selections (the existing single-node branch already shows the Ungroup button when a single group is selected).
  • Hidden when allComments is true (mirror existing guard at line ~228).
  • Click handler captures cachedNodes.slice() BEFORE opening the modal (selection may change between click and confirm).
  • Modal call: WhiteboardPromptModal.open({ title: 'Group Selected', label: 'Group name', defaultValue: 'Group', confirmLabel: 'Create', cancelLabel: 'Cancel' }).
  • On resolve: null (cancel) → no-op; else WhiteboardGroups.createGroup(capturedNodes, name || 'Group').
  • Tooltip Group (Ctrl+G).
  • Uses _buildLabelBtn to match the visual style of the existing Ungroup button.
  • The toolbar's props panel must be made visible in this branch when the Group button is appended (currently _showPropsGroup(false) hides it for multi-select).

Files to Modify/Create

  • Modify: crates/hero_whiteboard_admin/static/web/js/whiteboard/selection_toolbar.js — single-file change.
  • No new files, no template/CSS/Rust changes.

Implementation Plan

Step 1: Add _renderMultiSelection helper

Files: selection_toolbar.js

  • Place next to _renderForNode. Appends a _buildLabelBtn('Group', 'Group (Ctrl+G)', clickHandler) to propsEl. The handler captures var capturedNodes = cachedNodes.slice();, opens WhiteboardPromptModal.open({...}), then on resolve calls WhiteboardGroups.createGroup(capturedNodes, name || 'Group') (skip on null). Defensive guards on typeof WhiteboardPromptModal/WhiteboardGroups.
    Dependencies: none

Step 2: Update the multi-select branch in update(nodes)

Files: selection_toolbar.js

  • Replace the current else { cachedNode = null; _showPropsGroup(false); } branch (around line 250-253) with:
    } else {
        cachedNode = null;
        if (!allComments && cachedNodes.length >= 2) {
            _renderMultiSelection();
            _showPropsGroup(true);
        } else {
            _showPropsGroup(false);
        }
    }
    
  • _clearProps() already ran above; _updateDivider() runs below and detects via propsEl.children.length > 0. No other change needed.
    Dependencies: Step 1

Step 3: Build & embed

  • cargo build --release -p hero_whiteboard_admin. No new files added; assets.rs does not need touching.

Acceptance Criteria

  • Selecting 2+ items shows a Group button in the floating selection toolbar.
  • Selecting a single item (any type, including a single group) does NOT show the new Group button (the single-group case still shows its existing Ungroup button).
  • Empty selection hides the toolbar (unchanged).
  • 2+ comment markers do NOT show the Group button (allComments guard).
  • Mixed comment + non-comment selection DOES show the Group button.
  • Tooltip reads Group (Ctrl+G).
  • Click opens the themed modal with the specified title/label/defaults; Confirm creates a group; Cancel/Escape/backdrop closes without grouping.
  • Snapshot semantics: changing the selection while the modal is open does not affect the resulting group.
  • Empty name confirms as Group.
  • Group result is identical to one made via Ctrl+G / context-menu (same WhiteboardGroups.createGroup path).
  • No regression to single-node toolbar rendering.

Notes

  • WhiteboardPromptModal (from #205) is loaded before selection_toolbar.js in board.html; even if load order varied, the click handler references it lazily at user-interaction time, mirroring how WhiteboardGroups is referenced from the Ungroup handler.
  • _buildLabelBtn(label, title, onClick) creates a .wb-pt-btn button; matches the Ungroup pattern visually.
  • Nested grouping is not blocked — createGroup accepts any nodes; the issue does not require preventing nested groups.
  • No CSS changes; existing toolbar styles apply.
## Implementation Spec for Issue #206 ### Objective Add a **Group** label button to the floating selection toolbar that appears whenever the current selection contains 2 or more items (and is not all comments). Clicking it opens the themed `WhiteboardPromptModal` for a group name and then calls `WhiteboardGroups.createGroup(capturedNodes, name)` against a snapshot taken at click time. Mirrors the existing **Ungroup** button at `selection_toolbar.js:1605` and exposes the Ctrl+G shortcut as a discoverable toolbar action. ### Requirements - Visible only when `cachedNodes.length >= 2`. - Hidden for single-node selections (the existing single-node branch already shows the Ungroup button when a single group is selected). - Hidden when `allComments` is true (mirror existing guard at line ~228). - Click handler captures `cachedNodes.slice()` BEFORE opening the modal (selection may change between click and confirm). - Modal call: `WhiteboardPromptModal.open({ title: 'Group Selected', label: 'Group name', defaultValue: 'Group', confirmLabel: 'Create', cancelLabel: 'Cancel' })`. - On resolve: `null` (cancel) → no-op; else `WhiteboardGroups.createGroup(capturedNodes, name || 'Group')`. - Tooltip `Group (Ctrl+G)`. - Uses `_buildLabelBtn` to match the visual style of the existing Ungroup button. - The toolbar's props panel must be made visible in this branch when the Group button is appended (currently `_showPropsGroup(false)` hides it for multi-select). ### Files to Modify/Create - Modify: `crates/hero_whiteboard_admin/static/web/js/whiteboard/selection_toolbar.js` — single-file change. - No new files, no template/CSS/Rust changes. ### Implementation Plan #### Step 1: Add `_renderMultiSelection` helper Files: `selection_toolbar.js` - Place next to `_renderForNode`. Appends a `_buildLabelBtn('Group', 'Group (Ctrl+G)', clickHandler)` to `propsEl`. The handler captures `var capturedNodes = cachedNodes.slice();`, opens `WhiteboardPromptModal.open({...})`, then on resolve calls `WhiteboardGroups.createGroup(capturedNodes, name || 'Group')` (skip on `null`). Defensive guards on `typeof WhiteboardPromptModal/WhiteboardGroups`. Dependencies: none #### Step 2: Update the multi-select branch in `update(nodes)` Files: `selection_toolbar.js` - Replace the current `else { cachedNode = null; _showPropsGroup(false); }` branch (around line 250-253) with: ``` } else { cachedNode = null; if (!allComments && cachedNodes.length >= 2) { _renderMultiSelection(); _showPropsGroup(true); } else { _showPropsGroup(false); } } ``` - `_clearProps()` already ran above; `_updateDivider()` runs below and detects via `propsEl.children.length > 0`. No other change needed. Dependencies: Step 1 #### Step 3: Build & embed - `cargo build --release -p hero_whiteboard_admin`. No new files added; `assets.rs` does not need touching. ### Acceptance Criteria - [ ] Selecting 2+ items shows a Group button in the floating selection toolbar. - [ ] Selecting a single item (any type, including a single group) does NOT show the new Group button (the single-group case still shows its existing Ungroup button). - [ ] Empty selection hides the toolbar (unchanged). - [ ] 2+ comment markers do NOT show the Group button (`allComments` guard). - [ ] Mixed comment + non-comment selection DOES show the Group button. - [ ] Tooltip reads `Group (Ctrl+G)`. - [ ] Click opens the themed modal with the specified title/label/defaults; Confirm creates a group; Cancel/Escape/backdrop closes without grouping. - [ ] Snapshot semantics: changing the selection while the modal is open does not affect the resulting group. - [ ] Empty name confirms as `Group`. - [ ] Group result is identical to one made via Ctrl+G / context-menu (same `WhiteboardGroups.createGroup` path). - [ ] No regression to single-node toolbar rendering. ### Notes - `WhiteboardPromptModal` (from #205) is loaded before `selection_toolbar.js` in `board.html`; even if load order varied, the click handler references it lazily at user-interaction time, mirroring how `WhiteboardGroups` is referenced from the Ungroup handler. - `_buildLabelBtn(label, title, onClick)` creates a `.wb-pt-btn` button; matches the Ungroup pattern visually. - Nested grouping is not blocked — `createGroup` accepts any nodes; the issue does not require preventing nested groups. - No CSS changes; existing toolbar styles apply.
Author
Owner

Implementation Summary

Added a Group label button to the floating selection toolbar's multi-select branch.

Changes

  • crates/hero_whiteboard_admin/static/web/js/whiteboard/selection_toolbar.js:
    • New _renderMultiSelection() helper that appends a Group (Ctrl+G) button via the existing _buildLabelBtn helper, captures cachedNodes.slice() at click time, opens the themed WhiteboardPromptModal, and on confirm calls WhiteboardGroups.createGroup(capturedNodes, name || 'Group').
    • The multi-select fallback branch in update(nodes) now renders this helper and shows the props panel when cachedNodes.length >= 2 and the selection is not all comments; otherwise it still hides the panel as before.

Behavior

  • Visible only for multi-selections (2+ items); hidden for single-item selections (where the existing Ungroup button still appears for a single group).
  • Hidden for all-comments selections; shown for mixed comment + non-comment selections.
  • Tooltip Group (Ctrl+G); clicking opens the modal pre-filled with Group; Enter confirms, Escape/Cancel/backdrop cancels.
  • Selection snapshotted at click time so the resulting group reflects the originally selected nodes even if the user changes selection while the modal is open.
  • Identical result to Ctrl+G / right-click → Group Selected (same WhiteboardGroups.createGroup code path).

Test results

  • cargo test --workspace --lib: compiled cleanly, no failures (change is JS-only; regression guard).
  • node --check on selection_toolbar.js: OK; control-byte count = 0.
  • Rebuilt and redeployed; the new helper is verified present in the served /js/whiteboard/selection_toolbar.js.
## Implementation Summary Added a **Group** label button to the floating selection toolbar's multi-select branch. ### Changes - `crates/hero_whiteboard_admin/static/web/js/whiteboard/selection_toolbar.js`: - New `_renderMultiSelection()` helper that appends a `Group (Ctrl+G)` button via the existing `_buildLabelBtn` helper, captures `cachedNodes.slice()` at click time, opens the themed `WhiteboardPromptModal`, and on confirm calls `WhiteboardGroups.createGroup(capturedNodes, name || 'Group')`. - The multi-select fallback branch in `update(nodes)` now renders this helper and shows the props panel when `cachedNodes.length >= 2` and the selection is not all comments; otherwise it still hides the panel as before. ### Behavior - Visible only for multi-selections (2+ items); hidden for single-item selections (where the existing Ungroup button still appears for a single group). - Hidden for all-comments selections; shown for mixed comment + non-comment selections. - Tooltip `Group (Ctrl+G)`; clicking opens the modal pre-filled with `Group`; Enter confirms, Escape/Cancel/backdrop cancels. - Selection snapshotted at click time so the resulting group reflects the originally selected nodes even if the user changes selection while the modal is open. - Identical result to Ctrl+G / right-click → Group Selected (same `WhiteboardGroups.createGroup` code path). ### Test results - `cargo test --workspace --lib`: compiled cleanly, no failures (change is JS-only; regression guard). - `node --check` on `selection_toolbar.js`: OK; control-byte count = 0. - Rebuilt and redeployed; the new helper is verified present in the served `/js/whiteboard/selection_toolbar.js`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_whiteboard#206
No description provided.