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;
}
.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 {
display: flex;
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
if (hashParams.has("features")) {
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
const selectedTags = [...document.querySelectorAll('.tag')].map(tag => tag.textContent);
selectedTags.length ? hashParams.set("features", selectedTags.join(",")) : hashParams.delete("features");
@ -228,6 +240,16 @@ document.addEventListener("DOMContentLoaded", function () {
filterBoards();
});
boardsToggle = document.getElementById("show-boards");
boardsToggle.addEventListener("change", () => {
filterBoards();
});
shieldsToggle = document.getElementById("show-shields");
shieldsToggle.addEventListener("change", () => {
filterBoards();
});
form.addEventListener("input", function () {
filterBoards();
});
@ -246,6 +268,9 @@ function resetForm() {
fillSocSeriesSelect();
fillSocSocSelect();
document.getElementById("show-boards").checked = true;
document.getElementById("show-shields").checked = true;
// Clear supported features
document.querySelectorAll('.tag').forEach(tag => tag.remove());
document.getElementById('tag-input').value = '';
@ -269,11 +294,13 @@ function filterBoards() {
const archSelect = document.getElementById("arch").value;
const vendorSelect = document.getElementById("vendor").value;
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 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");
} else {
resetFiltersBtn.classList.add("btn-disabled");
@ -287,17 +314,22 @@ function filterBoards() {
const boardVendor = board.getAttribute("data-vendor") || "";
const boardSocs = (board.getAttribute("data-socs") || "").split(" ").filter(Boolean);
const boardSupportedFeatures = (board.getAttribute("data-supported-features") || "").split(" ").filter(Boolean);
const isShield = board.classList.contains("shield");
let matches = true;
const selectedSocs = [...socSocSelect.selectedOptions].map(({ value }) => value);
matches =
!(nameInput && !boardName.includes(nameInput)) &&
!(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)));
if ((isShield && !showShields) || (!isShield && !showBoards)) {
matches = false;
} else {
matches =
!(nameInput && !boardName.includes(nameInput)) &&
!(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);
});

View file

@ -5,13 +5,33 @@
<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>
<input type="text" id="name"
placeholder='Name (or partial name) of the board/shield, e.g. "reel board", "nucleo", &hellip;'
oninput="filterBoards()" />
</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">
<label for="arch">Architecture</label>
<div class="select-container">