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

Plain Ui Components Laravel Package

lemonsqueezy/plain-ui-components

Plain UI Components is a Laravel Blade component library from Lemon Squeezy for building clean, consistent interfaces fast. Drop reusable, customizable UI pieces into your views, with sensible defaults for forms, buttons, and admin screens. Easy to adapt to your own design system.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Blade component library, so treat onboarding as three steps: install, publish, and inventory.

composer require lemonsqueezy/plain-ui-components
php artisan vendor:publish --provider="LemonSqueezy\PlainUiComponents\PlainUiComponentsServiceProvider"

Run the publish command with --tag variants if the provider exposes several (typically plain-ui-components-config, -views, -assets). Publishing views is the single most important step — with 24 stars and zero dependents, the package's source is its documentation, and you will end up reading the Blade files more than any README.

Where to look first, in order:

  1. vendor/lemonsqueezy/plain-ui-components/src/View/Components/ — this directory is the authoritative component list. Each class's render() tells you the view name and therefore the tag (Button → <x-plain-button> or <x-plain::button> depending on the namespace registered in the service provider).
  2. vendor/.../resources/views/components/ — the props are declared in @props([...]) at the top of each file. That array is your API reference.
  3. config/plain-ui-components.php after publishing — prefix, theme/token settings, and any asset registration live here.
  4. composer.json require block — confirm whether it expects Tailwind, Alpine, or ships standalone CSS. This determines your build setup more than anything else.

The first real use case to target is a low-risk internal screen, not your marketing homepage: a settings page or an admin resource with a form, a table, and a couple of modals. That exercises inputs, validation state, buttons, and overlays — the four areas where a component library either fits your app or doesn't — and it fails loudly in a place where you can iterate.

Implementation Patterns

Wrap, don't scatter. Create resources/views/components/ui/* wrappers that proxy to the package components and hard-code your conventions (size, colour, spacing, icon slot). Call sites then use <x-ui.button> and you retain a one-file escape hatch if the package changes or you swap it out. Given the project's maturity, this layer is cheap insurance.

Form binding. If inputs expose name/id props, prefer binding them to a model or old() rather than passing raw values:

<x-plain-input name="email" :value="old('email', $user->email)" />

Check whether the component forwards $attributes to the underlying <input> — if it does, wire:model, x-model, and required all pass through for free. If it doesn't, wrap it and spread $attributes yourself rather than patching vendor files.

Livewire / Inertia. For Livewire, the package's value is entirely in whether $attributes reaches the root element (wire:model.live, wire:loading.attr). Test one input and one button before committing. For Inertia/Vue, use the components only in your Blade root layout and error pages — don't try to reimplement them in JS.

Theming via tokens. Look for CSS custom properties in the published stylesheet (--plain-* or similar). Redefine them in your app's CSS entry point rather than overriding individual component classes; class names are the least stable part of a small package.

Build a demo route. A local-only route rendering every component with every variant is worth the 30 minutes. With no dependents and no docs site, it's the only reliable way to see a breaking change after composer update.

Layout composition. Use a package layout (if one ships) as the base for auth screens and error pages, and your own layout for the app shell. Mixing two layout systems is where these libraries usually get painful.

Gotchas and Tips

  • Tailwind content scanning. If the package ships Tailwind classes rather than compiled CSS, add './vendor/lemonsqueezy/plain-ui-components/resources/views/**/*.blade.php' to tailwind.config.js content. Skipping this produces components that render correctly in local (where a full build exists) and lose all styling in production — the classic version of this bug.
  • Publish vs. reference. Publish views only when you must customise them, and record every edit. Published views freeze at the installed version and silently stop receiving upstream fixes; after each composer update, diff vendor/ against your published copy.
  • Pin the version. With one release in the wild and no dependents, treat minor bumps as potentially breaking. "lemonsqueezy/plain-ui-components": "~1.0.0" (or an exact constraint) plus a read of the changelog beats a surprise refactor.
  • View cache after publishing. php artisan view:clear when newly published or newly registered components return "Unable to locate a class or view". Anonymous components are resolved at compile time from the component namespace, so a stale cache is the usual culprit.
  • Attribute merging. Inspect $attributes->merge([...]) in each component. If the component hard-merges a class after your class attribute, your overrides lose; pass conditional classes through a dedicated prop instead of fighting specificity.
  • Alpine dependencies. If any overlay/dropdown component uses x-data, confirm Alpine is loaded once and that you're not double-registering plugins (@livewireScripts + a manual CDN tag is a common conflict).
  • Extension points. The realistic ones are: your wrapper layer, CSS custom properties, and the published views. Avoid subclassing the component classes — the constructor signatures are the least documented and most likely to shift.
  • Debugging. When a component renders empty, dd($component->data()) inside a wrapper, or add {{ $slot }} temporarily to the published view. Blade swallows slot errors quietly.
  • License is MIT, support is not. You can fork and patch freely, but budget for reading source when something misbehaves; there is no community Stack Overflow corpus for a package this size. Keep a short docs/ui-components.md in your repo listing which components you actually use and where — it's the cheapest hedge against the package being abandoned.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core