doc: _extensions: board: show/hide boards and shield in catalog

Adds the ability to show/hide boards and shields in the board catalog.

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
This commit is contained in:
Benjamin Cabé 2025-05-26 16:39:30 +02:00 committed by Benjamin Cabé
commit f38946428e
3 changed files with 112 additions and 8 deletions

View file

@ -125,6 +125,58 @@
background-color: transparent; background-color: transparent;
} }
.visibility-toggles {
display: flex;
gap: 8px;
align-items: center;
justify-content: center;
}
.toggle-group input {
display: none;
}
.toggle-label {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
}
.toggle-switch {
width: 36px;
height: 18px;
background: #ccc;
border-radius: 18px;
position: relative;
transition: 0.3s;
}
.toggle-switch::before {
content: '';
width: 14px;
height: 14px;
background: white;
border-radius: 50%;
position: absolute;
top: 2px;
left: 2px;
transition: 0.3s;
}
.toggle-text {
font-size: 14px;
text-transform: none;
}
input:checked + .toggle-label .toggle-switch {
background: var(--admonition-note-title-background-color);
}
input:checked + .toggle-label .toggle-switch::before {
left: 20px;
}
#catalog { #catalog {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;

View file

@ -29,6 +29,13 @@ function populateFormFromURL() {
} }
}); });
// Restore visibility toggles from URL
["show-boards", "show-shields"].forEach(toggle => {
if (hashParams.has(toggle)) {
document.getElementById(toggle).checked = hashParams.get(toggle) === "true";
}
});
// Restore supported features from URL // Restore supported features from URL
if (hashParams.has("features")) { if (hashParams.has("features")) {
const features = hashParams.get("features").split(","); const features = hashParams.get("features").split(",");
@ -70,6 +77,11 @@ function updateURL() {
} }
}); });
["show-boards", "show-shields"].forEach(toggle => {
const isChecked = document.getElementById(toggle).checked;
isChecked ? hashParams.delete(toggle) : hashParams.set(toggle, "false");
});
// Add supported features to URL // Add supported features to URL
const selectedTags = [...document.querySelectorAll('.tag')].map(tag => tag.textContent); const selectedTags = [...document.querySelectorAll('.tag')].map(tag => tag.textContent);
selectedTags.length ? hashParams.set("features", selectedTags.join(",")) : hashParams.delete("features"); selectedTags.length ? hashParams.set("features", selectedTags.join(",")) : hashParams.delete("features");
@ -228,6 +240,16 @@ document.addEventListener("DOMContentLoaded", function () {
filterBoards(); filterBoards();
}); });
boardsToggle = document.getElementById("show-boards");
boardsToggle.addEventListener("change", () => {
filterBoards();
});
shieldsToggle = document.getElementById("show-shields");
shieldsToggle.addEventListener("change", () => {
filterBoards();
});
form.addEventListener("input", function () { form.addEventListener("input", function () {
filterBoards(); filterBoards();
}); });
@ -246,6 +268,9 @@ function resetForm() {
fillSocSeriesSelect(); fillSocSeriesSelect();
fillSocSocSelect(); fillSocSocSelect();
document.getElementById("show-boards").checked = true;
document.getElementById("show-shields").checked = true;
// Clear supported features // Clear supported features
document.querySelectorAll('.tag').forEach(tag => tag.remove()); document.querySelectorAll('.tag').forEach(tag => tag.remove());
document.getElementById('tag-input').value = ''; document.getElementById('tag-input').value = '';
@ -269,11 +294,13 @@ function filterBoards() {
const archSelect = document.getElementById("arch").value; const archSelect = document.getElementById("arch").value;
const vendorSelect = document.getElementById("vendor").value; const vendorSelect = document.getElementById("vendor").value;
const socSocSelect = document.getElementById("soc"); const socSocSelect = document.getElementById("soc");
const showBoards = document.getElementById("show-boards").checked;
const showShields = document.getElementById("show-shields").checked;
const selectedTags = [...document.querySelectorAll('.tag')].map(tag => tag.textContent); const selectedTags = [...document.querySelectorAll('.tag')].map(tag => tag.textContent);
const resetFiltersBtn = document.getElementById("reset-filters"); const resetFiltersBtn = document.getElementById("reset-filters");
if (nameInput || archSelect || vendorSelect || socSocSelect.selectedOptions.length || selectedTags.length) { if (nameInput || archSelect || vendorSelect || socSocSelect.selectedOptions.length || selectedTags.length || !showBoards || !showShields) {
resetFiltersBtn.classList.remove("btn-disabled"); resetFiltersBtn.classList.remove("btn-disabled");
} else { } else {
resetFiltersBtn.classList.add("btn-disabled"); resetFiltersBtn.classList.add("btn-disabled");
@ -287,17 +314,22 @@ function filterBoards() {
const boardVendor = board.getAttribute("data-vendor") || ""; const boardVendor = board.getAttribute("data-vendor") || "";
const boardSocs = (board.getAttribute("data-socs") || "").split(" ").filter(Boolean); const boardSocs = (board.getAttribute("data-socs") || "").split(" ").filter(Boolean);
const boardSupportedFeatures = (board.getAttribute("data-supported-features") || "").split(" ").filter(Boolean); const boardSupportedFeatures = (board.getAttribute("data-supported-features") || "").split(" ").filter(Boolean);
const isShield = board.classList.contains("shield");
let matches = true; let matches = true;
const selectedSocs = [...socSocSelect.selectedOptions].map(({ value }) => value); const selectedSocs = [...socSocSelect.selectedOptions].map(({ value }) => value);
matches = if ((isShield && !showShields) || (!isShield && !showBoards)) {
!(nameInput && !boardName.includes(nameInput)) && matches = false;
!(archSelect && !boardArchs.includes(archSelect)) && } else {
!(vendorSelect && boardVendor !== vendorSelect) && matches =
(selectedSocs.length === 0 || selectedSocs.some((soc) => boardSocs.includes(soc))) && !(nameInput && !boardName.includes(nameInput)) &&
(selectedTags.length === 0 || selectedTags.every((tag) => boardSupportedFeatures.includes(tag))); !(archSelect && !boardArchs.includes(archSelect)) &&
!(vendorSelect && boardVendor !== vendorSelect) &&
(selectedSocs.length === 0 || selectedSocs.some((soc) => boardSocs.includes(soc))) &&
(selectedTags.length === 0 || selectedTags.every((tag) => boardSupportedFeatures.includes(tag)));
}
board.classList.toggle("hidden", !matches); board.classList.toggle("hidden", !matches);
}); });

View file

@ -5,13 +5,33 @@
<form class="filter-form" aria-label="Filter boards & shields by name, architecture, and vendor"> <form class="filter-form" aria-label="Filter boards & shields by name, architecture, and vendor">
<div class="form-group" style="flex-basis: 100%"> <div class="form-group" style="flex-basis: 60%">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" id="name" <input type="text" id="name"
placeholder='Name (or partial name) of the board/shield, e.g. "reel board", "nucleo", &hellip;' placeholder='Name (or partial name) of the board/shield, e.g. "reel board", "nucleo", &hellip;'
oninput="filterBoards()" /> oninput="filterBoards()" />
</div> </div>
<div class="form-group">
<label>Showing</label>
<div class="visibility-toggles">
<div class="toggle-group">
<input type="checkbox" id="show-boards" checked>
<label for="show-boards" class="toggle-label">
<span class="toggle-switch"></span>
<span class="toggle-text">Boards</span>
</label>
</div>
<div class="toggle-group">
<input type="checkbox" id="show-shields" checked>
<label for="show-shields" class="toggle-label">
<span class="toggle-switch"></span>
<span class="toggle-text">Shields</span>
</label>
</div>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="arch">Architecture</label> <label for="arch">Architecture</label>
<div class="select-container"> <div class="select-container">