Guides

Patterns

Every design decision in flux was carefully and intentionally made. Understanding these intentions will make your experience with flux more intuitive.


Ideally, after internalizing some of flux's design philosophy, you will be able to almost guess how to use a component you're unfamiliar with.

Props vs attributes

Props and attributes are indistinguishable on the surface, however, we've found it helpful to make a distinction between flux-provided properties called "props" and bespoke "attributes" that will be forwarded directly to an underlying HTML element.
For example, the following component uses a prop called variant as well as a bespoke x-on:change.prevent attribute:
Copy to clipboard
<flux:button variant="primary" x-on:change.prevent="...">
When the component is rendered in the browser, the output HTML might will look something like this:
Copy to clipboard
<button type="button" class="bg-zinc-900 ..." x-on:change.prevent="...">
As you can see, the x-on:change.prevent attribute was forwarded directly to the underlying HTML element, while the variant prop was instead internally used to customize which classes were applied to the input.

Class merging

Most flux components apply Tailwind classes to their underlying elements, however, you can also pass your own classes into components and they will be automatically merged with the classes applied by flux.
Here's an example of making a button full width by passing in the w-full Tailwind utility class:
Copy to clipboard
<flux:button class="w-full">
Now, when the component is rendered, the output HTML will contain both the w-full class and other classes applied by flux:
Copy to clipboard
<button type="button" class="w-full border border-zinc-200 ...">

Dealing with class merging conflicts

Occasionally, you may run into conflicts when passing in a Tailwind utility that flux also applies internally.
For example, you may try to customize the background color of a button by passing in the bg-zinc-800 Tailwind utility class:
Copy to clipboard
<flux:button class="bg-zinc-800 hover:bg-zinc-700">
However, because flux applies it's own bg-* attributes, both classes will be rendered in the output HTML:
Copy to clipboard
<button type="button" class="bg-zinc-800 hover:bg-zinc-700 bg-white hover:bg-zinc-100...">
Because both classes exist on the element, the one defined last in CSS wins.
Tailwind's important (!) modifier is the simplest way to resolve these conflicts:
Copy to clipboard
<flux:button class="bg-zinc-800! hover:bg-zinc-700!">
The conflicting utilities will still both be rendered, however the user-defined ones with the ! modifier will take precedence.
Usage of the ! modifier can cause more problems than it solves. Below are a few alternatives to consider instead:
  • Publishing the component and adding your own variant
  • Globally customizing the component by styling the data attributes
  • Writing a new component for your unique case

Split attribute forwarding

In a perfect world, each flux component would directly render a single HTML element. However, in practice, some components are more complex than that.
For example, the flux:input component actually renders two HTML elements by default. A wrapping <div> and an underlying <input> element:
Copy to clipboard
<div class="...">    <input type="text" class="..."></div>
This presents a problem when passing bespoke Tailwind classes into the component: which element should receive the provided classes?
In these cases flux will often split up the forwarded attributes into two groups: styling related ones like class and behavioral ones like autofocus. It will then apply each to wherever is most appropriate.
For example consider passing in the following class and autofocus attributes:
Copy to clipboard
<flux:input class="w-full" autofocus>
Flux will apply the w-full class to the wrapping <div> element and the autofocus attribute to the underlying <input> element:
Copy to clipboard
<div class="w-full ...">    <input type="text" class="..." autofocus></div>

Common props

Now that you've seen some of the nuances of attributes, let's look at some common prop patterns you will encounter as you use Flux.

Variant

First up is "variant". Any component that offers an alternate visual style uses the variant prop to do so.
Here's a list of a few common component variants:
Copy to clipboard
<flux:button variant="primary" /><flux:input variant="filled" /><flux:modal variant="flyout" /><flux:badge variant="solid" /><flux:select variant="combobox" /><flux:separator variant="subtle" /><flux:tabs variant="segmented" />
If you find the need for a variant we don't offer, don't be afraid to publish a component and add your own.

Icon

Rather than manually adding, styling, and spacing icons inside component slots, you can simply pass the icon prop to any component that supports it.
Flux uses Heroicons for its icon collection. Heroicons is a set of beautiful and functional icons crafted by the fine folks at Tailwind Labs.
Here's a handful of components you can pass icons into:
Copy to clipboard
<flux:button icon="magnifying-glass" /><flux:input icon="magnifying-glass" /><flux:tab icon="cog-6-tooth" /><flux:badge icon="user" /><flux:breadcrumbs.item icon="home" /><flux:navlist.item icon="user" /><flux:navbar.item icon="user" /><flux:menu.item icon="plus" />
Occasionally, if a component supports adding an icon to the end of an element instead of the beginning by default, you can pass the icon:trailing prop as well:
Copy to clipboard
<flux:button icon:trailing="chevron-down" /><flux:input icon:trailing="credit-card" /><flux:badge icon:trailing="x-mark" /><flux:navbar.item icon:trailing="chevron-down" />

Size

Some components offer size variations through the size prop.
Here are a few components that can be sized-down:
Copy to clipboard
<flux:button size="sm" /><flux:select size="sm" /><flux:input size="sm" /><flux:tabs size="sm" />
Here are a few that can be sized up for larger visual contexts:
Copy to clipboard
<flux:heading size="lg" /><flux:badge size="lg" />

Keyboard hints

Similar to the icon prop, many components allow you to add decorative hints for keyboard shortcuts using the kbd prop:
Copy to clipboard
<flux:button kbd="⌘S" /><flux:tooltip kbd="D" /><flux:input kbd="⌘K" /><flux:menu.item kbd="⌘E" /><flux:command.item kbd="⌘N" />

Inset

Certain components offer the inset prop which makes it easy to add the exact amount of negative margin needed to "inset" an element on any axis you specify.
This is extremely useful for putting a button or a badge inline with other text and not stretching the entire height of the container.
Copy to clipboard
<flux:badge inset="top bottom"><flux:button variant="ghost" inset="left">

Prop forwarding

Occasionally, one component will wrap another and expose it as a simple prop.
For example, here is the Button component that allows you to set the icon using the simple icon prop instead of passing an entire Icon component into the Button as a child:
Copy to clipboard
<flux:button icon="bell" />
This is often a more desirable alternative to composing the entire component like so:
Copy to clipboard
<flux:button>   <flux:icon.bell /></flux:button>
However, when using the icon prop, you are unable to add additional props to the Icon component like variant.
In these cases, flux will often expose nested props via prefixes like so:
Copy to clipboard
<flux:button icon="bell" icon:variant="solid" />

Opt-out props

Sometimes flux will turn a prop "on" by default, or manage its state internally. For example, the current prop on the navbar.item component.
However, you may want to enforce that its value remains false for a specific instance of the component.
In these cases, you can use Laravel's dynamic prop syntax (:) and pass in false.
Copy to clipboard
<flux:navbar.item :current="false">

Shorthand props

Sometimes a component arrangement is both common and verbose enough that it warrants a shorthand syntax.
For example, here's a full input field:
Copy to clipboard
<flux:field>    <flux:label>Email</flux:label>    <flux:input wire:model="email" type="email" />    <flux:error name="email" /></flux:field>
This can be shortened to the following:
Copy to clipboard
<flux:input type="email" wire:model="email" label="Email" />
Internally, flux will expand the above into the full assembly of field, label, input, and error components.
This way you can keep syntax short and concise, but still have the ability to fully customize things if you'd like to use the full longform syntax.
You'll also encounter this pattern with tooltips and buttons.
Here's a long-form toolip:
Copy to clipboard
<flux:tooltip content="Settings">    <flux:button icon="cog-6-tooth" /></flux:tooltip>
Because the above is often repetitive, you can shorten it to a simple tooltip prop:
Copy to clipboard
<flux:button icon="cog-6-tooth" tooltip="Settings" />

Data binding

In Livewire you are used to adding wire:model directly to input elements inside your forms.
In Flux, the experience is no different. Here are some common components you will often be adding wire:model to:
Copy to clipboard
<flux:input wire:model="email" /><flux:checkbox wire:model="terms" /><flux:switch wire:model.live="enabled" /><flux:textarea wire:model="content" /><flux:select wire:model="state" />
In addition to these common ones you'd expect, here are a few other components you can control via wire:model:
Copy to clipboard
<flux:checkbox.group wire:model="notifications"><flux:radio.group wire:model="payment"><flux:tabs wire:model="activeTab">
Of course, you can also pass x-model or x-on:change to any of these and they should behave exactly like native input elements.

Component Groups

When a Flux component can be "grouped", but is otherwise a stand-alone component, its wrapper component has a .group suffix.
All of the following components can be used on their own, or grouped together:
Copy to clipboard
<flux:button.group>    <flux:button /></flux:button.group><flux:input.group>    <flux:input /></flux:input.group><flux:checkbox.group>    <flux:checkbox /></flux:checkbox.group><flux:radio.group>    <flux:radio /></flux:radio.group>
Alternatively, if a component can NOT be used on its own, but can be grouped, the wrapper will often be the main name of the component, and each child will have a .item suffix:
Copy to clipboard
<flux:accordion>    <flux:accordion.item /></flux:accordion><flux:menu>    <flux:menu.item /></flux:menu><flux:breadcrumbs>    <flux:breadcrumbs.item /></flux:breadcrumbs><flux:navbar>    <flux:navbar.item /></flux:navbar><flux:navlist>    <flux:navlist.item /></flux:navlist><flux:navmenu>    <flux:navmenu.item /></flux:navmenu><flux:command>    <flux:command.item /></flux:command><flux:autocomplete>    <flux:autocomplete.item /></flux:autocomplete>

Root components

Most of the time, when a component can be composed of many sub-components, you will see compound names like the ones mentioned above.
However, for components that are larger or more "primitive" feeling than the others, they will lack a common prefix, and instead use the name of the component itself.
For example, this is flux's field component:
Copy to clipboard
<flux:field>    <flux:label></flux:label>    <flux:description></flux:description>    <flux:error></flux:error></flux:field>
You'll notice bare component names like flux:label, instead of flux:field.label.
The reasoning for this is to avoid overly verbose heirarchies in common components that would result in naming like: flux:field.label.badge.
You will also see this pattern with <flux:table>.

Anomalies

As painful as it is, sometimes for something to "feel right", you have to abandon consistency for one reason or another.
For example, the flux:tabs component doesn't follow the aforementioned rules:
Copy to clipboard
<flux:tab.group>    <flux:tabs>        <flux:tab>    </flux:tabs>    <flux:tab.panel></flux:tab.group>

Slots

In general, Flux prefers composing multiple components together rather than using slots.
However, there are times where there is no substitute and slots are the perfect solution.
To demonstrate, consider the following input component with an x-mark icon:
Copy to clipboard
<flux:input icon:trailing="x-mark" />
If you wanted to wrap the icon in a clickable button to perform an action there is no way to achieve that without slots (or without offering an extremely verbose, custom syntax).
Here is the above, rewritten with a wrapping button:
Copy to clipboard
<flux:input>    <x-slot name="iconTrailing">        <flux:button icon="x-mark" size="sm" variant="subtle" wire:click="clear" />    </x-slot></flux:input>

Paper cuts

Here are a few gotchas that you might encounter while using Flux.

Blade components vs HTML elements

When dealing with plain HTML elements in Blade, you are free to use expressions like @if inside opening tags.
However, those expressions are not supported inside the opening tag of a Blade or Flux component.
Instead, you must stay within the confines of the Blade component dynamic attribute syntax:
Copy to clipboard
<!-- Conditional attributes: --><input @if ($disabled) disabled @endif><flux:input :disabled="$disabled">
Copyright © 2025 Wireable LLC ·Terms of Service
Built with by
Caleb Porzio and Hugo Sainte-Marie