Filter bar
canonRow of filter chips with add, reset and save controls.
React implementation lives in the app (apps/web/src/components/FilterBar.tsx), not in @acrm/ui. Phone (owner 2026-09-28, acrm !4088): with onOpenChange the bar is the bottom sheet „Filtry" (search, conditions with ⋮ Odebrat, Přidat filtr, Vymazat vše, Hotovo); the Filtr toggle shows a neutral CountBadge, Řadit (SegmentScreen) a sort sheet; „Uložit pro všechny" moves to the bar's ⋮ (phoneOnly). „Vymazat filtry" = Button ghost tone muted. Desktop unchanged. 14 Oct 2026 (owner "24c approved", proto/lista-vypisu@a16fe17a7, acrm !5045): no word labels — Filtr = icon (+ dot), Seskupit/Řadit/Zobrazení = icon + chosen value, field name only in aria-label/tooltip; open row: chip = field icon + value, „+" and „×" icons; closed by default, „Jen moje" is a chip inside Filtr. Dev check 14 Oct on /tasks /pipeline /objednavky /setkani /lide, 1440 + 390: 0 label words, no overflow. Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .fb-add, .fb-reset, .fb-save.
Used in 23 files · 21 areas · 48× — components/communication, components/datamart, pages/AccountingInvoicesPage, pages/AccountingReceivedInvoicesPage, pages/AsistentAuditPage, pages/DokumentyPage …
apps/web <FilterBar> <FilterToggleChip>.fb-clear .fb-conj .fb-menu .fb-sheet +3SourceStoryLegacy card filter-bar.htmlDefault
export const Default = () => <Bar initial={{ faze: 'jednani', vlastnik: 'ja' }} />;Variants
export const Variants = () => (
<div style={{ display: 'grid', gap: 'var(--sp-5)' }}>
<Labeled text="empty bar — add a filter and the chip appears already filled in (Notion: a chip without a value does not exist)">
<Bar />
</Labeled>
<Labeled text="always-open search in the bar (.fb-search — field kind 'text', inline)">
<Bar initial={{ kraj: 'praha' }} inlineSearch saveForAll={false} />
</Labeled>
<Labeled text="conjunction between chips — click it: „a zároveň“ turns into „nebo“ and the two chips merge into one tinted group — the bar stays 47px tall either way (ACRM-43/49)">
<Bar initial={{ faze: 'jednani', vlastnik: 'ja' }} groupable saveForAll={false} />
</Labeled>
<Labeled text="host without segments — no „Uložit pro všechny“, only reset">
<Bar initial={{ termin: 'mesic' }} saveForAll={false} />
</Labeled>
</div>
);States
export const States = () => (
<div style={{ display: 'grid', gap: 'var(--sp-5)' }}>
<Labeled text="empty — no filter set, so no „Vymazat filtry“ and no „Uložit pro všechny“">
<Bar />
</Labeled>
<Labeled text="chip with an open menu (.open)">
<div className="fb">
<button type="button" className="fb-chip open" aria-haspopup="menu" aria-expanded="true">
<Icon name="target" />
<span className="k">Fáze</span>
<span className="v">Jednání</span>
<Icon name="chevron-down" className="chev" />
</button>
<button type="button" className="fb-chip">
<Icon name="user" />
<span className="k">Vlastník</span>
<span className="v">Já</span>
<Icon name="chevron-down" className="chev" />
</button>
</div>
</Labeled>
<Labeled text="long value — clipped at 148px, the chip never grows past it">
<div className="fb">
<button type="button" className="fb-chip">
<Icon name="tag" />
<span className="k">Štítky</span>
<span className="v">Investoři · Dluhopisy · Praha · Retenční kampaň 2026</span>
<Icon name="chevron-down" className="chev" />
</button>
</div>
</Labeled>
<Labeled text="toggle chip in the Section top bar (.lst-toggle) — the accent dot means „a filter is on“">
<div className="fb">
<button type="button" className="fb-chip lst-toggle set" aria-pressed="true">
<Icon name="filter" />
<span className="k">Filtr</span>
</button>
<button type="button" className="fb-chip">
<Icon name="target" />
<span className="k">Fáze</span>
<span className="v">Jednání</span>
<Icon name="chevron-down" className="chev" />
</button>
</div>
</Labeled>
<Labeled text="disabled toggle chip — the look comes from .lst-toggle:disabled (ds/list-view.css)">
<div className="fb">
<button type="button" className="fb-chip lst-toggle" disabled>
<Icon name="filter" />
<span className="k">Filtr</span>
</button>
</div>
</Labeled>
</div>
);With icon & kbd
export const WithIconAndKbd = () => (
<div style={{ display: 'grid', gap: 'var(--sp-5)' }}>
<Labeled text="every chip carries the field icon on the left and a chevron on the right — both are part of the chip, not optional decoration">
<Bar initial={{ faze: 'jednani', vlastnik: 'ja', termin: 'mesic', stitky: ['investor'] }} />
</Labeled>
<span style={label}>
The bar actions carry icons too: plus (add), x (reset), users (save for everyone). The bar has
no keyboard shortcut chips — Escape closes an open menu, Enter confirms a typed value.
</span>
</div>
);Composition
export const Composition = () => {
const [open, setOpen] = useState(true);
return (
<div
style={{
border: '1px solid var(--border)',
borderRadius: 'var(--radius-lg)',
overflow: 'hidden',
background: 'var(--bg-canvas)',
}}
>
{/* Shipped order: Section top bar first, filter bar as the second row under it. The
toggle chip that opens it is FilterBar's own `.fb-chip.lst-toggle`, not the bar's
`.tchip` — see the Usage tab, "two chips for one job". */}
<SectionTopBar title={<SectionTopBarTitle name="Obchody" tileIcon="target" tone="blue" />}>
<SectionTopBarSpacer />
<button
type="button"
className={'fb-chip lst-toggle set' + (open ? ' open' : '')}
aria-pressed={open}
onClick={() => setOpen((v) => !v)}
>
<Icon name="filter" />
<span className="k">Filtr</span>
</button>
</SectionTopBar>
{open ? <Bar initial={{ faze: 'jednani', vlastnik: 'ja' }} /> : null}
<div style={{ padding: 'var(--sp-5)', color: 'var(--fg-muted)', font: 'var(--small)' }}>
Closing the bar does not switch the filters off — the accent dot on the toggle chip says
they are still on.
</div>
</div>
);
};