* feat(header): add opt-in auto-hide-on-scroll for the header
New per-user header preference (default off): when enabled, the
header slides away while scrolling down and reappears on scroll-up or
near the top of the page. Disabled while in board edit mode, and
skipped entirely while focus is inside the header. Only applies when
the header is set to visible - the existing hover-to-reveal floating
controls already cover the hidden-header case.
* chore(api): regenerate the checked-in OpenAPI schema
check:openapi was failing in CI - the schema on disk hadn't been
regenerated after the header preferences gained autoHideOnScroll.
Add scripts/generate-openapi-schema.mts (and a generate:openapi
package script) alongside the existing check script so this is a
one-command fix next time the schema drifts.
* docs(users): document the header studio's visibility and auto-hide options
Header customization (drag-to-arrange controls, hide/show, hover-reveal
and pin, auto-hide-on-scroll) had no documentation on the user general
settings page.
* fix(dataTable): resizing a column no longer squashes the others
mantine-datatable's built-in column resize keeps the table's total
width fixed by shrinking every other column to compensate, which
collapses columns toward zero in a narrow widget (open upstream
issue, no fix: icflorescu/mantine-datatable#discussions-757).
Replaced it with our own resize handle that only ever changes the
width of the column being dragged - the table grows and scrolls
horizontally instead. Shared via usePersistedTableLayout, so docker,
downloads, and beszel-system-table all get it.
* feat(docker): enable hold-Shift advanced focus preview
The widget already renders differently for displayMode="advanced",
but was missing supportsAdvancedFocus: true, so the board never
offered the hold-Shift preview for it - matching downloads and
media-server, which both set this flag.
* style(docker): tighten row density, decouple icon size from row height
Circular avatar, denser row/footer padding, and action icons rendered
larger than their button via absolute positioning so they don't
inflate row height (the button stays small and fixed - it repeats
once per row, so any growth there multiplies across every visible
container).
* fix(data-table): harden shared column resizing
* fix(data-table): account for board scaling
* fix(data-table): compact shared headers
* fix(data-table): fit columns to widget
* fix(downloads): simplify advanced details
* test(widgets): align Docker advanced focus
* fix(downloads): widen expanded details
---------
Co-authored-by: ajnart <thomas@ajnart.dev>
The compact view auto-reveals name/change/range as the widget gets
bigger, which can overlap badly depending on how the widget's actual
proportions land relative to those breakpoints. Add a switch (on by
default, matching current behavior) to force the minimal symbol+price
look regardless of size. Scoped to the compact layout only - the
Shift-triggered advanced view is untouched.
Replace the stacked install modals (browse -> details -> import review)
with page-based flows so the primary action is always reachable:
- /manage/custom-widgets/workshop browses submissions as a card grid
with large previews, sitting in a tab next to the installed widgets
- /manage/custom-widgets/workshop/[id] merges the listing, security
review and source setup onto one page with a sticky install footer
- /manage/custom-widgets/publish/[id] replaces the publish modal
- /manage/workshop redirects; its navbar entry is gone
- the Custom CSS picker collapses from three modals to one
Extract useCustomWidgetImport and ImportReviewContent so the Workshop
page and the file/clipboard dialog share one import pipeline.
Votes now show the viewer's own choice filled Reddit-style, backed by a
new user-votes query, and screenshots get a zoomable lightbox.
Rework the installed list onto ManageCollectionItem: show the widget
description, replace the cryptic "JSX - 2" badge with plain request and
origin facts, and swap the toggle and bare pencil for a status badge,
a labelled Edit button and a menu entry for enable/disable.
Fixes found while reviewing:
- importing could run twice and duplicate a widget; guard on pending and
succeeded, and return to the installed list instead of the heavy edit
form
- a background refetch of the submission (window focus, or the
invalidation a vote triggers) reset the source setup and silently wiped
part-typed credentials; key the reset on the sources, not the object
- breadcrumbs raised MISSING_MESSAGE for unmapped dynamic segments; fall
back to the raw segment via t.has
- publishing had no in-flight guard and could post duplicate listings
- tooltips on disabled vote and report controls never fired, making the
sign-in hint unreachable