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

Tall Mobile Laravel Package

johntrickett86/tall-mobile

johntrickett86/tall-mobile is a Laravel package aimed at the TALL stack (Tailwind, Alpine, Livewire), adding mobile-oriented tooling for building responsive, mobile-first interfaces. Early-stage with a small following, it may suit developers exploring Livewire-driven mobile UIs.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what you're adopting. tall-mobile is a preset, not a runtime library. You run it once against a Laravel app and it scaffolds Blade layouts, Livewire components, Alpine wiring, and a Tailwind config. After that, the code lives in your repo. That distinction drives every decision below — you are not integrating a dependency you'll call at runtime, you're adopting a starter skeleton you will then own and edit.

Prerequisites (non-negotiable, because presets assume them):

  • Laravel with Livewire installed and booting (php artisan livewire:about or composer show livewire/livewire).
  • Node + a working Vite/Tailwind pipeline (npm run dev succeeds on the bare app before you install).
  • A clean git working tree. Presets overwrite files; you want a diff you can git checkout.

Install:

composer require johntrickett86/tall-mobile --dev   # preset = dev dependency; it's scaffolding, not runtime
php artisan list | grep -i tall                    # confirm the installer signature the package registers

The exact command name (tall-mobile:install, ui tall-mobile, etc.) is the first thing to verify — it's registered by the package's service provider and is the single source of truth for what gets published. Do not guess it from the README; confirm it against the installed package.

Where to look first, in this order:

  1. php artisan vendor:publish --provider="JohnTrickett86\TallMobile\...ServiceProvider" — enumerate the publish groups and tags before publishing. This tells you exactly which files the preset will drop where.
  2. vendor/johntrickett86/tall-mobile/src/ — the command class. Read its handle(): it lists the stub-to-destination mapping. That's your real documentation.
  3. vendor/johntrickett86/tall-mobile/resources/views/ — the actual Blade components. Post-v1.0.1, modals live under a components directory; that's the path you care about.
  4. stubs/ and the Tailwind config stub — what your tailwind.config.js will look like after install.

First use case — prove the round trip in 10 minutes:

git checkout -b try-tall-mobile
php artisan <preset-command>
npm install && npm run dev
php artisan serve

Then confirm two things on the rendered page: (a) the layout renders and Tailwind classes are present (inspect an element, don't just eyeball spacing), and (b) the modal component resolves — drop <x-modal> / <x-...modal> into a page and check the browser console for Alpine errors. If Alpine is silent and the modal toggles, the preset is wired correctly. Commit that green state before you customise anything.


Implementation Patterns

The core pattern: run once, then detach. Because this is scaffolding, the healthiest end state is that the package is not in your require after generation — or at least pinned and treated as read-only reference. Commit the generated files, then decide whether the dependency stays. If it does, pin it ("johntrickett86/tall-mobile": "1.0.1" exactly) since the repo is archived and no future version will fix anything for you.

Own the views, not the tag. Publish the Blade components into resources/views/components/ and use app-level tags. This is the difference between a swappable primitive and a lock-in:

{{-- resources/views/components/app-modal.blade.php - your façade --}}
<x-dialog {{ $attributes }}>
    {{ $slot }}
</x-dialog>

Every feature uses <x-app-modal>. If you later replace the preset's markup, fork the file or swap the inner tag — product code never changes. For a 1-star archived package, this wrapper is the whole risk mitigation story.

Modals over Livewire — the day-to-day workflow. The common shape is a Livewire component whose open/close state is a public boolean, with Alpine handling the animation and the server owning validation:

class InviteUser extends Component
{
    public bool $show = false;
    public string $email = '';

    #[On('open-invite-modal')]
    public function open(): void { $this->resetValidation(); $this->show = true; }

    public function save(): void
    {
        $this->validate(['email' => 'required|email']);
        // ...
        $this->show = false;
        $this->dispatch('modal-closed');
    }
}

Dispatch from Blade with $dispatch('open-invite-modal') (Alpine) or wire:click on a Livewire parent. Keep the modal component mounted at the layout level and toggle visibility rather than conditionally rendering it if the package's Alpine transitions rely on the element existing — check the component's x-show/x-transition setup to know which. If it's x-show, mount-always is required; if x-if, it isn't. This one detail causes most "modal flashes/doesn't animate" reports.

Stacking and z-index. Register a single modal root near the end of <body> (in your layout), not inline in each page. Nested modals inside Livewire components that get re-rendered will lose Alpine state and can leave a backdrop orphaned over the page.

Tailwind content paths. If you keep the package as a dependency and don't publish its views, you must add its Blade path to content or every class the preset's components use gets purged in production:

content: [
  './resources/**/*.blade.php',
  './vendor/johntrickett86/tall-mobile/resources/views/**/*.blade.php',
],

Publishing the views sidesteps this entirely and is the better default.

Mobile-first as a working convention, not a slogan. Base classes are the phone layout; add sm:/md: upward. When you extend a package component, keep that direction — if you find yourself writing max-md: overrides, you're fighting the preset's mental model and will fight it again at every breakpoint.

Integration tip for existing apps. Don't run a preset over a live app's resources/views. Install into a throwaway Laravel app of the same major version, then copy in only the pieces you want (the modal component, the layout shell, the Tailwind config fragment). You keep the useful parts and skip the overwrites.


Gotchas and Tips

This package is archived. Treat it as a snapshot, not a dependency. Packagist serves it, Composer installs it, and nothing will ever be patched — no security fixes, no Livewire 4 compatibility, no Tailwind 4 support. Pin the exact version, and if you keep it in require, add it to your dependency-review list. The clean long-term move is: generate once, then delete the dependency and own the files.

v1.0.1's modal move is a silent-override trap. The release "moved the modal directory into components." If anyone on the team published modal views at the old path and edited them, those edits will simply stop being used — no error, no deprecation, just a modal that looks like the stock one again. Before any upgrade:

grep -rn "tall-mobile" resources/ app/ config/ tailwind.config.js
git log --oneline -- resources/views/components   # spot the published-then-abandoned files

Re-publish, diff against your customisations, reapply. Keep published views in version control so this is a diff and not archaeology.

Preset commands overwrite files. tailwind.config.js, resources/js/app.js, resources/views/layouts/, sometimes routes/web.php. Always install on a clean commit. There is no uninstall command.

Double Alpine. Livewire 3 bundles Alpine. If the preset's app.js stub also imports and starts Alpine, you get two instances: x-data initialises twice, $dispatch fires twice, dropdowns close instantly. Symptom is a console warning about Alpine already being loaded. Fix is to delete the package's Alpine import and let Livewire own it — but check the stub first, because presets written for Livewire 2 assume the opposite.

Livewire 3 deferred binding inside modals. wire:model no longer validates as you type. Inside a modal that's especially visible: users open the dialog, type an invalid email, see nothing until submit. Use wire:model.live (or .blur) on fields where inline validation matters, and $this->resetValidation() in the open() method — otherwise errors from a previous open persist into the next one, because the component stays mounted.

Stale published views. When your edits to a published modal don't appear: php artisan view:clear. Blade caches compiled vendor views aggressively, and this is the #1 false alarm when iterating on a modal's markup.

Accessibility is yours to verify. Escape-to-close, focus trapping on open, focus restoration to the trigger on close, aria-modal, and aria-labelledby pointing at a real heading. Archived single-component packages are exactly where these are half-implemented. Test with keyboard only before you ship it into an approval or destructive-action flow — that's where a broken focus trap is a real problem, not a lint warning.

Debugging checklist when the modal won't open:

  1. View-source the page — does the <x-...modal> output exist at all? If not, the component name/path changed (see v1.0.1 above).
  2. Inspect the modal's root element — is x-data present in the DOM? If the attribute is there but nothing works, Alpine didn't boot (see double-Alpine).
  3. Check npm run dev is running and the Vite manifest includes the preset's entry.
  4. php artisan view:clear and hard-reload before deeper debugging.

Extension points worth knowing. Blade component resolution means an app-level component of the same name generally wins over a vendor one — which is convenient but also how a stale copy silently shadows the package. If you want both, use the vendor namespace explicitly (<x-tall-mobile::modal>) and reserve the bare tag for your own wrapper. Publish tags are the sanctioned override surface; the service provider is where aliases and namespaces are registered if you need to inspect them.

The strongest day-to-day leverage is not the component itself — it's the pattern: one wrapper component, one modal root in the layout, published-and-committed views, and a pinned version. That gets you consistent dialogs across approval flows, invite forms, and destructive-action guards in an afternoon, and a one-file swap if the package ever needs replacing.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib