Koala logo Design

Period filters

Standard period filter dropdowns used on list pages and dashboards to scope data by time range.

Default period

Period filters should always default to 30 days (30d). This provides a useful window of recent data without overwhelming users with too much history.

7d 30d 3m 12m
@foreach (var (key, label) in new[] { ("7d", "7d"), ("30d", "30d"), ("3m", "3m"), ("12m", "12m") })
{
    var isActive = activePeriod == key;
    <a href="@(Route())?period=@key"
       x-target.push="container-id"
       class="px-3 py-1.5 rounded-lg text-sm font-medium
              @(isActive
                  ? "bg-gray-900 text-white dark:bg-white dark:text-gray-900"
                  : "text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700")">
        @label
    </a>
}

Standard options

The standard set of period options used across the application.

Key Label Description
7d 7 days Last 7 days of data
30d 30 days Last 30 days of data (default)
3m 3 months Last 3 months of data
12m 12 months Last 12 months of data
all All time No time restriction (use sparingly)

Toggle filter

An animated toggle between two filter modes with a sliding indicator. Used in activity tabs to switch between "Everything" and "Filter by users".

<div x-data="{ filterMode: 'all' }">
    <div class="relative grid grid-cols-2 rounded-full bg-gray-100 dark:bg-gray-700 p-1 w-fit mx-auto">
        <div class="absolute inset-1 w-[calc(50%-4px)] rounded-full bg-white dark:bg-gray-600 shadow-sm transition-transform duration-200 ease-in-out"
             :class="filterMode === 'users' ? 'translate-x-full' : 'translate-x-0'"></div>
        <button type="button"
                x-on:click="filterMode = 'all'"
                :class="filterMode === 'all'
                    ? 'text-gray-900 dark:text-white'
                    : 'text-gray-500 dark:text-gray-400'"
                class="relative z-[1] px-4 py-2 rounded-full font-medium transition-colors duration-200">
            Everything
        </button>
        <button type="button"
                x-on:click="filterMode = 'users'"
                :class="filterMode === 'users'
                    ? 'text-gray-900 dark:text-white'
                    : 'text-gray-500 dark:text-gray-400'"
                class="relative z-[1] px-4 py-2 rounded-full font-medium transition-colors duration-200">
            Filter by users
        </button>
    </div>
</div>

Usage guidance

When and where to use period filters.

Do Don't
Default to 30 days for all period filters Default to "All time" (too much data on first load)
Use on dashboards, list pages, and activity tabs Use on detail pages that show a single entity
Persist the selected period in the URL query string Store the period in Alpine.js state (loses on navigation)
Use Alpine-AJAX (x-target.push) for smooth filter switching Use full page reloads when filtering