PHPackages                             ironflow/halo-ui - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. ironflow/halo-ui

ActiveLibrary[Templating &amp; Views](/categories/templating)

ironflow/halo-ui
================

Modern, composable Blade UI component library for Laravel — elegant as shadcn, native as Blade.

v4.4.0(1mo ago)5201MITPHPPHP ^8.2CI passing

Since Oct 18Pushed 1mo agoCompare

[ Source](https://github.com/AureDulvresse/halo-ui)[ Packagist](https://packagist.org/packages/ironflow/halo-ui)[ RSS](/packages/ironflow-halo-ui/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (10)Dependencies (26)Versions (19)Used By (1)

HaloUI
======

[](#haloui)

 [ ![Latest Version](https://camo.githubusercontent.com/d04fa6c1919be734efea3e348f5d0d16b583aeef136ef3a1e5a8d17e868184ed/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f69726f6e666c6f772f68616c6f2d7569) ](https://packagist.org/packages/ironflow/halo-ui) [ ![Total Downloads](https://camo.githubusercontent.com/24dc1d017f90db123a7bafa2913c0254c41b5bb5ea0a006d6a0a2e51403cc2e0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f69726f6e666c6f772f68616c6f2d7569) ](https://packagist.org/packages/ironflow/halo-ui) [ ![License](https://camo.githubusercontent.com/76f5374e5252aaf3d1d1a7f84a1941335e404fdd3f34175e2afc30863e8aaaf0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f69726f6e666c6f772f68616c6f2d7569) ](https://packagist.org/packages/ironflow/halo-ui) [ ![GitHub issues](https://camo.githubusercontent.com/4be938bf4124d812945604cc7bbcd26d5688dec925f49a18f9ec6dbc00830461/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f4175726544756c7672657373652f68616c6f2d7569) ](https://github.com/AureDulvresse/halo-ui/issues)

 **Modern, composable Blade UI component library for Laravel**
 Elegant as shadcn/ui, native as Blade. Built with Tailwind CSS v4, Alpine.js, and Blade Icons.

 [Status](#status) • [Installation](#installation) • [Components](#components) • [Theming](#theming) • [Customization](#customization) • [Testing](#testing) • [Contributing](#contributing)

---

Status
------

[](#status)

**v4 is a from-scratch rebuild, currently at an early, deliberately small stage.** Earlier versions accumulated dead code and a documentation/reality gap (classes and templates that were never wired up, a theme system that didn't actually theme anything). Rather than carry that forward, v4 starts over with a strict rule: **every component that exists is real, tested, and themed correctly** — nothing is listed here until it ships.

Today that's **35 components** (including 6 layout components). More are added incrementally; see [CHANGELOG.md](CHANGELOG.md) for what's shipped and `docs/` for what's next.

Features
--------

[](#features)

- **Zero-config assets** — `@haloStyles`/`@haloScripts` serve the package's own built CSS/JS (Alpine.js bundled in) with no `vendor:publish`, no Vite config, no separate Alpine install
- **Anonymous Blade components** — no PHP classes to maintain, just `@props()` and a Blade file
- **Real runtime theming** — colors, radius, and dark/light are CSS custom properties (`--halo-*`) mapped into Tailwind v4 via `@theme`; switching themes changes an attribute, not a build step
- **Copy-and-own** — works out of the box after `composer require`; `php artisan halo:install` is an optional eject for full customization
- **Blade Icons integration** — icons resolve through Blade Icons' native component API, not a hand-rolled resolver
- **Accessible by default** — ARIA attributes and keyboard behavior are part of a component's first version, not an afterthought
- **Alpine.js for interactivity** — registered as named `Alpine.data()`/`Alpine.store()`, invoked directly in Blade

---

Installation
------------

[](#installation)

### Requirements

[](#requirements)

- PHP 8.2+
- Laravel 11+ or 12+

Tailwind and Alpine.js are **not** separate requirements — HaloUI ships its own built CSS and JS (Alpine.js is bundled inside the JS build), so there's nothing extra to install for the fast path below.

### Install via Composer

[](#install-via-composer)

```
composer require ironflow/halo-ui
```

### Fastest path: two tags in your layout

[](#fastest-path-two-tags-in-your-layout)

No `vendor:publish`, no Vite config, no separate Alpine.js install. `@haloStyles`/`@haloScripts` serve the package's own built assets directly:

```
>

    @haloStyles

    {{ $slot }}

    @haloScripts

```

That's the whole setup. ``, ``, ``, theme switching, focus traps, roving-focus menus — all working, with no build step of your own.

### Integrated path: your own Vite/Tailwind pipeline

[](#integrated-path-your-own-vitetailwind-pipeline)

If your app already runs Tailwind v4 and Alpine.js and you want HaloUI's classes to be purgeable/tree-shakeable alongside your own, skip `@haloStyles`/`@haloScripts` and wire the package's sources into your own build instead:

```
/* resources/css/app.css */
@import "tailwindcss";
@import "../../vendor/ironflow/halo-ui/resources/css/theme.css";
@source "../../vendor/ironflow/halo-ui/resources/views";
```

```
// resources/js/app.js
import Alpine from 'alpinejs';
import '../../vendor/ironflow/halo-ui/resources/js/init.js'; // registers haloModal, haloDropdown, etc.

window.Alpine = Alpine;
Alpine.start();
```

Set `'assets' => ['serve' => false]` in `config/halo.php` (publish it first with `php artisan vendor:publish --tag=halo-config`) so `@haloStyles`/`@haloScripts`, if you still use them anywhere, point at your own published/bundled files instead of the package's asset routes.

### Eject and customize (optional)

[](#eject-and-customize-optional)

`halo:install` copies the package's own component files into your app, so you can edit them directly:

```
# Eject every component
php artisan halo:install --all

# Eject specific components
php artisan halo:install button input

# Overwrite files already ejected
php artisan halo:install --all --force
```

Once ejected to `resources/views/components/halo/`, your local copy takes precedence — the package's own components still work for anything you didn't eject.

---

Quick Start
-----------

[](#quick-start)

```

    Save changes

Active

    Something went wrong — please try again.

{{-- Modal: opened by name, from anywhere --}}

    Delete account

    Delete account?
    This can't be undone.

        Cancel
        Delete

```

---

Components
----------

[](#components)

Full props reference for each lives in `docs/{component}.md`; this is the map.

### Typography

[](#typography)

ComponentNotes**Heading**``–`` via `level`, each with a matching default type scale; `size` overrides the look without changing the tag**Text**Body copy; `as` (`p`/`span`/`div`/`blockquote`), `size`, `muted`### Form

[](#form)

ComponentNotes**Button**Variants `primary`/`secondary`/`outline`/`ghost`/`danger`; sizes `sm`/`md`/`lg`; `icon`, `iconPosition`, `loading`, `disabled`**Input**Sizes `sm`/`md`/`lg`; `icon`, `iconPosition`, `invalid`, `error` (message + `aria-describedby`), `disabled`, auto-generated `id`**Textarea**Same size/invalid/error/disabled pattern as Input, plus `rows` and `resize`**Label**Pairs with any field via `for`; `required` adds a decorative `*`**Checkbox**Native `` wrapped in a ``; themed via `accent-halo-primary`**Radio**Same pattern as Checkbox; never derives its `id` from the shared group `name`**Select**`options` prop (`value => label`) or slot-authored `` tags; `invalid`/`error` like Input**Switch**Native `` styled as a track/thumb toggle**File Upload**Drag-and-drop over a real ``; removable file list, `multiple`, `accept`**Image Upload**Same drag-and-drop pattern, restricted to images, with live thumbnail previews### Display

[](#display)

ComponentNotes**Icon**Resolves any icon in the `halo` Blade Icons set (`resources/icons/halo/*.svg`) by name; sizes `xs`–`xl`**Badge**Variants `primary`/`secondary`/`success`/`danger`/`warning`**Avatar**`src` image, `initials` fallback, or generic icon; `status` dot**Spinner**Standalone loading indicator; also used internally by Button's `loading` state**Progress**Determinate (`value`/`max`) or `indeterminate` progress bar**Divider**Horizontal (with optional centered `label`) or `vertical`**Card** (+ `.header`/`.body`/`.footer`)Variants `default`/`bordered`/`elevated`**Table** (+ `.row`/`.head`/`.cell`)Styled wrappers around native ``/``/``/``; ``/`` stay plain HTML### Feedback

[](#feedback)

ComponentNotes**Alert**Variants `info`/`success`/`warning`/`danger`, each with a matching default icon; `dismissible`### Overlays (Alpine-powered)

[](#overlays-alpine-powered)

ComponentNotes**Modal** (+ `.header`/`.body`/`.footer`)Opened/closed by `name` via `$dispatch('open-modal', name)` — no `:open` prop to sync; traps focus while open, returns it to the trigger on close**Dropdown** (+ `.item`)`trigger` named slot; arrow keys move between items, closes on escape/outside click/selecting an item, returns focus to the trigger**Popover**`trigger` named slot for arbitrary rich content; no menu semantics, focus returns to the trigger on close**Tooltip**`trigger` named slot; shown on hover/focus, `aria-describedby` wired automatically**Toast**One global queue rendered by a single ``; push via `$store.haloToast.push(message, variant)`### Navigation (Alpine-powered)

[](#navigation-alpine-powered)

ComponentNotes**Tabs** (`.list`, `.trigger`, `.panel`)`default` active tab; arrow keys roam between triggers**Accordion** (+ `.item`)`multiple` allows more than one item open at once; each item tracked by an explicit `name` or an auto-generated one**Breadcrumb** (+ `.item`)`href` for links, `current` for the non-interactive last item### Layouts

[](#layouts)

ComponentNotes**Layout: Base**A full ``…`` skeleton, `@haloStyles`/`@haloScripts` already wired in — the fastest way to get a page rendering**Layout: Container**Max-width, centered content wrapper; `size` `sm`–`xl`|`full`**Layout: App Shell**Sidebar + topbar dashboard layout; off-canvas drawer below `lg`, static above it**Layout: Auth**Centered layout for login/register pages, optional `logo` slot**Layout: Two Column**Content + secondary sidebar (docs nav, settings nav); `sidebarPosition` `left`|`right`**Layout: Page Header**Title + description + right-aligned `actions` slotEach component's props, variant maps, and rendered markup live directly in its `.blade.php` file under `resources/views/components/halo/` — read the source, it's short by design.

See [CHANGELOG.md](CHANGELOG.md) for release history and `docs/` for per-component prop references.

---

Theming
-------

[](#theming)

Colors, radius, and light/dark are CSS custom properties defined in `resources/css/theme.css`, scoped to a `data-theme` attribute, and mapped into real Tailwind utility classes (`bg-halo-primary`, `rounded-halo`, ...) via Tailwind v4's `@theme` directive. There is no build-time "active theme" setting — switching themes means changing an attribute.

### Built-in themes

[](#built-in-themes)

Theme`data-theme`Character**Halo**`halo` (default)Blue, neutral radius — the baseline**Aurora**`aurora`Violet/teal accent, larger radius**Eclipse**`eclipse`Dark background, same blue family as Halo**Ember**`ember`Light, warm orange accent, sharper corners**Nocturne**`nocturne`Dark, near-black background, emerald accent```

```

### Switching at runtime

[](#switching-at-runtime)

`resources/js/init.js` registers an `Alpine.store('haloTheme', ...)` that persists the choice in `localStorage` and applies it to ``:

```
Aurora
```

Render the correct theme on first paint (before Alpine boots) by reading the configured default server-side:

```

```

### Adding a theme

[](#adding-a-theme)

Add a `[data-theme="yourname"]` block to `resources/css/theme.css` defining the same `--halo-*` variables as the existing themes, then add `'yourname'` to `config('halo.theme.available')` and to the `THEMES` array in `resources/js/init.js`.

---

Customization
-------------

[](#customization)

### Component-level

[](#component-level)

Every component merges any extra classes you pass, with the last-wins conflict resolution in `halo_merge_classes()` — a class you pass always overrides the component's own default for the same Tailwind utility family (`bg-*`, `text-*`, `p{x,y,...}-*`, etc.):

```

    Wider button

```

### Defaults

[](#defaults)

`config/halo.php` sets each component's default variant/size:

```
'defaults' => [
    'button' => ['variant' => 'primary', 'size' => 'md'],
],
```

### Helper functions

[](#helper-functions)

```
// CVA-style variant recipe: base classes + variant/size maps + defaults
halo_variants($config, $props, $extraClass);

// Merge class strings, deduping conflicting utilities (last wins)
halo_merge_classes(...$classGroups);

// Read a component's configured default prop
halo_default('button', 'variant'); // 'primary'

// Read a theme.* config value
theme('radius'); // 'rounded-halo'
```

---

Testing
-------

[](#testing)

HaloUI uses Pest:

```
composer test
composer test-coverage
```

```
it('applies the default variant and size classes', function () {
    $html = renderComponent('button', ['slot' => 'Save']);

    expect($html)
        ->toHaveClass('bg-halo-primary')
        ->toHaveClass('px-4 py-2');
});
```

Every component has a render test in `tests/Components/`, including a regression test on Icon that guards against a real bug this rebuild fixed (an icon resolver that could recurse into itself).

---

Contributing
------------

[](#contributing)

Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).

```
git clone https://github.com/AureDulvresse/halo-ui.git
cd halo-ui
composer install
npm install

composer test
vendor/bin/pint --test
npm run build
```

---

License
-------

[](#license)

HaloUI is open-sourced software licensed under the [MIT license](LICENSE).

Credits
-------

[](#credits)

- Inspired by [shadcn/ui](https://ui.shadcn.com)
- Built with [Tailwind CSS](https://tailwindcss.com)
- Powered by [Alpine.js](https://alpinejs.dev)
- Icons by [Blade Icons](https://github.com/blade-ui-kit/blade-icons)

---

 **HaloUI — Built with ❤️ by Aure Dulvresse**

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance92

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~17 days

Recently: every ~0 days

Total

16

Last Release

41d ago

Major Versions

v1.2.0 → v2.0.02025-10-23

v2.3.1 → v3.0.02025-11-02

v3.0.0 → v4.0.02026-07-08

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/147180124?v=4)[Aure Dulvresse](/maintainers/AureDulvresse)[@AureDulvresse](https://github.com/AureDulvresse)

---

Top Contributors

[![AureDulvresse](https://avatars.githubusercontent.com/u/147180124?v=4)](https://github.com/AureDulvresse "AureDulvresse (106 commits)")

---

Tags

laraveluicomponentsbladetailwindalpineblade-iconshalo-ui

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/ironflow-halo-ui/health.svg)

```
[![Health](https://phpackages.com/badges/ironflow-halo-ui/health.svg)](https://phpackages.com/packages/ironflow-halo-ui)
```

###  Alternatives

[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

731189.9k16](/packages/tallstackui-tallstackui)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k31.8M161](/packages/laravel-cashier)[livewire/flux

The official UI component library for Livewire.

9628.9M155](/packages/livewire-flux)[moonshine/moonshine

Laravel administration panel

1.3k268.2k89](/packages/moonshine-moonshine)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[robsontenorio/mary

Gorgeous UI components for Livewire powered by daisyUI and Tailwind

1.5k612.7k24](/packages/robsontenorio-mary)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
