{% extends "brickwork/shell/app.html" %} {% comment %} A date RANGE picker, and the single-date variant of the same file. COPY THIS FILE into your project and edit it. It is not on the template loader path, so you cannot extend it (ADR-056). It is not a brickwork component: no {% templatetag openblock %} bw_date_picker {% templatetag closeblock %} tag exists and never will (BR-BW-INPUT-004 is a Fixed rule: date fields stay native , never a JS calendar widget, as a package-shipped component). What you are copying is EXT-006's documented slot filled in once, properly, so you do not have to build it yourself: the wrapper chrome is brickwork tokens, the popover content is entirely yours from the moment you copy this file (FRM-013). WHAT YOUR VIEW MUST SUPPLY, and this is deliberately small: nav_items / nav_active as in list.html bw_drp_weekday_labels 7 short weekday names, MONDAY FIRST, translated. One line: list(django.utils.dates.WEEKDAYS_ABBR[i] for i in range(7)) (values, not the dict; the dict is already keyed 0=Monday regardless of locale, so no rotation is needed here). bw_drp_month_labels 12 month names, JANUARY FIRST, translated. One line: list(django.utils.dates.MONTHS[i] for i in range(1, 13)) bw_drp_first_day the locale's first day of the week, 0=Sunday.. 6=Saturday (Django's OWN convention, NOT the Monday-first convention WEEKDAYS_ABBR uses). One line: django.utils.formats.get_format( "FIRST_DAY_OF_WEEK") Both lists are Django's own lazily-translated calendar names (django.utils.dates), resolved through the active language exactly like every other string on the page. Nothing here invents an English fallback table: if your view forgets to pass them, the grid header renders empty text nodes rather than silently falling back to English, which is the honest failure mode for a copied example with no defaults of its own. THE FLOOR (Phase 1). Two native (start, end) OR, in single mode below, one. They ARE the submitted form control at all times, before and after JS runs: the popover only ever writes ISO values into them via .value, exactly as the combobox module mirrors its floor , always the submitted controls. --------------------------------------------------------------------------- {% endcomment %}
Date raised {% comment %} CONSTRAINTS (Phase 3), edited directly here rather than passed from the view: unlike the localisation data above, min/max/disabled dates/weekend masking are THIS FIELD's own business rule, not translated copy, so they belong in the file you now own. All four are optional; delete any you do not need. min / max ISO date strings ("2026-01-01"); either or both. disabledDates an array of ISO date strings, individually disabled (e.g. public holidays). disableWeekends true disables Saturday/Sunday throughout. Every disabled day is unselectable by pointer AND keyboard-unreachable (arrow-key movement skips over it entirely) AND announced ", Unavailable" by its aria-label, never conveyed by dimmed colour alone (WCAG 1.4.1). {% endcomment %}
Start date
End date {% comment %} One popover markup, shown beside whichever trigger opened it (positioned in JS by moving focus/aria only; the DOM position stays here so both fields can share one instance rather than duplicating the whole grid twice in markup that never both show at once). {% endcomment %}

Format YYYY-MM-DD. Leave either field blank for an open-ended range.

{% bw_button "Apply filter" type="submit" variant="primary" %}
{% comment %} --------------------------------------------------------------------------- SINGLE-DATE MODE: most fields need exactly one date, not a range. Delete the block above and keep this one if that is all you need; it is the same mechanism with one input, one endpoint, and a shorter preset list (Today, Yesterday, This month, Last month: a range-relative preset like "Last 7 days" describes a SPAN, which has no meaning for a single date). --------------------------------------------------------------------------- {% endcomment %}

Format YYYY-MM-DD.

{% bw_button "Save" type="submit" variant="primary" %}
{% endblock %} {% block body_js %} {% comment %} This component is NOT registered through registerBrickworkComponents: it is not a shipped brickwork behaviour, so it never touches frontend/src/js or the package's Alpine registration hook. It defines its own Alpine.data() the moment Alpine parses this {% endblock %}