How it works › Filters and facets
Filters and facets
The rail is <data-facets for="views-id"> beside a <data-views>. It draws the .base file's facets: list and edits one thing: the all-views filter, the same filter the Filter menu, the URL and an agent writing the file use. A tick in the rail shows in the table, the cards and the chart alike.
Every kind of facet
Liverobotparts' 1,149 actuators with one facet of each kind. The tabs McMaster-style, Amazon-style, Digi-Key-style and Obsidian-style each carry their own facets:, so switching tab switches the rail.
The live view starts when it scrolls into sight.
- type: table
name: Every kind
order: [model, brand, form, drivetrain, peak_torque, mass, od, price, in_stock, listed, level]
sort:
- { property: peak_torque, direction: DESC }From the example Filters
Write it
A facet is a property name, or {property, as: <kind>, …options}. Every kind also takes label, info (the ⓘ), diagram and collapsed. An unknown kind draws as values and warns; it never breaks the page.
facets:
- { as: current, label: Current filters }
- { property: model, as: search, properties: [model, name], label: Search, placeholder: "Model or name, e.g. AK80" }
- property: price
as: popular
label: Popular filters
options:
- { label: In stock, filter: 'in_stock == "yes"' }
- { label: CAN bus, filter: 'buses.contains("can")' }
- { label: Under $100, filter: 'price < 100' }
- { label: Has a photo, filter: '!photo.isEmpty()' }
- { property: form, as: tree, levels: [form, brand], label: Form › brand }
- property: form
as: gallery
label: Form
columns: 2
info: "How the actuator is built: a hobby servo's case and horn, an integrated joint with its driver inside, a frameless direct-drive ring, a motor with a separate gearbox, or a motor inside a wheel."
images:
hobby servo: icons/form-hobby_servo.svg
integrated actuator: icons/form-integrated_actuator.svg
direct drive: icons/form-direct_drive.svg
bare gearmotor: icons/form-bare_gearmotor.svg
wheel hub: icons/form-wheel_hub.svg
- property: drivetrain
as: picture-list
label: Drivetrain
images:
geared: icons/drivetrain-geared.svg
direct_drive: icons/drivetrain-direct_drive.svg
motor: icons/drivetrain-motor.svg
- property: brand
as: swatch
label: Brand (logos)
limit: 12
images:
Steadywin: logos/steadywin.webp
Damiao: logos/damiao.webp
JMC: logos/jmc.webp
- { property: brand, as: values, exclude: true, label: Brand, searchable: true }
- { property: in_stock, as: toggle, value: "yes", text: In stock only }
- { property: in_stock, as: select, label: Stock }
- { property: checks, as: toggle, value: cad, text: Has CAD, label: CAD }
- { property: photo, as: has, properties: [photo, torque_density, price], label: Has data, match: all }
- { property: price, as: buckets, buckets: [50, 100, 250, 500], unit: USD, label: Price }
- { property: price, as: range, choices: [25, 50, 100, 250, 500, 1000, 2500], label: Price (min / max) }
- { property: peak_torque, as: slider-histogram, log: true, label: Peak torque }
- { property: mass, as: slider, log: true, label: Mass }
- { property: od, as: range, diagram: diagrams/od.svg, label: Outer diameter, info: "Across the actuator's face, housing to housing; not the output flange." }
- { property: length, as: range, diagram: diagrams/length.svg, label: Axial length, collapsed: true }
- { property: torque_density, as: buckets, label: Peak N·m/kg }
- { property: level, as: rating, max: 5, label: robotparts level }
- { property: level, as: min-level, max: 5, label: Level }
- { property: listed, as: date, presets: [7d, 30d, year], older: [14d, 90d], label: First listed }
- { property: buses, as: chips, label: Bus }
- { property: gear_ratio, as: grid, columns: 3, sort: value, limit: 15, label: Gear ratio, info: "Output turns per motor turn; 1 is direct drive." }
- { property: voltage, as: listbox, sort: value, label: Voltage }The kinds
as: | Draws | Writes |
|---|---|---|
values | checkboxes with counts, Show N more, a find box | p == v, or {or:}; .contains on a list |
select | Any + radios, or a dropdown | one p == v |
toggle | a switch | p == <value> |
has | "Has a value" per property | !p.isEmpty(), all or any |
range | min / max boxes (dates on a date) | p >= a, p <= b |
slider / slider-histogram | two thumbs, the second over the distribution | p >= a, p <= b |
buckets | preset ranges as chips | p >= a, p < b |
rating / min-level | "★★★☆ & up", "Level ≥ N" | p >= N |
date | from / until, presets, "Older than" | p >= "date", p < "date" |
chips, swatch, gallery, picture-list, grid | pressable values: tags, logos, colours, pictures | as values |
listbox | a native multi-select | as values |
tree | a hierarchical menu | one p == v per level |
search | a text box | p.contains("x"), over one or more properties |
popular | named shortcuts with counts | each option's clause |
current | every pick as a removable chip, Clear all | (removes) |
The URL
The rail's part of the filter stays readable in the address: ?brand=A,B, brand!=A (exclude), price=50..<100 (a range, < marking an exclusive end), model~=ak (search), has=photo. A clause no facet can draw stays as a custom filter, shown in the rail as "+N custom filters · Edit".
Keyboard and phone
Native controls or buttons with aria-pressed, each group labelled, the match count a polite live region. Under 700 px the rail is a closed disclosure above the view. The rail's right edge drags (Resizable panels).
Comes from docs/CONTRACT.md §7 and its 2026-10-26 amendment (filters) in docs/.