feat(timeline): contain buckets with a colour rail and collapse oversized ones
The grouped view flooded: buckets had no visual containment (a tiny floating pill over cards identical to the ungrouped view) and the >12-letter density collapse was gone, so "Weitere Briefe · 325" / "Sonstiges · 10" dumped every card. LetterBucket now binds each cluster with a coloured left rail (tag colour in Thema, mint for an Ereignis cluster, neutral for the fallback), renders compact cards, and — above BUCKET_DENSE_THRESHOLD (6) — collapses to the existing month-density YearLetterStrip instead of a flood. Adds a `nested` mode (no header) for letters that sit under their event pill, and shares the tag-colour token allow-list via tagColorVar. Refs #827
This commit is contained in:
@@ -14,6 +14,41 @@ export type GroupingMode = 'date' | 'event' | 'thema';
|
||||
/** The default mode — chronological, as #779 shipped. */
|
||||
export const DEFAULT_GROUPING: GroupingMode = 'date';
|
||||
|
||||
/**
|
||||
* A bucket larger than this collapses to a month-density strip instead of flooding the
|
||||
* timeline with individual cards (#827) — the catch-all "Weitere Briefe"/"Ohne Thema"
|
||||
* buckets are always the biggest, so without this they swamp the grouped view. Lower than
|
||||
* Datum mode's `DENSE_THRESHOLD` (12) because a bucket is a narrower context than a year.
|
||||
*/
|
||||
export const BUCKET_DENSE_THRESHOLD = 6;
|
||||
|
||||
export function isBucketDense(letterCount: number): boolean {
|
||||
return letterCount > BUCKET_DENSE_THRESHOLD;
|
||||
}
|
||||
|
||||
/** The `--c-tag-*` colour-name tokens (sage/sienna/…); shared by the chip and the rail. */
|
||||
const TAG_COLOR_TOKENS = new Set([
|
||||
'sage',
|
||||
'sienna',
|
||||
'amber',
|
||||
'slate',
|
||||
'violet',
|
||||
'rose',
|
||||
'cobalt',
|
||||
'moss',
|
||||
'sand',
|
||||
'coral'
|
||||
]);
|
||||
|
||||
/**
|
||||
* Maps a root-tag colour-name token to its CSS variable reference, or `null` for an absent
|
||||
* or unknown token (so a colourless/unrecognised tag falls back to a neutral rail, never a
|
||||
* broken `var(--c-tag-undefined)`).
|
||||
*/
|
||||
export function tagColorVar(token: string | null | undefined): string | null {
|
||||
return token && TAG_COLOR_TOKENS.has(token) ? `var(--c-tag-${token})` : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* One bundle of loose letters under a single header, within a year (Ereignis/Thema modes).
|
||||
* `kind` decides the header: a curated-event title, a tinted root-tag chip, or the localized
|
||||
|
||||
Reference in New Issue
Block a user