product-list
A directory list: one linked row per listing, as a list or as Tiles.
{
"kind": "section",
"shell": {
"inset": "contained",
"density": "section"
},
"block": {
"type": "product-list",
"title": "Benches in Duluth, by kind",
"note": "8 kinds",
"view": "cards",
"views": [
{
"href": "/",
"label": "Kinds",
"icon": "layout-grid",
"on": true
},
{
"href": "/city/duluth",
"label": "List",
"icon": "list"
}
],
"rows": [
{
"href": "/city/duluth?kind=kiln",
"mark": "sparkles",
"name": "Kiln rooms",
"summary": "Electric kilns to cone 10, with shelves and posts. Bisque or glaze.",
"tag": "Clay",
"note": "2 listed, from $18 an hour"
},
{
"href": "/city/duluth?kind=wood",
"mark": "blocks",
"name": "Woodshop benches",
"summary": "Hardwood benches beside a cabinet saw, jointer and planer.",
"tag": "Wood",
"note": "2 listed, from $16 an hour"
},
{
"href": "/city/duluth?kind=metal",
"mark": "gauge",
"name": "Metal bays",
"summary": "A metal lathe with tooling, or a ventilated welding booth.",
"tag": "Metal",
"note": "2 listed, from $24 an hour"
},
{
"href": "/city/duluth?kind=print",
"mark": "files",
"name": "Print presses",
"summary": "A tabletop letterpress with type, or a four-color screen press.",
"tag": "Print",
"note": "2 listed, from $14 an hour"
},
{
"href": "/city/duluth?kind=textile",
"mark": "layers",
"name": "Looms",
"summary": "A four-shaft floor loom, warped on request a day ahead.",
"tag": "Textile",
"note": "1 listed, $12 an hour"
},
{
"href": "/city/duluth?kind=jewelry",
"mark": "badge-check",
"name": "Jewelry benches",
"summary": "A bench pin, flex shaft and torch, in a room with a safe.",
"tag": "Jewelry",
"note": "1 listed, $9 an hour"
},
{
"href": "/list-a-bench",
"mark": "sparkles",
"name": "Glass studios",
"summary": "No glass kiln or torch bench is listed yet. A host who lists one sets its rate.",
"tag": "Glass",
"note": "0 listed"
},
{
"href": "/list-a-bench",
"mark": "film",
"name": "Darkrooms",
"summary": "No darkroom is listed yet. Enlargers, trays and a sink by the hour.",
"tag": "Photo",
"note": "0 listed"
}
]
}
}
{
"title": "product-list",
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "product-list"
},
"title": {
"type": "string",
"minLength": 1,
"maxLength": 48
},
"note": {
"type": "string",
"minLength": 1,
"maxLength": 24
},
"rail": {
"type": "object",
"properties": {
"groups": {
"minItems": 1,
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"minLength": 1,
"maxLength": 20
},
"links": {
"minItems": 1,
"maxItems": 12,
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 24
},
"on": {
"type": "boolean"
},
"count": {
"type": "integer",
"minimum": 0,
"maximum": 1000000
}
},
"required": [
"href",
"label"
],
"additionalProperties": false
}
}
},
"required": [
"label",
"links"
],
"additionalProperties": false
}
}
},
"required": [
"groups"
],
"additionalProperties": false
},
"sort": {
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 16
},
"on": {
"type": "boolean"
}
},
"required": [
"href",
"label"
],
"additionalProperties": false
}
},
"view": {
"type": "string",
"enum": [
"list",
"cards"
]
},
"views": {
"maxItems": 2,
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 16
},
"icon": {
"type": "string",
"enum": [
"activity",
"anchor",
"arrow-right",
"arrow-up-right",
"badge-check",
"bell",
"blocks",
"bot",
"check",
"chevron-down",
"chevron-left",
"chevron-right",
"clock",
"code",
"compass",
"copy",
"credit-card",
"database",
"file-code-2",
"file-text",
"files",
"film",
"fingerprint",
"gauge",
"git-commit-horizontal",
"globe",
"history",
"key-round",
"landmark",
"layers",
"layout-grid",
"library",
"link",
"list",
"map-pin",
"menu",
"message-square",
"mic",
"plug",
"radar",
"refresh-cw",
"search",
"shield-check",
"ship",
"shopping-cart",
"sliders-horizontal",
"sparkles",
"terminal",
"ticket",
"waves",
"webhook",
"x"
]
},
"on": {
"type": "boolean"
}
},
"required": [
"href",
"label"
],
"additionalProperties": false
}
},
"rows": {
"maxItems": 50,
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"mark": {
"type": "string",
"enum": [
"activity",
"anchor",
"arrow-right",
"arrow-up-right",
"badge-check",
"bell",
"blocks",
"bot",
"check",
"chevron-down",
"chevron-left",
"chevron-right",
"clock",
"code",
"compass",
"copy",
"credit-card",
"database",
"file-code-2",
"file-text",
"files",
"film",
"fingerprint",
"gauge",
"git-commit-horizontal",
"globe",
"history",
"key-round",
"landmark",
"layers",
"layout-grid",
"library",
"link",
"list",
"map-pin",
"menu",
"message-square",
"mic",
"plug",
"radar",
"refresh-cw",
"search",
"shield-check",
"ship",
"shopping-cart",
"sliders-horizontal",
"sparkles",
"terminal",
"ticket",
"waves",
"webhook",
"x"
]
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 32
},
"summary": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"tag": {
"type": "string",
"minLength": 1,
"maxLength": 24
},
"note": {
"type": "string",
"minLength": 1,
"maxLength": 32
}
},
"required": [
"href",
"name",
"summary"
],
"additionalProperties": false
}
},
"pager": {
"type": "object",
"properties": {
"prev": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"next": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"page": {
"type": "integer",
"minimum": 1,
"maximum": 10000
},
"pages": {
"type": "integer",
"minimum": 1,
"maximum": 10000
}
},
"required": [
"page",
"pages"
],
"additionalProperties": false
},
"empty": {
"type": "string",
"minLength": 1,
"maxLength": 80
}
},
"required": [
"type",
"rows"
],
"additionalProperties": false
}When to use
Use a product list for a directory index or a category page. It holds up to 50 rows, each a link with a mark, a name of 32 characters, a summary of 120, a tag and a note, under an optional title, sort links, view links and a pager.
list sets one row per listing; cards sets each as a Tile in a grid. Every control is a link, so sorting and paging need no script. For posts, use post-list.
Write each summary as what the listing does, so a reader chooses from the list without opening every row.
post-list: posts, not listings
The record
{
"kind": "section",
"shell": { "inset": "contained", "density": "section" },
"block": {
"type": "product-list",
"title": "Benches in Duluth, by kind",
"note": "8 kinds",
"view": "cards",
"views": [
{ "href": "/", "label": "Kinds", "icon": "layout-grid", "on": true },
{ "href": "/city/duluth", "label": "List", "icon": "list" }
],
"rows": [
{
"href": "/city/duluth?kind=kiln",
"mark": "sparkles",
"name": "Kiln rooms",
"summary": "Electric kilns to cone 10, with shelves and posts. Bisque or glaze.",
"tag": "Clay",
"note": "2 listed, from $18 an hour"
},
{
"href": "/city/duluth?kind=wood",
"mark": "blocks",
"name": "Woodshop benches",
"summary": "Hardwood benches beside a cabinet saw, jointer and planer.",
"tag": "Wood",
"note": "2 listed, from $16 an hour"
},
{
"href": "/city/duluth?kind=metal",
"mark": "gauge",
"name": "Metal bays",
"summary": "A metal lathe with tooling, or a ventilated welding booth.",
"tag": "Metal",
"note": "2 listed, from $24 an hour"
},
{
"href": "/city/duluth?kind=print",
"mark": "files",
"name": "Print presses",
"summary": "A tabletop letterpress with type, or a four-color screen press.",
"tag": "Print",
"note": "2 listed, from $14 an hour"
},
{
"href": "/city/duluth?kind=textile",
"mark": "layers",
"name": "Looms",
"summary": "A four-shaft floor loom, warped on request a day ahead.",
"tag": "Textile",
"note": "1 listed, $12 an hour"
},
{
"href": "/city/duluth?kind=jewelry",
"mark": "badge-check",
"name": "Jewelry benches",
"summary": "A bench pin, flex shaft and torch, in a room with a safe.",
"tag": "Jewelry",
"note": "1 listed, $9 an hour"
},
{
"href": "/list-a-bench",
"mark": "sparkles",
"name": "Glass studios",
"summary": "No glass kiln or torch bench is listed yet. A host who lists one sets its rate.",
"tag": "Glass",
"note": "0 listed"
},
{
"href": "/list-a-bench",
"mark": "film",
"name": "Darkrooms",
"summary": "No darkroom is listed yet. Enlargers, trays and a sink by the hour.",
"tag": "Photo",
"note": "0 listed"
}
]
}
}Smallest that parses
{
"type": "product-list",
"title": "Benches in Duluth, by kind",
"rows": []
}Fields and bounds
From @mdxui/site@7.0.0-alpha.0. A count reads as min–max × item; a string bound is its maximum length in characters, and links its refusal.
| Prop | Type and bound | Required |
|---|---|---|
title | string ≤48 | no |
note | string ≤24 | no |
rail | object | no |
rail.groups | 1–4 × object | yes |
rail.groups[].label | string ≤20 | yes |
rail.groups[].links | 1–12 × object | yes |
sort | 0–4 × object | no |
sort[].href | string ≤160 | yes |
sort[].label | string ≤16 | yes |
sort[].on | boolean | no |
view | "list" | "cards" | no |
views | 0–2 × object | no |
views[].href | string ≤160 | yes |
views[].label | string ≤16 | yes |
views[].icon | icon or mark name (52) | no |
views[].on | boolean | no |
rows | 0–50 × object | yes |
rows[].href | string ≤160 | yes |
rows[].mark | icon or mark name (52) | no |
rows[].name | string ≤32 | yes |
rows[].summary | string ≤120 | yes |
rows[].tag | string ≤24 | no |
rows[].note | string ≤32 | no |
pager | object | no |
pager.prev | string ≤160 | no |
pager.next | string ≤160 | no |
pager.page | integer 1–10000 | yes |
pager.pages | integer 1–10000 | yes |
empty | string ≤80 | no |
Variants and counts
Two views, list and cards. A record names the view it renders and links to the other.
One record in five Themes
Shells
In three Businesses
Carried by the article and directory-list Templates. Seen on pages/benchlist/home.json, section 3.
Do and do not
"name": "Chartplot for every chart plotter"Accessibility
| Check, on the exemplar render | Limit | Now | Pass |
|---|---|---|---|
| Skipped heading levels | 0 | 0 | yes |
| Unnamed nav landmarks | 0 | 0 of 1 | yes |
| Scroll regions a keyboard cannot reach | 0 | 0 of 0 | yes |
| Copy controls that announce the result | all | 0 of 0 | yes |
| Images and icons with no text alternative | 0 | 0 | yes |
Text pairs below AA across the 5 Themes and every scheme they emit: 5. See Render checks.
- Landmark The list sits in
main. Sort, view and pager are each anavwith its own name. - Heading level The title renders as an
h2; the listings are a list,ul. - Focus order Tab runs sort, view, each listing link, then the pager. The current sort and view carry
aria-current.