Skip to main content

WireKit v2.0.0

Major release

Major release. First publicly-cut tag after v1.6.3, aggregating every change since. Two breaking changes (both in ### Changed): custom Pushery\WireKit\Contracts\ChartAdapter implementations must add three new methods to satisfy the expanded interface, AND <x-wirekit::container> inline-padding tiers now read from the --padding-wk-x-* token family instead of --space-wk-* so a container nested in <x-wirekit::main> inherits the same content-edge spine. Developers using only the built-in ChartJsAdapter or the new ApexChartsAdapter, and developers using <x-wirekit::container> with default padding values, see no behavioral change beyond a 0.5-rem horizontal alignment correction. Every other change is additive and back-compatible.

Added

  • Optional ApexCharts chart adapter alongside the existing Chart.js adapter. Switch with one line in config/wirekit.php: 'charts' => ['library' => 'apexcharts']. Same <x-wirekit::chart> Blade tag for both libraries; zero breaking change. ApexCharts unlocks 9 chart types Chart.js does not ship natively — candlestick, boxplot, range-bar, range-area, heatmap, treemap, funnel, radial-bar, sparkline. Dedicated dist/wirekit-apex.js adapter bundle (~2 KB gzip glue, no ApexCharts library code; the developer installs apexcharts via npm). Note: ApexCharts is not MIT-licensed — the free Community License covers organizations under $2M USD annual revenue; Commercial License required above. WireKit ships only the adapter glue (MIT). See docs/components/chart.md#license-apexcharts-only for the full terms.
  • <x-wirekit::sparkline> — NEW first-class component. Inline trend sparkline (axis-less line chart) for KPI strips and dashboard cells. Six props (data / trend / inline / height / scope). Auto-detects trend from first-vs-last data and tints green / red / muted accordingly; manual trend="up|down|neutral" override available. Inline mode renders at surrounding text height (1.25em / 4rem width); block mode at configurable height (default 2.5rem). Delegates to <x-wirekit::chart type="sparkline"> so both adapters render correctly — ApexCharts uses native sparkline mode, Chart.js falls back to a plain line.
  • <x-wirekit::chart-mixed> — NEW component for multi-axis dashboards. Each dataset declares its own type (line / bar / column / area) plus an optional yAxisID for multi-axis configurations. Both adapters consume the per-dataset type field natively — Chart.js via the per-dataset type field, ApexCharts via series[].type.
  • wireStream prop on <x-wirekit::chart> for real-time data updates. Subscribe a chart to a Livewire-emitted event and append each fired payload via the library's imperative API (chart.update('none') for Chart.js / chart.appendData() for ApexCharts). wireStreamMode="strict" (default) FIFO-trims at wireStreamCap points (default 100); wireStreamMode="stream" grows unbounded.
  • annotations prop on <x-wirekit::chart> for vertical lines / horizontal regions / point callouts. ApexCharts has annotations built-in; Chart.js requires chartjs-plugin-annotation (the Alpine factory emits a console.warn when annotations are supplied but the plugin is missing — graceful degradation).
  • Smooth dark-mode preset transitions on chart re-theming (~250 ms ease-out). Both adapters interpolate colors during .dark toggle instead of snapping. Collapsed to instant under prefers-reduced-motion: reduce.
  • Two new chart-system docs subhierarchies on docs.wirekit.app: /components/charts-chartjs/ (full Chart.js demo set — bar / line / area / pie-doughnut / scatter-bubble / radar-polar / advanced / theming) and /components/charts-apex/ (full ApexCharts demo set — line / area / bar / column / range-bar / pie-donut / radial-bar / radar / scatter-bubble / heatmap / treemap / candlestick / boxplot / funnel / timeline / sparklines / annotations / streaming / mixed / motion / theming). Every page ships realistic seed data drawn from B2B SaaS, e-commerce, DevOps, finance, marketing domains.
  • wirekit:install --apex-license=community|commercial|oem flag. Records the developer's license tier into config/wirekit.php charts.apex_license after printing the License Notice once at install time. Suppresses the wirekit:doctor reminder for commercial and oem tiers.
  • wirekit:doctor ApexCharts checks. Detects apexcharts npm package presence, validates the active license tier, confirms dist/wirekit-apex.js is published.
  • wirekit-apex.js registered as publishable under both the wirekit-scripts and wirekit-assets tags. Running php artisan vendor:publish --tag=wirekit-assets now copies the adapter glue to public/vendor/wirekit/wirekit-apex.js alongside the other JS bundles. The route fallback at /wirekit/wirekit-apex.js also works for setups that prefer route-based serving over publishing. Eliminates the manual cp vendor/.../dist/wirekit-apex.js public/vendor/wirekit/ step that ApexCharts adopters previously had to run after every composer update.
  • <x-wirekit::reading-toc> — NEW primitive in the reading family. Horizontal sticky-strip TOC sibling to reading-spine. Same auto-build-from-headings + IntersectionObserver active-section model, different rendered shape (a flat row of links across the top or bottom of the article container). Use case: marketing landing pages with 3-4 anchored sections (Hero, Features, Pricing, FAQ) where a vertical sidebar feels excessive. Seven props (target, levels, position, offset, hideBelow, flush, scope). Defaults to levels="2" for landing-page flat structure; mobile-hidden via hideBelow="sm" since narrow viewports cannot host a horizontal strip without overflow. The flush prop zeroes the first link's left-edge padding and the last link's right-edge padding so the visible text aligns flush with the strip's content edges (use when the TOC sits directly under <x-wirekit::brand-bar> or <x-wirekit::main> and the developer wants the first link on the same vertical content-edge spine as the surrounding brand text and h2 headings). Real <a href="#section-id"> links inside a <nav aria-label="Page sections"> landmark — keyboard-navigable + screen-reader native. prefers-reduced-motion: reduce collapses smooth-scroll to instant. Reuses spine's --reading-spine-color-idle / -active for theme consistency; adds 5 layout-specific tokens (--reading-toc-bg / -padding-y / -padding-x / -gap / -link-max-width) plus 2 color aliases.
  • <x-wirekit::brand-bar> — NEW navigation primitive. Page-chrome wrapper for the canonical "logo + tagline + actions" header pattern. Three named slots: brand (typically a <x-wirekit::brand> primitive), tagline (secondary muted text), actions (right-anchored sign-in / theme-toggle / account-widget content via margin-left: auto). Props: as (header | nav), divider (bottom | none), padding (none/sm/md/lg/xl), sticky (pins to top: 0 during scroll with an opaque background fallback). Carries the content-edge spine via padding="lg" reading from --padding-wk-x-lg, so the brand visible-text aligns with <x-wirekit::main padding="lg">, <x-wirekit::reading-toc flush>, and the article h2 headings below on the same vertical X-coordinate — out of the box, no custom CSS.
  • <x-wirekit::prose :density> — NEW prop on the existing component. comfortable (default) keeps the long-form-article heading scale (h2 mt = 2.5 rem for generous section breaks, h1 = 1.875 rem). compact tightens for marketing pages (h2 mt = 0.75 rem, h1 one type-scale tier smaller, p mb = 0.5 rem). Eliminates the need to override prose typography with developer-side .my-section h2 { margin: ... } rules when the prose lives inside a tight marketing layout. Default comfortable keeps backward-compatible rendering.
  • <x-wirekit::reading-shell :toc="true"> — opt-in toc toggle. Defaults to false in every density preset (comfortable / compact / minimal). Marketing landing pages explicitly opt in via :toc="true" :spine="false"; blog posts and docs pages keep the spine sidebar.
  • Marketing Landing TOC recipe at /recipes/marketing-landing-toc — sibling to long-form-article. Demonstrates the canonical Hero / Features / Pricing / FAQ landing-page pattern with the new sticky TOC strip, plus the offset prop pattern for layouts with a fixed nav above the strip.
  • Long-form Article recipe at /recipes/long-form-article — canonical Medium / Substack-style article layout: reading-progress bar at the top, reading-spine sidebar on the right, reading-bookmark resume pill, reading-meta time-to-read. Demonstrates the full reading-* family in one composition, both via the <x-wirekit::reading-shell> sugar wrapper and via direct primitive composition for power-user customization.
  • Documentation Reader recipe at /recipes/documentation-reader — documentation-style article shell with reading-progress bar, dense-section reading-spine, fixed-nav offset on the TOC strip, reading-bookmark across multi-page-session reads. Shows the docs-rhythm pattern (heading-scale + dense per-paragraph code blocks) alongside the same reading-* primitives.
  • <x-wirekit::reading-minimap> — NEW primitive in the reading family. Every-item density overview of a scrollable container, with two rendering modes:
    • mode="stripes" (default) — every item matched by itemSelector renders as a 1–2 px stripe at proportional vertical position. itemStyle="block" upgrades to per-paragraph rectangles whose height tracks the source item's natural height (skeleton-style content texture).
    • mode="rendered" — code-editor-style abstract content canvas. Walks every text-bearing node via TreeWalker, gets per-rendered-line rects via Range.getClientRects(), draws each as a rectangle on a DPR-aware canvas. Per-element-type color palette (h1–h6 each its own alpha tier, code indigo, table rose, blockquote slate-bolder, image amber, WireKit wk-* components emerald, prose / default slate-muted). 13 --reading-minimap-color-{h1..h6,code,table,blockquote,prose,wirekit,image,default} tokens for full re-theming without JS.
    • Translucent viewport-overlay rectangle tracks the host's visible region; click stripe → smooth-scroll target so item is centered (instant under prefers-reduced-motion: reduce); drag overlay → pan host scroll position with browser-scrollbar-matched translation; hover stripe (non-touch) → tooltip following the cursor with the item label.
    • Two canonical use cases: long-form article density-overview (sibling to reading-spine) and sidebar navigation density-overview.
    • 5000-tag silent fallback to stripe mode on very long articles. No DOM clone in rendered mode → no parse step → no surface for HTML-injection vectors.
  • <x-wirekit::reading-meta perParagraph> — Medium-style inline annotations. Opt-in mode that injects small <span class="wk-reading-meta-paragraph">N min</span> annotations immediately before each <p> in the target with at least paragraphMinWords words (default 30). Annotations show estimated remaining-time FROM that paragraph onward, re-computed on scroll. aria-hidden="true" on every annotation — canonical SR text remains the total/remaining display. Default off; opt-in.
  • <x-wirekit::reading-progress variant="auto"> — theme-reactive fill mode. Falls back to currentColor when the developer hasn't set --reading-progress-fill — useful for embedded contexts (iframes, browser extensions) where the bar should match the surrounding text color. Joins the canonical 6-value variant set (primary | neutral | success | warning | danger | info).
  • <x-wirekit::reading-shell density> preset prop. Three values (comfortable | compact | minimal) adjust the shell's per-primitive defaults: progress-bar height, spine expand mode, which primitives render by default. Per-primitive toggles (:spine="false" etc.) win over the density preset.
  • 14 new design tokens for the reading- family*: 1 on reading-progress (--reading-progress-fill), 7 on the new reading-minimap (width, stripe-height, stripe-gap, color-idle, color-active, viewport-bg, viewport-border), 2 on reading-meta perParagraph mode (paragraph-color, paragraph-spacing). All themeable in :root {}.
  • <x-wirekit::stat> composes animate (counter count-up) with animateIn (entrance reveal). The Blade template emits an outer wrapper that carries the entrance reveal while the inner element keeps the counter handler — the two scopes layer cleanly. Single-flag usages render byte-identical.
  • <x-wirekit::cta> and <x-wirekit::footer> accept the animateIn prop. Both marketing primitives now match the existing animateIn surface on <x-wirekit::card>, <x-wirekit::feature>, <x-wirekit::hero>, and others. Passing animateIn="slide-up" (or any of the 11 base presets) wires <x-wirekit::reveal> semantics inline without an extra wrapper element. Honors prefers-reduced-motion: reduce.
  • stagger prop on <x-wirekit::feature-grid> and <x-wirekit::stats>. When set on the wrapper and an entrance preset is configured on the children, each child's animation fires with an incremental delay — produces a clean cascade instead of every card landing at once. Boolean form uses a 75ms step (stagger); integer form overrides for custom rhythm (:stagger="125"). Pure CSS via :nth-child rules with an index cap at 8 to bound delay on long lists; collapses to 0 under reduced motion. Zero JS bundle impact.
  • delay prop on <x-wirekit::reveal>. Holds the entrance for a beat before it begins — useful for sequencing cards or letting a hero-section heading land before the supporting copy follows. Accepts five named tokens (none, sm, md, lg, xl) mapping to themeable CSS variables, or a raw integer in milliseconds for one-offs. Composed via inline animation-delay on the existing wk-animate-{preset} class — no JS plugin change needed. Collapses to 0ms under prefers-reduced-motion: reduce.
  • Five new motion-delay tokens in dist/wirekit.css: --motion-wk-delay-none (0ms), --motion-wk-delay-sm (75ms), --motion-wk-delay-md (150ms), --motion-wk-delay-lg (300ms), --motion-wk-delay-xl (500ms). All developer-overridable in :root {}.
  • CSS class .wk-stagger plus eight :nth-child rules and a cap-at-8 index ceiling. Drives the stagger prop on feature-grid and stats. Reduced-motion override zeroes per-child delays inside the existing @media (prefers-reduced-motion: reduce) block.
  • wirekit:doctor thirteenth check — :root vs .dark color-token symmetry. The doctor now reads the developer's resources/css/app.css, extracts the :root {} and .dark {} blocks, and emits a warning when --color-wk-* tokens are declared in one block but missing from the other. Asymmetric color tokens produce theme drift the developer sees as "looks wrong in dark mode" without an obvious cause.
  • <x-wirekit::reading-progress> — viewport-pinned reading-progress indicator for long-form articles. Bar (default) or dot (indicator="dot") variants; both fill 0 → 100% on scroll using compositor-only properties (transform: scaleX / stroke-dasharray). Five variant colors, three height tokens (sm/2px, md/3px, lg/5px), showAfter scroll threshold, target= selector, segments chapter markers, milestones events (wirekit:reading-progress:milestone Alpine dispatch fired ONCE per session at 25 / 50 / 75 / 100% boundaries). role="progressbar" + dynamic aria-valuenow. Zero-KB bundle impact.
  • <x-wirekit::reading-spine> — sidebar mini-TOC that auto-builds from page headings. Pins to the right edge at md+ breakpoints; tracks scroll position via IntersectionObserver; expands on hover or focus. Configurable target=, levels=, position=, expand= (hover / focus / always / always-md), offset=. Real anchor links so navigation works without JS. Five opt-in extensions: numbered, fillSections, backToTop, expand="always-md", and a wirekit:reading-spine:section-changed event. Filter slot composition pattern. Bundle impact: ~600 bytes gzip.
  • <x-wirekit::reading-bookmark> — persists scroll position to localStorage while reading; surfaces a "Resume reading where you left off?" pill on return-visit when conditions are met (previous-session dwell time ≥ minDwellSeconds, scroll moved past threshold * scrollHeight). Cross-tab consistency via storage event. try/catch wrapping every storage op — silently degrades on private-browsing / quota-exceeded. Required key prop (typically "article-{slug}").
  • <x-wirekit::reading-meta> — small text element showing ~12 min read (initial estimate) and optionally ~5 min remaining (live-tracking on scroll). Skips non-prose nodes (pre, code, figure, figcaption, img, picture, svg, [data-language]). CJK-aware: when more than 40% of text is CJK ideographs, falls back to character-based estimation with a configurable cjkCharsPerMinute baseline (default 500). wpm clamps to ≥ 50; totalMinutes floors to 1. role="status" aria-live="polite".
  • <x-wirekit::reading-shell> — composition wrapper that renders <x-wirekit::reading-progress> + <x-wirekit::reading-spine> + <x-wirekit::reading-bookmark> + <x-wirekit::reading-minimap> + <x-wirekit::reading-meta> around the slot content in one tag. Mirrors the <x-wirekit::app-shell> "one tag, full UX" pattern. Per-component opt-out via :progress="false" etc. Forwards every documented child prop via flat surface.
  • CSS variable tokens for the reading- family in dist/wirekit.css:* three height tokens for the bar (--reading-progress-height-{sm,md,lg}), the dot diameter (--reading-progress-dot-size), seven spine layout / color tokens, three bookmark pill tokens, two reading-meta tokens.
  • @media print { display: none !important } rule for every reading-* primitive — only the article body prints, not the reading chrome.
  • prefers-reduced-motion: reduce gating for the entire reading- family* in the global @media (prefers-reduced-motion: reduce) block.
  • <x-wirekit::replay-button> — NEW companion primitive. Renders an icon-button that walks the closest [data-replay-target] ancestor and re-mounts it (Alpine.initTree) so its x-data="wirekitAnimate(...)" / counter / chart-motion fires again. Standardizes the "re-play this animation" affordance every animation-capable component carries via the data-replayable="true" contract — developers can place the button explicitly anywhere alongside a primitive, or rely on docs.wirekit.app's preview chrome auto-injecting it. Two props: label (button aria-label, default "Replay"), scope (named personalization scope).
  • replayable prop on <x-wirekit-chart>. Opt INTO the docs.wirekit.app ↻ Replay button surface by emitting data-replayable="true" on the chart root. Set it explicitly when the entrance animation is worth re-watching (bar-grow / line-trace / slice-sweep on /components/charts-apex/motion), or rely on the auto-detect path: whenever wireStream is bound (every streaming chart on /components/charts-apex/streaming), the attribute is emitted automatically. Back-compat preserved: callers who already passed data-replayable raw via the attribute bag continue to work — the Blade view skips its own emission to avoid duplication.

Changed

  • Pushery\WireKit\Contracts\ChartAdapter interface expanded from 4 → 7 methods. Net-new: name() / rendersTo() / supportedTypes(). Existing scripts() / normalizeData() / defaultOptions() / alpineComponent() unchanged. Developers using only built-in adapters see no impact (both ChartJsAdapter and ApexChartsAdapter ship the new methods). Custom adapter implementations need to add the three new methods to satisfy the interface. BREAKING for developers with a hand-written ChartAdapter implementation.
  • <x-wirekit::container> inline-padding moved from --space-wk-* to --padding-wk-x-*. padding="sm|md|lg|xl" now reads from the --padding-wk-x-* content-edge spine instead of the --space-wk-* block-rhythm scale. Resolves a silent 0.5 rem horizontal drift when nesting <x-wirekit::container padding="lg"> inside <x-wirekit::main padding="lg"> — both now share the same content-edge X-coordinate. Developers who depended on the wider previous value (e.g. padding="lg" was 1.5 rem, now 1 rem) should bump to padding="xl" (also 1.5 rem) for unchanged visual output. BREAKING for developers relying on the exact pixel value of container's horizontal padding.
  • <x-wirekit::sidebar> inline-padding fixed. Was applying --padding-wk-y-sm (the y-axis token) on all four edges; now correctly splits into px-[var(--padding-wk-x-sm)] py-[var(--padding-wk-y-sm)] and moves the inter-item gap to --space-wk-sm (the canonical gap token). Sidebar items at the inboard edge now align with <x-wirekit::header> and <x-wirekit::main> rendered alongside on the same vertical content-edge spine. Back-compat: visual change is a few-pixel adjustment to the sidebar's internal padding; no API change.
  • Color-prop unification across <x-wirekit::message>, <x-wirekit::alert>, <x-wirekit::callout>, and <x-wirekit::progress>. Every component that exposes a color prop now accepts the same canonical six-value set (primary, neutral, success, warning, danger, info). progress adopts primary as the canonical name; the historical accent value continues to work as a back-compat alias. New Variants & Intents page documents the canonical set, the per-component prop tables, and the visual-synonym semantics in one place.
  • Bundle size: dist/wirekit.js grew from 25 → 26 KB gzip (83 → 86 KB raw) covering the new reading-* family and chart-adapter expansion. Stays within the ±2 KB drift budget per docs/dependencies.md. Core bundle (chart-only) unchanged at ~2 KB gzip / 11 KB raw. ESM bundle ~25 KB gzip / 82 KB raw.
  • .wk-reading-toc__list inline-padding ships without !important. Developers running a typography prose-wrapper (e.g. a @tailwindcss/typography body or any body.prose-style class) should carve out [class*="wk-"] from their ul/ol/li rules — same pattern they already use for the max-width: 75ch typography clamp. Without the carve-out the padding-left: 1.75rem in a typical prose stylesheet wins on specificity over .wk-reading-toc__list { padding-inline: 0.25rem } and pushes WireKit list-based components (reading-toc, list, breadcrumb) off the content-edge spine. Recommended typography rule shape: .prose ul:not([class*="wk-"]), .prose ol:not([class*="wk-"]) { padding-left: 1.75rem }.

Documentation

  • docs/integration.md — new "Performance — Conditional Asset Loading" section documenting a server-side flag pattern for emitting highlight.js and Chart.js <script> tags only on pages that actually use <x-wirekit::code-block> or <x-wirekit::chart>. Saves ~95 KB gzip on lightweight routes (landing pages, theming guide, recipes without code/charts) without breaking caching or first-paint correctness. Pattern is documentation-only; no helper class shipped — adapt the str_contains() detection to your DocsParser / class-naming conventions.
  • /theming/design-tokens — NEW comprehensive reference page for every WireKit CSS variable: colors, typography, motion, sizing, component-specific tokens, and the chart-theming palette. Single landing page where developers can find any token by name before reaching for its component's docs page.
  • /getting-started/livewire-starter-kit — NEW recipe page for fitting WireKit into an existing Livewire Starter Kit project. Walks the four touchpoints where Starter-Kit defaults differ from a clean-room wirekit:install (theme preset, font stack, dark-mode flip, sidebar conflict resolution) so existing Starter-Kit developers don't have to discover them ad-hoc.