A page is a document: drop the sticky chrome and the bounded-frame opt-out
CI / full-gate (push) Successful in 2m49s

This commit is contained in:
2026-09-09 15:26:45 +02:00
parent 33065afd18
commit f959404c6f
12 changed files with 39 additions and 170 deletions
+1 -5
View File
@@ -5,9 +5,6 @@
caption?, selectable?, actions? sr-only caption; toggle the check / kebab columns
actionsId? id stem for the row-action menus (default `row-actions`);
name it when two tables share a page
scrollRegion? take the leftover height and scroll, so the header stays
put — needs the shell's `fill: true` and a flex chain
above (README → The menu system)
columns: { label, sortable?, sort?: "asc"|"desc", href?, className? }[]
rows: { name?, cells: Cell[], actions?: Action[] }[]
Cell ∈ string | { text, className? } | { user:{name,initials} } | { rowHeader:{text,href?} } | { badge:{tone,label} } | { html, className? }
@@ -23,9 +20,8 @@
const rows = locals.rows || [];
const emptyText = locals.emptyText || t("table.empty"); // shown when a table that has columns has no rows
const actionsId = locals.actionsId || "row-actions";
const scrollRegion = locals.scrollRegion === true;
-%>
<div class="table-wrap<%= scrollRegion ? " scroll-region" : "" %>">
<div class="table-wrap">
<table class="table">
<% if (caption) { -%>
<caption class="sr-only"><%= caption %></caption>
+2 -5
View File
@@ -9,16 +9,13 @@
(the <title> tag; defaults to title or the brand), `brand` ({ name, logo?, sub? }), `theme`
(theme-switch default), `user`, `breadcrumbs`, `csrfToken` (the Sign-out form's hidden field),
`signInHref` (anonymous "Sign in" target; default /login). `menu` (default true) — set false to
drop the sidebar and render a focused single-column page. `fill` (default false) — set true when the
page is a bounded frame whose own region scrolls (a board, a table with a fixed header) rather than
the document. `t`, `locale`, `dir` and `localeSwitch`
drop the sidebar and render a focused single-column page. `t`, `locale`, `dir` and `localeSwitch`
come from the host with every render (README → Languages).
%><%
const brand = locals.brand || { name: "Plainpages" };
const title = locals.title || ""; // topbar heading; empty ⇒ no topbar <h1> (the body owns it)
const docTitle = locals.docTitle || title || brand.name;
const menu = locals.menu !== false; // sidebar shown by default; a page may opt out
const fill = locals.fill === true; // the document scrolls unless a page says it owns the viewport
const hideSignIn = locals.hideSignIn === true; // the auth pages are already a way in — no footer Sign-in there
const user = locals.user || { name: "Guest", initials: "G", email: "" };
const breadcrumbs = locals.breadcrumbs || [];
@@ -44,7 +41,7 @@
<input type="checkbox" id="nav-toggle" aria-hidden="true" tabindex="-1" />
<% } %>
<div class="app<%= menu ? "" : " app-bare" %><%= fill ? " app-fill" : "" %>">
<div class="app<%= menu ? "" : " app-bare" %>">
<% if (menu) { %>
<aside class="sidebar" aria-label="<%= t("shell.sidebar") %>">
<div class="brand">