Styling Guide

Complete guide to styling in LaraDashboard using Tailwind CSS v4 utility classes, component styles, and module asset setup.

Styling Guide

LaraDashboard uses Tailwind CSS v4 with custom utility classes defined in resources/css/components.css. This guide covers how to use these classes and set up styling for modules.

Quick Start

For Backend Admin Modules

If your module uses the core admin layout (backend.layouts.app), you automatically have access to all utility classes:

{{-- Your module view --}}
<div>
    <h1 class="page-title">My Module</h1>
    <p class="page-description">Module description here.</p>

    <div class="card">
        <div class="card-header">
            <h2 class="card-title">Section Title</h2>
        </div>
        <div class="card-body">
            <form>
                <div class="mb-4">
                    <label class="form-label">Name</label>
                    <input type="text" class="form-control" placeholder="Enter name">
                </div>
                <button type="submit" class="btn-primary">Save</button>
            </form>
        </div>
    </div>
</div>

For Frontend Theme Modules

Modules with separate assets (like themes) need their own Vite setup. See Module Asset Setup below.


Button Classes

Solid Buttons

Class Description
btn Base button with primary styling
btn-primary Primary brand color button
btn-secondary Gray secondary button
btn-success Green success button
btn-danger Red danger/delete button
btn-warning Orange warning button
btn-info Blue informational button
btn-default Neutral gray button
btn-link Text-only link style button
<button class="btn-primary">Save Changes</button>
<button class="btn-secondary">Cancel</button>
<button class="btn-danger">Delete</button>
<button class="btn-success">Approve</button>
<button class="btn-warning">Warning</button>
<button class="btn-info">Info</button>
<button class="btn-default">Default</button>
<button class="btn-link">Learn More</button>

Outline Buttons

Class Description
btn-outline-primary Primary outline button
btn-outline-secondary Secondary outline button
btn-outline-success Success outline button
btn-outline-danger Danger outline button
btn-outline-warning Warning outline button
<button class="btn-outline-primary">Edit</button>
<button class="btn-outline-secondary">View</button>
<button class="btn-outline-danger">Remove</button>

Button Sizes

Class Description
btn-sm Small button (add to any button)
btn-lg Large button (add to any button)
<button class="btn-primary btn-sm">Small Button</button>
<button class="btn-primary">Default Button</button>
<button class="btn-primary btn-lg">Large Button</button>

Icon Buttons

Class Description
btn-icon Base icon button
btn-icon-primary Primary icon button
btn-icon-secondary Secondary icon button
<button class="btn-icon-primary">
    <x-icon name="lucide:plus" class="w-5 h-5" />
</button>
<button class="btn-icon-secondary">
    <x-icon name="lucide:settings" class="w-5 h-5" />
</button>

Form Classes

Input Fields

Class Description
form-control Standard text input styling
form-control-textarea Textarea styling
form-control-file File input styling
form-control-combobox Combobox/select dropdown styling
form-label Form field label
form-checkbox Checkbox input styling
<!-- Text Input -->
<div class="mb-4">
    <label class="form-label">Email Address</label>
    <input type="email" class="form-control" placeholder="you@example.com">
</div>

<!-- Select -->
<div class="mb-4">
    <label class="form-label">Country</label>
    <select class="form-control">
        <option>United States</option>
        <option>Canada</option>
        <option>United Kingdom</option>
    </select>
</div>

<!-- Textarea -->
<div class="mb-4">
    <label class="form-label">Description</label>
    <textarea class="form-control-textarea" rows="4" placeholder="Enter description..."></textarea>
</div>

<!-- File Input -->
<div class="mb-4">
    <label class="form-label">Upload File</label>
    <input type="file" class="form-control-file">
</div>

<!-- Checkbox -->
<div class="mb-4 flex items-center gap-2">
    <input type="checkbox" class="form-checkbox" id="terms">
    <label for="terms" class="text-sm text-gray-700 dark:text-gray-300">
        I agree to the terms
    </label>
</div>

Input Groups

<div class="form-input-group">
    <span class="form-control flex items-center px-3 bg-gray-50 text-gray-500 border-r-0">
        https://
    </span>
    <input type="text" class="form-control" placeholder="example.com">
</div>

Badge Classes

Class Description
badge Default gray badge
badge-primary Primary brand badge
badge-success Green success badge
badge-info Blue info badge
badge-warning Orange warning badge
badge-danger Red danger badge
badge-secondary Gray secondary badge
<span class="badge">Default</span>
<span class="badge-primary">Primary</span>
<span class="badge-success">Active</span>
<span class="badge-warning">Pending</span>
<span class="badge-danger">Expired</span>
<span class="badge-info">New</span>

Card Classes

Class Description
card Card container
card-header Card header section
card-body Card body/content section
card-footer Card footer section
card-title Card title text
card-description Card description text
<div class="card">
    <div class="card-header">
        <h3 class="card-title">Card Title</h3>
        <p class="card-description">Optional description text</p>
    </div>
    <div class="card-body">
        <p>Card content goes here...</p>
    </div>
    <div class="card-footer">
        <button class="btn-primary">Save</button>
        <button class="btn-secondary">Cancel</button>
    </div>
</div>

Alert Classes

Class Description
alert Base alert container
alert-success Green success alert
alert-danger Red error alert
alert-warning Orange warning alert
alert-info Blue info alert
<div class="alert alert-success">
    <x-icon name="lucide:check-circle" class="w-5 h-5 text-green-600" />
    <span>Operation completed successfully!</span>
</div>

<div class="alert alert-danger">
    <x-icon name="lucide:x-circle" class="w-5 h-5 text-red-600" />
    <span>An error occurred. Please try again.</span>
</div>

<div class="alert alert-warning">
    <x-icon name="lucide:alert-triangle" class="w-5 h-5 text-amber-600" />
    <span>Please review before submitting.</span>
</div>

<div class="alert alert-info">
    <x-icon name="lucide:info" class="w-5 h-5 text-blue-600" />
    <span>This is an informational message.</span>
</div>

Table Classes

Class Description
table-responsive Responsive table container
table Base table styling
table-thead Table header styling
table-thead-th Table header cell
table-thead-th-last Last header cell (centered)
table-tr Table row
table-td Table data cell
<div class="table-responsive">
    <table class="table">
        <thead class="table-thead">
            <tr>
                <th class="table-thead-th">Name</th>
                <th class="table-thead-th">Email</th>
                <th class="table-thead-th">Status</th>
                <th class="table-thead-th table-thead-th-last">Actions</th>
            </tr>
        </thead>
        <tbody>
            <tr class="table-tr">
                <td class="table-td">John Doe</td>
                <td class="table-td">john@example.com</td>
                <td class="table-td"><span class="badge-success">Active</span></td>
                <td class="table-td text-center">
                    <button class="btn-outline-primary btn-sm">Edit</button>
                </td>
            </tr>
        </tbody>
    </table>
</div>

Link Classes

Class Description
link Primary colored link
link-secondary Gray secondary link
link-danger Red danger link
<a href="#" class="link">Primary Link</a>
<a href="#" class="link-secondary">Secondary Link</a>
<a href="#" class="link-danger">Delete</a>

Typography Classes

Page Titles

Class Description
page-title Main page heading
page-description Page subtitle/description
section-title Section heading
<div class="mb-6">
    <h1 class="page-title">Dashboard</h1>
    <p class="page-description">Welcome back! Here's what's happening.</p>
</div>

<h2 class="section-title">Recent Activity</h2>

Prose (Rich Content)

Use the prose class for markdown/rich text content:

<div class="prose">
    <h1>Article Title</h1>
    <p>This is a paragraph with <strong>bold</strong> and <em>italic</em> text.</p>

    <h2>Section Heading</h2>
    <ul>
        <li>First item</li>
        <li>Second item</li>
    </ul>

    <blockquote>This is a quote.</blockquote>

    <pre><code>const example = 'code block';</code></pre>
</div>

<!-- Smaller prose variant -->
<div class="prose prose-sm">
    <p>Smaller text content...</p>
</div>

Container Class

Class Description
ld-container Centered container with responsive padding
<div class="ld-container">
    <!-- Content centered with max-width and padding -->
</div>

Module Asset Setup

For modules that need their own CSS/JS assets (like frontend themes), you need to set up Vite.

1. Create vite.config.js

Create modules/YourModule/vite.config.js:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Determine if we're building for distribution (self-contained) or development
const isDistBuild = process.env.MODULE_DIST_BUILD === 'true';

// For distribution: build inside module directory (self-contained ZIP)
// For development: build to public directory (hot reload works)
const distOutDir = path.resolve(__dirname, 'dist/build-yourmodule');
const devOutDir = path.resolve(__dirname, '../../public/build-yourmodule');

export default defineConfig({
    build: {
        outDir: isDistBuild ? distOutDir : devOutDir,
        emptyOutDir: true,
        manifest: 'manifest.json',
    },
    plugins: [
        laravel({
            publicDirectory: isDistBuild
                ? path.resolve(__dirname, 'dist')
                : path.resolve(__dirname, '../../public'),
            buildDirectory: 'build-yourmodule',
            input: [
                path.resolve(__dirname, 'resources/assets/css/app.css'),
                path.resolve(__dirname, 'resources/assets/js/app.js'),
            ],
            refresh: true,
        }),
        tailwindcss(),
    ],
});

2. Create Module CSS

Create modules/YourModule/resources/assets/css/app.css:

@import "tailwindcss" prefix(ym);

/* Use class-based dark mode */
@custom-variant dark (&:is(.dark *));

@source '../../views/**/*.blade.php';
@source '../js/**/*.js';

/* Define theme colors */
@theme {
    --color-primary: #635bff;
}

/* Safelist for dynamic Alpine.js classes */
@source inline("border-primary bg-primary text-primary");

/* Runtime color inheritance from core */
@layer base {
    :root, :host {
        --ym-color-primary: var(--color-primary, #635bff);
    }
}

/* Add custom component styles */
@layer components {
    /* Your module-specific styles */
}

3. Add package.json

Create modules/YourModule/package.json:

{
    "private": true,
    "type": "module",
    "scripts": {
        "dev": "vite --config vite.config.js",
        "build": "vite build --config vite.config.js"
    },
    "devDependencies": {
        "@tailwindcss/vite": "^4.0.0",
        "laravel-vite-plugin": "^1.0.0",
        "tailwindcss": "^4.0.0",
        "vite": "^6.0.0"
    }
}

4. Include Assets in Views

In your module layout, include the Vite assets:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{ $title ?? config('app.name') }}</title>

    {{-- Module-specific assets --}}
    @vite([
        'resources/assets/css/app.css',
        'resources/assets/js/app.js'
    ], 'build-yourmodule')

    @livewireStyles
</head>
<body>
    {{ $slot }}
    @livewireScripts
</body>
</html>

5. Build Assets

# Install dependencies
cd modules/YourModule && npm install

# Development (with hot reload)
npm run dev

# Production build
npm run build

# Distribution build (self-contained in dist/)
MODULE_DIST_BUILD=true npm run build

CSS Prefix System

When modules have their own Tailwind setup, use a prefix to avoid class name conflicts:

/* In your module's app.css */
@import "tailwindcss" prefix(ym);  /* prefix with "ym:" */

Then in your views:

<!-- Prefixed classes -->
<div class="ym:bg-white ym:p-4 ym:rounded-lg">
    <h1 class="ym:text-xl ym:font-bold">Title</h1>
    <button class="ym:bg-primary ym:text-white ym:px-4 ym:py-2">
        Click Me
    </button>
</div>

This prevents your module's Tailwind classes from conflicting with core or other modules.


Dark Mode Support

All utility classes support dark mode via the dark: variant. The dark mode is controlled by adding the .dark class to the <html> element.

<!-- Automatically adapts to dark mode -->
<div class="card">
    <div class="card-body">
        <p class="text-gray-700 dark:text-gray-300">
            This text adapts to dark mode.
        </p>
    </div>
</div>

<!-- Custom dark mode overrides -->
<div class="bg-white dark:bg-gray-800 p-4 rounded">
    <span class="text-gray-900 dark:text-white">Dark mode text</span>
</div>

Best Practices

  1. Prefer Blade components - Use <x-button>, <x-card>, etc. when available
  2. Use utility classes - Leverage the pre-built classes for consistency
  3. Follow dark mode - Always include dark: variants for custom styles
  4. Prefix module styles - Use CSS prefixes for isolated module assets
  5. Don't override core - Avoid modifying resources/css/components.css
  6. Use gap for spacing - Prefer gap-* over margins in flex/grid layouts

CSS File Reference

File Purpose
resources/css/app.css Main entry point, imports all CSS
resources/css/components.css Utility classes (buttons, forms, etc.)
resources/css/base.css Base HTML element styles
resources/css/sidebar.css Admin sidebar styles
resources/css/utilities.css Additional utility classes
resources/css/third-party.css Third-party library styles

Next Steps

/