# Fluxon Documentation
## Fluxon.Components.Accordion
A flexible and accessible accordion component for organizing content into collapsible sections.
Built with progressive disclosure in mind, it provides an interactive way to manage content density
while maintaining full keyboard navigation and screen reader support.
The accordion system consists of two main components working together:
- `accordion`: The main container that manages state, accessibility, and animations
- `accordion_item`: Individual sections containing headers and expandable panels
The accordion follows a structured hierarchical organization:
```
accordion
├── accordion_item
│ ├── header (slot)
│ └── panel (slot)
├── accordion_item
│ ├── header (slot)
│ └── panel (slot)
└── accordion_item
├── header (slot)
└── panel (slot)
```
Each `accordion_item` consists of two required slots:
- `header`: The always-visible clickable area that toggles the panel
- `panel`: The expandable content area that shows/hides on interaction
This structure ensures proper state management, accessibility, and visual organization while
maintaining flexibility for various content patterns, from simple text to complex interactive
components.
## Usage
The accordion component consists of two main parts: the container (`accordion`) and individual
sections (`accordion_item`). Each section has a header that toggles visibility and a panel
that contains the expandable content:
```heex
<.accordion>
<.accordion_item>
<:header>What is Fluxon?
<:panel>
Fluxon is a powerful UI component library for Phoenix LiveView applications.
<.accordion_item>
<:header>How do I get started?
<:panel>
Add Fluxon to your dependencies and follow the installation guide.
```
## Expansion Behavior
The accordion supports two primary modes of operation: single-section and multi-section expansion.
You can also control whether all sections can be collapsed simultaneously.
### Single Section Expansion (Default)
By default, only one section can be expanded at a time. Opening a new section automatically
closes the previously expanded one:
```heex
<.accordion>
<.accordion_item>
<:header>Section 1
<:panel>Content for section 1
<.accordion_item>
<:header>Section 2
<:panel>Content for section 2
```
### Multiple Section Expansion
Enable multiple section expansion by setting the `multiple` attribute:
```heex
<.accordion multiple>
<.accordion_item>
<:header>Section 1
<:panel>Can be open while other sections are expanded
<.accordion_item>
<:header>Section 2
<:panel>Also can remain open with other sections
```
### Preventing All Closed State
For cases where at least one section should always remain expanded, use `prevent_all_closed`:
```heex
<.accordion prevent_all_closed>
<.accordion_item expanded>
<:header>Always One Open
<:panel>This or another section will always be expanded
<.accordion_item>
<:header>Another Section
<:panel>More content here
```
## Rich Headers
Headers can contain complex content including icons, badges, or additional text. This is useful
for creating more informative and visually appealing accordions:
```heex
<.accordion>
<.accordion_item>
<:header class="flex items-center gap-3">
<.icon name="document" class="size-5 text-zinc-400" />
Documentation
View the complete documentation
<.badge class="ml-auto">New
<:panel>
Detailed documentation content...
```
## Keyboard Support
The accordion component implements the WAI-ARIA Accordion Pattern with comprehensive keyboard navigation:
| Key | Element Focus | Description |
|-----|---------------|-------------|
| `Tab`/`Shift+Tab` | Header | Moves focus between accordion headers and other focusable elements |
| `Space`/`Enter` | Header | Toggles the expansion state of the focused section |
| `↑` | Header | Moves focus to the previous accordion header |
| `↓` | Header | Moves focus to the next accordion header |
| `Home` | Header | Moves focus to the first accordion header |
| `End` | Header | Moves focus to the last accordion header |
| `Tab` | Panel | When panel is expanded, allows navigation through focusable elements within |
### function accordion/1
**Signatures:**
- `accordion(assigns)`
Renders an accordion component with customizable attributes and slots.
The accordion component serves as a container for collapsible sections, managing their state,
interactions, and accessibility. It provides a foundation for building expandable content areas
with proper keyboard navigation, ARIA support, and animation capabilities.
## Attributes
* `id` (`:string`) - Unique identifier for the accordion container. When not provided, a random ID will be generated.
This ID is used to establish ARIA relationships between components and manage focus state.
* `class` (`:any`) - Additional CSS classes to apply to the accordion container. These classes will be merged
with the default styles. Useful for controlling spacing, width, borders, and other visual
properties of the entire accordion.
Defaults to `nil`.
* `multiple` (`:boolean`) - When true, allows multiple accordion items to be expanded simultaneously. When false
(default), expanding one item will automatically collapse any other expanded items,
maintaining a single-section view.
Defaults to `false`.
* `prevent_all_closed` (`:boolean`) - When true, prevents all accordion items from being closed simultaneously. This ensures
that at least one item remains expanded at all times, useful for maintaining content
visibility in critical interfaces.
Defaults to `false`.
* `animation_duration` (`:integer`) - Duration of the expand/collapse animation in milliseconds. This value controls the
transition speed of panels opening and closing. Adjust this to match your application's
animation preferences or accessibility requirements.
Defaults to `300`.
## Slots
* `inner_block` (required) - Content to be rendered inside the accordion. This should contain one or more
accordion_item components that define the collapsible sections. Each item consists
of a header and panel slot.
### function accordion_item/1
**Signatures:**
- `accordion_item(assigns)`
Renders an individual accordion item with a header and expandable panel.
Each accordion item consists of a clickable header that toggles the visibility of its associated
panel. The component handles all necessary ARIA attributes, state management, and animations to
ensure proper accessibility and user interaction.
## Attributes
* `id` (`:string`) - Unique identifier for the accordion item. When not provided, a random ID will be generated.
This ID is used to establish ARIA relationships between the header button and its associated
panel, ensuring proper accessibility.
* `class` (`:any`) - Additional CSS classes to apply to the accordion item container. These classes will be
merged with the default styles. Useful for customizing the appearance of individual
sections, such as borders, backgrounds, or spacing.
Defaults to `nil`.
* `expanded` (`:boolean`) - Controls the initial expanded state of the accordion item. When true, the item will be
expanded when first rendered. This is useful for pre-expanding important content or
maintaining state across renders.
Defaults to `false`.
* `icon` (`:boolean`) - Controls the visibility of the chevron icon that indicates expand/collapse state.
Set to false to hide the icon for a more minimal appearance or when using custom
indicators in the header slot.
Defaults to `true`.
## Slots
* `panel` (required) - Content to be displayed in the expandable panel. This content is hidden when the
accordion item is collapsed and visible when expanded. The panel supports any HTML
content, including other Phoenix components and LiveView features.
Accepts attributes:
* `class` (`:any`) - Additional CSS classes to apply to the panel content container. Useful for styling
the expanded content area with custom padding, typography, or other visual properties.
* `header` (required) - Content to be displayed in the clickable header. This is always visible and toggles
the expansion state when clicked. The header can contain complex content including
icons, text, or other interactive elements.
Accepts attributes:
* `class` (`:any`) - Additional CSS classes to apply to the header button. Useful for customizing the
appearance of the clickable area, including layout, spacing, and hover states.
## Fluxon.Components.Alert
A versatile alert component for displaying status messages, notifications, and interactive feedback.
Built with accessibility and flexibility in mind, it provides a comprehensive solution for
communicating important information through visually distinct and accessible alerts.
> #### Flash Messages {: .neutral}
>
> The alert component is not intended to replace Phoenix's flash messages. For a similar aesthetic
> in flash messages, it's recommended to apply the alert component's styles to the original
> `<.flash />` component.
## Usage
The component can be used with simple text content for straightforward messages:
```heex
<.alert>Simple alert message
```

## Visual Variants
The component supports different visual styles through the `variant` attribute, each designed
for specific types of messages:
```heex
<.alert variant="info" title="Update Available">
A new version of the application is ready to install.
<.alert variant="success" title="Order Confirmed">
Your order has been successfully processed.
<.alert variant="warning" title="Session Expiring">
Your session will expire in 5 minutes.
<.alert variant="error" title="Connection Lost">
Unable to connect to the server.
```

Each variant comes with its own color scheme and icon, optimized for both light and dark modes:
- `default`: Neutral styling for general messages
- `info`: Blue accents for informational messages
- `success`: Green accents for success messages
- `warning`: Amber accents for warning messages
- `error`: Red accents for error messages
- `neutral`: Gray styling for system messages
## Content Structure
Alerts can display content in multiple ways to match your messaging needs:
#### Simple Text
For basic messages without additional context:
```heex
<.alert>Your changes have been saved.
```
#### With Title
For messages that need a clear heading:
```heex
<.alert title="Profile Updated">
Your profile changes have been saved successfully.
```
#### With Title and Subtitle
For complex messages that need additional context:
```heex
<.alert
title="Scheduled Maintenance"
subtitle="System Update"
variant="info">
The system will be unavailable on Saturday from 2 AM to 4 AM.
```
## Interactive Features
### Dismissible Alerts
By default, alerts include a close button. This behavior can be customized:
```heex
<.alert hide_close>
This alert cannot be dismissed
<.alert on_close={JS.push("handle_alert_close", value: %{id: @alert_id})}>
This alert triggers a custom event when closed
```
### Custom Actions
Alerts can include interactive elements for user actions:
```heex
<.alert
variant="warning"
title="Unsaved Changes"
on_close={JS.push("dismiss_warning")}>
You have unsaved changes that will be lost.
```

## Icon Customization
The component provides flexibility in how icons are displayed:
```heex
<.alert hide_icon>
Message without icon
<.alert>
<:icon>
<.icon name="hero-bell" class="size-5" />
Custom notification icon
```

### function alert/1
**Signatures:**
- `alert(assigns)`
Renders an alert component with support for various visual styles and interactive elements.
## Attributes
* `id` (`:string`) - The unique identifier for the alert element. If not provided, a random ID will be generated.
* `class` (`:any`) - Additional CSS classes to apply to the alert element. These are merged with the component's
base classes and variant-specific styles.
Defaults to `nil`.
* `title` (`:string`) - The main heading text of the alert. When provided, creates a title section styled according
to the chosen variant's color scheme.
Defaults to `nil`.
* `subtitle` (`:string`) - Secondary text displayed alongside the title. Only rendered when either title or subtitle
is present.
Defaults to `nil`.
* `variant` (`:string`) - The visual style variant of the alert. Affects the entire component's appearance:
- `default`: White background with zinc accents
- `neutral`: Light gray background with zinc accents
- `error`: Light red background with red accents
- `success`: Light green background with green accents
- `info`: Light blue background with sky blue accents
- `warning`: Light amber background with amber accents
Defaults to `"default"`.
* `hide_icon` (`:boolean`) - When true, hides the alert's status icon. Defaults to `false`.
* `hide_close` (`:boolean`) - When true, hides the alert's close button. Defaults to `false`.
* `on_close` (`Phoenix.LiveView.JS`) - LiveView JS commands to execute when the alert is closed. Defaults to `%Phoenix.LiveView.JS{ops: []}`.
## Slots
* `inner_block` - The main content to be displayed in the alert body. Renders with variant-specific text colors.
* `icon` - Optional custom icon to replace the default status icon. If not provided and `hide_icon`
is false, a default icon based on the variant will be shown.
## Fluxon.Components.Autocomplete
A modern, accessible autocomplete component with rich search capabilities.
The autocomplete component provides a text input that filters a list of options as the user types,
with keyboard navigation and accessibility features. It supports both client-side and server-side
search capabilities, making it suitable for both small and large datasets.
> #### Select vs Autocomplete {: .info}
>
> While both components enable users to choose from a list of options, they offer different interaction patterns
> that may better suit certain use cases.
>
> **Select Component**
> Best suited for browsing through predefined options, especially when users benefit from seeing
> all choices at once. Supports multiple selection.
>
> **Autocomplete Component**
> Optimized for searching through large datasets, with both client and server-side filtering.
> Features a type-to-search interface with custom empty states and loading indicators.
>
> **Key Differences:**
>
> | Feature | Select | Autocomplete |
> |---------|---------|--------------|
> | Primary Interaction | Click to browse | Type to search |
> | Data Size | Small to medium lists | Any size dataset |
> | Filtering | Client-side only | Client or server-side |
> | Multiple Selection | Supported | Not supported |
> | Clearing Selection | Supported | Supported |
## Usage
Basic usage with a list of options:
```heex
<.autocomplete
name="country"
options={[{"United States", "us"}, {"Canada", "ca"}]}
placeholder="Search countries..."
/>
```
The autocomplete component follows the same options API as [`Phoenix.HTML.Form.options_for_select/2`](https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html#options_for_select/2),
supporting:
- List of strings: `["Option 1", "Option 2"]`
- List of tuples: `[{"Label 1", "value1"}, {"Label 2", "value2"}]`
- List of keyword pairs: `[key: "value"]`
- Grouped options: `[{"Group", ["Option 1", "Option 2"]}]`
A full-feature example would look like this:
```heex
<.autocomplete
name="user"
label="Select User"
sublabel="Search by name or email"
description="Choose a user to assign the task to"
help_text="Type to search through all registered users"
placeholder="Search users..."
search_threshold={3}
options={@users}
/>
```
## Form Integration
The autocomplete component integrates with Phoenix forms in two ways: using the `field` attribute for form integration
or using the `name` attribute for standalone inputs.
### Using with Phoenix Forms (Recommended)
Use the `field` attribute to bind the autocomplete to a form field:
```heex
<.form :let={f} for={@changeset} phx-change="validate" phx-submit="save">
<.autocomplete
field={f[:user_id]}
label="Assigned To"
options={@users}
/>
```
Using the `field` attribute provides:
- Automatic value handling from form data
- Error handling and validation messages
- Form submission with correct field names
- Integration with changesets
- Nested form data handling
Example with a complete changeset implementation:
```elixir
defmodule MyApp.Task do
use Ecto.Schema
import Ecto.Changeset
schema "tasks" do
field :title, :string
belongs_to :assigned_to, MyApp.User
timestamps()
end
def changeset(task, attrs) do
task
|> cast(attrs, [:assigned_to_id, :title])
|> validate_required([:assigned_to_id])
end
end
# In your LiveView
def mount(_params, _session, socket) do
users = MyApp.Accounts.list_active_users() |> Enum.map(&{&1.name, &1.id})
changeset = Task.changeset(%Task{}, %{})
{:ok, assign(socket, users: users, form: to_form(changeset))}
end
def render(assigns) do
~H"""
<.form :let={f} for={@form} phx-change="validate">
<.autocomplete
field={f[:assigned_to_id]}
options={@users}
label="Assigned To"
placeholder="Search users..."
/>
"""
end
def handle_event("validate", %{"task" => params}, socket) do
changeset =
%Task{}
|> Task.changeset(params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, form: to_form(changeset))}
end
```
### Using Standalone Autocomplete
For simpler cases or when not using Phoenix forms, use the `name` attribute:
```heex
<.autocomplete
name="search_user"
options={@users}
value={@user_id}
placeholder="Search users..."
/>
```
When using standalone autocomplete:
- The `name` attribute determines the form field name
- Values are managed through the `value` attribute
- Errors are passed via the `errors` attribute
## Search Behavior
The autocomplete component offers two distinct search strategies: client-side and server-side filtering.
This flexibility allows the component to efficiently handle both small, static datasets and large,
dynamic data sources that require server-side processing.
### Client-side Search
Client-side search provides immediate feedback as users type, filtering the provided options directly
in the browser. This approach is ideal for small to medium datasets that do not require server-side processing,
such as language selections, predefined categories, list of countries, etc.
```heex
<.autocomplete
name="language"
search_mode="contains"
search_threshold={2}
no_results_text="No languages matching '%{query}'"
options={[
{"English", "en"},
{"Spanish", "es"},
{"French", "fr"},
{"German", "de"}
]}
/>
```
The component offers three search modes through the `search_mode` attribute, each providing different
matching behavior:
- `"contains"` (default): Matches if the option label contains the search query anywhere
- `"starts-with"`: Matches only if the option label begins with the search query
- `"exact"`: Matches only if the option label exactly matches the search query
The `search_threshold` attribute determines how many characters must be typed before filtering begins,
helping to prevent unnecessary filtering operations for very short queries.
### Server-side Search
For large datasets, dynamic data sources, or when complex search logic is required, the component
supports server-side search through LiveView integration. This is particularly useful when dealing
with database queries, API calls, or when implementing features like debounced search or
typeahead suggestions.
Server-side search is activated by providing the `on_search` attribute with a LiveView event name.
When users type, the component sends this event with the search query as a parameter:
```heex
<.autocomplete
name="movie"
options={@movies}
on_search="search_movies"
search_threshold={2}
placeholder="Type to search movies..."
/>
```
In your LiveView, handle the search event to fetch and update the options:
```elixir
def mount(_params, _session, socket) do
{:ok, assign(socket, movies: [])}
end
def handle_event("search_movies", %{"query" => query}, socket) when byte_size(query) >= 2 do
case MyApp.Movies.search(query) do
{:ok, movies} ->
{:noreply, assign(socket, movies: movies)}
{:error, _reason} ->
{:noreply, assign(socket, movies: [])}
end
end
```
The component automatically manages the search state, including:
- Debouncing requests to prevent excessive server calls
- Displaying a loading indicator during searches
- Maintaining the selected value while searching
- Handling empty states and error conditions
#### Initial Options
While server-side search is primarily focused on dynamic filtering, you can optionally provide
an initial set of options that will be available when the component loads:
```elixir
def mount(_params, _session, socket) do
{:ok, assign(socket, movies: MyApp.Movies.featured_movies())}
end
```
```heex
<.autocomplete
name="movie"
options={@movies}
on_search="search_movies"
search_threshold={2}
placeholder="Search movies..."
/>
```
These initial options are accessible as soon as the user interacts with the component, whether by
clicking the input field, using arrow keys (↑/↓), or focusing the input when `open_on_focus` is enabled.
The choice between providing initial options or starting with an empty list depends on your use case:
- **Initial Options**: Ideal when you want to showcase popular or recommended choices upfront,
reducing the need for typing and improving discoverability. This works well for scenarios like
movie recommendations, frequently used items, or recently accessed content.
- **Empty Initial State**: Better suited when the dataset is too large to meaningfully preload
options, when you want to encourage specific search terms, or when options are highly contextual
to the user's input. This is common in scenarios like user search in large organizations or
product search in extensive catalogs.
#### ⚠️ Selected Value and Initial Options
When the component is initialized with a value, it attempts to find the corresponding label from
the provided options to display in the input. For example, if the component is initialized with
`value={2}` and the options include `{"Alice", 2}`, the input will display "Alice" as the
selected value.
```elixir
def mount(_params, _session, socket) do
# Bad: Selected user (id: 2) is not included in initial options
{:ok, assign(socket,
selected_user_id: 2,
users: [] # Empty initial options
)}
end
```
```elixir
def mount(_params, _session, socket) do
featured_users = MyApp.Accounts.featured_users() |> Enum.map(&{&1.name, &1.id})
selected_user = MyApp.Accounts.get_user!(2)
# Good: Include the selected user in initial options
{:ok, assign(socket,
selected_user_id: selected_user.id,
users: [{selected_user.name, selected_user.id} | featured_users]
)}
end
```
When using server-side search with a selected value, it's crucial to ensure that the selected
option is included in the initial options list, even if you're starting with an otherwise empty
list. If the selected value's option is not found in the list, the raw value will be displayed
in the input, resulting in a poor user experience.
## Custom Option Rendering
The autocomplete component supports custom option rendering through its `:option` slot. For each option in the list,
the component passes a tuple `{label, value}` to the slot:
```heex
<.autocomplete
name="user"
options={@users}
placeholder="Search users..."
>
<:option :let={{label, value}}>
{label}
{user_email(value)}
```
## Header and Footer Content
The autocomplete component allows you to add custom content at the top and bottom of the listbox using
the `:header` and `:footer` slots. This is useful for adding actions like buttons or links or additional information
to the dropdown.
```heex
<.autocomplete field={f[:product]} options={@products}>
<:header class="p-2 border-b">
<:footer class="p-2 border-t">
<.button type="button" size="sm" class="w-full" as="link" navigate={~p"/products/new"}>
<.icon name="u-plus" class="size-4" /> Create new
```
Both slots support a `class` attribute for custom styling and maintain proper borders
with the options list.
### Empty State
The autocomplete component also supports a custom empty state through the `:empty_state` slot:
```heex
<.autocomplete options={@users}>
<:empty_state>
```
## Clearable Selection
By default, once a selection is made in the autocomplete component, users need to manually clear the input
field to change their selection. The `clearable` attribute adds an "✕" button that appears when a value is
selected, making it easy to reset the selection with a single click.
```heex
<.autocomplete
name="language"
clearable
options={[
{"English", "en"},
{"Spanish", "es"},
{"French", "fr"},
{"German", "de"}
]}
/>
```
This feature is particularly useful in forms where users might want to change their selection or
when the autocomplete is used for optional fields that can be left blank.
## Keyboard Support
The autocomplete component provides comprehensive keyboard navigation:
| Key | Element Focus | Description |
|-----|---------------|-------------|
| `Tab`/`Shift+Tab` | Input | Moves focus to and from the input |
| `↑` | Input | Opens listbox and highlights last option |
| `↓` | Input | Opens listbox and highlights first option |
| `↑` | Option | Moves highlight to previous visible option |
| `↓` | Option | Moves highlight to next visible option |
| `Enter` | Option | Selects the highlighted option |
| `Escape` | Any | Closes the listbox |
| Type characters | Input | Filters options based on input |
## Common Use Cases
### User Search with Avatar
```elixir
defmodule MyApp.UsersLive do
use FluxlandWeb, :live_view
def mount(_params, _session, socket) do
{:ok, socket |> assign(users: fetch_users()) |> assign(form: to_form(%{}, as: :search))}
end
def render(assigns) do
~H"""
<.form :let={f} for={@form} phx-change="search">
<.autocomplete field={f[:user_id]} options={user_options(@users)} on_search="search_users" clearable>
<:option :let={{label, value}}>
{label}
{user_by_id(value, @users)["email"]}
<:empty_state>
No matching users found
Try searching by name or email
"""
end
def handle_event("search_users", %{"query" => query}, socket) do
{:noreply, assign(socket, users: fetch_users(query))}
end
def handle_event("search", _params, socket), do: {:noreply, socket}
defp fetch_users(query \\ "") do
case Req.get("https://dummyjson.com/users/search", params: [limit: 10, q: query]) do
{:ok, %{body: %{"users" => users}}} -> users
_ -> []
end
end
defp user_options(users), do: Enum.map(users, &{&1["firstName"] <> " " <> &1["lastName"], &1["id"]})
defp user_by_id(id, users), do: Enum.find(users, &(&1["id"] == id))
end
```
### function autocomplete/1
**Signatures:**
- `autocomplete(assigns)`
Renders an autocomplete component with rich search capabilities and full keyboard navigation support.
This component provides a flexible way to build search interfaces with real-time filtering,
server-side search capabilities, and rich option rendering. It includes built-in form integration,
error handling, and accessibility features.
## Attributes
* `id` (`:any`) - The unique identifier for the autocomplete component. Defaults to `nil`.
* `name` (`:any`) - The form name for the autocomplete. Required when not using the `field` attribute.
* `field` (`Phoenix.HTML.FormField`) - The form field to bind to. When provided, the component automatically handles
value tracking, errors, and form submission.
* `class` (`:any`) - Additional CSS classes to apply to the autocomplete component. These classes are
applied to the listbox container.
Defaults to `nil`.
* `label` (`:string`) - The primary label for the autocomplete. This text is displayed above the input
and is used for accessibility purposes.
Defaults to `nil`.
* `sublabel` (`:string`) - Additional context displayed to the side of the main label. Useful for providing
extra information without cluttering the main label.
Defaults to `nil`.
* `help_text` (`:string`) - Help text to display below the autocomplete. This can provide additional context
or instructions for using the input.
Defaults to `nil`.
* `description` (`:string`) - A longer description to provide more context about the autocomplete. This appears
below the label but above the input element.
Defaults to `nil`.
* `placeholder` (`:string`) - Text to display in the input when empty. This text appears in the search input
and helps guide users to start typing.
Defaults to `nil`.
* `autofocus` (`:boolean`) - Whether the input should have the autofocus attribute. Defaults to `false`.
* `disabled` (`:boolean`) - When true, disables the autocomplete component. Disabled inputs cannot be
interacted with and appear visually muted.
Defaults to `false`.
* `size` (`:string`) - Controls the size of the autocomplete component:
- `"sm"`: Small size, suitable for compact UIs
- `"base"`: Default size, suitable for most use cases
- `"lg"`: Large size, suitable for prominent inputs
- `"xl"`: Extra large size, suitable for hero sections
Defaults to `"base"`.
* `search_threshold` (`:integer`) - The minimum number of characters required before showing suggestions.
This helps prevent unnecessary searches and improves performance.
Defaults to `0`.
* `no_results_text` (`:string`) - Text to display when no options match the search query. Use `%{query}` as a
placeholder for the actual search term. This is only shown when no custom
empty state is provided.
Defaults to `"No results found for \"%{query}\"."`.
* `on_search` (`:string`) - Name of the LiveView event to be triggered when searching. If provided, filtering
will be handled server-side. The event receives `%{"query" => query}` as parameters.
Defaults to `nil`.
* `debounce` (`:integer`) - The debounce time in milliseconds for server-side searches. This delays the `on_search`
event until the user stops typing for the specified duration.
Defaults to `200`.
* `search_mode` (`:string`) - The mode of the client-side search to use for the autocomplete:
- `"contains"`: Match if option contains the search query (default)
- `"starts-with"`: Match if option starts with the search query
- `"exact"`: Match only if option exactly matches the search query
Defaults to `"contains"`.
* `open_on_focus` (`:boolean`) - When true, the listbox opens when the input is focused, even if no search
query has been entered yet.
Defaults to `false`.
* `value` (`:any`) - The current selected value of the autocomplete. When using forms, this is
automatically handled by the `field` attribute.
* `errors` (`:list`) - List of error messages to display below the autocomplete. These are automatically
handled when using the `field` attribute with form validation.
Defaults to `[]`.
* `options` (`:list`) (required) - A list of options for the autocomplete. Can be provided in multiple formats:
- List of strings: `["Option 1", "Option 2"]`
- List of tuples: `[{"Label 1", "value1"}, {"Label 2", "value2"}]`
- List of keyword pairs: `[key: "value"]`
* `animation` (`:string`) - The animation style for the listbox. This controls how the listbox appears
and disappears when opening/closing.
Defaults to `"transition duration-150 ease-in-out"`.
* `animation_enter` (`:string`) - CSS classes applied to the listbox when it enters (opens). Defaults to `"opacity-100 scale-100"`.
* `animation_leave` (`:string`) - CSS classes applied to the listbox when it leaves (closes). Defaults to `"opacity-0 scale-95"`.
* `clearable` (`:boolean`) - When true, displays a clear button to remove the current selection.
This allows users to easily reset the input value without having to delete it manually.
Defaults to `false`.
## Slots
* `option` - Optional slot for custom option rendering. When provided, each option can be
fully customized with rich content. The slot receives a tuple `{label, value}`
for each option.
* `empty_state` - Optional slot for custom empty state rendering. When provided, this content is shown
instead of the default "no results" message when no options match the search query.
Accepts attributes:
* `class` (`:any`) - Additional CSS classes to apply to the empty state container.
* `header` - Optional slot for custom header rendering. When provided, this content is shown
in the top of the listbox.
Accepts attributes:
* `class` (`:any`) - Additional CSS classes to apply to the header container.
* `footer` - Optional slot for custom footer rendering. When provided, this content is shown
in the bottom of the listbox.
Accepts attributes:
* `class` (`:any`) - Additional CSS classes to apply to the footer container.
## Fluxon.Components.Badge
A versatile badge component for displaying status indicators, categories, and counts.
Badges are compact visual elements that help highlight information, categorize content, or show counts.
They are designed to be highly visible while maintaining readability and can adapt their appearance
for both light and dark modes.
## Usage
Badges can be used to highlight status, categorize content, or display counts:
```heex
<.badge>Default
<.badge color="blue">In Progress
<.badge color="green">Completed
<.badge color="red">Failed
```

## Colors and Theming
The badge component offers an extensive color palette optimized for both light and dark modes:
```heex
<.badge color="blue">Blue
<.badge color="green">Green
<.badge color="red">Red
<.badge color="yellow">Yellow
<.badge color="purple">Purple
<.badge color="pink">Pink
<.badge color="indigo">Indigo
<.badge color="teal">Teal
```

Each color includes carefully designed variations:
- Light mode: Semi-transparent background with matching ring
- Dark mode: Darker background with adjusted contrast
Available color spectrums:
- Base colors: `zinc` (default)
- Red spectrum: `red`, `rose`, `pink`
- Orange spectrum: `orange`, `amber`
- Yellow spectrum: `yellow`
- Green spectrum: `green`, `emerald`, `lime`
- Blue spectrum: `blue`, `sky`, `cyan`
- Purple spectrum: `purple`, `violet`, `indigo`
- Special colors: `fuchsia`, `teal`
## Visual Variants
The component offers three distinct visual styles:
```heex
<.badge variant="default">Default Badge
<.badge variant="pill">Pill Badge
<.badge variant="flat">Flat Badge
```

## Working with Icons
Badges work seamlessly with icons for enhanced visual communication. The component automatically
handles icon sizing and alignment through the `icon` class:
```heex
<.badge color="green">
<.icon name="hero-check-circle" class="icon" /> Verified
<.badge color="amber">
<.icon name="hero-clock" class="icon" /> Pending
<.badge color="red">
<.icon name="hero-x-circle" class="icon" /> Failed
```

> #### Icon Class Required {: .info}
>
> The `icon` class is required for proper icon sizing and alignment within badges:
>
> ```heex
> <.badge>
> <.icon name="hero-check" class="icon" />
> <.icon name="hero-check" />
>
> ```
## Real-World Examples
### Status Indicators
```heex
<.badge color="green" variant="pill">Active
<.badge color="amber" variant="pill">Pending
<.badge color="red" variant="pill">Inactive
```

### Category Labels
```heex
<.badge color="blue" variant="flat">Documentation
<.badge color="purple" variant="flat">Feature
<.badge color="orange" variant="flat">Bug Fix
```

### Notification Counts
```heex
<.badge color="red" variant="pill">99+
<.badge color="blue" variant="pill">New
<.badge color="green" variant="pill">4
```

### function badge/1
**Signatures:**
- `badge(assigns)`
Renders a badge component with the given attributes and content.
The badge component provides a flexible way to highlight information through visual indicators.
It supports various styles, colors, and can contain both text and icons.
## Attributes
* `class` (`:any`) - Additional CSS classes to apply to the badge element. These are merged with the component's
base classes, variant styles, and color styles.
Defaults to `nil`.
* `color` (`:string`) - The color scheme of the badge. Each color includes light and dark mode variants that affect
the background, text, and ring colors.
Defaults to `"zinc"`.
* `variant` (`:string`) - The visual style variant of the badge:
- `default`: Standard rounded corners with ring
- `pill`: Fully rounded edges for a softer look
- `flat`: Similar to default but without ring/border
Defaults to `"default"`.
* Global attributes are accepted. Additional HTML attributes to apply to the badge element.
## Slots
* `inner_block` (required) - The content to be displayed within the badge. Supports text and icons with automatic
spacing and alignment.
## Fluxon.Components.Button
A versatile button component that provides consistent, accessible, and visually appealing interactive elements.
This component offers a comprehensive solution for building interactive elements across your application,
from simple actions to complex workflows. It seamlessly integrates with Phoenix LiveView and provides
built-in support for both button and anchor tag rendering, making it suitable for navigation, form submissions,
and general user interactions.
## Usage
Buttons can be used in their simplest form for actions and interactions:
```heex
<.button>Default Button
<.button variant="solid">Solid Button
<.button variant="ghost">Ghost Button
```

## Visual Variants
The component supports three distinct visual styles:
```heex
<.button variant="default">Default
<.button variant="solid">Solid
<.button variant="ghost">Ghost
```

Each variant is designed for specific use cases:
- `default`: Standard button with subtle gradient and border, ideal for secondary actions
- `solid`: Filled button with stronger visual weight, perfect for primary actions
- `ghost`: Borderless button with hover state, great for tertiary actions
## Colors and Theming
The button supports multiple color schemes, each carefully designed for both light and dark modes:
```heex
<.button color="blue" variant="solid">Primary
<.button color="green" variant="solid">Success
<.button color="red" variant="solid">Danger
<.button color="yellow" variant="solid">Warning
```

Available colors and their common use cases:
- `default`: Neutral gray tones for general actions
- `red`: Error and destructive actions
- `yellow`: Warning or attention actions
- `green`: Success or confirmation actions
- `blue`: Primary or call-to-action buttons
Each color includes specific styling for all variants:
- Default: Semi-transparent with matching border
- Solid: Full color with white text
- Ghost: Colored text with transparent background
## Size Options
The component offers five size variants to accommodate different use cases:
```heex
<.button size="xs">Extra Small
<.button size="sm">Small
<.button size="md">Medium
<.button size="lg">Large
<.button size="xl">Extra Large
```

Size specifications:
| Size | Height | Text | Icon Size | Use Case |
|------|--------|------|-----------|-----------|
| `xs` | 32px | xs | 14px | Compact UI elements |
| `sm` | 36px | sm | 16px | Secondary actions |
| `md` | 40px | sm | 16px | Default size |
| `lg` | 44px | base | 18px | Primary actions |
| `xl` | 48px | base/lg | 20px | Hero sections |
## Working with Icons
The button component automatically handles icon sizing and spacing:
```heex
<.button>
<.icon name="hero-plus" class="icon" /> Add Item
<.button variant="solid" color="green">
<.icon name="hero-check" class="icon" /> Confirm
```

> #### Icon Class Required {: .info}
>
> The `icon` class is required for proper icon sizing and alignment:
>
> ```heex
> <.button>
> <.icon name="hero-check" class="icon" />
> <.icon name="hero-check" />
>
> ```
## Link Mode
The button can be rendered as a link while maintaining consistent styling:
```heex
<.button as="link" navigate={~p"/dashboard"}>
Go to Dashboard
```
When used as a link, it supports all LiveView link attributes:
- `navigate`: For live navigation
- `patch`: For live patches
- `href`: For regular navigation
- Standard anchor attributes (`target`, `rel`, etc.)
## Real-World Examples
### Primary Action
```heex
<.button variant="solid" color="blue" size="lg">
<.icon name="hero-arrow-right" class="icon" />
Get Started
```

### Destructive Action
```heex
<.button variant="solid" color="red" phx-click="delete_account" phx-value-id={@account_id}>
<.icon name="hero-trash" class="icon" />
Delete Account
```

### Navigation Link
```heex
<.button as="link" navigate={~p"/settings"} variant="ghost">
<.icon name="hero-cog-6-tooth" class="icon" />
Settings
```

### function button/1
**Signatures:**
- `button(assigns)`
Renders a button or link with customizable styles and attributes.
This component provides a flexible way to create interactive elements with consistent styling
across your application. It supports various sizes, colors, and visual variants while maintaining
proper accessibility and user experience standards.
## Attributes
* `color` (`:string`) - The color scheme of the button. Each color includes specific styles for all variants
and maintains proper contrast in both light and dark modes.
Defaults to `"default"`.
* `size` (`:string`) - The size variant of the button. Affects height, padding, font size, and icon sizing. Defaults to `"md"`.
* `type` (`:string`) - The type attribute for button elements. Common values: `button`, `submit`, `reset`.
Only applies when `as` is set to `button`.
Defaults to `nil`.
* `variant` (`:string`) - The visual style variant of the button:
- `default`: Standard button with subtle gradient and border
- `solid`: Filled button with stronger visual weight
- `ghost`: Borderless button with hover state
Defaults to `"default"`.
* `as` (`:string`) - Determines whether the component renders as a button or link element.
When `link` is used, all Phoenix LiveView link attributes are supported.
Defaults to `"button"`.
* `class` (`:any`) - Additional CSS classes to be applied to the button. These are merged with
the component's base classes, variant styles, and size styles.
Defaults to `nil`.
* Global attributes are accepted. Additional HTML attributes to apply to the button element.
Supports both standard button attributes and anchor/link attributes.
Supports all globals plus: `["target", "download", "rel", "hreflang", "type", "referrerpolicy", "navigate", "patch", "href", "replace", "method", "csrf_token", "autofocus", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "type", "value"]`.
## Slots
* `inner_block` (required) - The content to be displayed within the button. Supports text and icons
with automatic spacing and sizing based on the selected size variant.
## Fluxon.Components.Checkbox
A versatile checkbox component for capturing single and multiple selections.
This component provides a comprehensive solution for building accessible form inputs, selection interfaces,
and rich interactive content. It seamlessly integrates with Phoenix forms and offers both standard and
card variants to accommodate various design patterns, from simple boolean toggles to visually rich
selection interfaces.
## Usage
The checkbox component can be used in its simplest form for single selections:
```heex
<.checkbox
name="terms"
label="I agree to the terms and conditions"
value="accepted"
/>
```

The checkbox value will be `"true"` when checked and `"false"` when unchecked.
```elixir
%{"_target" => ["terms"], "terms" => "true"}
%{"_target" => ["terms"], "terms" => "false"}
```
For more context, you can add sublabels and descriptions:
```heex
<.checkbox
name="notifications"
label="Enable notifications"
sublabel="Receive updates about your account"
description="We'll send you important updates about your account status and security."
/>
```

## Form Integration
The checkbox component offers two ways to handle form data: using the `field` attribute for Phoenix form integration
or using the `name` attribute for standalone checkboxes. Each approach has its own benefits and use cases.
### Using with Phoenix Forms (Recommended)
When working with Phoenix forms, use the `field` attribute to bind the checkbox to a form field:
```heex
<.form :let={f} for={@form} phx-change="validate" phx-submit="save">
<.checkbox
field={f[:marketing_emails]}
label="Marketing emails"
sublabel="Receive updates about new features and promotions"
/>
<.checkbox
field={f[:terms_accepted]}
label="Terms and Conditions"
description="I agree to the terms of service and privacy policy"
value="accepted"
/>
<.checkbox
field={f[:newsletter_frequency]}
label="Weekly newsletter"
value="weekly"
checked={@user.newsletter_frequency == "weekly"}
/>
```
Using the `field` attribute provides several advantages:
- Automatic value handling from the form data
- Built-in error handling and validation messages
- Proper form submission with correct field names
- Integration with changesets for data validation
- Automatic ID generation for accessibility
- Proper handling of nested form data
The component will automatically:
- Set the checkbox field's name based on the form structure
- Display the current value from the form data
- Show validation errors when present
- Handle nested form data with proper input naming
### Using Standalone Checkboxes
For simpler cases or when not using Phoenix forms, use the `name` attribute:
```heex
<.checkbox
name="show_archived"
checked={@show_archived}
label="Show archived items"
/>
<.checkbox
name="user[preferences][dark_mode]"
checked={@user_preferences.dark_mode}
errors={@errors["dark_mode"]}
label="Dark mode"
sublabel="Use dark theme"
/>
```
When using standalone checkboxes:
- You must provide the `name` attribute
- Values must be managed manually via the `checked` attribute
- Errors must be passed explicitly via the `errors` attribute
- Form submission handling needs to be implemented manually
- Nested data requires manual name formatting (e.g., `user[preferences][dark_mode]`)
> #### When to use each approach {: .tip}
>
> Use the `field` attribute when:
> - Working with changesets and data validation
> - Handling complex form data structures
> - Need automatic error handling
> - Building CRUD interfaces
>
> Use the `name` attribute when:
> - Building simple toggle controls
> - Creating standalone filters
> - Handling one-off form controls
> - Need more direct control over the checkbox behavior
## Card Variant
The component offers a card variant that transforms checkboxes into rich, interactive selection cards:
```heex
<.checkbox
control="left"
field={f[:notifications]}
variant="card"
label="Push Notifications"
sublabel="Stay informed"
description="Get real-time updates for messages and activity"
value="enabled"
/>
```

## Checkbox Group
Checkbox groups are used to map a list of options to a single form field:
```heex
<.checkbox_group
name="preferences"
label="Notification Preferences"
description="Choose when you want to receive notifications"
>
<:checkbox value="email" label="Email notifications" />
<:checkbox value="push" label="Push notifications" />
<:checkbox value="sms" label="SMS notifications" />
```

### Form Integration
Like the single checkbox component, checkbox groups seamlessly integrate with Phoenix forms. See the form integration section in the [Form Integration](#module-form-integration) section for a detailed guide on form handling.
Here's a simple example using the `field` attribute:
```heex
<.form :let={f} for={@form} phx-change="validate" phx-submit="save">
<.checkbox_group
field={f[:notification_preferences]}
label="Notification Preferences"
description="Choose how you want to be notified"
>
<:checkbox value="email" label="Email" sublabel="Get notified via email" />
<:checkbox value="push" label="Push" sublabel="Receive push notifications" />
<:checkbox value="sms" label="SMS" sublabel="Get SMS alerts" />
```
Different from the single checkbox, the group will send a list of selected values in the form submission:
```elixir
%{"_target" => ["preferences"], "preferences" => ["", "email", "push"]}
```
> #### Empty Values in Checkbox Groups {: .info}
>
> When working with checkbox groups, it's important to understand how browsers handle unselected checkboxes:
>
> - By HTML specification, browsers only submit values for checked checkboxes
> - If no checkboxes are selected, the field will be completely absent from the form data
>
> To ensure consistent form handling, this component includes a hidden input with an empty value:
>
> ```elixir
>
> ```
>
> This means your form submissions will always include the field, with these possible values:
>
> ```elixir
> # No checkboxes selected
> %{"group" => [""]}
>
> # One or more selected
> %{"group" => ["", "option1", "option2"]}
> ```
>
> When processing the form data, you'll want to:
> 1. Filter out the empty string value
> 2. Handle an empty list as "no selection"
>
> ```elixir
> # Example processing
> selected = Enum.reject(params["group"] || [], &(&1 == ""))
> ```
### Card Variant
The card variant transforms checkboxes into rich, interactive selection cards:
```heex
<.checkbox_group
label="Weekdays"
description="Select the days of the week you want to work"
field={f[:weekdays]}
variant="card"
class="flex gap-x-2"
>
<:checkbox
:for={{label, value} <- [{"S", "sun"}, {"M", "mon"}, {"T", "tue"}, {"W", "wed"}, {"T", "thu"}, {"F", "fri"}, {"S", "sat"}]}
value={value}
class="flex items-center justify-center rounded-full has-checked:bg-zinc-800 text-zinc-700 has-checked:text-white size-10"
>
{label}
```

### function checkbox/1
**Signatures:**
- `checkbox(assigns)`
Renders a single checkbox input for capturing boolean or single-value selections.
This component provides a flexible way to build form inputs with support for labels,
descriptions, and rich styling options. It includes built-in form integration, error
handling, and accessibility features.
## Attributes
* `id` (`:any`) - The unique identifier for the checkbox. When not provided, a random ID will be generated. Defaults to `nil`.
* `name` (`:any`) - The form name for the checkbox. Required when not using the `field` attribute.
* `checked` (`:boolean`) - Whether the checkbox is checked. When using forms, this is automatically handled
by the `field` attribute.
* `value` (`:any`) - The value associated with the checkbox. This value is submitted when the checkbox
is checked.
* `errors` (`:list`) - List of error messages to display below the checkbox. These are automatically
handled when using the `field` attribute with form validation.
Defaults to `[]`.
* `label` (`:string`) - The primary label for the checkbox. This text is displayed next to the checkbox
and is used for accessibility purposes.
Defaults to `nil`.
* `sublabel` (`:string`) - Additional context displayed to the side of the main label. Useful for providing extra
information without cluttering the main label.
Defaults to `nil`.
* `description` (`:string`) - Detailed description of the checkbox option. This text appears below the label
and can contain longer explanatory text.
Defaults to `nil`.
* `class` (`:any`) - Additional CSS classes to apply to the checkbox. Useful for controlling the
appearance of the checkbox.
Defaults to `nil`.
* `field` (`Phoenix.HTML.FormField`) - The form field to bind to. When provided, the component automatically handles
value tracking, errors, and form submission.
* `variant` (`:string`) - The visual variant of the checkbox. Currently supports:
- `nil` (default): Standard checkbox with label
- `"card"`: Rich selection card with support for custom content
Defaults to `nil`.
* `control` (`:string`) - Controls the position of the checkbox input in card variants. It's only available when `variant="card"`.
- `"left"`: Places the checkbox on the left side of the card
- `"right"`: Places the checkbox on the right side of the card
Must be one of `"left"`, or `"right"`.
* Global attributes are accepted. Additional HTML attributes to apply to the checkbox input. Currently supports
the `disabled` attribute.
Supports all globals plus: `["disabled"]`.
## Slots
* `inner_block` - Optional custom content for the checkbox. When provided in card variants,
this content replaces the standard label/sublabel/description structure.
### function checkbox_group/1
**Signatures:**
- `checkbox_group(assigns)`
Renders a checkbox group for managing multiple related selections.
This component provides a flexible way to handle multiple choice selections, with support for both
standard checkbox lists and rich card-based interfaces. It includes built-in form integration,
error handling, and accessibility features.
## Attributes
* `id` (`:any`) - The unique identifier for the checkbox group. When not provided, a random ID will be generated. Defaults to `nil`.
* `name` (`:string`) - The form name for the checkbox group. For groups, this will be suffixed with `[]` to support
multiple selections. Required when not using the `field` attribute.
* `value` (`:any`) - The current value(s) of the checkbox group. For groups, this should be a list of selected values.
When using forms, this is automatically handled by the `field` attribute.
* `label` (`:string`) - The primary label for the checkbox group. This text is displayed above the checkboxes
and is used for accessibility purposes.
Defaults to `nil`.
* `sublabel` (`:string`) - Additional context displayed on the side of the main label. Useful for providing extra information
about the checkbox group without cluttering the main label.
Defaults to `nil`.
* `description` (`:string`) - Detailed description of the checkbox group. This text appears below the label and
can contain longer explanatory text about the available options.
Defaults to `nil`.
* `errors` (`:list`) - List of error messages to display below the checkbox group. These are automatically
handled when using the `field` attribute with form validation.
Defaults to `[]`.
* `class` (`:any`) - Additional CSS classes to apply to the checkbox group container. Useful for controlling
layout, spacing, and visual styling of the group.
Defaults to `nil`.
* `field` (`Phoenix.HTML.FormField`) - The form field to bind to. When provided, the component automatically handles value
tracking, errors, and form submission.
* `disabled` (`:boolean`) - When true, disables all checkboxes in the group. Disabled checkboxes cannot be
interacted with and appear visually muted.
Defaults to `false`.
* `variant` (`:string`) - The visual variant of the checkbox group. Currently supports:
- `nil` (default): Standard stacked checkboxes
- `"card"`: Rich selection cards with support for custom content
Defaults to `nil`.
* `control` (`:string`) - Controls the position of the checkbox input in card variants. It's only available when `variant="card"`.
- `"left"`: Places the checkbox on the left side of the card
- `"right"`: Places the checkbox on the right side of the card
Must be one of `"left"`, or `"right"`.
## Slots
* `checkbox` (required) - Defines the individual checkboxes within the group. Each checkbox can have:
- `value`: The value associated with this checkbox
- `label`: The checkbox label
- `sublabel`: Additional context on the side of the label
- `description`: Detailed description of the option
- `disabled`: Whether this specific checkbox is disabled
- `class`: Additional CSS classes for this checkbox
- `checked`: Whether this checkbox should be checked by default
Accepts attributes:
* `value` (`:any`) (required)
* `label` (`:string`)
* `sublabel` (`:string`)
* `description` (`:string`)
* `disabled` (`:boolean`)
* `class` (`:any`)
* `checked` (`:boolean`)
## Fluxon.Components.DatePicker
A date picker component that provides calendar-based date selection with support for time picking and date ranges.
## Usage
The component provides three specialized functions to handle different date selection needs. Here are examples
of each use case:
```heex
<.date_picker
name="appointment"
label="Appointment Date"
/>
<.date_time_picker
name="meeting"
label="Meeting Time"
time_format="12" # or "24" for 24-hour format
/>
<.date_range_picker
start_name="check_in"
end_name="check_out"
label="Stay Period"
/>
```
Like all other form components, the date picker supports various labeling options to provide
context and guidance to users:
```heex
<.date_picker
name="appointment"
label="Appointment Date"
sublabel="Required"
description="Choose when you'd like to schedule your consultation"
help_text="Our office is open Monday through Friday, 9 AM to 5 PM"
/>
```
## Date Range Constraints
The date picker supports limiting the selectable dates through the `min` and `max` attributes.
Both attributes expect an Elixir `Date` struct and provide client-side validation only. For
security purposes, you should always implement corresponding backend validations, typically
through Ecto changesets.
Here's an example that limits date selection to the next 30 days:
```heex
<.date_picker
field={f[:deadline]}
label="Project Deadline"
min={Date.utc_today()}
max={Date.add(Date.utc_today(), 30)}
/>
```
You can also use date literals with the `~D` sigil for fixed dates:
```heex
<.date_picker
name="birth_date"
label="Birth Date"
min={~D[1900-01-01]}
max={Date.utc_today()}
/>
```
When date constraints are set, the component:
- Disables and visually styles dates outside the allowed range
- Prevents keyboard navigation to disabled dates
- Automatically disables month/year navigation buttons when the visible month would not show any selectable dates
- Ensures the calendar opens to a month containing selectable dates, even if the current month is outside the allowed range
- Maintains the constraints when switching between months or years
- Clears the selection if a previously selected date becomes invalid due to dynamically changed constraints
## Multiple Date Selection
The date picker supports selecting multiple dates through the `multiple` attribute. This mode is
particularly useful for scenarios like scheduling recurring events, selecting holiday dates, or
planning multiple appointments:
```heex
<.date_picker
field={f[:holidays]}
label="Company Holidays"
multiple
description="Select all company holidays for the year"
help_text="Click dates to toggle selection"
/>
```
When multiple date selection is enabled:
- The calendar remains open after each selection to facilitate choosing multiple dates
- Each selected date is visually highlighted in the calendar
- Clicking a selected date deselects it
- The toggle button displays "X dates selected" when more than one date is chosen
- Time picker integration is not supported (see [Time Picker Integration](#module-time-picker-integration))
- Auto-close mode is not supported (see [Closing Strategies](#module-closing-strategies))
> #### Browser Behavior with Multiple Fields {: .info}
>
> When using multiple selection fields in HTML forms (e.g., `name="dates[]"`), browsers have a
> specific behavior that can affect form submissions:
>
> - When options are selected, each value is included in the form data
> - However, when all options are deselected, the browser omits the field entirely from the form submission
> - This means the server cannot distinguish between "no form submitted" and "user deselected all dates"
>
> To work around this browser limitation, the component automatically includes a hidden input with an
> empty value. As a result, when all dates are deselected, an empty string is sent to the backend
> instead of omitting the field entirely. This results in consistent form submissions:
>
> ```elixir
> # When dates are selected
> %{
> "date_form" => %{
> "holidays" => ["2025-05-15", "2025-05-14", "2025-05-22"]
> }
> }
>
> # When all dates are deselected (hidden input provides the empty value)
> %{
> "date_form" => %{
> "holidays" => [""] # Instead of field being omitted entirely
> }
> }
> ```
## Date Formatting
The date picker uses Elixir's [strftime](https://hexdocs.pm/calendar/Calendar.Strftime.html#strftime/3)
under the hood to format dates. Control how dates are displayed using the `display_format` attribute:
```heex
<.date_picker
field={f[:date]}
label="Date"
display_format="%B %-d, %Y" # Displays as "January 1, 2024"
/>
```
Common date format patterns:
- `"%Y-%m-%d"`: ISO format (2024-01-01)
- `"%b %-d, %Y"`: Short month (Jan 1, 2024)
- `"%B %-d, %Y"`: Full month (January 1, 2024)
- `"%d/%m/%Y"`: European format (01/01/2024)
- `"%m/%d/%Y"`: US format (01/01/2024)
When using the `date_time_picker/1` component, you should include time format patterns in your display format. Here are some common datetime patterns:
```heex
<.date_time_picker
field={f[:appointment]}
label="Appointment"
time_format="12"
display_format="%B %-d, %Y at %I:%M %p" # January 1, 2024 at 02:30 PM
/>
<.date_time_picker
field={f[:meeting]}
label="Meeting"
time_format="24"
display_format="%Y-%m-%d %H:%M" # 2024-01-01 14:30
/>
```
Common datetime format patterns:
- `"%Y-%m-%d %H:%M:%S"`: ISO format with 24h time (2024-01-01 14:30:00)
- `"%B %-d, %Y at %I:%M %p"`: Full month with 12h time (January 1, 2024 at 02:30 PM)
- `"%d/%m/%Y %H:%M"`: European format with 24h time (01/01/2024 14:30)
- `"%m/%d/%Y %I:%M %p"`: US format with 12h time (01/01/2024 02:30 PM)
- `"%a, %b %-d at %I:%M %p"`: Short format (Mon, Jan 1 at 02:30 PM)
Time format specifiers:
- `%H`: 24-hour format (00-23)
- `%I`: 12-hour format (01-12)
- `%M`: Minutes (00-59)
- `%S`: Seconds (00-59)
- `%p`: AM/PM indicator
> #### Format Specifier Compatibility {: .info}
>
> Time-related format specifiers (`%H`, `%M`, `%S`, `%I`, `%p`) should only be used with the
> `date_time_picker/1` component. Using these specifiers with `date_picker/1` or `date_range_picker/1`
> will raise formatting errors since these components do not handle time values.
## Week Start Configuration
The date picker allows customizing which day of the week appears in the first column
through the `week_start` attribute. This is particularly useful for adapting to different
cultural preferences, as some regions start their weeks on Sunday while others prefer Monday:
```heex
<.date_picker
field={f[:date]}
label="Date"
week_start={1} # Week starts on Monday
/>
```
The `week_start` attribute accepts a number from 0 to 6, where each number maps to a day:
| Integer | Weekday | Notes |
|---------|----------|--------|
| 0 | Sunday | Default |
| 1 | Monday | Common in Europe |
| 2 | Tuesday | |
| 3 | Wednesday| |
| 4 | Thursday | |
| 5 | Friday | Common in Islamic countries |
| 6 | Saturday | Common in Nepal |
When you change the week start day:
- The calendar grid adjusts to show the specified day in the first column
- All other days shift accordingly while maintaining their order
- Week-based keyboard navigation (e.g., up/down arrows) adapts to the new week structure
- The calendar maintains the new week start even when navigating between months
## Date Time Picker
The `date_time_picker/1` function combines date selection with precise time input, supporting both 12-hour and 24-hour time formats. This is particularly useful for scheduling appointments, meetings, or any event that requires specific timing:
```heex
<.date_time_picker
field={f[:appointment]}
label="Appointment Time"
time_format="12"
display_format="%B %-d, %Y at %I:%M %p"
/>
```
The time input interface appears below the calendar and includes hours and minutes fields. When using 12-hour format (`time_format="12"`), an AM/PM selector is also displayed. The component handles time entry through both keyboard input and increment/decrement controls:
```heex
<.date_time_picker
field={f[:meeting_start]}
label="Meeting Start"
time_format="24"
display_format="%d/%m/%Y %H:%M"
/>
<.form :let={f} for={@changeset} phx-change="validate">
<.date_time_picker
field={f[:scheduled_at]}
label="Schedule For"
time_format="12"
min={~D[2025-02-01]}
max={~D[2025-03-31]}
/>
```
When working with the date time picker, keep in mind:
The field value must be a `NaiveDateTime` or `DateTime` struct. Using a `Date` struct will raise runtime errors since it cannot store time information. For example, in your schema:
```elixir
schema "appointments" do
field :scheduled_at, :naive_datetime
# ...
end
```
The component provides a natural interface for time selection:
- Direct keyboard input for quick value entry
- Up/down arrow keys to increment/decrement values
- Automatic value constraints (hours: 0-23 or 1-12, minutes: 0-59)
- Tab navigation between hour, minute, and AM/PM fields
- AM/PM toggle with 'a' and 'p' keys in 12-hour mode
- Enter key to confirm and close the date time picker
> #### Timezone Handling {: .warning}
>
> The DatePicker component currently does not support timezone handling. All dates and times are treated as UTC. Timezone support is planned for future versions.
## Date Range Picker
The `date_range_picker/1` function provides a specialized interface for selecting date ranges, making it ideal for booking systems, reporting tools, or any feature requiring start and end dates. The component offers both form-integrated and standalone usage:
```heex
<.form :let={f} for={@changeset} phx-change="validate">
<.date_range_picker
start_field={f[:start_date]}
end_field={f[:end_date]}
label="Booking Period"
min={Date.utc_today()}
max={Date.add(Date.utc_today(), 90)}
/>
```
Unlike the single date picker, the range picker handles two distinct fields (start and end dates) individually. This means each date has its own field in your schema and form, providing more flexibility for validation and data handling. The component provides visual feedback during selection, highlighting the range as users make their choices. When a date is selected, it becomes either the start or end date based on its position relative to any existing selection. The calendar remains open until both dates are chosen, allowing users to adjust their selection with immediate visual feedback.
The component supports several intuitive interaction patterns:
- Click two different dates to select a range
- Click the same date twice to create a single-day range
- Click a date within an existing range to shrink the range
- Click outside an existing range to expand it
- Click a selected date to clear the selection and start over
For standalone usage without form integration, use the name-based attributes:
```heex
<.date_range_picker
start_name="check_in"
end_name="check_out"
start_value={@check_in}
end_value={@check_out}
label="Stay Period"
description="Select your check-in and check-out dates"
/>
```
The component handles various selection patterns intuitively:
```heex
<.date_range_picker
start_field={f[:period_start]}
end_field={f[:period_end]}
label="Report Period"
display_format="%B %-d, %Y" # January 1, 2024
min={Date.utc_today()}
max={Date.add(Date.utc_today(), 365)}
help_text="Select dates within the current year"
/>
```
Form submissions include both start and end dates as separate fields, making it straightforward to handle in your LiveView:
```elixir
def handle_event("validate", %{"booking" => params}, socket) do
changeset =
%Booking{}
|> Booking.changeset(params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, form: to_form(changeset))}
end
# In your schema
schema "bookings" do
field :start_date, :date
field :end_date, :date
timestamps()
end
def changeset(booking, attrs) do
booking
|> cast(attrs, [:start_date, :end_date])
|> validate_required([:start_date, :end_date])
|> validate_start_before_end()
end
defp validate_start_before_end(changeset) do
case {get_field(changeset, :start_date), get_field(changeset, :end_date)} do
{start_date, end_date} when not is_nil(start_date) and not is_nil(end_date) ->
if Date.compare(end_date, start_date) == :lt do
add_error(changeset, :end_date, "must be after start date")
else
changeset
end
_ ->
changeset
end
end
```
The component automatically sorts the selected dates, ensuring that the earlier date becomes the start date regardless of selection order. This behavior, combined with the visual feedback and intuitive interaction patterns, creates a natural and error-resistant date range selection experience.
## Closing Strategies
The date picker provides three distinct modes for handling when the calendar closes and when changes are confirmed. Each mode serves different use cases and can be controlled through the `close` attribute.
### Auto Mode (default)
The default `"auto"` mode provides the most streamlined experience for single date selection. In this mode, the calendar closes immediately after a date is selected, and change events are emitted as soon as the selection is made. This is ideal for simple date picking scenarios where immediate feedback is desired:
```heex
<.date_picker
field={f[:date]}
close="auto"
/>
```
The component automatically falls back to manual mode when using features that require multiple interactions, such as time picker integration, range selection, or multiple date selection.
### Manual Mode
The `"manual"` mode keeps the calendar open after selection, offering more flexibility for users who need to compare dates or make multiple adjustments. While the calendar stays open, change events are still emitted immediately as selections change:
```heex
<.date_picker
field={f[:date]}
close="manual"
/>
```
Users can explicitly close the calendar through standard interactions: pressing the Escape key, clicking outside the calendar, or clicking the toggle button.
### Confirm Mode
The `"confirm"` mode adds an explicit confirmation step, making it ideal for scenarios where accuracy is crucial. This mode introduces Cancel and Confirm buttons at the bottom of the calendar and treats changes as "pending" until explicitly confirmed:
```heex
<.date_picker
field={f[:date]}
close="confirm"
/>
```
In confirm mode, the calendar stays open until explicitly confirmed or cancelled, and change events are only emitted after clicking the confirm button. If the user cancels or closes the calendar, the previous selection is restored, ensuring data integrity.
> #### Mode Selection Tips {: .tip}
>
> Choose the mode that best fits your use case:
> - Use `"auto"` for simple, single date selections where immediate feedback is appropriate
> - Use `"manual"` when users need to compare or review dates before finalizing
> - Use `"confirm"` when accuracy is crucial and changes need explicit confirmation
> - The component will automatically adjust to `"manual"` mode when using time picker, range selection, or multiple selection features for better user experience
## Navigation Modes
The date picker provides three navigation modes that determine how users can move between months and years. Each mode is configured through the `navigation` attribute.
### Default Mode
The default mode offers a simple and clean interface focused on month-to-month navigation. It displays the current month and year as text, with arrow buttons on either side for moving to the previous or next month.
```heex
<.date_picker field={f[:date]} navigation="default" />
```
### Extended Mode
Extended mode enhances the default navigation by adding year navigation arrows alongside the month arrows. This creates a more efficient way to navigate through larger time spans while maintaining the familiar arrow-based interaction.
```heex
<.date_picker field={f[:date]} navigation="extended" />
```
### Select Mode
Select mode transforms the navigation interface by combining month arrows with dropdown menus for both month and year selection. The dropdowns provide direct access to any month or year within the allowed range.
```heex
<.date_picker field={f[:date]} navigation="select" />
```
> #### Navigation and Constraints {: .info}
>
> The date picker intelligently handles navigation when date constraints are set:
> - Navigation buttons and dropdowns automatically disable when reaching min/max limits
> - The calendar ensures the visible month always contains selectable dates
> - Year dropdown options are limited to the years within the allowed range
## Form Integration
The date picker component provides robust form integration through two approaches: using Phoenix form fields
(recommended) or using standalone name attributes. Each approach supports single dates, multiple dates, and
date ranges.
### Using with Phoenix Forms (Recommended)
Use the `field` attribute to bind the date picker to a form field:
```heex
<.form :let={f} for={@changeset} phx-change="validate" phx-submit="save">
<.date_picker
field={f[:appointment_date]}
label="Appointment Date"
min={Date.utc_today()}
max={Date.add(Date.utc_today(), 30)}
/>
```
Using the `field` attribute provides:
- Automatic value handling from form data
- Error handling and validation messages
- Form submission with correct field names
- Integration with changesets
- ID generation for accessibility
- Proper type conversion between form data and Elixir date types
- Nested form data handling
Here's a complete example showing different date field types and validations:
```elixir
defmodule MyApp.Booking do
use Ecto.Schema
import Ecto.Changeset
schema "bookings" do
# Single date field
field :appointment_date, :date
# Date with time
field :meeting_datetime, :naive_datetime
# Multiple dates
field :blocked_dates, {:array, :date}
# Date range
field :start_date, :date
field :end_date, :date
timestamps()
end
def changeset(booking, attrs) do
booking
|> cast(attrs, [:appointment_date, :meeting_datetime, :blocked_dates, :start_date, :end_date])
|> validate_required([:appointment_date])
|> validate_future_date(:appointment_date)
|> validate_date_range()
end
# Custom validation for future dates
defp validate_future_date(changeset, field) do
validate_change(changeset, field, fn _, date ->
if Date.compare(date, Date.utc_today()) == :lt do
[{field, "must be in the future"}]
else
[]
end
end)
end
# Validate that end_date comes after start_date
defp validate_date_range(changeset) do
case {get_field(changeset, :start_date), get_field(changeset, :end_date)} do
{start_date, end_date} when not is_nil(start_date) and not is_nil(end_date) ->
if Date.compare(end_date, start_date) == :lt do
add_error(changeset, :end_date, "must be after start date")
else
changeset
end
_ ->
changeset
end
end
end
# In your LiveView
def mount(_params, _session, socket) do
changeset = Booking.changeset(%Booking{}, %{})
{:ok, assign(socket, form: to_form(changeset))}
end
def render(assigns) do
~H"""
<.form :let={f} for={@form} phx-change="validate">
<.date_picker
field={f[:appointment_date]}
label="Appointment Date"
min={Date.utc_today()}
/>
<.date_time_picker
field={f[:meeting_datetime]}
label="Meeting Time"
time_format="12"
/>
<.date_picker
field={f[:blocked_dates]}
label="Blocked Dates"
multiple
help_text="Select multiple dates that should be unavailable"
/>
<.date_range_picker
start_field={f[:start_date]}
end_field={f[:end_date]}
label="Booking Period"
/>
"""
end
def handle_event("validate", %{"booking" => params}, socket) do
changeset =
%Booking{}
|> Booking.changeset(params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, form: to_form(changeset))}
end
```
### Using Standalone Date Pickers
For simpler cases or when not using Phoenix forms, use the `name` attribute:
```heex
<.date_picker
name="filter_date"
label="Filter By Date"
value={@selected_date}
/>
<.date_picker
name="holiday_dates[]"
label="Holiday Dates"
multiple
value={@selected_dates}
/>
<.date_range_picker
start_name="check_in"
end_name="check_out"
start_value={@check_in}
end_value={@check_out}
label="Stay Period"
/>
<.date_time_picker
name="event_time"
label="Event Time"
time_format="24"
value={@event_datetime}
/>
```
When using standalone date pickers:
- The `name` attribute determines the form field name
- Values are managed through the `value` attribute (or `start_value`/`end_value` for ranges)
- For multiple selection, append `[]` to the name attribute
- Errors are passed via the `errors` attribute
- Values are submitted in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DD HH:mm:ss)
- For date ranges, use `start_name` and `end_name` to specify field names
> #### Type Handling {: .info}
>
> The date picker automatically handles conversion between string values and Elixir date types:
> - `:date` fields expect and return `Date` structs
> - `:naive_datetime` fields expect and return `NaiveDateTime` structs
> - `:datetime` fields expect and return `DateTime` structs
> - Multiple selection fields work with lists of these types
> - When using standalone mode, values are always in ISO 8601 string format
## Keyboard Support
The component provides comprehensive keyboard navigation:
| Key | Element Focus | Description |
|-----|---------------|-------------|
| `Tab`/`Shift+Tab` | Toggle button | Moves focus to and from the date picker |
| `Space`/`Enter` | Toggle button | Opens/closes the date picker |
| `↑` | Calendar | Moves to the same day in the previous week |
| `↓` | Calendar | Moves to the same day in the next week |
| `←` | Calendar | Moves to the previous day |
| `→` | Calendar | Moves to the next day |
| `Home` | Calendar | Moves to the first day of the current week |
| `End` | Calendar | Moves to the last day of the current week |
| `PageUp` | Calendar | Moves to the same day in the previous month |
| `PageDown` | Calendar | Moves to the same day in the next month |
| `Enter`/`Space` | Calendar | Selects the focused date |
| `Escape` | Any | Closes the date picker |
| `Backspace` | Toggle button | Clears selection (when `clearable={true}`) |
When time picker is enabled:
| Key | Element Focus | Description |
|-----|---------------|-------------|
| `↑`/`↓` | Time input | Increments/decrements the value |
| `0-9` | Time input | Sets the value directly |
| `a`/`p` | AM/PM select | Switches between AM/PM |
The component implements a focus trap when open, ensuring keyboard navigation stays within the calendar.
### function date_picker/1
**Signatures:**
- `date_picker(assigns)`
Renders a date picker for single or multiple date selection.
The date picker provides calendar-based date selection with support for both single
and multiple date picking. It includes form integration, validation, and comprehensive
keyboard navigation.
## Attributes
* `field` (`Phoenix.HTML.FormField`) - The form field to bind to. When provided, the component automatically handles
value tracking, errors, and form submission.
* `name` (`:any`) - The form name for the date picker. Required when not using the `field` attribute.
For multiple selections, this will be automatically suffixed with `[]`.
* `value` (`:any`) - The current selected value(s). For multiple selections, this should be a list.
When using forms, this is automatically handled by the `field` attribute.
* `id` (`:any`) - The unique identifier for the date picker component. When not provided, a random ID will be generated. Defaults to `nil`.
* `min` (`Date`) - The earliest date that can be selected. Dates before this will be disabled. Defaults to `nil`.
* `max` (`Date`) - The latest date that can be selected. Dates after this will be disabled. Defaults to `nil`.
* `week_start` (`:integer`) - The day of the week that should appear in the first column.
- `0`: Sunday (default)
- `1`: Monday
- `2`: Tuesday
- `3`: Wednesday
- `4`: Thursday
- `5`: Friday
- `6`: Saturday
Defaults to `0`.
* `size` (`:string`) - Controls the size of the date picker component:
- `"sm"`: Small size, suitable for compact UIs
- `"base"`: Default size, suitable for most use cases
- `"lg"`: Large size, suitable for prominent selections
- `"xl"`: Extra large size, suitable for hero sections
Defaults to `"base"`.
* `class` (`:any`) - Additional CSS classes to be applied to the date picker calendar container.
These classes will be merged with the default styles.
Defaults to `nil`.
* `close` (`:string`) - Controls how the date picker closes after selection:
- `"auto"`: Closes immediately after selection (default)
- `"manual"`: Stays open after selection
- `"confirm"`: Requires explicit confirmation via button
Defaults to `"auto"`.
* `navigation` (`:string`) - Controls the calendar navigation interface:
- `"default"`: Month arrows only
- `"extended"`: Month and year arrows
- `"select"`: Month arrows + year/month dropdowns
Defaults to `"default"`.
* `inline` (`:boolean`) - When true, renders the calendar inline instead of in a dropdown. Defaults to `false`.
* `disabled` (`:boolean`) - When true, disables the date picker component. Disabled date pickers cannot be
interacted with and appear visually muted.
Defaults to `false`.
* `label` (`:string`) - The primary label for the date picker. This text is displayed above the date picker
and is used for accessibility purposes.
Defaults to `nil`.
* `sublabel` (`:string`) - Additional context displayed to the side of the main label. Useful for providing
extra information without cluttering the main label.
Defaults to `nil`.
* `description` (`:string`) - A longer description to provide more context about the date picker. This appears
below the label but above the date picker element.
Defaults to `nil`.
* `help_text` (`:string`) - Help text to display below the date picker. This can provide additional context
or instructions for using the date picker.
Defaults to `nil`.
* `placeholder` (`:string`) - Text to display when no date is selected. This text appears in the date picker
toggle and helps guide users to make a selection.
Defaults to `nil`.
* `errors` (`:list`) - List of error messages to display below the date picker. These are automatically
handled when using the `field` attribute with form validation.
Defaults to `[]`.
* `multiple` (`:boolean`) - When true, allows selecting multiple dates. This submits an array of dates. Defaults to `false`.
* `display_format` (`:string`) - The format string used to display the selected date(s) in the toggle button. Uses strftime format.
Common patterns:
- `"%Y-%m-%d"`: ISO format (2024-01-01)
- `"%b %-d, %Y"`: Short month (Jan 1, 2024)
- `"%B %-d, %Y"`: Full month (January 1, 2024)
- `"%d/%m/%Y"`: European format (01/01/2024)
- `"%m/%d/%Y"`: US format (01/01/2024)
Defaults to `"%b %-d, %Y"`.
### function date_range_picker/1
**Signatures:**
- `date_range_picker(assigns)`
Renders a date picker configured for selecting date ranges.
The date range picker enables selection of start and end dates with visual feedback
for the selected range. It supports both form-integrated and standalone usage with
proper validation and error handling.
## Attributes
* `start_field` (`Phoenix.HTML.FormField`) - The form field for the start date when using range selection with forms.
Required when `range={true}` and using form integration.
* `end_field` (`Phoenix.HTML.FormField`) - The form field for the end date when using range selection with forms.
Required when `range={true}` and using form integration.
* `start_name` (`:any`) - The form name for the start date when using range selection without forms.
Required when `range={true}` and not using form integration.
* `end_name` (`:any`) - The form name for the end date when using range selection without forms.
Required when `range={true}` and not using form integration.
* `start_value` (`:any`) - The current start date value when using range selection without forms.
* `end_value` (`:any`) - The current end date value when using range selection without forms.
* `id` (`:any`) - The unique identifier for the date picker component. When not provided, a random ID will be generated. Defaults to `nil`.
* `min` (`Date`) - The earliest date that can be selected. Dates before this will be disabled. Defaults to `nil`.
* `max` (`Date`) - The latest date that can be selected. Dates after this will be disabled. Defaults to `nil`.
* `week_start` (`:integer`) - The day of the week that should appear in the first column.
- `0`: Sunday (default)
- `1`: Monday
- `2`: Tuesday
- `3`: Wednesday
- `4`: Thursday
- `5`: Friday
- `6`: Saturday
Defaults to `0`.
* `size` (`:string`) - Controls the size of the date picker component:
- `"sm"`: Small size, suitable for compact UIs
- `"base"`: Default size, suitable for most use cases
- `"lg"`: Large size, suitable for prominent selections
- `"xl"`: Extra large size, suitable for hero sections
Defaults to `"base"`.
* `class` (`:any`) - Additional CSS classes to be applied to the date picker calendar container.
These classes will be merged with the default styles.
Defaults to `nil`.
* `close` (`:string`) - Controls how the date picker closes after selection:
- `"auto"`: Closes immediately after selection (default)
- `"manual"`: Stays open after selection
- `"confirm"`: Requires explicit confirmation via button
Defaults to `"auto"`.
* `navigation` (`:string`) - Controls the calendar navigation interface:
- `"default"`: Month arrows only
- `"extended"`: Month and year arrows
- `"select"`: Month arrows + year/month dropdowns
Defaults to `"default"`.
* `inline` (`:boolean`) - When true, renders the calendar inline instead of in a dropdown. Defaults to `false`.
* `disabled` (`:boolean`) - When true, disables the date picker component. Disabled date pickers cannot be
interacted with and appear visually muted.
Defaults to `false`.
* `label` (`:string`) - The primary label for the date picker. This text is displayed above the date picker
and is used for accessibility purposes.
Defaults to `nil`.
* `sublabel` (`:string`) - Additional context displayed to the side of the main label. Useful for providing
extra information without cluttering the main label.
Defaults to `nil`.
* `description` (`:string`) - A longer description to provide more context about the date picker. This appears
below the label but above the date picker element.
Defaults to `nil`.
* `help_text` (`:string`) - Help text to display below the date picker. This can provide additional context
or instructions for using the date picker.
Defaults to `nil`.
* `placeholder` (`:string`) - Text to display when no date is selected. This text appears in the date picker
toggle and helps guide users to make a selection.
Defaults to `nil`.
* `errors` (`:list`) - List of error messages to display below the date picker. These are automatically
handled when using the `field` attribute with form validation.
Defaults to `[]`.
* `display_format` (`:string`) - The format string used to display the selected date(s) in the toggle button. Uses strftime format.
Common patterns:
- `"%Y-%m-%d"`: ISO format (2024-01-01)
- `"%b %-d, %Y"`: Short month (Jan 1, 2024)
- `"%B %-d, %Y"`: Full month (January 1, 2024)
- `"%d/%m/%Y"`: European format (01/01/2024)
- `"%m/%d/%Y"`: US format (01/01/2024)
Defaults to `"%b %-d, %Y"`.
### function date_time_picker/1
**Signatures:**
- `date_time_picker(assigns)`
Renders a date picker with integrated time selection capabilities.
The date time picker combines date selection with time input fields, supporting both 12-hour
and 24-hour time formats. It maintains all core date picker features while adding precise
time selection controls.
## Attributes
* `field` (`Phoenix.HTML.FormField`) - The form field to bind to. When provided, the component automatically handles
value tracking, errors, and form submission.
* `name` (`:any`) - The form name for the date picker. Required when not using the `field` attribute.
For multiple selections, this will be automatically suffixed with `[]`.
* `value` (`:any`) - The current selected value(s). For multiple selections, this should be a list.
When using forms, this is automatically handled by the `field` attribute.
* `id` (`:any`) - The unique identifier for the date picker component. When not provided, a random ID will be generated. Defaults to `nil`.
* `min` (`Date`) - The earliest date that can be selected. Dates before this will be disabled. Defaults to `nil`.
* `max` (`Date`) - The latest date that can be selected. Dates after this will be disabled. Defaults to `nil`.
* `week_start` (`:integer`) - The day of the week that should appear in the first column.
- `0`: Sunday (default)
- `1`: Monday
- `2`: Tuesday
- `3`: Wednesday
- `4`: Thursday
- `5`: Friday
- `6`: Saturday
Defaults to `0`.
* `size` (`:string`) - Controls the size of the date picker component:
- `"sm"`: Small size, suitable for compact UIs
- `"base"`: Default size, suitable for most use cases
- `"lg"`: Large size, suitable for prominent selections
- `"xl"`: Extra large size, suitable for hero sections
Defaults to `"base"`.
* `class` (`:any`) - Additional CSS classes to be applied to the date picker calendar container.
These classes will be merged with the default styles.
Defaults to `nil`.
* `close` (`:string`) - Controls how the date picker closes after selection:
- `"auto"`: Closes immediately after selection (default)
- `"manual"`: Stays open after selection
- `"confirm"`: Requires explicit confirmation via button
Defaults to `"auto"`.
* `navigation` (`:string`) - Controls the calendar navigation interface:
- `"default"`: Month arrows only
- `"extended"`: Month and year arrows
- `"select"`: Month arrows + year/month dropdowns
Defaults to `"default"`.
* `inline` (`:boolean`) - When true, renders the calendar inline instead of in a dropdown. Defaults to `false`.
* `disabled` (`:boolean`) - When true, disables the date picker component. Disabled date pickers cannot be
interacted with and appear visually muted.
Defaults to `false`.
* `label` (`:string`) - The primary label for the date picker. This text is displayed above the date picker
and is used for accessibility purposes.
Defaults to `nil`.
* `sublabel` (`:string`) - Additional context displayed to the side of the main label. Useful for providing
extra information without cluttering the main label.
Defaults to `nil`.
* `description` (`:string`) - A longer description to provide more context about the date picker. This appears
below the label but above the date picker element.
Defaults to `nil`.
* `help_text` (`:string`) - Help text to display below the date picker. This can provide additional context
or instructions for using the date picker.
Defaults to `nil`.
* `placeholder` (`:string`) - Text to display when no date is selected. This text appears in the date picker
toggle and helps guide users to make a selection.
Defaults to `nil`.
* `errors` (`:list`) - List of error messages to display below the date picker. These are automatically
handled when using the `field` attribute with form validation.
Defaults to `[]`.
* `time_format` (`:string`) - The time format to use:
- `"12"`: 12-hour format with AM/PM selection
- `"24"`: 24-hour format
Defaults to `"12"`.
* `display_format` (`:string`) - The format string used to display the selected date in the toggle button. Uses strftime format.
Common patterns:
- `"%Y-%m-%d %H:%M:%S"`: ISO format with 24h time (2024-01-01 14:30:00)
- `"%B %-d, %Y at %I:%M %p"`: Full month with 12h time (January 1, 2024 at 02:30 PM)
- `"%d/%m/%Y %H:%M"`: European format with 24h time (01/01/2024 14:30)
- `"%m/%d/%Y %I:%M %p"`: US format with 12h time (01/01/2024 02:30 PM)
- `"%a, %b %-d at %I:%M %p"`: Short format (Mon, Jan 1 at 02:30 PM)
Defaults to `"%b %-d %I:%M %p"`.
## Fluxon.Components.Dropdown
A comprehensive dropdown system for creating accessible, interactive menus and selection interfaces.
This component provides a flexible solution for building dropdown menus across your application.
It offers a fully accessible implementation with keyboard navigation, automatic positioning, and
proper focus management. The component is designed to work seamlessly with LiveView while
maintaining proper accessibility standards.
## Usage
Create a simple dropdown menu with default styling:
```heex
<.dropdown>
<.dropdown_link navigate={~p"/profile"}>Profile
<.dropdown_link navigate={~p"/settings"}>Settings
<.dropdown_separator />
<.dropdown_link href={~p"/logout"} method="delete">Sign Out
```

## Custom Toggle
Replace the default button with a custom toggle element:
```heex
<.dropdown>
<:toggle>
<.dropdown_button>Profile
<.dropdown_button>Billing
<.dropdown_button>Settings
```

## Disabled Items
The dropdown supports disabled menu items that are automatically skipped during keyboard navigation
and cannot be selected or activated:
```heex
<.dropdown>
<.dropdown_button>Account
<.dropdown_button disabled>Upgrade Plan
<.dropdown_separator />
<.dropdown_link navigate={~p"/settings"}>Settings
<.dropdown_link navigate={~p"/restricted"} data-disabled>Admin Panel
```
For button items, use the standard `disabled` attribute. For link items, use the `data-disabled`
attribute since HTML links don't support the native `disabled` attribute. Disabled items are visually
dimmed and are completely skipped during keyboard navigation.
## Rich Content
Create complex dropdown interfaces with headers, separators, and custom content:
```heex
<.dropdown class="w-64">
<.dropdown_custom class="flex items-center p-2">
Emma Johnsonemma@acme.com
<.dropdown_separator />
<.dropdown_header>Account
<.dropdown_link navigate={~p"/profile"}>Profile
<.dropdown_link navigate={~p"/billing"}>Billing
<.dropdown_header>Support
<.dropdown_link navigate={~p"/help"}>Documentation
<.dropdown_link navigate={~p"/contact"}>Contact Us
<.dropdown_separator />
<.dropdown_link href={~p"/logout"} method="delete" class="text-red-600">
Sign Out
```

## Hover Interaction
Enable hover-based opening with custom delays:
```heex
<.dropdown open_on_hover hover_open_delay={200} hover_close_delay={300}>
<.dropdown_link navigate={~p"/profile"}>Profile
<.dropdown_link navigate={~p"/settings"}>Settings
```
## Menu Positioning
Control the dropdown's placement relative to its toggle:
```heex
<.dropdown placement="bottom-end">
<.dropdown_link>Bottom End Aligned
<.dropdown placement="right-start">
<.dropdown_link>Right Side Menu
```
## Custom Animations
Customize the dropdown's enter/leave animations:
```heex
<.dropdown
animation="transition-all duration-300"
animation_enter="opacity-100 translate-y-0"
animation_leave="opacity-0 -translate-y-2"
>
<.dropdown_link>Smooth Slide Animation
```
## Keyboard Navigation
The component provides comprehensive keyboard support following ARIA best practices:
| Key | Element Focus | Description |
|-----|--------------|-------------|
| `Tab`/`Shift+Tab` | Toggle button | Moves focus to and from the dropdown toggle |
| `Space`/`Enter` | Toggle button | Opens/closes the dropdown when focused |
| `↑` | Toggle button | Opens dropdown and highlights last item |
| `↓` | Toggle button | Opens dropdown and highlights first item |
| `↑` | Menu item | Moves highlight to previous item |
| `↓` | Menu item | Moves highlight to next item |
| `Enter`/`Space` | Menu item | Activates the highlighted item |
| `Escape` | Any | Closes the dropdown |
## Focus Management
The dropdown implements sophisticated focus management to ensure a seamless user experience.
Focus remains on the toggle button while users navigate through menu items using arrow keys.
Menu items are not focusable through tab navigation, maintaining a streamlined keyboard
interaction model. The component manages proper ARIA attributes to communicate the current
selection to assistive technologies.
## Positioning System
The dropdown menu intelligently positions itself relative to its toggle button. It automatically
adjusts its placement based on available viewport space, ensuring optimal visibility regardless
of the toggle button's position. The positioning system handles window resizing and scrolling,
maintaining proper alignment in dynamic layouts.
### function dropdown/1
**Signatures:**
- `dropdown(assigns)`
Renders a fully accessible dropdown menu with rich interaction support.
This component provides a flexible way to create dropdown menus with proper keyboard
navigation, focus management, and positioning. It supports both click and hover
interactions, custom toggle elements, and various animation options.
## Attributes
* `id` (`:string`) - The unique identifier for the dropdown component. If not provided, one will be
automatically generated.
* `label` (`:string`) - The text label for the default dropdown toggle button. Only used when no
custom toggle is provided via the `:toggle` slot.
Defaults to `"Menu"`.
* `class` (`:any`) - Additional CSS classes for the dropdown menu panel. Useful for controlling
width, max-height, and other menu-specific styles.
Defaults to `nil`.
* `container_class` (`:string`) - Additional CSS classes for the dropdown's outer container. Affects the
positioning wrapper element.
Defaults to `nil`.
* `toggle_class` (`:string`) - Additional CSS classes for the dropdown toggle button. Only applies to
the default toggle button, not custom toggles.
Defaults to `nil`.
* `disabled` (`:boolean`) - When true, disables the dropdown toggle and prevents the menu from opening. Defaults to `false`.
* `placement` (`:string`) - Controls the placement of the dropdown menu relative to its toggle button.
Supports different positions with automatic repositioning when needed.
The possible values are: `top`, `top-start`, `top-end`, `right`, `right-start`, `right-end`,
`bottom`, `bottom-start`, `bottom-end`, `left`, `left-start`, `left-end`
Defaults to `"bottom-start"`.
* `animation` (`:string`) - Base animation classes applied to the dropdown menu. Controls the transition
timing and easing function.
Defaults to `"transition ease-in-out duration-150"`.
* `animation_enter` (`:string`) - Classes applied when the dropdown menu enters. Usually defines the final
state of the animation.
Defaults to `"opacity-100 scale-100"`.
* `animation_leave` (`:string`) - Classes applied when the dropdown menu leaves. Usually defines the initial
state of the exit animation.
Defaults to `"opacity-0 scale-95"`.
* `open_on_hover` (`:boolean`) - When true, opens the dropdown menu on mouse hover instead of click.
Can be combined with hover delays for better user experience.
Defaults to `false`.
* `hover_open_delay` (`:integer`) - Delay in milliseconds before opening the menu when hovering. Only applies
when `open_on_hover` is true.
Defaults to `0`.
* `hover_close_delay` (`:integer`) - Delay in milliseconds before closing the menu when mouse leaves. Only
applies when `open_on_hover` is true.
Defaults to `0`.
## Slots
* `inner_block` (required) - The content of the dropdown menu. Usually contains `dropdown_link`,
`dropdown_button`, or other dropdown components.
* `toggle` - Optional custom toggle element. When provided, replaces the default button
toggle while maintaining proper accessibility attributes.
Accepts attributes:
* `class` (`:any`) - Additional CSS classes for the wrapper of the custom toggle element.
### function dropdown_button/1
**Signatures:**
- `dropdown_button(assigns)`
Renders a dropdown button item.
A dropdown button is an interactive item within the dropdown menu that triggers an action
rather than navigating to a new page. It renders as a `