feat(documents): timeline date-range filter with density bars (#385) #478

Merged
marcel merged 52 commits from feat/issue-385-timeline-density-filter into main 2026-05-08 12:27:17 +02:00
3 changed files with 8 additions and 6 deletions
Showing only changes of commit 52827ccc87 - Show all commits

View File

@@ -193,10 +193,10 @@ export function buildDensityUrl(filters: DensityFilters = {}): string {
} }
/** /**
* Loads the density data for the timeline widget. Mobile (sm: breakpoint and below) * Loads the density data for the timeline widget. Tablet and below (lg breakpoint,
* and calendar view both skip the request entirely — the widget isn't rendered * <1024px) and calendar view both skip the request entirely — the widget isn't
* there. A non-ok response or network failure degrades to an empty bucket list * rendered there. A non-ok response or network failure degrades to an empty
* instead of throwing, so the document list page keeps rendering. * bucket list instead of throwing, so the document list page keeps rendering.
*/ */
export async function fetchDensity( export async function fetchDensity(
fetch: typeof globalThis.fetch, fetch: typeof globalThis.fetch,

View File

@@ -241,7 +241,7 @@ $effect(() => {
onblur={() => (qFocused = false)} onblur={() => (qFocused = false)}
/> />
<div class="mt-3 mb-4 hidden sm:block"> <div class="mt-3 mb-4 hidden lg:block">
<TimelineDensityFilter <TimelineDensityFilter
density={data.density} density={data.density}
minDate={data.minDate} minDate={data.minDate}

View File

@@ -4,7 +4,9 @@ import type { PageLoad } from './$types';
export const load: PageLoad = async ({ url, fetch, data }) => { export const load: PageLoad = async ({ url, fetch, data }) => {
const view = url.searchParams.get('view'); const view = url.searchParams.get('view');
const isDesktop = browser && window.matchMedia('(min-width: 640px)').matches; // Tailwind `lg` breakpoint — bars below this width fall under the 44×44 touch
// target floor (Leonie's tablet finding) and the chart skips the fetch.
const isDesktop = browser && window.matchMedia('(min-width: 1024px)').matches;
// Forward active filters (excluding from/to) so the chart matches the list. // Forward active filters (excluding from/to) so the chart matches the list.
const tagOp = url.searchParams.get('tagOp'); const tagOp = url.searchParams.get('tagOp');