Version 5.2.1

October 13, 2026

Fixed

  • Sortable headers are column headers again (#4). The runtime gave each sortable <th> role="button", which replaced its column header role: screen readers stopped announcing it as a header or reading its sort state, and axe reported a critical aria-allowed-attr violation (WCAG 4.1.2) for every sortable column. Each header now keeps its role and its aria-sort, and a real <button> inside it does the sorting — the WAI-ARIA sortable table pattern. It looks the same; keyboard and click behave as before. A header that contains a link keeps it, and gets a separate “Sort by …” button over the arrow. If you turn registerCss off and style tables yourself, style .legs-sort-button (and .legs-sort-button-icon), or the browser's default button look will show in your headers.

Version 5.2.0

October 9, 2026

Added

  • GraphQL. legsTables, legsTable and legsTableCount queries, a LegsTable type and the Legs field in both modes, so a headless site can read its tables. grid hands out the renderer's own layout as data — header, body and footer rows, visible columns, merges as spans, purified cell HTML, evaluated formulas and sort values — alongside options and an optional rendered html. Schemas get nothing until they're given tables: the whole library, or one table at a time. Disabled and trashed tables are never served, and a query-backed table's criteria stay on the server. Available on Lite and Pro.

Version 5.1.1

October 2, 2026

Security

  • Query tables are an admin's to point at anything but content. The Manage tables permission was enough to build a table from users — email addresses and password hashes included — or to add a template column reading craft.app.config.db.password, and then offer it as a public download. Someone who isn't an admin can now query entries, categories, assets, tags and Commerce products and variants only, can't add template columns, can't list sensitive attributes, and gets live content only. The rules are enforced when a table is saved and every time it's rebuilt.
  • Template columns not saved by an admin render only inside Craft's Twig sandbox (enableTwigSandbox, Craft 5.9+), and render nothing without it. Tables saved before this release aren't marked as an admin's, so an admin-built query table using users, other element types or template columns fills in again once an admin re-saves it.

Fixed

  • php craft legs/tables/… printed an empty handle in its "No table with the handle" message: a curly quote straight after $handle became part of the variable name.

Changed

  • PHPStan (level 4) and ECS configuration.