Examples › robotparts › The query bar: tokens, autocomplete and bulk actions
The query bar: tokens, autocomplete and bulk actions
robotparts' 1,149 actuators with the bar's query box in token mode: type brand: and it suggests the brands with
their counts, Enter makes the clause a token, and a tick in the rail shows up as a token too, because both edit the one
filter. Shift-click a range of rows, ctrl-click to add one, and Shopify's bulk bar offers Compare, Copy IDs and Export
CSV (docs/CONTRACT.md §15).
The .base file and its data
Every tab above is one entry of this file; the views read these rows. ⋯ in the toolbar copies the current view as YAML.
# The query bar and selection (docs/CONTRACT.md §15) over robotparts' 1,149 actuators: the toolbar-bar case's file,
# shown with filters="query-tokens rail" and display="popover", so every clause of the filter is a token inside the
# query bar (a rail tick shows there at once) and rows select with shift / ctrl-click into Shopify's bulk bar.
# Obsidian Bases grammar plus data-ui's keys (docs/CONTRACT.md §5). Check it: node bin/data-ui.mjs check <this file>
data: ../robotparts-actuators/actuators.json
facets:
- brand
- form
- drivetrain
- buses
- level
- { property: peak_torque, as: range }
- { property: mass, as: range }
- { property: price, as: range }
- { property: torque_density, as: has }
properties:
model: { displayName: Model }
brand: { displayName: Brand }
form: { displayName: Form }
drivetrain: { displayName: Drivetrain }
peak_torque: { displayName: Peak torque }
rated_torque: { displayName: Rated torque }
max_speed: { displayName: Max speed }
mass: { displayName: Mass }
gear_ratio: { displayName: Ratio }
voltage: { displayName: Voltage }
od: { displayName: OD }
length: { displayName: Length }
buses: { displayName: Bus }
torque_density: { displayName: Peak N·m/kg }
price: { displayName: Price from }
sellers: { displayName: Sellers }
level: { displayName: Level }
views:
- type: table
name: Rows
order: [model, brand, form, drivetrain, peak_torque, rated_torque, mass, price, buses]
sort:
- { property: peak_torque, direction: DESC }
- type: cards
name: Gallery
order: [model, brand, peak_torque, mass, price]
image: photo
imageFit: contain
imageAspectRatio: 0.8
cardSize: 190
- type: chart
name: Torque vs mass
chart:
mark: point
encoding:
x: { field: mass, type: quantitative }
y: { field: peak_torque, type: quantitative }
color: { field: brand, type: nominal }
- type: table
name: By brand
order: [model, form, peak_torque, rated_torque, max_speed, mass, gear_ratio, voltage, od, length, buses, price]
groupBy: { property: brand, direction: ASC }
sort:
- { property: peak_torque, direction: DESC }
summaries: { peak_torque: Max, mass: Min, price: Min }
- type: table
name: Brand › form
order: [model, peak_torque, mass, gear_ratio, voltage, price]
groupBy: { property: brand, direction: ASC }
subGroupBy: { property: form, direction: ASC }
sort:
- { property: peak_torque, direction: DESC }
summaries: { peak_torque: Max, price: Min }
fold: closed
- type: table
name: Torque density
filters: '!torque_density.isEmpty()'
order: [model, brand, torque_density, peak_torque, mass, price]
sort:
- { property: torque_density, direction: DESC }
display: { torque_density: bar }
- type: table
name: Geared CAN under $150
filters:
and:
- 'drivetrain == "geared"'
- 'buses.contains("can")'
- 'price < 150'
order: [model, brand, price, peak_torque, mass, gear_ratio, voltage]
sort:
- { property: price, direction: ASC }
display: { price: bar }
- type: table
name: All, flat
order: [model, brand, form, drivetrain, peak_torque, rated_torque, max_speed, mass, gear_ratio, voltage, od, length, buses, torque_density, price, sellers, level]
sort:
- { property: brand, direction: ASC }
- { property: model, direction: ASC }
- type: pivot
name: Brand × form
order: [brand]
splitBy: [form]
value: { property: null, summary: Count }
sort:
- { property: brand, direction: ASC }
- type: pivot
name: Torque by drivetrain × form
order: [drivetrain]
splitBy: [form]
value: { property: peak_torque, summary: Median, display: dist }
// ../robotparts-actuators/actuators.json: 1,149 rows, 608 KB; the first 3
{
"id": "actuators",
"title": "Actuators",
"titleProperty": "name",
"linkProperty": "url",
"source": "robotparts dist/site/v2/catalog.json, release 2026.10.25 (lane/tables @ ab5ba92); mass from each spec's own unit; photo: robotparts media/photos.jsonl, 150 of 1725 copied at 240 px",
"properties": {
"name": {
"type": "text",
"hidden": true
},
"model": {
"type": "text",
"width": 190
},
"brand": {
"type": "text",
"width": 120
},
"form": {
"type": "text",
"width": 140,
"display": "badge"
},
"drivetrain": {
"type": "text",
"width": 104
},
"buses": {
"type": "list",
"width": 120
},
"level": {
"type": "number",
"width": 58
},
"url": {
"type": "text",
"hidden": true
},
"torque_density": {
"type": "number",
"unitText": "N·m/kg",
"width": 130,
"derived": "peak torque / mass, by robotparts"
},
"price": {
"type": "number",
"unitText": "USD",
"decimals": 0,
"width": 120
},
"sellers": {
"type": "number",
"width": 70
},
"peak_torque": {
"type": "number",
"unitText": "N·m",
"width": 126
},
"rated_torque": {
"type": "number",
"unitText": "N·m",
"width": 126
},
"max_speed": {
"type": "number",
"unitText": "rpm",
"width": 126
},
"mass": {
"type": "number",
"unitText": "g",
"width": 126
},
"gear_ratio": {
"type": "number",
"unitText": ":1",
"width": 126
},
"voltage": {
"type": "number",
"unitText": "V",
"width": 126
},
"od": {
"type": "number",
"unitText": "mm",
"width": 126
},
"length": {
"type": "number",
"unitText": "mm",
"width": 126
},
"photo": {
"type": "text",
"hidden": true,
"display": "image",
"note": "robotparts' primary photo, resized; only the parts this case copied have one"
},
"step_up": {
"type": "text",
"hidden": true,
"derived": "the next photographed part of the same brand up in peak torque (build_examples.py)",
"note": "an edge for the graph view: among the parts with a photo here, the brand's next one up in peak torque"
}
},
"rows": [
{
"id": "aifitlab-8541438771336",
"name": "Steadywin GIM4305-10",
"brand": "Steadywin",
"model": "GIM4305-10",
"form": "integrated actuator",
"drivetrain": "geared",
"buses": [
"can",
"rs485"
],
"level": 4,
"url": "https://robotparts.dev/actuator/aifitlab-8541438771336/",
"peak_torque": {
"value": 3.82,
"basis": "seller",
"source": "aifitlab.com"
},
"rated_torque": 1.05,
"max_speed": 402,
"mass": {
"value": 150,
"basis": "seller",
"source": "aifitlab.com"
},
"gear_ratio": 10,
"voltage": 24,
"od": 53,
"length": 26,
"torque_density": 25.467,
"price": 70,
"sellers": 1,
"photo": "photos/aifitlab-8541438771336.webp",
"step_up": "aifitlab-8542347853960"
},
{
"id": "aifitlab-8542347853960",
"name": "Steadywin GIM6010-8",
"brand": "Steadywin",
"model": "GIM6010-8",
"form": "integrated actuator",
"drivetrain": "geared",
"buses": [
"can",
"rs485"
],
"level": 1,
"url": "https://robotparts.dev/actuator/aifitlab-8542347853960/",
"peak_torque": {
"value": 11,
"basis": "seller",
"source": "aifitlab.com"
},
"rated_torque": 5,
"max_speed": 420,
"mass": {
"value": 388,
"basis": "seller",
"source": "aifitlab.com"
},
"gear_ratio": 8,
"voltage": 24,
"od": 80,
"length": 40,
"torque_density": 28.351,
"price": 70,
"sellers": 1,
"photo": "photos/aifitlab-8542347853960.webp",
"step_up": "aifitlab-8542620287112"
},
{
"id": "aifitlab-8542620287112",
"name": "Steadywin GIM8108-8",
"brand": "Steadywin",
"model": "GIM8108-8",
"form": "integrated actuator",
"drivetrain": "geared",
"buses": [
"can",
"rs485"
],
"level": 1,
"url": "https://robotparts.dev/actuator/aifitlab-8542620287112/",
"peak_torque": {
"value": 22,
"basis": "seller",
"source": "aifitlab.com"
},
"rated_torque": 7.5,
"max_speed": 320,
"mass": {
"value": 396,
"basis": "seller",
"source": "aifitlab.com"
},
"gear_ratio": 8,
"voltage": 48,
"od": 92,
"length": 55,
"torque_density": 55.556,
"price": 85,
"sellers": 1,
"photo": "photos/aifitlab-8542620287112.webp",
"step_up": null
}
],
"imageProperty": "photo"
}README.md
# The query bar: tokens, autocomplete and bulk actions
robotparts' 1,149 actuators with the bar's query box in token mode: type `brand:` and it suggests the brands with
their counts, Enter makes the clause a token, and a tick in the rail shows up as a token too, because both edit the one
filter. Shift-click a range of rows, ctrl-click to add one, and Shopify's bulk bar offers Compare, Copy IDs and Export
CSV (docs/CONTRACT.md §15).
- **App:** robotparts
- **Replaces:** Shopify admin's order search (its query builder suggesting properties, operators and values) and its
bulk bar ("2 selected ▾ · actions · ⋯ · Show all selected"); Obsidian Bases' advanced filter expression.
- **Shows:** `filters="query-tokens rail"`, `views="dropdown"`, `display="popover"`, `selectable`: tokens in the box,
red underlines for a clause that does not parse, value counts under the current filters, shift / ctrl ranges in the
table and the gallery, the table's `wrap` and `freeze`, the gallery's `maxColumns`.
- **Data:** `../robotparts-actuators/actuators.json` (the robotparts-actuators case's file).
The original UI it replaces
Shopify admin's order search (its query builder suggesting properties, operators and values) and its bulk bar ("2 selected ▾ · actions · ⋯ · Show all selected"); Obsidian Bases' advanced filter expression.
What it shows
filters="query-tokens rail", views="dropdown", display="popover", selectable: tokens in the box, red underlines for a clause that does not parse, value counts under the current filters, shift / ctrl ranges in the table and the gallery, the table's wrap and freeze, the gallery's maxColumns.
Data
../robotparts-actuators/actuators.json (the robotparts-actuators case's file).