Per-widget action menu (refresh, maximize, duplicate, remove) #27

Closed
opened 2026-07-28 16:54:31 +00:00 by claude-bot · 1 comment
Collaborator

Problem

A GridStackItem currently offers exactly two affordances: the drag grip and the close button (added in #14). Everything else a dashboard widget normally does — refresh, expand to fullscreen, export, duplicate — has nowhere to live.

Proposal

Add a kebab/overflow menu next to the grip:

  • Refresh (re-request data for this widget only)
  • Maximize / fullscreen (temporarily expand the widget over the grid, restore on close)
  • Duplicate
  • Remove (the existing close, folded in — or kept separate as the fast path)
  • Export (see the export issue)

Implementation note: the drag handle and close button are already siblings of .grid-stack-item-content, deliberately outside it because the content wrapper is overflow: auto and anything inside it would scroll out of view. A third sibling follows the same pattern. The menu must sit outside the DRAG_HANDLE_CLASS selector so opening it never starts a drag — same reasoning as the close button.

Menu items should be individually enableable, since not every widget type supports every action.

Acceptance criteria

  • Menu opens without initiating a drag.
  • Actions are keyboard reachable (the close button already sets role="button" / tabindex="0"; match that standard).
  • Maximize restores the previous grid position exactly.
  • German copy with keys in all three bundles.
  • Playwright e2e for at least the menu-does-not-drag behaviour.

Depends on

#23 for refresh to be non-janky.

Scope

Medium.

## Problem A `GridStackItem` currently offers exactly two affordances: the drag grip and the close button (added in #14). Everything else a dashboard widget normally does — refresh, expand to fullscreen, export, duplicate — has nowhere to live. ## Proposal Add a kebab/overflow menu next to the grip: - Refresh (re-request data for this widget only) - Maximize / fullscreen (temporarily expand the widget over the grid, restore on close) - Duplicate - Remove (the existing close, folded in — or kept separate as the fast path) - Export (see the export issue) Implementation note: the drag handle and close button are already **siblings** of `.grid-stack-item-content`, deliberately outside it because the content wrapper is `overflow: auto` and anything inside it would scroll out of view. A third sibling follows the same pattern. The menu must sit outside the `DRAG_HANDLE_CLASS` selector so opening it never starts a drag — same reasoning as the close button. Menu items should be individually enableable, since not every widget type supports every action. ## Acceptance criteria - Menu opens without initiating a drag. - Actions are keyboard reachable (the close button already sets `role="button"` / `tabindex="0"`; match that standard). - Maximize restores the previous grid position exactly. - German copy with keys in all three bundles. - Playwright e2e for at least the menu-does-not-drag behaviour. ## Depends on #23 for refresh to be non-janky. ## Scope Medium.
claude-bot added the enhancement label 2026-07-28 16:54:31 +00:00
pitfriedrich added the ai-ready label 2026-07-28 18:52:45 +00:00
claude-bot added ai-wip and removed ai-ready labels 2026-07-28 18:58:07 +00:00
Author
Collaborator

PR offen: #37

Umgesetzt: Overflow-Menü als drittes Geschwister-Element neben Griff und Close-Button, mit Refresh / Maximize / Duplicate / Remove — pro Widget einzeln freischaltbar (setActions / setActionEnabled). Maximieren setzt nur eine CSS-Klasse, die gs-*-Attribute bleiben unangetastet, damit ist das Wiederherstellen exakt die alte Position. Copy in allen drei Bundles. ./mvnw test grün (55 Tests), inkl. neuem Playwright-Test, der am Menü-Button zieht und prüft, dass das Widget stehen bleibt.

Export ist nicht Teil des PRs — bleibt beim eigenen Export-Issue.

PR offen: https://gitea.pitfriedrich.net/pitfriedrich/chart-app/pulls/37 Umgesetzt: Overflow-Menü als drittes Geschwister-Element neben Griff und Close-Button, mit Refresh / Maximize / Duplicate / Remove — pro Widget einzeln freischaltbar (`setActions` / `setActionEnabled`). Maximieren setzt nur eine CSS-Klasse, die `gs-*`-Attribute bleiben unangetastet, damit ist das Wiederherstellen exakt die alte Position. Copy in allen drei Bundles. `./mvnw test` grün (55 Tests), inkl. neuem Playwright-Test, der am Menü-Button zieht und prüft, dass das Widget stehen bleibt. Export ist nicht Teil des PRs — bleibt beim eigenen Export-Issue.
claude-bot added ai-review and removed ai-wip labels 2026-07-28 19:26:47 +00:00
Sign in to join this conversation.