Files
collective-lists/apps/web/tailwind.config.ts
Oier Bravo Urtasun 8fa629ad74 feat(fase-11): TagChip + TagPicker components + filter unit tests (11.3.1-2)
TagChip — small pill rendering a tag's name with the colour from the 8-preset
palette. Three usage shapes (mutually exclusive):
  * display-only (default)
  * with onRemove → renders an inline X (used by picker-selected chips)
  * with onSelect → renders the whole chip as a button (used by the lateral
    filter bar and by item-row chips that filter the list on click)
Nested <button> was the SSR warning from the first cut — fixed by making
onSelect / onRemove mutually exclusive.

TagPicker — combobox-style picker driven by filterTagOptions (pure helper
in tag-picker-filter.ts so it can be unit-tested without rendering). Lists
matches by substring, surfaces a "Create `{query}`" affordance only when no
existing tag matches the trimmed query exactly. Enter key prefers toggling
the first match, falls back to creating. Re-usable from the item modal,
the list-filter bar, and the settings tag-management section.

tag-picker-filter.test.ts — 7 unit tests (TP-01..07) covering case-
insensitive substring match, empty query → full list, create affordance
gating on exact-match absence, exclusion of already-selected ids, and
createName preserving verbatim user input (no lowercasing).

tailwind.config.ts safelists the runtime-built bg-/text-/ring-/dot
combinations for all 8 preset colours so JIT doesn't strip them.

Messages: 9 new keys in en + es (tag picker, filter bar, settings section).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 03:08:54 +02:00

48 lines
1.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Config } from 'tailwindcss';
// Fase 11: tag colours are picked at runtime from an 8-preset palette
// (see public.item_tags.color CHECK constraint). Tailwind cannot statically
// see the class names (they're built from the colour string), so safelist
// every (variant × intensity) combination the chip + dot use.
const TAG_COLORS = ['slate', 'red', 'amber', 'green', 'sky', 'indigo', 'pink', 'stone'];
const tagSafelist = TAG_COLORS.flatMap((c) => [
`bg-${c}-100`,
`text-${c}-700`,
`ring-${c}-200`,
`dark:bg-${c}-900/40`,
`dark:text-${c}-200`,
`dark:ring-${c}-700/50`,
`bg-${c}-500`
]);
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
safelist: tagSafelist,
// Fase 9.1: drive dark mode from <html data-theme="dark"> so the inline
// anti-FOUC script in app.html can set the attribute synchronously before
// the first paint. Existing `dark:` utilities keep working as-is.
darkMode: ['selector', '[data-theme="dark"]'],
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif']
},
colors: {
// Semantic aliases — "The Monolith Editorial" surface hierarchy.
// Use background shifts (never 1px borders) to separate major UI areas.
background: 'rgb(var(--background) / <alpha-value>)',
'surface-container-low': 'rgb(var(--surface-container-low) / <alpha-value>)',
surface: 'rgb(var(--surface) / <alpha-value>)',
'surface-raised': 'rgb(var(--surface-raised) / <alpha-value>)',
// Text hierarchy
'text-primary': 'rgb(var(--text-primary) / <alpha-value>)',
'text-secondary': 'rgb(var(--text-secondary) / <alpha-value>)',
'text-muted': 'rgb(var(--text-muted) / <alpha-value>)',
// Only non-slate color allowed in the system
destructive: 'rgb(var(--destructive) / <alpha-value>)'
}
}
},
plugins: []
} satisfies Config;