Skip to content

feat(grid): render grid widgets on a gridstack canvas - #3079

Open
remko48 wants to merge 5 commits into
feat/noid/views-api-v2-gridfrom
feat/noid/grid-widget-canvas
Open

remko48 wants to merge 5 commits into
feat/noid/views-api-v2-gridfrom
feat/noid/grid-widget-canvas

Conversation

@remko48

@remko48 remko48 commented Oct 12, 2026

Copy link
Copy Markdown

Frontend building blocks to show a grid view: a canvas that places widgets on a grid, the card around each widget, and the first two widget types (header and text). Nothing uses them yet; the grid view page comes in a later PR of this stack.

What changes

  • New dependency gridstack for the grid layout (drag, resize, reflow). It does the hard part of a dashboard grid; writing that ourselves would be a lot more code to maintain.
  • GridCanvas: 12 columns on a wide screen, 6 on a medium one, 1 on a phone, based on the canvas width. A narrower layout is only how the page is shown; the stored layout always stays the 12-column one. Widgets can therefore only be arranged at full width: on a narrow screen edit mode shows a hint instead.
  • GridWidget: the card with an optional title and, in edit mode, a menu to configure, remove, move and resize the widget, so the grid can be arranged with the keyboard as well as by dragging. In edit mode the card always shows a heading, the widget's title or else its type name.
  • Widgets: HeaderWidget (heading, subheading, alignment, colors) and TextWidget (paragraphs, split on empty lines). Colors are only applied when they are hex, the same rule as the backend.
  • Widget types are loaded from GET /api/2/views/widget-types the first time a widget is shown, with one shared request; the frontend only maps each type to the component that renders it.
  • Tests: a Cypress component test covers the layout helpers and the hex color check.

🖼️ Screenshots

No visible change yet, since nothing renders the canvas until the grid view page PR.

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not needed
  • 🔙 Backport requests are created or not needed: /backport to stableX.X
  • 📅 Milestone is set
  • 🌸 PR title is meaningful (if it should be in the changelog: is it meaningful to users?)

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

remko48 and others added 3 commits October 12, 2026 13:56
Adds the building blocks of a grid view: a canvas that places widgets on
a 12 column grid with gridstack, the card around each widget, and the
header and text widgets. The widget types are loaded from the server.

- the grid reflows to 6 and 1 columns on narrower screens, while the
  stored layout keeps the 12 column positions
- in edit mode widgets can be dragged and resized, or moved and resized
  from the widget menu with the keyboard
- colors from widget content are applied only when they are hex values

Co-authored-by: Ruben van der Linde <ruben@conduction.nl>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Remko <remko@conduction.nl>
…azily

- on a canvas narrower than 12 columns drag, resize and the move actions are
  off with a hint, since that reflow is only shown and never stored
- widget types load the first time a widget needs them, in one request,
  instead of on every app start
- the column choice and the layout mapping are pure, named functions with
  component tests, together with the widget defaults, the grid copy and the
  hex color check
- one deep copy for defaults and grids, which also copies reactive data
- a header widget's heading sits below the card's own heading
- widgets no longer get an editable attribute they do not declare, and the
  grid baseline variable is used without a fallback

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Remko <remko@conduction.nl>
- the grid constants and pure helpers move to gridLayout.js, widgetRegistry.js
  only maps widget types to components
- move and resize steps are disabled when they cannot apply
- a widget card is labelled by its visible heading, and editor placeholders
  only show while the page is edited
- data-cy names are camelCase, the edit outline uses the max-contrast border
  and the header subtitle no longer lowers contrast with opacity
- GridStack and the resize observer are no longer reactive state, so they
  need no markRaw; the margin is a named constant
- one comment style, JSDoc on every method and one way to use icons

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Remko <remko@conduction.nl>
@remko48
remko48 requested review from blizzz and enjeck as code owners October 12, 2026 14:56
@remko48
remko48 added this pull request to stack #3080 October 12, 2026 14:56
@remko48
remko48 force-pushed the feat/noid/grid-widget-canvas branch from 3178aaf to aa62e3c Compare October 12, 2026 15:37
Signed-off-by: Remko <remko@conduction.nl>
Signed-off-by: Remko <remko@conduction.nl>
Assisted-by: ClaudeCode:claude-opus-5-5
@remko48
remko48 force-pushed the feat/noid/grid-widget-canvas branch from aa62e3c to b64ea53 Compare October 14, 2026 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants