Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ui Laravel Package

nuewire/ui

nuewire/ui is a Laravel package that provides a set of reusable Blade UI components, helping you build clean, consistent interfaces faster with minimal markup and sensible defaults.

View on GitHub
Deep Wiki
Context7

Getting Started

Install into a scratch app first, not your main one.

composer require nuewire/ui:1.0.1   # exact pin — see Gotchas
php artisan vendor:publish --provider="Nuewire\Ui\UiServiceProvider"

If the publish command lists tags, capture the output — php artisan vendor:publish with no arguments prints every registered tag, and that list is the fastest way to learn what the package actually ships (config, views, assets, or nothing but a service provider).

Where to look first, in this order:

  1. vendor/nuewire/ui/resources/views/components/ — this is the documentation. With no meaningful README, the Blade files are the contract: read @props([...]) and $attributes handling to learn every prop, every slot, and every default.
  2. vendor/nuewire/ui/composer.json — the real support matrix. Check illuminate/support, php, and whether Livewire is a hard requirement or a suggestion.
  3. vendor/nuewire/ui/config/ (if published) — component prefixes, class overrides, and anything that lets you redirect paths without forking.

First use case. Don't build a feature. Build a throwaway route that renders three components back to back — one form input with a validation error, one button, one navigation/modal element — inside a minimal <x-app-layout>-style shell. That single page exercises the two things that actually break: Tailwind class resolution and Livewire/Alpine wiring. If styles render and a modal opens and closes, integration is done.

Then check the Tailwind side, which is the only genuinely non-obvious step:

// tailwind.config.js
content: [
  './resources/**/*.blade.php',
  './vendor/nuewire/ui/resources/views/**/*.blade.php', // add this
],

If the package ships precompiled CSS instead, look for a @nuewireUiStyles-style Blade directive or a publishable dist/*.css and import it from resources/css/app.css. Determine which of the two models applies before writing any markup — guessing wrong produces unstyled components that look like broken markup.

Implementation Patterns

Pattern 1: consume from vendor, wrap locally. The single most valuable habit with an undocumented, low-bus-factor component library. Never call package components directly from feature views. Instead create thin anonymous components in resources/views/components/ui/ that own your defaults:

{{-- resources/views/components/ui/input.blade.php --}}
@props(['label' => null, 'hint' => null])

<x-nuewire::input {{ $attributes->merge(['class' => 'text-sm']) }} />
@if ($hint) <p class="mt-1 text-xs text-gray-500">{{ $hint }}</p> @endif

Feature code then says <x-ui.input wire:model="email" />. When the upstream prop signature shifts in a 1.x minor, you edit one file per component instead of grepping every view. This is the difference between a two-hour upgrade and a two-day one.

Pattern 2: pick publish-and-own or vendor-and-pin, and write the decision down. These are materially different ownership models:

  • Vendor — composer require, wrap as above, pin exactly, accept that a breaking upstream release forces a coordinated upgrade.
  • Publish — vendor:publish --tag=views, move components into resources/views/components/, drop the runtime dependency. Zero upstream risk, but you now maintain a design system. Good fit if you expect heavy customisation; bad fit if you wanted upstream fixes.

Hybrid is the common failure: publish the views and keep the package installed, then get confused about which copy renders. Publishing wins on path collision, so stale published views silently shadow fixes.

Pattern 3: Livewire pass-through. Package form components are almost certainly plain Blade that merge $attributes, which means wire:model, wire:blur, and wire:dirty pass through for free:

<x-ui.input wire:model.live.debounce.500ms="search" />

Validate this assumption on day one. If the component hardcodes attributes or drops $attributes in the wrong place, Livewire binding breaks and the fix is to fork that one view locally rather than abandon the component.

Pattern 4: theme through Tailwind, not through the package. If the package uses semantic classes (bg-primary, text-muted) rather than raw palette names, align your tailwind.config.js theme tokens to it and you get app-wide restyling with no view edits. If it hardcodes bg-indigo-600, your only lever is a wrapper class plus !important — which is a signal to consider publishing the views.

Pattern 5: compose layout from the package's nav + your routes. Navigation components usually take an items array or a slot. Generate the items from a single config or Route::currentRouteName()-based helper rather than hardcoding them per view — the nav becomes the one place a new section is registered.

Integration tip: smoke-test the component surface. One Blade render test per component you actually consume:

public function test_ui_input_renders(): void
{
    $this->blade('<x-ui.input name="email" />')->assertSee('email');
}

Ten of these cost an hour and catch the silent-prop-rename failure mode that plagues undocumented 1.x libraries. Run them in CI alongside the asset build.

Gotchas and Tips

Tailwind purge in production only. The classic failure: styles look fine in npm run dev, and in production every package component loses its classes. The vendor glob is missing from content, or the CSS build runs before composer install --no-dev in the deploy pipeline so vendor/nuewire/ui doesn't exist yet when Tailwind scans. Order the pipeline composer install → npm ci → npm run build.

Pin exactly, not with a caret. "nuewire/ui": "1.0.1". The version history here is 0.0.1 → 1.0.1 with a one-line changelog; there is no observable release discipline yet. A caret constraint hands upgrade authority to a maintainer whose process you can't inspect. Relax to ^1 only after you've watched two or three subsequent tags and confirmed the component API survives them.

Read @props before trusting any example. With no README, every prop name in your head is a guess. Ten seconds in the Blade source beats an hour debugging a slot that never renders because it's actually called title and not header.

$attributes->merge() ordering bugs. If your wrapper sets class after the package component's own merge, your classes win — sometimes desirable, sometimes it wipes intent. If it's before, they lose. Establish one convention across all wrappers and comment it, or you'll get inconsistent overrides that look like random Tailwind behaviour.

Slot vs prop ambiguity. Undocumented components frequently accept content both ways. slot content is escaped/unmanaged differently from a prop string — notably, passing HTML through a prop gets escaped. If a component renders literal <strong> tags on screen, that's the cause, and you need the slot form.

Livewire wire:key on lists. Any package component that renders a repeating structure inside @foreach needs a stable wire:key on the wrapper or Livewire's DOM diffing will corrupt state on reorder. This is generic Livewire advice, but package components that hide their internal markup make it easy to forget.

Alpine collision. If the package ships JS (modal, dropdown, tabs) it very likely uses Alpine. Two Alpine instances or a duplicate x-data name silently breaks interactivity with no console error. Check whether the package bundles Alpine or expects yours; if it bundles it, disable the package's copy and use the app's single instance. Confirm by inspecting window.Alpine.version and looking for a double-registered component warning.

Debugging checklist, in order: php artisan view:clear (stale compiled component views after a publish are the #1 phantom bug) → php artisan vendor:publish with no args to confirm tags → grep -r "@props" vendor/nuewire/ui/resources/views to confirm the actual API → composer why-not nuewire/ui 1.0.1 if install or upgrade misbehaves.

Extension points worth knowing. Blade::componentNamespace('Nuewire\Ui\View\Components', 'nuewire') in a service provider lets you register your own classes under the same prefix, so you can replace a single component with a subclass without touching the others. Pair that with published views (vendor:publish --tag=... then edit) as the escape hatch when a component is 90% right.

Bus factor. Solo namespace, zero stars, one-line release notes. Do not put this on a customer-facing critical path without either published views (you own it) or a written fork procedure (you can take it). Budget an internal owner for the UI layer regardless — with a shared component library, that role exists whether or not you name it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo