WireKit v2.69.0
Minor. Three new components: a live list that keeps the reader's place while the server adds entries, a card stack that draws parts in a remembered order, and a sign-in button for Google, Apple, Facebook, PayPal and Amazon, drawn the way each service asks. A table can stack its rows as cards on a phone, a field can follow a value derived from other fields until the reader sets their own, a tab bar can wrap instead of scrolling, and an application that bundles the stylesheet itself loads the compact sheet with @wirekit. A button with loading-target no longer starts disabled without a wire: attribute, a server-searched combobox draws its next results after a group came or went, and a modal or drawer leaves the focus in a field the reader moved into while it opened and gives it back to its trigger after a tap in Safari. Under the Phosphor and Tabler presets, heart and star now draw filled, as they do under Heroicons.
Added
-
New live list for a list the server re-renders while it is read.
<x-wirekit::keeps the first row in view where it was when entries arrive above it, in a scroll region of its own as on the page, and whether or not the browser anchors the scroll itself. Rows carrylive-list> data-wk-live-row; a row markeddata-wk-live-freshthat lands out of sight raises a hint, "New entries above" or "New entries below", which a screen reader hears as well and which brings the row into view with the focus on its link. Only a render markedlivekeeps the place, so a filter or the next page starts where the reader expects. -
New sign-in button for signing in with Google, Apple, Facebook, PayPal or Amazon.
<x-wirekit::draws each service's button the way its own guidelines ask: its colors and looks, Google's and Apple's following the page's mode, its words ("Continue with", "Sign in with", "Sign up with"), translated, and the place and size of its logo. WireKit ships no service's logo, since each service asks for its own artwork under its own terms;sign-in-button service="google" href="…"> wirekit.names the files an application downloads, and for Amazon, which allows its own buttons only, the file is the whole button. It is as wide as its container by default, a link withsign_ in. logos hrefand a button without it. -
New card stack for parts in a remembered order.
<x-wirekit::draws named slots, such as the cards of a record page, in the ordercard-stack> ordergives, a reader's own or a default for a role. A part the order marks as not shown is drawn hidden rather than left out, so a Livewire component inside it keeps its element, and it shows for the visit when a link's fragment leads into it or whenwirekit:card-stack-shownames it. Each part sits in a wrapper with no box of its own and awire:key, so a new order moves the parts and the order in the document stays the order on screen. -
A table can lay its rows out as cards below a breakpoint. With
stack-below="md"(orsm,lg,xl,2xl), each row of the body stands as a card and each cell as a line that starts with the name of its column, so a wide table does not scroll sideways on a phone; a cell withalign="right", the row's actions, stands as the card's footer. The names come from the header above each column, the rows a Livewire update adds included, andlabelon a cell names it directly. The table writes its roles out, so it stays a table for a screen reader while its rows are cards. -
An input can follow a value derived from other fields, with a switch for a value of the reader's own.
:own="false"makes the field read-only while it follows the value, such as a code worked out from a name, and puts a switch below it, labeled withown-label, that opens the field and locks it again. The lock follows the switch in the browser at once, andown-modelsends the switch live to a Livewire property, so the server derives the value again when it is turned off and the focus stays on the switch. -
A tab bar can wrap its tabs onto further lines instead of scrolling.
wrapon tabs and ontabs.listwraps a horizontal bar at every width, andwrap="md"(orsm,lg,xl) from that width up, so a phone keeps the bar that scrolls. Each tab keeps its label on one line, and the arrow keys move along the tabs as before. Without the prop the bar scrolls sideways as it always did. -
@wirekitlinks the compact sheet alone, while compact classes are on. For an application that importsCompact Styles wirekit.cssinto its own build instead of using@wirekitStyles: the components write short names only while the switch is on, and an import in a build cannot follow the switch. The directive linkswirekit-compact.while it is on and writes nothing while it is off, and takes a CSP nonce ascss @wirekitStylesdoes.wirekit:verifyandwirekit:doctorwarn when compact classes are on,wirekit.cssis imported, and no stylesheet that declares the short names is loaded. -
A keyboard shortcut can work out what it does.
window.registers a shortcut that runs a function instead of clicking or focusing an element, such aswirekit Shortcut({ keys, label, run, el, global }) jfor the next link of a list, and returns the function that removes it. It follows the rules every shortcut follows, a field, the switch for single keys and the area of an open dialog, and the overview lists it under itslabel. A bundled app imports the same function asdefineShortcut. -
A filter builder takes operators without a value. An operator a field brings with
valueless: true, such as "has a value" or "is empty", hides the value editor while it is picked and adds its filter without a value. The chip reads the field and the operator alone, and the filter carriesvalue: null. Before, every operator waited for a value, so such a condition could not be added at all. The default operators are unchanged. -
A data list takes
layout="inline"for a few entries in a narrow place. One line per entry, "Label: value", in the small text size and without the padding and rules of a row, for what a customer entered under a line of an order in a table cell. The value keeps the line breaks it was typed with, and a long token breaks where the line ends. -
Inline code takes
break, astextandheadingdo. A name with no break point, such as a channel or a file, broke inside its own box, but a flex row could not shrink it, and the row ran out of its box. A class such as[overflow-wrap:anywhere]given at the call site stood beside the component's default rule, and the order of the stylesheet decided which one applied.break="anywhere"now sets that rule in place of the default, so the row shrinks the name and it wraps where the line would overflow;allandnormalmean what they mean ontext. -
The icon alias
heart-outline, the heart in outline besideheart, asstar-outlineis besidestar. A wishlist toggle takeson-icon="heart"andoff-icon="heart-outline"and fills its heart when it is pressed. Every preset draws it from its own set; Lucide draws only outlines, so there the two names are one glyph. -
The icon alias
layoutfor a page's arrangement, such as a menu entry that chooses which cards a page shows and where. Lucide, Phosphor and Tabler draw their own layout glyph; Heroicons has none and draws its group of rectangles. Before, the picture had no word, and a glyph name in its place broke with a change of preset. -
The icon aliases
expand-allandcollapse-allfor the entries that open or close every part of a page at once. Lucide and Phosphor draw arrows leaving and meeting a fold line, Tabler a line with arrows leaving it and its fold, and Heroicons, which has no fold glyph, its arrows pointing out and in. Before, neither picture had a word, and a glyph name in its place broke with a change of preset. -
A neutral tone for charts,
--color-wk-chart-neutraland--color-wk-chart-neutral-edge. For what a chart draws beside its subject: the line of a comparison period, the share of tax beside the net amount, the rest of a list as "Other". It has no hue, so it stands apart from every series of the palette without meaning anything, and it follows the palette's rules in both modes: the edge holds 3:1 on the page, and--color-wk-chart-labelreads on the fill. -
AccentLadder::writes the four accent tokens asfor() #rrggbbcolors withhex: true. For a store or a validator that takes hex only: every ratio is then measured on the hex values themselves, so the label holds 4.5:1 on the fill and on the hover as written, where a hex color converted from the roundedoklch()value could fall just short. A fill given in hex comes back as the same hex color unless a dark page lifts it, andlift: falsekeeps a fill chosen for the dark mode on purpose at its own lightness. See the theming page.
Changed
- The Phosphor and Tabler icon presets draw
heartandstarfilled, as Heroicons does. Both sets carry a filled heart and star, and with themheartandheart-outline,starandstar-outlineare two glyphs in every preset that can draw both, so a toggle between the two shows its state in the glyph itself. Where the outline was meant,heart-outlineandstar-outlinedraw it. Lucide has no filled glyphs and is unchanged.
Fixed
-
A button with
loading-targetwaits for that request, also without awire:attribute of its own. A button whose click runs through Alpine and calls$wire.save(), and the submit button of a<form wire:submit>, carry nowire:attribute, andloading-targeton them was read as a loading state set by hand: the button rendered disabled from the start, its spinner turning, and a form with it as its default button could not be sent, not even with Enter. A named target now always means the Livewire request of that name. -
A combobox with
serverdraws the results of the next search after its options gained a group or lost one. The list was drawn by one of two templates, chosen by whether the current options carried a group, and the options of a server search change with every render. A list of recently used records under a group before a search, followed by the hits of a search without one, swapped the template under a list that was already built, and the hits were not drawn: a single empty row stood where they belonged. A server-searched combobox now always draws its list grouped, and an ungrouped result as one group without a heading. -
A modal or drawer opened by a click or a tap in Safari gives the focus back to its trigger when it is dismissed. Safari does not focus a button on a click or a tap, and the overlay took the element that held the focus as its opener, so Escape left the focus on the page itself.
drawer.trigger, a namedmodal.trigger, an unnamed one and thetriggerslot of a modal or an alert dialog now hand the overlay their own element as the opener. -
A field the reader has already moved into keeps the focus when a modal, drawer or alert dialog opens. A dialog places its initial focus a moment after it opens, once its panel is shown, and in that moment a click into a field of the panel was taken back: focus moved to the first control, or to Cancel in an alert dialog, and the next keys went there. Every overlay that traps the focus now leaves it where it stands when it is inside the panel already, and starts where it always did otherwise.
-
A command palette sends the query of a search before its submit. The field reports the query 300 ms after the last keystroke, and Enter with nothing highlighted reports the submit at once, so text typed and submitted within 300 ms reached the page as the submit first and the query for the same text after it. A search that keeps only the answer to its newest request dropped the answer to Enter. Enter now sends a query not yet reported first, and the field reports nothing for that text afterwards.
-
A click on a column of an ApexCharts chart with categories on its x-axis follows that column's address. ApexCharts hands a click on a column the series its shared tooltip took up rather than the column's own. With more than one series, in a chart that mixes columns with lines as in one of grouped columns, a click on a column followed the address the first series has at that point, or nothing where it has none. The chart now reads the series off the column under the pointer, and where nothing names one, takes the one dataset with an address at that point.
-
x-wk-scroll-into-viewbrings a region out from under a pinned header. A sticky page header reports its band to the box it scrolls in asscroll-padding, and the browser keeps a scrolled element clear of it, but the check whether a region was already in full view measured the whole box. A region whose top stood in that band counted as in view: it took the focus without a scroll and stayed covered by the header. The check now takes thescroll-paddingof the window and of every box that scrolls off what counts as visible, so such a region comes into view below the header. -
A brand with
truncategives way in thebrandslot of a navbar. The slot kept the full width of its content, so on a phone a long name ran past the screen, the page scrolled sideways, and the menu button dropped to a line of its own under the brand. Around a brand withtruncatethe slot now gives way as well: the name ends in an ellipsis, and the menu button and the actions keep their place beside it. Where the bar has room, the brand keeps its whole name, and a navbar around any other brand renders as before. -
Two checkboxes or radios one under the other in a field set no longer stand nearly twice as far apart on a touch screen as under a mouse. On a touch screen the label of each is a 44px row, the size of a fingertip, and the field set kept its gap between controls on top of it. Between two such rows the gap now drops away, since the rows already stand apart by their own height; around every other control of the set it stays.
-
The question mark of a field's help stays usable in a field set with
disabled. A disabled field set disables every form control inside it, and the question mark was a<button>: it took no focus, showed its tooltip only to the pointer, and a click reported nothing. A reader who may only look at a form is the one who needs the explanation of its fields, so the question mark is now an element with the button role, which a field set does not disable. Enter and Space work on it as before, and the event it reports is unchanged. -
A link or a button that holds several cut texts shows one tooltip for them on the keyboard focus. With
truncate="tooltip", every cut text in a control opened its own tooltip above its own line when the control took the focus, so a list entry with a cut name and a cut code under it stacked two panels over each other. Now the first cut text speaks for all of them: one tooltip carries every cut text of the control, joined by a middle dot. The pointer still shows the tooltip of the text it is on. -
An empty state without an action ends as close to its edge as its icon starts. The description kept a bottom margin of its own for the action below it, so a state with no action stood 16px taller at the bottom than at the top. The space now belongs to the action, the same 24px after a description and 8px after a title alone as before.
-
Safari no longer reports the overlay stylesheet as missing while it is still loading. When the first overlay is set up, the bundle checks once that the stylesheet positions a modal, a drawer or the command palette over the page, and logs an error to the console when it does not. WebKit runs a deferred script as soon as it has arrived, before the stylesheets in front of it apply, so on a full page load the check could read a stylesheet still in flight as missing and log that error on a page that rendered correctly. The check now waits until the page has loaded, and a stylesheet that really is missing is reported as before.
-
The Spanish catalog calls the cart one thing: "Cesta". The cart's own name said "Carrito" while "Add to cart" said "Añadir a la cesta", so a Spanish shop with the cart and a product card named it two ways. "Cesta" is the word Spanish online shops use for both.
-
wirekit:doctor:propsreads the props of a class component from its constructor. An application component that hands its attributes to a WireKit component is checked against both, and a class component declares its own props as constructor parameters, which Laravel takes out of the attribute bag before the template renders. The linter read only@propsand reported those parameters as unknown props of the WireKit component, so--require-in-scopefailed on a correct call site. It now counts the constructor parameters of the class Blade takes for the tag, a registered one or the one Laravel's naming points to. -
Schema::graph()declares that a node may benull. It always left anullnode out, so that a node built only on a condition can be written inline, and its docblock allowed only arrays, so static analysis reported every call that did what the structured data page now describes.
Documentation
- The table page says how a printout chooses its columns. A printed table keeps every word whole, so a table with more columns than a sheet leaves room for prints the columns that fit, and the page now says so for wide tables as well as for long words. It also says that on paper the width of the sheet counts as the width of the window, so a column with
hide-belowstays off a portrait sheet as it stays off a phone.
Components
Every component this release changes, each linked to its page: Alert Dialog · App Shell · Brand · Button · Card Stack · Chart · Checkbox · Code · Color Picker · Combobox · Command Palette · Data List · Drawer · Empty State · Field · File Upload · Filter Builder · Inline Edit · Input · Label · Lightbox · Live List · Message · Modal · Navbar · Popover · Radio · Rating · Shortcuts · Sign-in Button · Slider · Table · Tabs · Toggle · Tooltip · Tour