FilterMenu
One filterable popover list for every "pick from many" trigger.
View code
<FilterMenu
id="ref-picker"
mode="navigate"
tabs
trigger={<><GitBranchIcon size={16} aria-hidden="true" /> main</>}
groups={[
{ label: "Branches", items: branches.map((branch) => ({
value: branch.name,
label: branch.name,
href: `/acme/delta/tree/${branch.name}`,
badge: branch.isDefault ? "default" : undefined,
selected: branch.name === current,
})) },
{ label: "Tags", items: tags.map((tag) => ({ value: tag, label: tag, href: `/acme/delta/tree/${tag}` })) },
]}
filterAction="/acme/delta/branches"
footer={<a href="/acme/delta/branches">View all branches</a>}
labels={{
title: "Switch branches/tags",
filter: "Find a branch…",
empty: "Nothing to show",
more: "{count} more",
save: "Save",
tabs: "Ref type",
}}
/>Demo apps
Whole pages built only from @sdxc/ui, each for an invented product with its own palette and type. They open in a new tab.
- Issue trackerCairnCairn, an invented issue tracker: grouped issue lists with filters in the address, a drag-and-drop board, projects on a roadmap, cycles with burn-up charts and an inbox./demo/apps/cairn
- Social networkChorusChorus, an invented social network: a live timeline with pictures, link cards, polls and threads, profiles, grouped notifications, search and messages./demo/apps/chorus
- Code hostDeltaDelta, a code host whose one repository is its own source: a file tree beside the code, line links, blame and the commits list, every file and commit read from git when the site is built./demo/apps/delta
- CMSInkwellInkwell, a demo CMS built from @sdxc/ui/app: posts with count tabs and quick edit, an editor with a quiet save status and a loud Publish, media and settings./demo/apps/inkwell
- Ops dashboardPulsePulse, an invented ops dashboard: Northwind's services with live filters, a peek sheet and a bulk bar, metrics that switch one chart, incidents, deploys and settings./demo/apps/pulse
- Support inboxRelayRelay, an invented support inbox: mailboxes, conversations and the open conversation on one screen, with contacts, reports and settings./demo/apps/relay
- Chat assistantTernTern, an invented chat assistant: conversations with streamed replies, code and tables, projects, a canvas, sharing and settings./demo/apps/tern
Every demo, landings and docs sites alike, is listed in the demo gallery.
Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/ui remiximport "@sdxc/ui/theme.css";Usage
import { FilterMenu } from "@sdxc/ui/app";Renders a trigger and its native popover: links in navigate mode, a form posted to action by
its Save button in single and multiple. Mapping @sdxc/ui/app/filter-menu in the browser
entry runs FilterMenuList: typing filters, arrows walk, and closing a changed picker posts.
Composition
The parts the component publishes, each a static property of the host.
FilterMenuFilterMenu.PopoverRenders the popover alone, for a trigger the page already has, such as a property row's edit button targetingid.
Examples
Labels, several at once
Apply labels to this issue
View code
<FilterMenu
id="issue-labels"
mode="multiple"
name="label"
action="/acme/delta/issues/231/labels"
trigger="Labels"
groups={[{ label: "Labels", items: labels.map((label) => ({
value: label.id,
label: label.name,
description: label.description,
color: label.color,
selected: issue.labels.includes(label.id),
})) }]}
labels={{
title: "Apply labels to this issue",
filter: "Filter labels",
empty: "No labels match",
more: "{count} more",
save: "Save",
}}
/>Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
| Prop | Type | Required | Description |
|---|---|---|---|
trigger | RemixNode | Yes | The trigger's content, such as a branch icon and the current branch's name. |
Also accepts everything in PopoverProps.
FilterMenu.Popover
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The popover's id, which the trigger, or any popovertarget, opens. |
mode | "navigate" | "single" | "multiple" | Yes | Whether rows are links, radios or checkboxes. |
groups | Group[] | Yes | Every choice, sent whole to the island so filtering never waits on the server. |
tabs | boolean | No | Draws the groups as tabs (Branches | Tags) instead of stacked sections. |
name | string | No | The field name radios and checkboxes post under; required for single and multiple. |
action | string | No | Where single and multiple post. Defaults to the current address. |
target | string | No | The named <Frame> the post loads into, so only that frame reloads. |
filterAction | string | No | A page that filters with ?q=, which the filter field submits to without script. |
query | string | No | The filter already applied, as the filterAction page read it. |
limit | number | No | How many matches the list draws before one closing "more" row. @default 100 |
footer | RemixNode | No | A closing link or action, such as "View all branches". |
placement | Popover.Placement | No | The trigger's side the popover opens on above phone widths. @default "bottom-start" |
labels | Labels | Yes | Every string the menu shows, so it reads in any language. |
Also accepts everything in Omit<TagProps<"div">, "id" | "children" | "popover">.
Types
| Name | Values | What it decides |
|---|---|---|
Mode | "navigate" | "single" | "multiple" | "navigate" makes every item a link (a branch picker); "single" and "multiple" make them radios or checkboxes named name, posted to action when the popover closes. |