Undo closing a widget #40

Closed
opened 2026-07-28 19:47:42 +00:00 by claude-bot · 1 comment
Collaborator

Problem

Closing a widget is instant and destructive. GridStackItem.close() detaches the element and fires the event:

private void close(boolean fromClient) {
    getElement().removeFromParent();
    fireEvent(new CloseEvent(this, fromClient));
}

One misclick on the X and the widget is gone, along with its size and position. There is no confirmation and no way back short of a full layout reset, which throws away every other widget's placement too.

Proposal

Show an undo affordance instead of a confirmation dialog (a dialog on every close would be worse than the problem):

  • On close, show a Notification with an "Rückgängig" action and a timeout.
  • Capture the item's Position (id, x, y, w, h) before detaching — after removeFromParent() the grid no longer reports it.
  • Undo re-adds the item at exactly the captured position, not at the grid's next free slot.
  • The CloseEvent already carries fromClient, so the undo can be limited to user-initiated closes and skip programmatic ones.

Note the id constraint from GridStackView.addWidget(): ids must stay stable, and a restored widget must come back under its original id or it loses its saved layout entry.

Acceptance criteria

  • Undo restores the widget at its original position and size.
  • Restored widget's gs-id is unchanged.
  • Programmatic close() does not spawn an undo toast.
  • Playwright e2e for close → undo → position unchanged.

Depends on

Nothing hard. Interacts with #22 — undo must not race the layout persistence (a close followed by undo should not leave a stale persisted layout).

Scope

Small.

## Problem Closing a widget is instant and destructive. `GridStackItem.close()` detaches the element and fires the event: ```java private void close(boolean fromClient) { getElement().removeFromParent(); fireEvent(new CloseEvent(this, fromClient)); } ``` One misclick on the X and the widget is gone, along with its size and position. There is no confirmation and no way back short of a full layout reset, which throws away every *other* widget's placement too. ## Proposal Show an undo affordance instead of a confirmation dialog (a dialog on every close would be worse than the problem): - On close, show a `Notification` with an "Rückgängig" action and a timeout. - Capture the item's `Position` (id, x, y, w, h) *before* detaching — after `removeFromParent()` the grid no longer reports it. - Undo re-adds the item at exactly the captured position, not at the grid's next free slot. - The `CloseEvent` already carries `fromClient`, so the undo can be limited to user-initiated closes and skip programmatic ones. Note the id constraint from `GridStackView.addWidget()`: ids must stay stable, and a restored widget must come back under its original id or it loses its saved layout entry. ## Acceptance criteria - Undo restores the widget at its original position and size. - Restored widget's `gs-id` is unchanged. - Programmatic `close()` does not spawn an undo toast. - Playwright e2e for close → undo → position unchanged. ## Depends on Nothing hard. Interacts with #22 — undo must not race the layout persistence (a close followed by undo should not leave a stale persisted layout). ## Scope Small.
claude-bot added the enhancement label 2026-07-28 19:47:42 +00:00
pitfriedrich added the ai-ready label 2026-07-28 20:59:39 +00:00
claude-bot added ai-wip and removed ai-ready labels 2026-07-28 21:00:05 +00:00
Author
Collaborator

PR ready, CI green: #48

PR ready, CI green: https://gitea.pitfriedrich.net/pitfriedrich/chart-app/pulls/48
claude-bot added ai-review and removed ai-wip labels 2026-07-28 21:30:26 +00:00
Sign in to join this conversation.