Koala logo Design

List filter modals

Index pages (Quotes, Transactions, Partners) ship with a row of filter dropdowns that need to render inline on desktop and as a full-screen modal on mobile. The <koala-list-filters> Portal tag helper wraps that row and handles the responsive collapse, the mobile backdrop, the close button, and the sticky "Apply filters" footer for you. You only write the filter dropdowns themselves.

When to use

Use this on every list page that has 1+ filter dropdowns. The pattern enforces a consistent layout across Quotes / Transactions / Partners — the search box and a mobile filter trigger live to the left of the row, and the dropdowns flow into a modal below that breakpoint.

  • The parent <form> declares x-data="{ filtersOpen: false, ... }".
  • The mobile trigger button (the funnel icon outside the tag helper) flips filtersOpen to open the modal.
  • Choose breakpoint="Medium" (default, 768px) for 1–2 dropdowns, or breakpoint="Large" (1024px) when 3+ dropdowns need more horizontal space.
  • The dropdowns inside should use the same breakpoint for their w-auto / left-auto classes to match.

Reference snippet

Inside the form (after the search box and the mobile filter trigger) wrap the dropdown sections in a <koala-list-filters> tag.

<form method="get" x-data="{ searching: false, filtersOpen: false }"
      x-target.push="filter-button quote-results">

    <div class="flex flex-wrap items-center justify-between gap-3 p-4">
        <!-- search input + mobile filter button (md:hidden) live OUTSIDE the tag helper -->

        <koala-list-filters>
            <!-- Status dropdown -->
            <div class="relative w-full md:w-auto" x-data="{ open: false }">
                <button id="status-dropdown-button" ... >Status</button>
                <!-- panel with checkboxes that auto-submit on change -->
            </div>

            <!-- Partner dropdown (only when relevant) -->
            @if (Model.Partners.Count > 0)
            {
                <div class="relative w-full md:w-auto" x-data="{ open: false }">
                    <button id="partner-dropdown-button" ... >Partner</button>
                    <!-- panel -->
                </div>
            }
        </koala-list-filters>
    </div>
</form>

Conventions

  • Mobile trigger lives outside the tag helper. The funnel-icon button that flips filtersOpen sits next to the search input on mobile so users can tap to open the filter modal. The tag helper renders only the modal/desktop-row content.
  • Auto-submit on change. Each dropdown checkbox calls $el.form.requestSubmit() on change so the list re-renders immediately. There is no draft / dirty state.
  • Apply button is mobile-only. The footer Apply Filters button is rendered for you and just dismisses the modal — every change has already been applied.
  • Don't nest forms. The dropdowns share the parent <form>; nesting a second form inside breaks auto-submit.
  • Mobile breakpoint must match the dropdowns inside. If the dropdowns use md:w-auto, keep the default breakpoint="Medium". If they use lg:w-auto, switch to breakpoint="Large".

Where it's used

  • /conveyancing/quotes — search + status + partner filter
  • /conveyancing/transactions — search + status + type + partner filter
  • /partner/quotes — search + status + referrer filter
  • /partner/transactions — search + status + type + referrer filter