This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-site.git


The following commit(s) were added to refs/heads/main by this push:
     new e619dc7796 Add filter input and current-version highlight to docs 
version selector (#1580)
e619dc7796 is described below

commit e619dc7796bcfc3a506565bb57fb7f50d4e3aacb
Author: Andrew Chang <[email protected]>
AuthorDate: Wed Jul 1 15:04:38 2026 +0000

    Add filter input and current-version highlight to docs version selector 
(#1580)
    
    * Add filter input and current-version highlight to docs version selector
    
    The docs version selector dropdown grows with every Airflow release and 
users
    arriving from a search engine cannot tell at a glance whether they are 
reading
    Airflow 2 or Airflow 3 documentation. This change:
    
    - Adds a filter input at the top of the dropdown; typing narrows the list by
      version prefix so ``1.`` shows the 1.x line without matching ``3.11.x`` 
as a
      substring.
    - Highlights the version the user is currently viewing so switching does not
      require scanning the entire list.
    - On the main ``apache-airflow`` package, prefixes the toggle label with the
      major line (e.g. ``Airflow 3 · 3.4.0``) so old-major docs are visually
      distinct from current ones. Provider packages keep their existing label.
    
    Closes https://github.com/apache/airflow/issues/51455.
    
    * Update sphinx_airflow_theme/LATEST_VERSION to 0.3.12
    
    * Update theme file hash and __init__ version to match LATEST_VERSION.txt
    
    The previous version bump only updated LATEST_VERSION.txt; the pre-commit
    check-sphinx-theme-version hook also expects .theme_files_hash and
    __init__.py to be in sync.
    
    * Bump theme version to 0.3.13 to match CI-computed hash
    
    The previous hash was computed locally with static/_gen/ build artefacts
    present, but static/_gen/ is gitignored and never present on CI when the
    check-sphinx-theme-version prek hook runs. That caused an infinite bump
    loop between local commits and CI complaints.
    
    The hash committed here is computed with static/_gen/ removed, matching
    what CI sees on a clean checkout.
---
 landing-pages/site/assets/scss/_dropdown.scss      | 41 +++++++++-
 landing-pages/src/js/versionSelector.js            | 93 ++++++++++++++++++++--
 sphinx_airflow_theme/.theme_files_hash             |  2 +-
 sphinx_airflow_theme/LATEST_VERSION.txt            |  2 +-
 .../sphinx_airflow_theme/__init__.py               |  2 +-
 .../sphinx_airflow_theme/version-selector.html     | 12 ++-
 6 files changed, 141 insertions(+), 11 deletions(-)

diff --git a/landing-pages/site/assets/scss/_dropdown.scss 
b/landing-pages/site/assets/scss/_dropdown.scss
index 51ec38b460..060f34c135 100644
--- a/landing-pages/site/assets/scss/_dropdown.scss
+++ b/landing-pages/site/assets/scss/_dropdown.scss
@@ -35,7 +35,46 @@
   }
 
   .dropdown-menu {
-    max-height: 100%;
+    max-height: 60vh;
     overflow-y: auto;
+    min-width: 220px;
+  }
+
+  .version-filter-wrapper {
+    padding: 8px 12px;
+    position: sticky;
+    top: 0;
+    background: inherit;
+    z-index: 1;
+    border-bottom: 1px solid map-get($colors, brownish-grey);
+  }
+
+  .version-filter {
+    width: 100%;
+    padding: 4px 8px;
+    border: 1px solid map-get($colors, brownish-grey);
+    border-radius: 4px;
+    font-size: 14px;
+    background: transparent;
+    color: inherit;
+
+    &:focus {
+      outline: none;
+      border-color: map-get($colors, cerulean-blue-aa);
+      box-shadow: 0 0 0 2px rgba(map-get($colors, cerulean-blue-aa), 0.2);
+    }
+  }
+
+  .dropdown-item.active {
+    font-weight: 600;
+    background-color: rgba(map-get($colors, cerulean-blue-aa), 0.1);
+    color: inherit;
+  }
+
+  .version-empty-state {
+    padding: 8px 12px;
+    color: map-get($colors, brownish-grey);
+    font-style: italic;
+    font-size: 13px;
   }
 }
diff --git a/landing-pages/src/js/versionSelector.js 
b/landing-pages/src/js/versionSelector.js
index bd9ddd24c3..d59d328527 100644
--- a/landing-pages/src/js/versionSelector.js
+++ b/landing-pages/src/js/versionSelector.js
@@ -19,6 +19,9 @@
 
 import {compareVersion} from "./sortVersions";
 
+const AIRFLOW_PACKAGE = "apache-airflow";
+const STABLE_KEY = "stable";
+
 const getCurrentPageInfo = () => {
 
   const [, , currentPackageName, currentVersion, ...pagePathParts] = 
document.location.pathname.split("/");
@@ -26,25 +29,103 @@ const getCurrentPageInfo = () => {
   return {currentVersion, currentPackageName, pagePath};
 };
 
+// Only the main airflow package gets the "Airflow N" major prefix; providers 
have self-explanatory versioning.
+const updateToggleLabel = (versionSelector, currentPackageName, 
currentVersion, stableVersion) => {
+  if (currentPackageName !== AIRFLOW_PACKAGE) {
+    return;
+  }
+  const resolvedVersion = currentVersion === STABLE_KEY ? stableVersion : 
currentVersion;
+  const major = resolvedVersion.split(".")[0];
+  if (!/^\d+$/.test(major)) {
+    return;
+  }
+  const label = versionSelector.querySelector(".version-label");
+  const version = versionSelector.querySelector(".version");
+  if (label && version) {
+    label.textContent = `Airflow ${major} · `;
+    version.textContent = resolvedVersion;
+  }
+};
+
 const updateVersionSelector = (versionSelector, packageAllVersions, 
stableVersion) => {
   const templateText = 
versionSelector.querySelector("#version-item-template").innerText;
   let templateElement = document.createElement("div");
   templateElement.innerHTML = templateText;
   templateElement = templateElement.firstElementChild;
 
-  const dropdownMenu = versionSelector.querySelector(".dropdown-menu");
+  const versionList = versionSelector.querySelector(".version-list");
+  const filterInput = versionSelector.querySelector(".version-filter");
+  const emptyState = versionSelector.querySelector(".version-empty-state");
 
-  const {currentPackageName, pagePath} = getCurrentPageInfo();
+  const {currentPackageName, currentVersion, pagePath} = getCurrentPageInfo();
+  updateToggleLabel(versionSelector, currentPackageName, currentVersion, 
stableVersion);
 
-  const appendNewVersionLink = (targetVersion, label) => {
+  const appendNewVersionLink = (targetVersion, label, matchVersion) => {
     const newElement = templateElement.cloneNode(true);
     const newDocsLink = 
`/docs/${currentPackageName}/${targetVersion}/${pagePath}`;
     newElement.setAttribute("href", newDocsLink);
+    newElement.setAttribute("data-version", targetVersion);
+    // Filter compares against ``data-match-version`` — for the "stable" alias 
this holds the actual version.
+    newElement.setAttribute("data-match-version", matchVersion);
     newElement.innerText = label;
-    dropdownMenu.appendChild(newElement);
+    if (targetVersion === currentVersion) {
+      newElement.classList.add("active");
+      newElement.setAttribute("aria-current", "true");
+    }
+    versionList.appendChild(newElement);
+  };
+
+  appendNewVersionLink(STABLE_KEY, `Stable (${stableVersion})`, stableVersion);
+  packageAllVersions.forEach((version) => appendNewVersionLink(version, 
version, version));
+
+  if (!filterInput) {
+    return;
+  }
+
+  const dropdownItems = () => 
Array.from(versionList.querySelectorAll(".dropdown-item"));
+
+  const applyFilter = (rawQuery) => {
+    const query = rawQuery.trim().toLowerCase();
+    let visibleCount = 0;
+    dropdownItems().forEach((item) => {
+      const matchVersion = (item.getAttribute("data-match-version") || 
"").toLowerCase();
+      // Prefix match so typing "1." shows 1.x releases (not 3.11.x which 
contains "1." as substring).
+      const match = query === "" || matchVersion.startsWith(query);
+      item.hidden = !match;
+      if (match) {
+        visibleCount += 1;
+      }
+    });
+    if (emptyState) {
+      emptyState.hidden = visibleCount > 0;
+    }
   };
-  appendNewVersionLink("stable", `Stable (${stableVersion})`);
-  packageAllVersions.forEach((version) => appendNewVersionLink(version, 
version));
+
+  filterInput.addEventListener("input", (event) => 
applyFilter(event.target.value));
+
+  const toggle = versionSelector.querySelector(".dropdown-toggle");
+  if (toggle) {
+    toggle.addEventListener("click", () => {
+      window.requestAnimationFrame(() => filterInput.focus());
+    });
+  }
+
+  filterInput.addEventListener("keydown", (event) => {
+    if (event.key === "Escape") {
+      if (filterInput.value) {
+        filterInput.value = "";
+        applyFilter("");
+      } else if (toggle) {
+        toggle.click();
+      }
+    } else if (event.key === "Enter") {
+      const firstVisible = dropdownItems().find((item) => !item.hidden);
+      if (firstVisible) {
+        event.preventDefault();
+        firstVisible.click();
+      }
+    }
+  });
 };
 
 const runVersionSelector = () => {
diff --git a/sphinx_airflow_theme/.theme_files_hash 
b/sphinx_airflow_theme/.theme_files_hash
index 032fbb02b6..540ee79e5e 100644
--- a/sphinx_airflow_theme/.theme_files_hash
+++ b/sphinx_airflow_theme/.theme_files_hash
@@ -1 +1 @@
-421d922d1ea1d4d45fa1acd23c8ecfa2780266f036b1a91f78ba4af7a9a3d0e8
+d21a543dd8af8cb4b4646a185f29fd46a2276d30c3b902ad7b92201d5ee9a29a
diff --git a/sphinx_airflow_theme/LATEST_VERSION.txt 
b/sphinx_airflow_theme/LATEST_VERSION.txt
index 208059121d..e4737652ca 100644
--- a/sphinx_airflow_theme/LATEST_VERSION.txt
+++ b/sphinx_airflow_theme/LATEST_VERSION.txt
@@ -1 +1 @@
-0.3.11
+0.3.13
diff --git a/sphinx_airflow_theme/sphinx_airflow_theme/__init__.py 
b/sphinx_airflow_theme/sphinx_airflow_theme/__init__.py
index 056e44df13..3ac2f3aad8 100644
--- a/sphinx_airflow_theme/sphinx_airflow_theme/__init__.py
+++ b/sphinx_airflow_theme/sphinx_airflow_theme/__init__.py
@@ -18,7 +18,7 @@
 from os import path
 from sphinx.application import Sphinx
 
-__version__ = '0.3.11'
+__version__ = '0.3.13'
 __version_full__ = __version__
 
 
diff --git a/sphinx_airflow_theme/sphinx_airflow_theme/version-selector.html 
b/sphinx_airflow_theme/sphinx_airflow_theme/version-selector.html
index f6267f78a9..c0b8779ce3 100644
--- a/sphinx_airflow_theme/sphinx_airflow_theme/version-selector.html
+++ b/sphinx_airflow_theme/sphinx_airflow_theme/version-selector.html
@@ -23,7 +23,17 @@
         <span class="version-label">Version: </span><span class="version">{{ 
version }}</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="versionDropdown">
-
+        <div class="version-filter-wrapper">
+            <input
+                type="search"
+                class="version-filter"
+                placeholder="Type to search versions..."
+                aria-label="Filter versions"
+                autocomplete="off"
+            >
+        </div>
+        <div class="version-list"></div>
+        <div class="version-empty-state" hidden>No matching versions</div>
     </div>
     <script type="application/x-template" id="version-item-template">
         <a class="dropdown-item"></a>

Reply via email to