v2.38.0
Minor. The overlay work of the last two releases reached the drawer: its geometry ships in the
stylesheet now rather than depending on your Tailwind build, and the panel became a real dialog
instead of one that only looked like it. Alongside that, three layout defects that each cost a
visible jump on a page load, and a row that lines its form controls up whatever mix of labels
they carry.
Added
- A
<x-wirekit::data-table>column takes asubKey, so a cell can be two lines. The
ordinary shape of an admin table is a value over a quieter second one — order number over date,
customer over email, product over SKU — and a column could previously render only a single
string, a number or a status pill. A row whose second field is empty draws one line rather than
one line and a gap. On anumbercolumn both lines stay tabular. See
Data Table. <x-wirekit::product-card>takes amediaslot and abadgeslot.imageis a URL, and
there was no branch for its absence — so a product whose artwork is drawn rather than
photographed, or is a video or a color field, had no way into the component at all. The slot
wins overimagewhen both are given, and with neither the card draws no media area, which is
deliberate: a placeholder invented here would appear on every card that legitimately has no
picture. Thebadgeslot sits beside the ones the card derives — those answer on-sale and
in-stock, and "New" or "Limited" had no equivalent — and the two stack rather than overlapping.
See Product Card.<x-wirekit::row align-fields>puts every control in a row on one line, and stacks them
below 48rem. A labeled field
is taller than an unlabeled one and a field with a hint is taller still, so no singlealign
value lines the controls up for every mix — and a submit button beside them has no label row
at all. The row becomes three shared tracks (labels, controls, messages) and each field hands
its parts to them. Opt-in: it changes the row's display model, andalign/justifystop
applying while it is on. See Row.<x-wirekit::app-rail.item as="button">. A rail entry that opens a menu is not a
destination, and as a link it was subtly broken: a link activates on Enter and not on Space,
so the key did nothing. Every click on the placeholderhrefalso pushed a history entry and
wrote a bare#into the address bar. See
App Rail.<x-wirekit::app-rail persist-driver="cookie">.persistkeeps the reader's choice in
localStorage, which no server can read — so a rail that remembers being expanded renders
collapsed and widens itself after the first paint. A cookie is the only store Blade and Alpine
both read, so the first render is already right. Opt-in, because writing a cookie is something
an application has to be able to account for. See
App Rail.wirekit:doctorsays what a stale published asset costs. "Outdated" undersold it: the
Blade directives compare size and hash, decide a stale copy cannot be trusted, and serve the
package route instead — so every asset travels through PHP, without the cache headers or the
precompressed sibling configured forpublic/vendor/. The report names that now, once per
run. See CLI Reference.- Two design tokens,
--size-wk-drawer-insetand--size-wk-rail-icon. Both were literals
repeated across rules that had to agree; each is one value now. See
Design Tokens.
Fixed
-
An icon whose set is not installed renders a placeholder instead of a 500. The
component degraded for two of the three ways an icon can go missing:blade-icons
absent, and an alias nobody has. The third is an alias that resolves perfectly onto a
set nobody registered —inboxbecomesheroicon-m-inboxout of a static table that
never checks whether the glyph is there — and that name reached the renderer, found
neither the set nor a fallback, and threw. Icons draw transitively through buttons,
dropdowns and modals, so the page it took down was most pages. It is the state an
application lands in by accident: one that already hadblade-iconsfor its own set
reads the set package as optional. The log line names the package to install, once per
prefix rather than once per icon, and a fallback you configured still wins. A console
command or a test still fails loudly, because there the missing package is fixable now.
See Icon. -
A restarted
<x-wirekit::stat>counter no longer stays on zero when its frames stop after
the first one. The counter carries a watchdog for exactly that case — a frame that is hidden
or unpainted pausesrequestAnimationFrameindefinitely while timers keep running — and the
watchdog was being called off by the first frame that landed. One frame does land: it writes
zero and is then never followed, so the one state the net was there for was the one state that
took it down. The watchdog now decides by whether the run actually finished. See
Stat. -
The scope-collision warning no longer fires at developers whose scope is fine. It told a
caller theirx-datawas discarded whenever the component's own template mentioned one — but
it read the template with a pattern that cannot see conditions, and a large minority of
components set theirs only inside one.<x-wirekit::card>is the case that surfaced it: its
x-databelongs to a debug warning that renders only when a card is composed wrongly, so a
correctly composed card collides with nothing and the message asked for working code to be
rewritten. The check now asks whether the component sets one on every render, which is the
claim the message makes. A component that sets one both ways still warns. -
The workspace mark in an expandable
<x-wirekit::app-rail>now shows its name when the rail
expands. The mark decided that in PHP, fromlabels, while rendering — and widening the rail
is a browser-side change that happens long after, so a rail that started narrow kept its name
hidden at every width. Move the workspace name out of your header because the rail was meant to
carry it, and it was nowhere. The failure was silent: the name was in the document and
announced, merely never drawn. The mark now reads the same live state its modules read. See
App Rail. -
The drawer's panel gets its geometry from the stylesheet, not from your Tailwind build.
Its position, size and edge came from bare utility classes, which exist only where a build
scanned this package — so an application that did not would get a panel with no position at
all. Alert dialog and modal already shipped theirs; the drawer was the one that did not. See
Drawer. -
The navigation drawer is a dialog to the keyboard, not only to the mouse. Below the
breakpoint it slid over the page like a modal sheet and had none of a dialog's semantics: no
role, noaria-modal, no focus trap, and Escape did nothing. Tab walked straight out of it
into the page behind. See App Shell. -
An expanded rail no longer makes the mobile drawer wider than the phone. The drawer took
the rail's expanded width with it, so a reader who had expanded the rail on a desktop got a
sheet wider than the viewport on their phone. See
App Shell. -
The shell's columns stay in the layout above the breakpoint while the page is still
booting. A shell column is a drawer belowlgand an ordinary column above it, and it was
hidden either way until Alpine ran — so the content column painted across the full width and
jumped aside when the columns arrived. Measured on a console shell at 0.1788 cumulative layout
shift against a budget of 0.1, and it was the page's entire CLS. See
App Shell. -
The rail no longer flashes a horizontal scrollbar or slides its rows while it expands. Its
scroller asked only for a vertical axis, and CSS promotes the other one toautoas soon as
one axis scrolls — so the region was horizontally scrollable by omission. Separately, a
module name sat in a line box taller than the glyph beside it, and every entry grew by the
difference the moment its name appeared. See
App Rail. -
The script tag carries
data-navigate-once, so a client-side navigation does not execute
the bundle again. The bundle registers Alpine components and document listeners, which is a
once-per-document job; without the attribute Livewire re-ran it on every hop and the listener
set grew for as long as somebody navigated without a full reload. See
Integration.
Documentation
- The one diagnostic WireKit emits at
errorlevel is now documented as such. A missing
package stylesheet makes every dialog and drawer render inside the page instead of over it —
finished-looking and unusable — so the message is an error rather than a warning. The
consequence worth knowing beforehand is that a console check gating onerrorgoes red in that
situation over an install step rather than a defect. See
Console Output Baseline. - The marketing icon preset no longer puts a number on its own size. Its docblock claimed a
count several times what the file declares: v2.37.0 moved the common semantic names into every
base preset and the sentence stayed behind. A reader deciding whether to stack the extension
at all was reading a figure that had been wrong for four minors — and the words it implied
were missing had in fact become reachable from every preset. See
Icon. - The shipped asset sizes match the files again. Four rows in the bundle catalog and three
on the dependencies page had drifted; the readable stylesheet's row now names its property
instead of a figure that moves whenever a rule gains a comment. See
Dependencies.