Skip to content

edumicro/daisyBladeAlpine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DaisyBlade

Pure Blade + Alpine.js + DaisyUI components for Laravel ERP/CRM interfaces.

No Livewire. No magic. No hidden server roundtrips.

composer require edumicro/daisyblade

Philosophy

DaisyBlade is the evolution of edumicro/daisylw4, rebuilt without Livewire. The stack is intentionally boring:

  • Blade renders structure
  • Alpine.js manages local UI state
  • Axios handles explicit server calls
  • DaisyUI 5 provides the design system

Every server interaction is a plain Laravel controller returning JSON. No protocol overhead, no wire attributes, no object inspector surprises. If something breaks, you know exactly where to look.


Requirements

Dependency Version
PHP ^8.2
Laravel ^11.0 | ^12.0
Alpine.js ^3.0
DaisyUI ^5.0
blade-heroicons ^2.4

Installation

composer require edumicro/daisyblade
php artisan daisyblade:install

The install command will ask whether to publish assets for Vite (recommended) or as a public script tag:

# Vite — assets published to resources/js/daisyblade.js
php artisan daisyblade:install --vite

# Script tag — assets published to public/vendor/daisyblade/
php artisan daisyblade:install --public

Vite setup

// vite.config.js
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'

export default defineConfig({
    plugins: [laravel({ input: ['resources/js/app.js'] })],
})
// resources/js/app.js
import './daisyblade.js'
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()

Script tag setup

<script src="/vendor/daisyblade/daisyblade.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>

Component prefix

All components use the dbl prefix:

<x-dbl::display.badge label="Active" color="success" />
<x-dbl::form.input name="email" type="email" label="Email" />
<x-dbl::display.data-table :load-url="route('products.data')" :columns="$columns" />

Component reference

Type 1 — Static (Blade + DaisyUI only)

No JavaScript. Receive props, render HTML.

Component Usage
display.accordion DaisyUI accordion (CSS-driven)
display.avatar User avatar with initials fallback
display.badge Status badges with color variants
display.card Content card with optional shadow
display.chat-bubble Chat message bubble
display.collapse DaisyUI collapse panel (CSS-driven)
display.compare Side-by-side property comparison table
display.diff Code diff viewer (line-by-line +/−/~)
display.hover-3d-card CSS 3D tilt card on hover
display.hover-gallery CSS-animated image gallery
display.kbd Keyboard shortcut display
display.list Styled list component
display.mask DaisyUI mask shapes
display.radial-progress Circular progress indicator
display.resource-details Detail view loaded from URL
display.stat KPI card with value, title, trend
display.status Status dot with label
display.table Static HTML table from array data
display.timeline Vertical event timeline
display.tree Recursive tree from nested array
feedback.alert Alert message with type variants
feedback.loading Loading spinner
feedback.progress Linear progress bar
feedback.skeleton Content skeleton placeholder
feedback.tooltip Tooltip wrapper
form.checkbox Checkbox field with label
form.input Text/email/number/date input
form.radio Radio button group
form.textarea Textarea with label
form.toggle Toggle switch
form.validator Inline validation message display
layout.divider Section divider
layout.footer Page footer
layout.hero Hero section
layout.indicator Badge indicator overlay
layout.join DaisyUI join group
layout.section-wrapper Padded section container
layout.stack DaisyUI stack layout
navigation.breadcrumb Breadcrumb trail
navigation.dock Bottom dock navigation
navigation.steps Step indicator
actions.button Button with variants, loading, icon
actions.fab Floating action button
actions.swap Toggle swap element
components.icon Heroicon wrapper

Type 2 — Interactive local (Alpine, no server calls)

UI state managed by Alpine. No Axios.

Component Usage
actions.modal Modal with Alpine open/close
display.carousel Image/content carousel
display.filters Filter bar with Alpine state
display.node-graph Tree graph with event timeline + detail modal
display.text-rotate Animated rotating text
feedback.toast Toast notification
form.kv-editor Key-value editor with auto-inferring type selector
form.list-editor Chip/tag array-of-strings editor
form.repeater Dynamic repeatable field group
navigation.menu Dropdown / nested menu
navigation.navbar Top navigation bar
navigation.pagination Page navigation controls
navigation.sidebar Collapsible sidebar
navigation.sidebar-tree Nested sidebar menu
layout.app Full page layout with slots
layout.auth Auth page layout
navigation.tabs Tab switcher (inline content)

Type 3 — Interactive remote (Alpine + Axios)

Receive a load-url or action prop. Call plain Laravel controllers returning JSON.

Component Usage
display.data-table Paginated, sortable, filterable table
form.filter Filter bar for data-table
form.select Select with remote search
import.spreadsheet Excel/CSV chunked import
sections.auto-form Declarative form from schema array
sections.tabs Tabs with lazy-loaded content
sections.wizard Multi-step form with localStorage resume

Usage examples

Static badge

<x-dbl::display.badge label="Active" color="success" />
<x-dbl::display.badge label="Pending" color="warning" size="lg" />
<x-dbl::display.badge label="Error" color="error" :outline="true" />

KPI stat card

<x-dbl::display.stat
    title="Monthly revenue"
    value="€ 12.400"
    description="vs last month"
    trend="up"
    icon="heroicon-o-banknotes"
/>

Node graph (Type 2)

Renders a tree of simulation/workflow nodes with per-event color coding and a detail modal. Each node is an array with id, parent (null for roots), label, status, events[], and optional meta{}.

@php
$nodes = [
    [
        'id'     => 1,
        'parent' => null,
        'label'  => 'Main trajectory',
        'status' => 'completed',
        'events' => [
            ['name' => 'timer_done', 'action_type' => 'terminate', 'termination_type' => 'end',   't_s' => 12.5],
            ['name' => 'heat_acc',   'action_type' => 'accumulator_abort', 'termination_type' => 'abort', 'acc_value' => 42.7],
        ],
        'meta' => ['h_max_m' => 350.2, 't_final_s' => 12.5],
    ],
    [
        'id'     => 2,
        'parent' => 1,
        'label'  => 'Branch — ricochet',
        'status' => 'failed',
        'events' => [
            ['name' => 'impact', 'action_type' => 'accumulator_fail', 'termination_type' => 'fail', 'acc_value' => 0.1],
        ],
        'meta' => [],
    ],
];
@endphp

<x-dbl::display.node-graph :nodes="$nodes" label="Execution tree" />

Event badge colours: end → green, abort → amber, fail → red, no termination → ghost. Accumulator events show acc_value inline. Click any node dot or event badge to open the detail modal.

Data table (Type 3)

{{-- In your Blade view --}}
<x-dbl::display.data-table
    :load-url="route('products.data')"
    :columns="$columns"
    :per-page="15"
    :filters-url="route('products.filters')"
/>
// In your controller
public function index()
{
    return view('products.index', [
        'columns' => [
            ['key' => 'name',     'label' => 'Name',     'sortable' => true],
            ['key' => 'category', 'label' => 'Category', 'sortable' => false],
            ['key' => 'price',    'label' => 'Price',    'sortable' => true],
        ],
    ]);
}

// Data endpoint — returns JSON
public function data(Request $request)
{
    $products = Product::query()
        ->when($request->search, fn($q) => $q->where('name', 'like', "%{$request->search}%"))
        ->orderBy($request->sort_by ?? 'name', $request->sort_dir ?? 'asc')
        ->paginate($request->per_page ?? 15);

    return response()->json($products);
}

Declarative form (Type 3)

<x-dbl::sections.auto-form
    :schema="[
        ['name' => 'name',        'label' => 'Product name', 'order' => 10],
        ['name' => 'category_id', 'label' => 'Category',     'type' => 'relation',
         'options-url' => route('categories.options'),        'order' => 20],
        ['name' => 'price',       'label' => 'Price',         'type' => 'money', 'order' => 30],
        ['name' => 'active',      'label' => 'Active',        'type' => 'toggle', 'order' => 40],
    ]"
    action="{{ route('products.store') }}"
    method="POST"
/>
// Controller — plain Laravel, no Livewire
public function store(Request $request)
{
    $validated = $request->validate([
        'name'        => 'required|string|max:255',
        'category_id' => 'required|exists:categories,id',
        'price'       => 'required|numeric|min:0',
        'active'      => 'boolean',
    ]);

    $product = Product::create($validated);

    // DaisyBlade expects: {success, redirect} or {success: false, errors}
    return response()->json([
        'success'  => true,
        'redirect' => route('products.index'),
    ]);
}

Repeater field (Type 2)

<x-dbl::form.repeater
    name="events"
    label="Events"
    :fields="[
        ['name' => 'label', 'type' => 'text',   'label' => 'Label'],
        ['name' => 'value', 'type' => 'number', 'label' => 'Value'],
    ]"
    :value="old('events', [])"
    add-label="Add event"
    :min="1"
    :max="10"
/>

Key-value editor (Type 2)

Renders a table of key/value rows with an auto-inferring type selector (num/str/bool/{…}). Serialises to a hidden <input> as JSON.

<x-dbl::form.kv-editor
    name="parameters"
    :value="$model->parameters ?? []"
    label="Parámetros"
    hint="Campos habituales: mass_kg, v0_ms, diameter_m"
/>

value accepts a PHP associative array. Types are inferred automatically when the user types; the selector lets them override if needed.

List editor (Type 2)

Chip/tag input for an array of strings. Enter or comma adds a chip; Backspace removes the last one.

<x-dbl::form.list-editor
    name="output_fields"
    :value="$model->output_fields ?? []"
    label="Campos de output"
    hint="Disponibles: t_s, x_m, h_m, v_ms, mach"
    placeholder="Escribe un campo y pulsa Enter…"
/>

Multi-step wizard with localStorage resume

<x-dbl::sections.wizard
    form-id="product-onboarding"
    schema-version="2"
    :user-id="auth()->id()"
    action="{{ route('products.store') }}"
    :steps="[
        ['title' => 'Basic info',  'fields' => ['name', 'category_id']],
        ['title' => 'Pricing',     'fields' => ['price', 'currency']],
        ['title' => 'Visibility',  'fields' => ['active', 'publish_at']],
    ]"
/>

If the user refreshes mid-wizard, their progress is automatically restored from localStorage. The storage key is versioned (product-onboarding_{userId}_v2), so changing schema-version invalidates stale state.

App layout

{{-- resources/views/products/index.blade.php --}}
<x-dbl::layout.app title="Products">

    <x-slot:navbar>
        <x-dbl::navigation.navbar>
            <x-dbl::navigation.breadcrumb :items="[
                ['label' => 'Dashboard', 'url' => route('dashboard')],
                ['label' => 'Products'],
            ]"/>
        </x-dbl::navigation.navbar>
    </x-slot:navbar>

    <x-slot:sidebar>
        <x-dbl::navigation.sidebar />
    </x-slot:sidebar>

    <x-dbl::display.data-table
        :load-url="route('products.data')"
        :columns="$columns"
    />

</x-dbl::layout.app>

JSON response contract

All Type 3 components expect controllers to return JSON following this contract:

// Success with redirect
{ "success": true, "redirect": "/products" }

// Success with data (for remote selects, resource-details, etc.)
{ "success": true, "data": [...], "meta": { "current_page": 1, "last_page": 5 } }

// Validation failure
{ "success": false, "errors": { "name": ["The name field is required."] } }

Laravel's response()->json() + standard validation exceptions handle this automatically if you let them.


Publishing views

To customise any component, publish the views:

php artisan vendor:publish --tag=daisyblade-views

Published views in resources/views/vendor/daisyblade/ take precedence over package views. Edit freely — your customisations survive package updates.


Testing

composer test
# or
vendor/bin/pest

188 tests, 294 assertions. All green.


License

MIT — Eduardo de Vicente / Microvalencia Soluciones Informáticas S.L.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors