Bring the aggressive, bold Neo Brutalism aesthetic to any web project. Fully framework-agnostic!
Install the core Tailwind CSS plugin via NPM. This works everywhere Tailwind works.
npm install neo-brutalism-tailwind
If you are using Tailwind v4, simply import the plugin in your main CSS file (e.g., input.css or app.css):
@import "tailwindcss";
@plugin "neo-brutalism-tailwind";
If you are using Tailwind v3, add the plugin to your tailwind.config.js:
module.exports = {
content: [
"./**/*.html",
"./**/*.php",
"./src/**/*.{vue,js,ts,jsx,tsx}"
],
plugins: [
require('neo-brutalism-tailwind')()
],
}
If you are using Laravel, we provide a specialized Blade component package for a better developer experience.
composer require vr/laravel-neo-ui
Want to see a fully working, standalone project with a real build step? Check out the sample folder in our repository!
View Sample Project on GitHubLearn how to customize prefixes to prevent CSS conflicts.
If you don't want our classes (like .btn) to conflict with Bootstrap or other libraries, you can add a prefix.
1. In tailwind.config.js:
plugins: [
require('neo-brutalism-tailwind')({ prefix: 'neo-' })
]
Now all components will be prefixed (e.g., class="neo-btn").
2. In Laravel (Optional):
Publish the config and update it so Blade components match your Tailwind prefix.
php artisan vendor:publish --tag=neo-ui-config
// config/neo-ui.php
return [
'prefix' => 'neo-',
];
Learn how to easily toggle between light and dark modes.
Neo Brutalism UI respects the dark class on your HTML <html> element to switch to dark mode. It natively integrates with Tailwind's class-based dark mode.
1. Enable class-based dark mode in Tailwind configuration:
// tailwind.config.js
module.exports = {
darkMode: 'class', // Add this line
// ...
}
2. Toggle using JavaScript or Alpine.js:
To activate dark mode, simply add the dark class to the <html> element. Below is an example using Alpine.js and a toggle switch:
<html lang="en" :class="{ 'dark': isDark }" x-data="{ isDark: false }">
<body>
<label class="flex items-center gap-2 cursor-pointer font-bold">
<input type="checkbox" class="toggle" x-model="isDark" />
Toggle Dark Mode
</label>
</body>
</html>
The primary action element with click and hover states.
<button class="btn btn-sm">Small</button>
<button class="btn">Default</button>
<button class="btn btn-lg">Large</button>
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-danger">Danger</button>
<button class="btn btn-info">Info</button>
<button class="btn" disabled>Disabled</button>
<x-neo::button class="btn-sm">Small</x-neo::button>
<x-neo::button>Default</x-neo::button>
<x-neo::button class="btn-lg">Large</x-neo::button>
<x-neo::button variant="primary">Primary</x-neo::button>
<x-neo::button variant="secondary">Secondary</x-neo::button>
<x-neo::button variant="danger">Danger</x-neo::button>
<x-neo::button variant="info">Info</x-neo::button>
<x-neo::button disabled>Disabled</x-neo::button>
Text inputs, textareas, selects, toggles, checkboxes, and more.
<input type="email" class="input" placeholder="Email" />
<textarea class="textarea" placeholder="Message"></textarea>
<select class="select">
<option>Option 1</option>
</select>
<input type="file" class="file-input" />
<input type="range" class="range" min="0" max="100" />
<input type="checkbox" class="toggle" checked />
<input type="checkbox" class="checkbox" checked />
<input type="radio" class="radio" />
<x-neo::input type="email" placeholder="Email" />
<x-neo::textarea placeholder="Message"></x-neo::textarea>
<x-neo::select>
<option>Option 1</option>
</x-neo::select>
<x-neo::file-input />
<x-neo::range min="0" max="100" />
<x-neo::toggle checked />
<x-neo::checkbox checked />
<x-neo::radio />
| # ID | Name | Role | Status |
|---|---|---|---|
| 1 | John Doe | Admin | Active |
| 2 | Jane Smith | User | Pending |
Welcome Home!
Your Profile Data
<table class="table">
<thead>...</thead>
<tbody>...</tbody>
</table>
<div class="avatar w-16 h-16">
<img src="image.jpg" alt="Profile" />
</div>
<div class="avatar w-20 h-20 rounded-full">
<img src="image.jpg" alt="Profile" />
</div>
<details class="accordion">
<summary>Title</summary>
<div class="accordion-content">Content...</div>
</details>
<x-neo::table>
<thead>...</thead>
<tbody>...</tbody>
</x-neo::table>
<x-neo::avatar src="image.jpg" class="w-16 h-16" />
<x-neo::avatar src="image.jpg" class="w-20 h-20 rounded-full" />
<x-neo::accordion title="Title">
Content...
</x-neo::accordion>
Ini adalah contoh komponen modal bergaya Neo Brutalism.
<span class="badge">Default</span>
<span class="badge badge-primary">Primary</span>
<span class="badge badge-secondary">Secondary</span>
<span class="badge badge-danger">Danger</span>
<span class="badge badge-info">Info</span>
<div class="alert alert-success">Success Message</div>
<div class="alert alert-danger">Error Message</div>
<div class="alert alert-warning">Warning Message</div>
<div class="alert alert-info">Info Message</div>
<div class="pagination">
<div class="page-item">1</div>
<div class="page-item page-active">2</div>
</div>
<x-neo::badge>Default</x-neo::badge>
<x-neo::badge variant="primary">Primary</x-neo::badge>
<x-neo::badge variant="secondary">Secondary</x-neo::badge>
<x-neo::badge variant="danger">Danger</x-neo::badge>
<x-neo::badge variant="info">Info</x-neo::badge>
<x-neo::alert variant="success">Success Message</x-neo::alert>
<x-neo::alert variant="danger">Error Message</x-neo::alert>
<x-neo::alert variant="warning">Warning Message</x-neo::alert>
<x-neo::alert variant="info">Info Message</x-neo::alert>
<x-neo::pagination>...</x-neo::pagination>
Neo UI bundles Lucide Icons out of the box via the mallardduck/blade-lucide-icons package.
Most components like Buttons, Inputs, Alerts, and Badges support the icon attribute directly. The component will automatically handle the SVG rendering and spacing.
Include our neo-icons.js script alongside Lucide JS, and you can write cleaner HTML.
<!-- Button -->
<button class="btn btn-primary" icon="send">
Send Message
</button>
<!-- Input -->
<input type="text" class="input" icon="search" placeholder="Search...">
<!-- Alert -->
<div class="alert alert-warning" icon="triangle-alert">
<div>Watch out!</div>
</div>
<!-- Standalone Icon -->
<icon name="home" class="text-blue-500"></icon>
Simply pass the icon name to the component properties.
<!-- Button -->
<x-neo::button variant="primary" icon="send">
Send Message
</x-neo::button>
<x-neo::button iconRight="arrow-right">
Next Step
</x-neo::button>
<!-- Input -->
<x-neo::input icon="search" placeholder="Search..." />
<!-- Alert -->
<x-neo::alert variant="warning" icon="triangle-alert">
Watch out!
</x-neo::alert>
<!-- Freeform Icon Wrapper -->
<x-neo::icon name="home" class="w-8 h-8 text-blue-500" />