Repository navigation
v0.4.0
0.4.0 moves the kit onto the Shipbytes design system (shipbytes/blade-ui).
The layouts, the shared components, the seven auth pages, the profile page and
the nine admin screens are all built from its ds:: components and semantic
tokens; the kit no longer carries a palette, fonts or components of its own.
Every route, route name, wire:model, Livewire method, validation message and
config('ui-kit.copy.*') string is unchanged. What changes is every file the
kit publishes, so an app on 0.3 has to merge: "Upgrading from 0.3" at the
end of this entry lists the steps.
Breaking
- Requires
shipbytes/blade-ui^1.2.2, which Composer installs with the
kit. The design system's contract with an app is three lines of CSS: import
itstokens.css, import itstheme.css, and@sourceits views so Tailwind
keeps the classes its components use. The published
resources/css/ui-kit.csscarries all three, soapp.cssstill imports only
./ui-kit.css. Without the@sourceline everyds::component renders as
unstyled HTML and nothing reports an error. resources/css/ui-kit-theme.cssis gone, and with it thebrand-*
colour ramp and the Poppins (font-boldtext) and Montserrat
(font-booktext) font utilities. The accent is the design system's blue and
the one font is its Inter, which the kit's three layouts load from
fonts.bunny.net. Classes such asbg-brand-600orfont-boldtextin an
app's own views no longer exist. Brand colours are now--ds-*token
overrides inapp.css, after theui-kit.cssimport
(:root { --ds-accent: … }, and.dark { … }for the dark value).- Every published view, and the admin Livewire classes and module models,
are rewritten. The layouts,<x-theme-toggle />, the session status
message, the impersonation ribbon and button, the auth pages, the profile
page and the nine admin screens useds::components and tokens
(bg-surface,text-fg-muted,border-border, …) that switch for dark mode
on their own, with no palette classes ordark:variants. The five
paginating admin components use the new pagination trait (below);
SupportTicket,ContactSubmissionandChangelogEntrygain badge-tone
methods. An app that edited any of these files must merge its edits into
the new ones; re-publishing with--forceand readinggit diffis the
way to do it. - Nav icons are Heroicons v2 names, rendered through
ds::icon, so any
outline icon on heroicons.com works as aniconin
config/admin.php. The kit's own entries are nowsquares-2x2(Dashboard),
users,ticket(Support),document-text(Changelog),envelope
(Contacts) andclock(Activity). Of the 0.3 names,grid,note,chart
andhistoryno longer resolve (usesquares-2x2,document-text,
chart-bar,clock);mailstill works through a design-system alias of
envelope;users,ticket,clockanduser-circleare unchanged. A
name that does not resolve makes every admin page fail withUnable to locate a class or view for component [heroicon-o-…], because the sidebar
renders on every page;ui-kit:doctornames each one. The
layouts/partials/nav-iconspartial and its hand-drawn SVGs are gone. ui-kit.cssnow carries two@sourcelines: the design system's views,
and the kit's own package views invendor/(<x-ui-kit::page-header>and
friends), which are not published either. A 0.3ui-kit.csshas neither.- The installer deletes the Laravel 12 skeleton's Instrument Sans. The
skeleton'sapp.cssends with an@themeblock setting--font-sansto
'Instrument Sans'. It comes after the kit's import, so it beat the design
system's Inter, and since nothing loads Instrument Sans the app rendered in
the system font.ui-kit:install(including a re-run on an existing app)
now deletes that one declaration, and the@themeblock if nothing else is
in it. A font the app chose for itself is left alone. - Admin lists paginate through
Shipbytes\UiKit\Livewire\Concerns\WithDesignSystemPagination. The five
paginating admin components (users, tickets, contacts, changelog, activity)
use it in place of Livewire'sWithPagination, so their pages render with
the design system's Livewire pagination.ui-kit:doctorfails while a
published admin component is still on plainWithPagination.
Added
WithDesignSystemPagination, for an app's own Livewire lists too. It
includesWithPagination; the design system's pagination view calls
gotoPage,previousPageandnextPage, so a page change is a Livewire
update that keeps the component's search and filters. A component that
definespaginationView()orpaginationSimpleView()itself keeps its own:
a class method wins over the trait's.<x-ui-kit::page-header title="…" subtitle="…">, a package component
with an optionalactionsslot that sits right of the title and wraps under
it on a phone. Every admin screen opens with it, and an app's own admin
screens can too.- Doctor rows for the design system, each with a hint that says how to fix
it:design system installed,ui-kit.css imports the design system,
ui-kit.css scans the kit's own views,no leftover ui-kit-theme.css,
app.css does not override the design system font(skipped, with a
reminder to load the font, when the app sets a font of its own there),
nav icons are Heroicons(it lists eachlabel => iconthat doesn't
resolve) andadmin lists paginate with the design system(it names each
published admin component still on plainWithPagination). StubStyleTest: the suite fails when any published view uses a raw palette
class, adark:variant, an inline<svg>or a raw form control instead of
the design system, or a published stylesheet setsaccent-color. It reads
every stub; there is no allowlist.
Changed
- The theme follows the OS until the user picks one. With nothing stored,
the theme store and the no-flash snippet take the initial theme from
prefers-color-scheme(in 0.3 it was always light), and the toggle stores
an explicit choice. Both set exactly one oflight/darkon<html>:
the design system's tokens follow the OS whenever neither class is present,
so a dark-OS user who chose light would otherwise have got dark tokens. - The profile page. The avatar field is a drop zone: the photo shows as a
roundds::avatar(initials when there is none) beside ads::file-upload
labelled "Profile photo", with Save photo, Cancel and Remove under it; the
hover overlay on the old square thumbnail is gone. Account deletion confirms
inds::modal, opened by Alpine state on the form (confirmingDeletion)
instead of theopen-modalwindow event; it stays open with the error shown
after a wrong password and closes with Cancel, the backdrop or Escape. The
two-factor confirm form shows Fortify's "invalid code" message under the
code field rather than below the buttons. - The nine admin screens. Each opens with the page header. Lists are
ds::tablewithds::badgestatuses, ads::empty-staterow when nothing
matches, and the design system's pagination. Filters are selects and a
search field with an icon, and the activity log's filters have visible
labels. The dashboard and the ticket and contact counts are
ds::stat-tiles; flash messages areds::alert. Rows link through a View
(or Open) button in a trailing column, withwire:navigate; the design
system has no whole-row link. In particular:- The ticket list is a table (Subject, From, Status, Priority, Category,
Updated) instead of a list of cards; on a ticket, the Status and Priority
selects share one panel with visible labels. - Contact messages are a table with a select column: each row has a
checkbox labelled "Select" plus the subject for screen readers, the header
has "Select all", and the bulk bar (Mark read, Mark unread, Archive,
Delete) appears when anything is selected. A message opens inds::modal,
driven by the component'sshowModalthrough$wire.entangle(); closing
it with the ✕, the backdrop or Escape callscloseModal()on the server
as the old close button did. - The changelog's Published toggle is
ds::switchbound withwire:model,
saved with the form like every other field, with a line under it saying
so. The old toggle saved nothing on its own either, but looked as if it
did. - The activity log drops its Log column: the log name is a small outline
badge under the event. - Badge tones come from one method per concept on the model:
SupportTicket::statusTone()andpriorityTone(),
ContactSubmission::statusTone(),ChangelogEntry::categoryTone().
- The ticket list is a table (Subject, From, Status, Priority, Category,
- The phone's "More" menu in the admin shell is the design system's bottom
sheet. - The design-system releases behind 1.2.2 fix and add what these screens need:
tone="danger"on ghost and secondary buttons (the avatar's Remove is a
quiet red ghost button), a readonly look fords::input(the
reset-password email looks fixed instead of editable),hideLabelon
ds::checkbox(the contact list's select column), and awire:model
field's id that stays the same from one render to the next, so a live
search keeps focus and keeps what was typed after the first response.
Fixed
- A profile photo never saved on a standard app. The profile module wrote
the file to the public disk and then setavatar_pathwithupdate(),
which a stockUsermodel (whose$fillableis name, email and password)
silently ignores, so the page went straight back to the initials. Remove
had the same bug. Both now useforceFill(). This dates from 0.1; existing
apps need the new profile view. - Dark mode switched off after any
wire:navigatepage change, including
the redirect from the login form to the two-factor challenge: Livewire
copies the next page's<html>attributes over the current one and does not
re-run the head snippet. The theme store now re-applies the theme on every
swap, before paint. Existing apps need the newresources/js/ui-kit.jsand
an asset build. - Every
ds::buttoninside a Livewire component showed a stray>before
its label ("> Sign in", with the>in its accessible name) on
blade-ui 1.1: Livewire placed one of its<!--[if BLOCK]>markers inside
the real button tag. Fixed in blade-ui 1.2.0, which 0.4 requires; the page
tests now fail if a Livewire marker ever lands inside a tag again. - After Save photo or Cancel, the drop zone still listed the file just saved
or discarded. It now resets. - The installer's closing checklist printed the layout tags as
<head>
and the build command asnpm install && npm run dev. It prints
<head>and&&now. ui-kit:installandui-kit:install-moduleno longer fail with
Undefined constant STDINwhen run outside a CLI script, such as through
Artisan::call()in a web request. Without a STDIN they treat the session
as non-interactive.
Removed
resources/css/ui-kit-theme.cssand its@themeblock (thebrand-*
palette,font-boldtext,font-booktext).- The kit's own
@custom-variant dark,[x-cloak]and.safe-area-bottom
rules. The design system'stheme.cssprovides all three. - The
layouts/partials/nav-iconspartial. - The
accent-colorrule for native checkboxes and radios inui-kit.css.
The kit has no native ones left, and the design system's controls paint
themselves. - The profile module's
<x-modal>component
(resources/views/components/modal.blade.php). Nothing in the kit uses it
now; an app that used it in its own views keeps its published copy.
Upgrading from 0.3
The same steps as "0.3 to 0.4" on
shipbytes.dev/docs/laravel-ui-kit/upgrading.
-
Start from a clean working tree (
git statusshows nothing). Step 3
overwrites files your app owns, and step 4 usesgit diffto get your
changes back. -
Require the new minor.
^0.3never picks up 0.4, and-Wlets Composer
addshipbytes/blade-ui:composer require shipbytes/laravel-ui-kit:^0.4 -W
-
Re-run the installer in update mode with
--force, naming every module
ui-kit:list-modulesshows as installed (--modules=allif that is all
seven). A module left out drops out ofinstalled_modules.php artisan ui-kit:list-modules php artisan ui-kit:install --force --modules=admin-middleware,support-tickets,changelog,contacts,profile,impersonation,activity-log
It re-publishes
config/ui-kit.php,config/admin.php, the route files,
every view and layout, the Livewire classes, the module models and
factories,resources/css/ui-kit.cssandresources/js/ui-kit.js, then
re-applies every module's routes, nav entries and middleware swap between
the markers and records the modules again. That replaces the kit's nav
icon names, puts the pagination trait in the admin lists, and deletes the
skeleton's Instrument Sans block fromapp.css. Migrations that already
exist are not published again, and the database is only migrated forward. -
Read
git diffand bring back what was yours: entries you added to
config/admin.phpoutside theui-kit:navmarkers, values you changed in
config/ui-kit.php(brand, copy, features), and edits to views, Livewire
classes or models. Re-apply view edits to the new markup rather than
restoring the old file: the 0.3 markup uses classes that no longer exist. -
Delete the 0.3 theme file and the old icon partial, which nothing uses now:
rm resources/css/ui-kit-theme.css resources/views/layouts/partials/nav-icons.blade.php
-
If you changed tokens in
ui-kit-theme.css, move them into
resources/css/app.css, after theui-kit.cssimport, as design-system
tokens:@import 'tailwindcss'; @import './ui-kit.css'; + +:root { --ds-accent: #0d9488; --ds-accent-hover: #0f766e; } +.dark { --ds-accent: #2dd4bf; --ds-accent-hover: #5eead4; }
-
Rename the icons of your own nav entries to Heroicons v2 names:
grid→squares-2x2,note→document-text,chart→chart-bar,
history→clock(mailstill works;envelopeis its real name).
Until you do, an entry with a 0.3 name makes every admin page fail with
Unable to locate a class or view for component [heroicon-o-…]. The
doctor'snav icons are Heroiconsrow names each one.-['label' => 'Reports', 'route' => 'admin.reports', 'icon' => 'chart'], +['label' => 'Reports', 'route' => 'admin.reports', 'icon' => 'chart-bar'],
-
In your own views, replace
brand-*classes with design-system token
classes such asbg-accentandtext-accent, andfont-boldtextor
font-booktextwithfont-semiboldor nothing. Your own Livewire lists
can useWithDesignSystemPaginationin place ofWithPagination. A layout
of your own that should look like the kit's needs<x-ui-kit::head />and
Inter in its<head>:<link rel="preconnect" href="https://fonts.bunny.net"> <link href="https://fonts.bunny.net/css?family=inter:400,500,600,700&display=swap" rel="stylesheet" />
-
Build the assets:
npm run build
-
Check the result:
php artisan ui-kit:doctor
Every row passes;
mail from address configuredstays a skip until
MAIL_FROM_ADDRESSis set.
Known
- A submit button with
wire:loading.attr="disabled"drops keyboard focus to
<body>while its request runs, because the browser moves focus off a
control that becomes disabled. Keyboard users tab from the top of the page
again after submitting a form. Not fixed in 0.4.0.