### Install Cinder using Igniter Source: https://github.com/sevenseacat/cinder/blob/main/README.md Recommended installation method using the Igniter tool. This command automates the setup process. ```bash mix igniter.install cinder ``` -------------------------------- ### Install Cinder and Configure Tailwind CSS Source: https://context7.com/sevenseacat/cinder/llms.txt Install Cinder and set up Tailwind CSS integration using the `mix cinder.install` mix task. ```bash # Install Cinder and configure Tailwind CSS mix cinder.install ``` -------------------------------- ### Quick Start Table Collection Source: https://github.com/sevenseacat/cinder/blob/main/README.md A simplified example for a table view, demonstrating essential column configurations for filtering and sorting. ```heex <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="email" filter>{user.email} <:col :let={user} field="role" filter>{user.role} ``` -------------------------------- ### Complete Manual Installation of Cinder Source: https://github.com/sevenseacat/cinder/blob/main/README.md After adding the dependency, run these commands to fetch dependencies and install Cinder, including Tailwind CSS configuration. ```bash mix deps.get mix cinder.install # Configure Tailwind CSS ``` -------------------------------- ### Autocomplete Filter Examples Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Implement autocomplete filters for searchable dropdowns with server-side option filtering. The first example shows basic usage with static options, and the second demonstrates custom placeholder and result limit. ```heex <:col :let={order} field="customer_id" filter={[type: :autocomplete, options: @customers]}> {order.customer.name} ``` ```heex <:col :let={order} field="product_id" filter={[ type: :autocomplete, options: @products, placeholder: "Search products...", max_results: 15 ]}> {order.product.name} ``` -------------------------------- ### Date Range Filter Examples Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Implement date range filters using from/to date pickers. The first example auto-detects for date/datetime fields, while the second includes time selection. ```heex <:col :let={order} field="created_at" filter sort>{order.created_at} ``` ```heex <:col :let={order} field="shipped_at" filter={[type: :date_range, include_time: true]}> {order.shipped_at} ``` -------------------------------- ### URL Examples for State Management Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Illustrates various URL query parameters for filtering, date range selection, pagination, and sorting within Cinder collections. ```url # Basic filtering /users?name=john&email=gmail ``` ```url # Date range /users?created_at_from=2024-01-01&created_at_to=2024-12-31 ``` ```url # Pagination and sorting /users?page=3&sort=-created_at ``` ```url # Complex state /users?name=admin&is_active=true&page=2&sort=name ``` -------------------------------- ### Basic Cinder Collection Usage Source: https://github.com/sevenseacat/cinder/blob/main/usage-rules.md Demonstrates the basic setup for a Cinder collection, specifying the resource and actor, and defining columns with filtering, sorting, and searching capabilities. ```heex <:col :let={user} field="name" filter sort search>{user.name} <:col :let={user} field="email" filter>{user.email} <:col :let={user} field="created_at" sort>{user.created_at} ``` -------------------------------- ### HTML with Data Attributes for Theming Source: https://github.com/sevenseacat/cinder/blob/main/docs/theming.md Example HTML structure showing `data-key` attributes that correspond to Cinder theme properties. ```html
Name
``` -------------------------------- ### Using Theme Modules Directly Source: https://github.com/sevenseacat/cinder/blob/main/docs/theme-showcase.md Alternatively, you can reference theme modules directly when applying themes, providing more flexibility for custom or complex theme setups. ```elixir # Or use theme modules directly theme={Cinder.Themes.Modern} theme={MyApp.CustomTheme} ``` -------------------------------- ### Filter Slot Attributes Example Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md This example demonstrates the various attributes available for filter slots, including required, optional, and type-specific parameters for different filter types. ```heex <:filter field="field_name" # Required type="filter_type" # Optional, auto-detected if not provided label="Custom Label" # Optional options={[...]} # For select/multi-select placeholder="..." # For text filters operator={:contains} # For text filters case_sensitive={true} # For text filters match_mode={:any} # For multi-select min={0} # For number range max={100} # For number range step={1} # For number range include_time={true} # For date range fn={&custom_filter/2} # Custom filter function /> ``` -------------------------------- ### Add Cinder Dependency to mix.exs Source: https://github.com/sevenseacat/cinder/blob/main/README.md Manual installation step to add Cinder as a project dependency in your `mix.exs` file. ```elixir def deps do [{:cinder, "~> 0.9"}] end ``` -------------------------------- ### Setup URL State Management in LiveView Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Integrate Cinder.UrlSync into your LiveView to synchronize collection state with the browser URL. This allows for bookmarkable and shareable views. ```elixir defmodule MyAppWeb.UsersLive do use MyAppWeb, :live_view use Cinder.UrlSync def mount(_params, _session, socket) do {:ok, assign(socket, :current_user, get_current_user(socket))} end def handle_params(params, uri, socket) do socket = Cinder.UrlSync.handle_params(params, uri, socket) {:noreply, socket} end def render(assigns) do ~H""" <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="email" filter>{user.email} <:col :let={user} field="is_active" filter={:boolean}> {if user.is_active, do: "Active", else: "Inactive"} """ end end ``` -------------------------------- ### Grid Layout Collection with Custom Item Template Source: https://github.com/sevenseacat/cinder/blob/main/README.md Example of using Cinder for a grid layout with a specified number of columns. Includes a custom item template for rendering each product. ```heex <:col field="name" filter sort /> <:item :let={product}>
{product.name}
``` -------------------------------- ### Dynamic Filter Options Rendering Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Example of a render function that fetches filter options dynamically from a database or context before rendering the filter UI. ```elixir def render(column, current_value, theme, assigns) do # Get options from database or context options = get_dynamic_options(column.field, assigns) assigns = Map.put(assigns, :dynamic_options, options) # ... render with dynamic options end ``` -------------------------------- ### Cinder Collection Component Example Source: https://context7.com/sevenseacat/cinder/llms.txt Use the Cinder.collection component to display a paginated and filterable list of resources. Allows per-component override of page size and query options. ```heex <%!-- Per-component override with user-selectable sizes --%> <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="department.name">{user.department.name} ``` -------------------------------- ### Number Range Filter Examples Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Use number range filters with Min/Max inputs for numeric filtering. The first example auto-detects for integer/decimal fields, and the second includes constraints for min, max, and step. ```heex <:col :let={product} field="price" filter sort>{product.price} ``` ```heex <:col :let={product} field="quantity" filter={[type: :number_range, min: 0, max: 10000, step: 10]}> {product.quantity} ``` -------------------------------- ### Extend and Override Theme Properties Source: https://github.com/sevenseacat/cinder/blob/main/docs/theme-showcase.md Inherit from an existing theme like `:retro` and override specific properties to create a new theme. This example darkens the retro theme and adds green accents. ```elixir defmodule MyApp.DarkRetro do use Cinder.Theme extends :retro # Table - Keep retro styling but make it even darker set :container_class, "bg-black border-4 border-green-400 shadow-green-400/50" set :th_class, "px-6 py-4 text-green-100 font-bold bg-green-900 border-b-4 border-green-400" end ``` -------------------------------- ### Slider Filter Module Documentation Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Provides documentation for a custom Slider filter module, detailing its purpose, available options (min, max, step, operator), and a usage example. ```elixir defmodule MyApp.Filters.Slider do @moduledoc """ Slider filter for numeric range filtering. ## Options - `:min` - Minimum value (default: 0) - `:max` - Maximum value (default: 100) - `:step` - Step increment (default: 1) - `:operator` - Comparison operator (default: :equals) ## Usage %{ field: "price", filter: :slider, filter_options: [min: 0, max: 1000, step: 50, operator: :less_than_or_equal] } """ use Cinder.Filter # ... implementation end ``` -------------------------------- ### Table Layout Cinder Collection Source: https://github.com/sevenseacat/cinder/blob/main/docs/getting-started.md The default table layout provides a traditional HTML table with sortable column headers. This example is identical to the minimal collection but explicitly shows the default layout. ```heex <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="email" filter>{user.email} ``` -------------------------------- ### Enable Keyset Pagination Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Use keyset pagination for large datasets, offering faster performance than offset pagination. ```heex ... ``` -------------------------------- ### Collapsible Filters - Per Component Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Configure individual Cinder collections to have collapsible filters. The `show_filters` attribute can be set to `:toggle` for filters that start collapsed, or `:toggle_open` to start expanded. ```heex <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="email" filter>{user.email} <:col :let={user} field="status" filter={:select}>{user.status} ... ``` -------------------------------- ### Initialize Cinder in Elixir Application Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Ensure Cinder is set up during your application's startup by calling `Cinder.setup()`. This integrates configured custom filters into the Cinder framework. ```elixir defmodule MyApp.Application do use Application def start(_type, _args) do # Set up Cinder with configured filters Cinder.setup() children = [ # your supervisors... ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end end ``` -------------------------------- ### Checkbox Filter Examples Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Use checkbox filters for boolean fields or to filter by a specific value when checked. The first example filters for true when checked, while the second filters for 'high' priority. ```heex <:col :let={article} field="published" filter={[type: :checkbox, label: "Published only"]}> {if article.published, do: "✓", else: "✗"} ``` ```heex <:col :let={article} field="priority" filter={[type: :checkbox, value: "high", label: "High priority only"]}> {article.priority} ``` -------------------------------- ### Cinder Layouts: Table, List, and Grid Source: https://github.com/sevenseacat/cinder/blob/main/usage-rules.md Illustrates how to configure different layouts for Cinder collections, including the default table layout, a list layout, and a grid layout with customizable columns. ```heex <:col :let={user} field="name" filter sort>{user.name} <:col field="name" filter sort /> <:item :let={user}>
{user.name}
<:col field="name" filter sort /> <:item :let={product}>
{product.name}
``` -------------------------------- ### Text Filter with Custom Placeholder Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Customize the placeholder text for text filters to guide user input. ```heex <:col :let={article} field="content" filter={[type: :text, placeholder: "Search content..."]} > {String.slice(article.content, 0, 100)}... ``` -------------------------------- ### Collection with Pre-filtered Query and Keyset Pagination Source: https://context7.com/sevenseacat/cinder/llms.txt Use this snippet when you need to display a pre-filtered set of resources. It also demonstrates how to configure keyset pagination for efficient data retrieval. ```heex <%!-- With pre-filtered query and keyset pagination --%> Ash.Query.filter(active: true)} actor={@current_user} pagination={:keyset} page_size={50} > <:col :let={user} field="name" filter sort>{user.name} ``` -------------------------------- ### Grid Layout with Responsive Columns Source: https://context7.com/sevenseacat/cinder/llms.txt Implement a grid layout for displaying resources. Control the number of columns across different screen sizes using `grid_columns`. Supports filtering and custom item rendering. ```heex <%!-- Grid layout with responsive columns --%> <:col field="name" filter sort search /> <:col field="category" filter={:select} /> <:item :let={product}>

{product.name}

${product.price}

``` -------------------------------- ### Run Cinder Upgrade Task Source: https://github.com/sevenseacat/cinder/blob/main/docs/upgrading.md Execute the `mix cinder.upgrade` task to automatically convert your theme files from the old `component/2` syntax to the new flat `set` calls. ```bash mix cinder.upgrade 0.8.1 0.9.0 ``` -------------------------------- ### Collection with Multi-Tenant Admin Query Source: https://github.com/sevenseacat/cinder/blob/main/docs/getting-started.md Configure collections for multi-tenant environments using the `query` attribute and specifying a `tenant`. ```heex ... ``` -------------------------------- ### Using String Theme Presets Source: https://github.com/sevenseacat/cinder/blob/main/docs/theme-showcase.md Apply built-in themes directly using their string names. This is a convenient way to quickly switch between predefined styles. ```elixir # String preset names theme="default" # Minimal unstyled theme="modern" # Professional blue theme theme="retro" # 80s cyberpunk neon theme="futuristic" # Sci-fi holographic theme="dark" # Elegant dark mode theme="daisy_ui" # daisyUI compatibility theme="flowbite" # Flowbite compatibility theme="compact" # High-density minimal ``` -------------------------------- ### Load Specific Data with query_opts Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Use `query_opts` to specify which related data to load and which fields to select for efficient data retrieval. ```heex ... ``` -------------------------------- ### Configurable Filter Options in Column Definition Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Example of a column definition specifying a slider filter with custom options like min, max, step, and operator. ```elixir %{ field: "score", filter: :slider, filter_options: [ min: 0, max: 1000, step: 10, operator: :less_than_or_equal ] } ``` -------------------------------- ### Configure User-Selectable Page Size Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Allow users to select their preferred page size from a list of options. ```heex ... ``` -------------------------------- ### Add Action Column with Custom Links and Buttons Source: https://github.com/sevenseacat/cinder/blob/main/docs/getting-started.md Create action columns without a `field` to include custom content like navigation links and buttons for performing actions. ```heex <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="email" filter>{user.email} <:col :let={user} label="Actions">
<.link navigate={~p"/users/#{user.id}"} class="text-blue-600 hover:underline"> View <.link navigate={~p"/users/#{user.id}/edit"} class="text-green-600 hover:underline"> Edit
``` -------------------------------- ### Configure Custom Filters in Elixir Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Add custom filters to your Cinder application by listing their module names in the application configuration. This example shows how to register a slider filter. ```elixir config :cinder, :filters, [ slider: MyApp.Filters.Slider, color_picker: MyApp.Filters.ColorPicker, date_picker: MyApp.Filters.DatePicker ] ``` -------------------------------- ### Define a Custom Theme with DSL Source: https://github.com/sevenseacat/cinder/blob/main/docs/theme-showcase.md Use Cinder.Theme and the `set` macro to define custom styles for components like tables and filters. Extend existing themes using `extends`. ```elixir defmodule MyApp.CustomTheme do use Cinder.Theme extends :modern # Table set :container_class, "bg-gradient-to-r from-purple-900 to-blue-900 rounded-2xl shadow-2xl" set :th_class, "px-6 py-4 text-yellow-300 font-bold uppercase tracking-widest" set :row_class, "border-b border-purple-500/30 hover:bg-purple-800/50" # Filters set :filter_container_class, "bg-black border-2 border-yellow-400 p-6 rounded-lg" set :filter_text_input_class, "bg-gray-900 border-yellow-400 text-yellow-100" end ``` ```html <:col field="name" /> ``` -------------------------------- ### Filter-Only Slots Example Source: https://github.com/sevenseacat/cinder/blob/main/docs/filters.md Use filter-only slots to add filtering UI without displaying columns. This is useful for filtering by metadata or keeping tables focused on essential information. ```heex <:col :let={order} field="order_number">{order.order_number} <:col :let={order} field="total">${order.total} <:filter field="created_at" type="date_range" label="Order Date" /> <:filter field="status" type="select" options={["pending", "shipped", "delivered"]} /> <:filter field="customer_name" type="text" placeholder="Customer name..." /> ``` -------------------------------- ### Handle Bulk Action Callbacks in LiveView Source: https://github.com/sevenseacat/cinder/blob/main/usage-rules.md Implement `handle_info` callbacks in your LiveView to process success or failure events from bulk actions, allowing you to display feedback to the user. ```elixir def handle_info({:deleted, %{count: count}}, socket) do {:noreply, put_flash(socket, :info, "Deleted #{count} users")} end def handle_info({:delete_failed, %{reason: reason}}, socket) do {:noreply, put_flash(socket, :error, "Failed: #{inspect(reason)}")} end ``` -------------------------------- ### Define Custom Bulk Actions Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Provide inner content for `bulk_action` slots for complete control over button rendering. ```heex <:col :let={user} field="name" filter sort>{user.name} <:bulk_action action={:archive} :let={context}> <:bulk_action action={:destroy} confirm="Delete {count} users?"> ``` -------------------------------- ### Table Layout with Filters, Sorting, and Search Source: https://context7.com/sevenseacat/cinder/llms.txt Use this snippet to display data in a table format. It supports column-specific filtering, sorting, and searching. Configure pagination with `page_size`. ```heex <%!-- Table layout with filters, sorting, and search --%> <:col :let={user} field="name" filter sort search>{user.name} <:col :let={user} field="email" filter>{user.email} <%!-- Auto-detects enum → select filter --%> <:col :let={user} field="role" filter sort>{user.role} <%!-- Relationship field via dot notation --%> <:col :let={user} field="department.name" filter sort>{user.department.name} <%!-- Embedded resource via double-underscore --%> <:col :let={user} field="profile__country" filter>{user.profile.country} <%!-- Action column: no field required --%> <:col :let={user} label="Actions"> <.link navigate={~p"/users/#{user.id}"}>View ``` -------------------------------- ### Cinder Column Configuration: Sorting Source: https://github.com/sevenseacat/cinder/blob/main/usage-rules.md Demonstrates basic sorting and custom sort cycles for Cinder columns. Basic sorting cycles through nil, ascending, and descending. ```heex <:col field="name" sort /> <:col field="priority" sort={[cycle: [:desc, :asc]]} /> <:col field="created_at" sort={[cycle: [:desc, :asc, nil]]} /> ``` -------------------------------- ### Filter Options Based on Dependencies Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Demonstrates how a filter's rendering can adapt its options based on the values of other filters present in the assigns. ```elixir def render(column, current_value, theme, assigns) do # Access other filter values category_filter = get_in(assigns, [:filters, "category"]) # Adjust options based on other filters options = get_options_for_category(category_filter) # ... render end ``` -------------------------------- ### Configure Custom Filters in Cinder Source: https://context7.com/sevenseacat/cinder/llms.txt Register custom filter modules in your application's configuration file (`config/config.exs`). Ensure `Cinder.setup()` is called in your application's start function to register these filters. ```elixir # config/config.exs config :cinder, :filters, [ slider: MyApp.Filters.Slider, color_picker: MyApp.Filters.ColorPicker ] # lib/my_app/application.ex defmodule MyApp.Application do use Application def start(_type, _args) do Cinder.setup() # registers all configured custom filters, returns :ok children = [MyAppWeb.Endpoint] Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor) end end ``` -------------------------------- ### Customize Sort Cycles Source: https://github.com/sevenseacat/cinder/blob/main/docs/sorting.md Customize the sort cycle for a column using the `cycle` option within the `sort` attribute. This allows for different sequences, including omitting the neutral state or starting with a specific direction. ```heex <:col field="name" sort={[cycle: [:asc, :desc]]} /> ``` ```heex <:col field="created_at" sort={[cycle: [:desc, :asc, nil]]} /> ``` ```heex <:col field="completed_at" sort={[cycle: [:desc_nils_last, :asc_nils_first, nil]]} /> ``` -------------------------------- ### Passing Additional Ash Bulk Options Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Provide extra Ash bulk options, such as `return_records?` and `notify?`, using the `action_opts` attribute. ```heex <:bulk_action action={:archive} action_opts={[return_records?: true, notify?: true]}> Archive Selected ``` -------------------------------- ### Override Cinder Gettext Strings Source: https://context7.com/sevenseacat/cinder/llms.txt Override default Cinder strings by providing custom translations in your application's Gettext catalog. Example shows overrides for 'Filters', 'Loading...', and 'No results found'. ```po # priv/gettext/en/LC_MESSAGES/cinder.po — override specific strings msgid "Filters" msgstr "Refine" msgid "Loading..." msgstr "Please wait..." msgid "No results found" msgstr "Nothing here yet" ``` -------------------------------- ### Migrate Custom Theme Keys Source: https://context7.com/sevenseacat/cinder/llms.txt Run the `mix cinder.upgrade` task to migrate custom theme keys after a breaking upgrade, ensuring compatibility with new Cinder versions. ```bash # Migrate custom theme keys after a breaking upgrade # (e.g., filter_boolean_* → filter_radio_group_* in 0.9.1→0.10.0) mix cinder.upgrade 0.9.1 0.10.0 ``` -------------------------------- ### Add Click Handler to Collection Rows Source: https://github.com/sevenseacat/cinder/blob/main/docs/getting-started.md Use the `click` attribute to make rows or items clickable. The function receives the record and returns a JS command. Rows with click handlers get automatic hover effects. ```heex JS.navigate(~p"/users/#{user.id}") end} > <:col :let={user} field="name" filter sort>{user.name} <:col :let={user} field="email">{user.email} ``` -------------------------------- ### Define a Custom Slider Filter in Elixir Source: https://github.com/sevenseacat/cinder/blob/main/docs/custom-filters.md Implement a custom slider filter for numeric values. This example shows how to define the rendering logic, process input, validate values, set default options, and build queries for filtering. ```elixir defmodule MyApp.Filters.Slider do @moduledoc """ A range slider filter for numeric values. Provides a visual slider interface for filtering numeric columns with configurable min, max, and step values. """ use Cinder.Filter @impl true def render(column, current_value, theme, assigns) do filter_options = Map.get(column, :filter_options, []) min_value = get_option(filter_options, :min, 0) max_value = get_option(filter_options, :max, 100) step_value = get_option(filter_options, :step, 1) current = current_value || min_value assigns = %{ column: column, current_value: current, min_value: min_value, max_value: max_value, step_value: step_value, theme: theme } ~H"""
{@min_value} {@current_value} {@max_value}
""" end @impl true def process(raw_value, column) when is_binary(raw_value) do case Integer.parse(raw_value) do {value, ""} -> filter_options = Map.get(column, :filter_options, []) operator = get_option(filter_options, :operator, :equals) %{ type: :slider, value: value, operator: operator } _ -> nil end end def process(_raw_value, _column), do: nil @impl true def validate(%{type: :slider, value: value, operator: operator}) when is_integer(value) and is_atom(operator) do operator in [:equals, :greater_than, :less_than, :greater_than_or_equal, :less_than_or_equal] end def validate(_), do: false @impl true def default_options do [ min: 0, max: 100, step: 1, operator: :equals ] end @impl true def empty?(value) do case value do nil -> true %{value: nil} -> true _ -> false end end @impl true def build_query(query, field, filter_value) do %{type: :slider, value: value, operator: operator} = filter_value # Handle relationship fields using dot notation if String.contains?(field, ".") do path_atoms = field |> String.split(".") |> Enum.map(&String.to_atom/1) {rel_path, [field_atom]} = Enum.split(path_atoms, -1) case operator do :equals -> Ash.Query.filter(query, exists(^rel_path, ^ref(field_atom) == ^value)) :greater_than -> Ash.Query.filter(query, exists(^rel_path, ^ref(field_atom) > ^value)) :greater_than_or_equal -> Ash.Query.filter(query, exists(^rel_path, ^ref(field_atom) >= ^value)) :less_than -> Ash.Query.filter(query, exists(^rel_path, ^ref(field_atom) < ^value)) :less_than_or_equal -> Ash.Query.filter(query, exists(^rel_path, ^ref(field_atom) <= ^value)) _ -> query end else # Direct field filtering field_atom = String.to_atom(field) case operator do :equals -> Ash.Query.filter(query, ^ref(field_atom) == ^value) :greater_than -> Ash.Query.filter(query, ^ref(field_atom) > ^value) :greater_than_or_equal -> Ash.Query.filter(query, ^ref(field_atom) >= ^value) :less_than -> Ash.Query.filter(query, ^ref(field_atom) < ^value) :less_than_or_equal -> Ash.Query.filter(query, ^ref(field_atom) <= ^value) _ -> query end end end end ``` -------------------------------- ### Define Themed Bulk Actions Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Use `label` and `variant` to define automatically styled bulk action buttons that match your theme. ```heex <:col :let={user} field="name" filter sort>{user.name} <:bulk_action action={:archive} label="Archive ({count})" variant={:primary} /> <:bulk_action action={:export} label="Export" variant={:secondary} /> <:bulk_action action={:destroy} label="Delete" variant={:danger} confirm="Delete {count} users?" /> ``` -------------------------------- ### Grid Layout with Responsive Columns Source: https://github.com/sevenseacat/cinder/blob/main/docs/getting-started.md Define responsive column counts for a grid layout using `grid_columns` with a map of breakpoints and column numbers. Available breakpoints include `xs`, `sm`, `md`, `lg`, `xl`, `2xl`. ```heex ... ``` -------------------------------- ### Setting All Theme Properties Source: https://github.com/sevenseacat/cinder/blob/main/docs/theming.md This snippet demonstrates how to set various CSS class names for different UI components to customize their appearance. Use these properties to control spacing, colors, borders, and other visual aspects. ```elixir set :bulk_actions_container_class, "p-4 bg-white border border-gray-200 rounded-lg shadow-sm flex gap-2 justify-end" set :button_class, "px-3 py-1.5 text-sm font-medium rounded" set :button_danger_class, "bg-red-600 text-white hover:bg-red-700" set :button_disabled_class, "opacity-50 cursor-not-allowed" set :button_primary_class, "bg-blue-600 text-white hover:bg-blue-700" set :button_secondary_class, "border border-gray-300 text-gray-700 hover:bg-gray-50" set :container_class, "" set :controls_class, "" set :empty_class, "text-center py-4" set :error_container_class, "text-red-600 text-sm" set :error_message_class, "" set :filter_checkbox_container_class, "" set :filter_checkbox_input_class, "" set :filter_checkbox_label_class, "" set :filter_clear_all_class, "" set :filter_clear_button_class, "" set :filter_container_class, "" set :filter_count_class, "" set :filter_date_input_class, "" set :filter_header_class, "" set :filter_input_wrapper_class, "" set :filter_inputs_class, "" set :filter_label_class, "" set :filter_multicheckboxes_checkbox_class, "" set :filter_multicheckboxes_container_class, "" set :filter_multicheckboxes_label_class, "" set :filter_multicheckboxes_option_class, "" set :filter_multiselect_checkbox_class, "" set :filter_multiselect_container_class, "" set :filter_multiselect_dropdown_class, "" set :filter_multiselect_empty_class, "" set :filter_multiselect_label_class, "" set :filter_multiselect_option_class, "" set :filter_number_input_class, "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none [-moz-appearance:textfield]" set :filter_radio_group_container_class, "" set :filter_radio_group_label_class, "" set :filter_radio_group_option_class, "" set :filter_radio_group_radio_class, "" set :filter_range_container_class, "" set :filter_range_input_group_class, "" set :filter_range_separator_class, "flex items-center px-2 text-sm text-gray-500" set :filter_select_arrow_class, "w-4 h-4 ml-2 flex-shrink-0" set :filter_select_container_class, "" set :filter_select_dropdown_class, "" set :filter_select_empty_class, "" set :filter_select_input_class, "" set :filter_select_label_class, "" set :filter_select_option_class, "" set :filter_select_placeholder_class, "text-gray-400" set :filter_text_input_class, "" set :filter_title_class, "" set :filter_toggle_class, "cursor-pointer select-none inline-flex items-center gap-1" set :filter_toggle_icon_class, "w-4 h-4" set :grid_container_class, "grid gap-4" set :grid_item_class, "p-4 bg-white border border-gray-200 rounded-lg shadow-sm" set :grid_item_clickable_class, "cursor-pointer hover:shadow-md transition-shadow" set :grid_selection_overlay_class, "mb-2" set :header_row_class, "" set :list_container_class, "divide-y divide-gray-200" set :list_item_class, "py-3 px-4 text-gray-900" set :list_item_clickable_class, "cursor-pointer hover:bg-gray-50 transition-colors" set :list_selection_container_class, "mb-2" set :loading_container_class, "" set :loading_overlay_class, "" set :loading_spinner_circle_class, "" set :loading_spinner_class, "" set :loading_spinner_path_class, "" set :page_size_container_class, "" set :page_size_dropdown_class, "" set :page_size_dropdown_container_class, "" set :page_size_label_class, "" set :page_size_option_class, "" set :page_size_selected_class, "" set :pagination_button_class, "" set :pagination_container_class, "" set :pagination_count_class, "" set :pagination_current_class, "" set :pagination_info_class, "" set :pagination_nav_class, "" set :pagination_wrapper_class, "" set :row_class, "" set :search_icon_class, "w-4 h-4" set :search_input_class, "w-full px-3 py-2 border rounded" set :selected_item_class, "ring-2 ring-blue-500" set :selected_row_class, "bg-blue-50" set :selection_checkbox_class, "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500" set :sort_arrow_wrapper_class, "inline-flex items-center" set :sort_asc_icon, "↑" set :sort_asc_icon_class, "w-3 h-3" set :sort_asc_icon_name, "hero-chevron-up" set :sort_button_active_class, "bg-blue-50 border-blue-300 text-blue-700" set :sort_button_class, "px-3 py-1 text-sm border rounded transition-colors" set :sort_button_inactive_class, "bg-white border-gray-300 hover:bg-gray-50" set :sort_buttons_class, "flex gap-1" set :sort_container_class, "bg-white border border-gray-200 rounded-lg shadow-sm mt-4" set :sort_controls_class, "flex items-center gap-2 p-4" set :sort_controls_label_class, "text-sm text-gray-600 font-medium" set :sort_desc_icon, "↓" set :sort_desc_icon_class, "w-3 h-3" set :sort_desc_icon_name, "hero-chevron-down" set :sort_icon_class, "ml-1" set :sort_indicator_class, "ml-1 inline-flex items-center align-baseline" set :sort_none_icon_class, "w-3 h-3 opacity-50" set :sort_none_icon_name, "hero-chevron-up-down" set :table_class, "w-full border-collapse" set :table_wrapper_class, "overflow-x-auto" set :tbody_class, "" set :td_class, "" ``` -------------------------------- ### Configure Fixed Page Size Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Set a fixed page size for collections using the `page_size` attribute. ```heex ... ``` -------------------------------- ### Workflow for Updating Theme Properties Source: https://github.com/sevenseacat/cinder/blob/main/docs/theming.md Illustrates a typical workflow using browser developer tools to identify a theme property via `data-key` and then update it in the theme configuration. ```bash # 1. Inspect element in browser # 2. Update your theme set :filter_text_input_class, "w-full px-4 py-3 border-2 border-blue-500 rounded-lg" # 3. Refresh to see changes ``` -------------------------------- ### Define a Custom Cinder Theme Module Source: https://github.com/sevenseacat/cinder/blob/main/docs/getting-started.md Create a custom theme by defining a module that uses Cinder.Theme and setting various styling properties. ```elixir defmodule MyApp.Theme.Corporate do use Cinder.Theme # Table set :container_class, "bg-white shadow-lg rounded-lg border border-gray-200" set :th_class, "px-6 py-4 bg-blue-50 text-left font-semibold text-blue-900" set :td_class, "px-6 py-4 border-b border-gray-100" set :row_class, "hover:bg-blue-50 transition-colors" # Filters set :filter_container_class, "bg-gray-50 p-4 rounded-lg mb-4" set :filter_text_input_class, "w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500" # Pagination set :pagination_button_class, "px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" end ``` -------------------------------- ### Define Custom Theme Module Source: https://github.com/sevenseacat/cinder/blob/main/docs/theming.md Create a custom theme by defining a module that uses `Cinder.Theme` and setting CSS classes with the `set` function. This allows for reusable and complex styling. ```elixir defmodule MyApp.CustomTheme do use Cinder.Theme set :container_class, "bg-white shadow-lg rounded-lg border" set :th_class, "px-6 py-4 bg-gray-50 font-semibold text-gray-900" set :row_class, "hover:bg-gray-50 transition-colors" end ``` -------------------------------- ### Function Actions with Pre-filtered Queries Source: https://github.com/sevenseacat/cinder/blob/main/docs/advanced.md Employ Function actions to receive a pre-filtered query that matches specific code interface signatures. ```heex <:bulk_action action={&MyApp.Users.archive/2}>Archive ``` -------------------------------- ### Switch from Pastel Theme Source: https://github.com/sevenseacat/cinder/blob/main/docs/upgrading.md If you were using the removed `pastel` theme, switch to an available alternative like `modern` or create a custom theme with similar styling. ```elixir # If you were using pastel, switch to another theme theme="modern" # or any other available theme ``` -------------------------------- ### Enable Selection and Bulk Actions in Cinder Collections Source: https://github.com/sevenseacat/cinder/blob/main/usage-rules.md Configure Cinder collections to be selectable and define bulk actions using themed or custom buttons. Themed buttons use `label` and `variant` for automatic styling. ```heex <:col :let={user} field="name" filter sort>{user.name} <:bulk_action action={:archive} label="Archive ({count})" variant={:primary} /> <:bulk_action action={:export} label="Export" variant={:secondary} /> <:bulk_action action={:destroy} label="Delete" variant={:danger} confirm="Delete {count}?" /> <:bulk_action action={&MyApp.Users.soft_delete/2} on_success={:deleted} :let={ctx}> ``` -------------------------------- ### Enable Bookmarkable URL States with UrlSync Source: https://github.com/sevenseacat/cinder/blob/main/usage-rules.md Integrate Cinder.UrlSync into your LiveView to manage URL parameters for bookmarkable and shareable collection states. ```elixir defmodule MyAppWeb.UsersLive do use MyAppWeb, :live_view use Cinder.UrlSync def handle_params(params, uri, socket) do socket = Cinder.UrlSync.handle_params(params, uri, socket) {:noreply, socket} end def render(assigns) do ~H""" <:col :let={user} field="name" filter sort>{user.name} """ end end ```