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
- Prefer Blade components - Use
<x-button>,<x-card>, etc. when available - Use utility classes - Leverage the pre-built classes for consistency
- Follow dark mode - Always include
dark:variants for custom styles - Prefix module styles - Use CSS prefixes for isolated module assets
- Don't override core - Avoid modifying
resources/css/components.css - 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
- Components Overview - Blade component documentation
- Module Development - Building custom modules
- Buttons Component - Button Blade component
- Inputs Component - Form input components