feat(picker): featured components sort first — breadboards lead the list

New optional `featured` metadata flag: ComponentRegistry stable-sorts
featured components to the front after loading (and indexes categories
from the sorted list, so per-category views keep the same order). The
two breadboards are marked featured in component-overrides.json — they
are everyday parts and now open the component grid instead of sitting
at the bottom below every diode.
This commit is contained in:
David Montero Crespo 2026-07-16 01:04:29 +02:00
parent 56686da95f
commit 57015212ab
4 changed files with 21 additions and 7 deletions

View File

@ -3371,7 +3371,8 @@
"tagName": "velxio-breadboard",
"name": "Breadboard (full)",
"category": "passive",
"description": "830-point solderless breadboard: 63 columns x two 5-hole banks (a-e / f-j) plus four full-length power rails. Holes in the same column strip or rail are electrically connected."
"description": "830-point solderless breadboard: 63 columns x two 5-hole banks (a-e / f-j) plus four full-length power rails. Holes in the same column strip or rail are electrically connected.",
"featured": true
},
{
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"8\" y=\"12\" width=\"48\" height=\"40\" rx=\"3\" fill=\"#ffffff\" stroke=\"#c8c4bc\"/><rect x=\"10\" y=\"29\" width=\"44\" height=\"5\" fill=\"#eceae4\"/><rect x=\"12\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"12\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"12\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"12\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/></svg>",
@ -3390,7 +3391,8 @@
"tagName": "velxio-breadboard-mini",
"name": "Breadboard Mini",
"category": "passive",
"description": "170-point mini solderless breadboard: 17 columns x two 5-hole banks (a-e / f-j), no power rails. Holes in the same column strip are electrically connected."
"description": "170-point mini solderless breadboard: 17 columns x two 5-hole banks (a-e / f-j), no power rails. Holes in the same column strip are electrically connected.",
"featured": true
},
{
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"64\" height=\"64\" fill=\"#1a2332\" rx=\"4\"/>\n <rect x=\"6\" y=\"29\" width=\"52\" height=\"3\" fill=\"#aaa\"/>\n <ellipse cx=\"32\" cy=\"30\" rx=\"14\" ry=\"9\" fill=\"#165696\"/>\n <ellipse cx=\"28\" cy=\"26\" rx=\"5\" ry=\"3\" fill=\"#3a7cc8\" opacity=\"0.5\"/>\n <text x=\"32\" y=\"56\" text-anchor=\"middle\" font-size=\"10\" font-family=\"sans-serif\" fill=\"#e5e7eb\" font-weight=\"bold\">1 nF</text></svg>",

View File

@ -230,12 +230,18 @@ export class ComponentRegistry {
* Process and index metadata
*/
private processMetadata(components: ComponentMetadata[]): void {
this.allComponents = components;
// Featured (everyday) parts — e.g. breadboards — surface first in the
// picker. Array.prototype.sort is stable, so the metadata-file order is
// preserved within the featured and non-featured groups.
this.allComponents = [...components].sort(
(a, b) => Number(!!b.featured) - Number(!!a.featured),
);
this.metadata.clear();
this.categories.clear();
// Index by ID
components.forEach((component) => {
// Index by ID. Iterate the sorted list so the per-category groups keep
// featured components first too.
this.allComponents.forEach((component) => {
this.metadata.set(component.id, component);
// Group by category

View File

@ -47,6 +47,10 @@ export interface ComponentMetadata {
// delegate the click on a pro_only component to a window-level gate
// (see ComponentPickerModal) which the overlay implements.
pro_only?: boolean;
// Everyday parts (e.g. breadboards) surface at the top of the picker:
// ComponentRegistry sorts featured components first after loading the
// metadata, keeping the original order within each group.
featured?: boolean;
}
export interface ComponentMetadataCollection {

View File

@ -2502,7 +2502,8 @@
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"14\" width=\"60\" height=\"36\" rx=\"3\" fill=\"#f4f1ec\" stroke=\"#c8c4bc\"/><line x1=\"5\" y1=\"19\" x2=\"59\" y2=\"19\" stroke=\"#e05050\" stroke-width=\"1.5\"/><line x1=\"5\" y1=\"45\" x2=\"59\" y2=\"45\" stroke=\"#5070e0\" stroke-width=\"1.5\"/><rect x=\"4\" y=\"30\" width=\"56\" height=\"4\" fill=\"#e6e2da\"/><rect x=\"7\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"7\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"7\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"7\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"12\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"12\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"12\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"12\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"17\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"17\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"17\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"17\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"22\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"22\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"22\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"22\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"27\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"27\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"27\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"27\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"32\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"32\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"32\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"32\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"37\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"37\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"37\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"37\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"42\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"42\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"42\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"42\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"47\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"47\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"47\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"47\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"52\" y=\"23\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"52\" y=\"26\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"52\" y=\"36\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/><rect x=\"52\" y=\"39\" width=\"2.4\" height=\"2.4\" fill=\"#333\"/></svg>",
"properties": [],
"defaultValues": {},
"description": "830-point solderless breadboard: 63 columns x two 5-hole banks (a-e / f-j) plus four full-length power rails. Holes in the same column strip or rail are electrically connected."
"description": "830-point solderless breadboard: 63 columns x two 5-hole banks (a-e / f-j) plus four full-length power rails. Holes in the same column strip or rail are electrically connected.",
"featured": true
},
{
"$comment": "Velxio-native passive: 170-point mini breadboard (17x2 banks, no rails). Same wokwi-compatible naming as the full breadboard.",
@ -2521,7 +2522,8 @@
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"8\" y=\"12\" width=\"48\" height=\"40\" rx=\"3\" fill=\"#ffffff\" stroke=\"#c8c4bc\"/><rect x=\"10\" y=\"29\" width=\"44\" height=\"5\" fill=\"#eceae4\"/><rect x=\"12\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"12\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"12\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"12\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"17\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"22\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"27\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"32\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"37\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"42\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"47\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"17\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"22\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"38\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/><rect x=\"52\" y=\"43\" width=\"2.6\" height=\"2.6\" fill=\"#333\"/></svg>",
"properties": [],
"defaultValues": {},
"description": "170-point mini solderless breadboard: 17 columns x two 5-hole banks (a-e / f-j), no power rails. Holes in the same column strip are electrically connected."
"description": "170-point mini solderless breadboard: 17 columns x two 5-hole banks (a-e / f-j), no power rails. Holes in the same column strip are electrically connected.",
"featured": true
}
],
"led": {