Skip to content

Commit 426338b

Browse files
authored
Unify navigation bar and theme with main Apache Sedona site (#88)
* Unify navigation bar and theme with main Apache Sedona site - Update nav tabs to match main site: Home, SedonaDB, SedonaSpark, SedonaFlink, SedonaSnow, SpatialBench, Blog, Community, ASF - Add custom theme overrides (header, footer, nav, copyright partials) - Add announcement bar auto-synced from sedona.apache.org - Update CSS to match main site styling (header layout, fonts, footer) - Update logo to full Apache Sedona wordmark * Add 2026
1 parent 8e7d954 commit 426338b

10 files changed

Lines changed: 672 additions & 65 deletions

File tree

docs/image/footer/logo-footer.svg

Lines changed: 10 additions & 0 deletions
Loading

docs/image/header/logo-mobile.svg

Lines changed: 10 additions & 0 deletions
Loading

docs/image/logo.svg

Lines changed: 10 additions & 0 deletions
Loading

docs/overrides/main.html

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{#-
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-#}
19+
{% extends "base.html" %}
20+
21+
{% block header %}
22+
<div id="announcement-bar"></div>
23+
{{ super() }}
24+
<script>
25+
(function () {
26+
// Fetch the main Sedona site and extract its announcement bar
27+
fetch("https://sedona.apache.org/latest/")
28+
.then(function (res) {
29+
if (!res.ok) throw new Error("Failed to fetch");
30+
return res.text();
31+
})
32+
.then(function (html) {
33+
var parser = new DOMParser();
34+
var doc = parser.parseFromString(html, "text/html");
35+
// The announcement bar is the first div inside <body> before the header,
36+
// styled with inline background: #CA463A
37+
var candidates = doc.querySelectorAll("body > div, header > div, .md-header ~ div, body > .md-banner");
38+
var announcement = null;
39+
40+
// Strategy 1: Look for a div with the Sedona red background color
41+
for (var i = 0; i < candidates.length; i++) {
42+
var style = candidates[i].getAttribute("style") || "";
43+
if (style.indexOf("CA463A") !== -1 || style.indexOf("ca463a") !== -1) {
44+
announcement = candidates[i];
45+
break;
46+
}
47+
}
48+
49+
// Strategy 2: Check for Material's built-in announcement banner
50+
if (!announcement) {
51+
announcement = doc.querySelector(".md-banner");
52+
}
53+
54+
// Strategy 3: Check first child of body if it's a div with a link
55+
if (!announcement) {
56+
var first = doc.body.firstElementChild;
57+
if (first && first.tagName === "DIV" && first.querySelector("a")) {
58+
var bg = first.style.backgroundColor || first.getAttribute("style") || "";
59+
if (bg && first.textContent.trim().length > 0) {
60+
announcement = first;
61+
}
62+
}
63+
}
64+
65+
if (announcement) {
66+
var bar = document.getElementById("announcement-bar");
67+
// Fix relative links to point to the main site
68+
var links = announcement.querySelectorAll("a");
69+
for (var j = 0; j < links.length; j++) {
70+
var href = links[j].getAttribute("href");
71+
if (href && !href.startsWith("http") && !href.startsWith("//")) {
72+
links[j].setAttribute("href", "/latest/" + href.replace(/^\//, ""));
73+
}
74+
}
75+
bar.innerHTML = announcement.outerHTML;
76+
}
77+
})
78+
.catch(function () {
79+
// Silently fail — no announcement bar shown
80+
});
81+
})();
82+
</script>
83+
{% endblock %}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{#-
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-#}
19+
<div class="md-copyright">
20+
{% if config.copyright %}
21+
{{ config.copyright }}
22+
{% endif %}
23+
{% if not config.extra.generator == false %}
24+
Made with
25+
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
26+
Material for MkDocs
27+
</a>
28+
{% endif %}
29+
</div>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{#-
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-#}
19+
<footer class="footer md-footer">
20+
<div class="container">
21+
22+
<div class="footer__top">
23+
24+
<div class="col-left">
25+
<img src="{{ 'image/footer/logo-footer.svg' | url }}" alt="" class="footer-logo">
26+
</div>
27+
28+
<div class="col-right">
29+
{% if config.extra.social %}
30+
{% include "partials/social.html" %}
31+
{% endif %}
32+
</div>
33+
</div>
34+
35+
<hr class="footer-hr"></hr>
36+
37+
<div class="footer__bot">
38+
{% include "partials/copyright.html" %}
39+
</div>
40+
41+
</div>
42+
</footer>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<!--
2+
Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to
6+
deal in the Software without restriction, including without limitation the
7+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
sell copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
IN THE SOFTWARE.
21+
-->
22+
23+
<!-- Determine classes -->
24+
{% set class = "md-header" %}
25+
{% if "navigation.tabs.sticky" in features %}
26+
{% set class = class ~ " md-header--shadow md-header--lifted" %}
27+
{% elif "navigation.tabs" not in features %}
28+
{% set class = class ~ " md-header--shadow" %}
29+
{% endif %}
30+
31+
<!-- Header -->
32+
<header class="{{ class }}" data-md-component="header">
33+
<nav
34+
class="md-header__inner md-grid container"
35+
aria-label="{{ lang.t('header') }}"
36+
>
37+
<div class="left-part">
38+
39+
<!-- Button to open drawer -->
40+
<label class="md-header__button md-icon" for="__drawer">
41+
{% set icon = config.theme.icon.menu or "material/menu" %}
42+
{% include ".icons/" ~ icon ~ ".svg" %}
43+
</label>
44+
45+
<!-- Link to home -->
46+
<a
47+
href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}"
48+
title="{{ config.site_name | e }}"
49+
class="header-logo"
50+
aria-label="{{ config.site_name }}"
51+
data-md-component="logo"
52+
>
53+
{% include "partials/logo.html" %}
54+
</a>
55+
56+
<!-- Header title -->
57+
<div class="md-header__title" data-md-component="header-title">
58+
<div class="md-header__ellipsis">
59+
<div class="md-header__topic">
60+
<span class="md-ellipsis">
61+
{{ config.site_name }}
62+
</span>
63+
</div>
64+
<div class="md-header__topic" data-md-component="header-topic">
65+
<span class="md-ellipsis">
66+
{% if page.meta and page.meta.title %}
67+
{{ page.meta.title }}
68+
{% else %}
69+
{{ page.title }}
70+
{% endif %}
71+
</span>
72+
</div>
73+
</div>
74+
</div>
75+
76+
<!-- Color palette toggle -->
77+
{% if config.theme.palette %}
78+
{% if not config.theme.palette is mapping %}
79+
{% include "partials/palette.html" %}
80+
{% endif %}
81+
{% endif %}
82+
83+
<!-- User preference: color palette -->
84+
{% if not config.theme.palette is mapping %}
85+
{% include "partials/javascripts/palette.html" %}
86+
{% endif %}
87+
88+
<!-- Site language selector -->
89+
{% if config.extra.alternate %}
90+
{% include "partials/alternate.html" %}
91+
{% endif %}
92+
</div>
93+
<div class="right-part">
94+
95+
<!-- Button to open search modal -->
96+
{% if "material/search" in config.plugins %}
97+
{% set search = config.plugins["material/search"] | attr("config") %}
98+
99+
<!-- Check if search is actually enabled - see https://t.ly/DT_0V -->
100+
{% if search.enabled %}
101+
<label class="md-header__button md-icon btn-search" for="__search">
102+
{% set icon = config.theme.icon.search or "material/magnify" %}
103+
{% include ".icons/" ~ icon ~ ".svg" %}
104+
</label>
105+
106+
<!-- Search interface -->
107+
{% include "partials/search.html" %}
108+
{% endif %}
109+
{% endif %}
110+
111+
<!-- Repository information -->
112+
{% if config.repo_url %}
113+
<div class="md-header__source">
114+
{% include "partials/source.html" %}
115+
</div>
116+
{% endif %}
117+
</div>
118+
</nav>
119+
120+
<!-- Navigation tabs (sticky) -->
121+
{% if "navigation.tabs.sticky" in features %}
122+
{% if "navigation.tabs" in features %}
123+
{% include "partials/tabs.html" %}
124+
{% endif %}
125+
{% endif %}
126+
</header>

docs/overrides/partials/nav.html

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{#-
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-#}
19+
{% import "partials/nav-item.html" as item with context %}
20+
{% set class = "md-nav md-nav--primary" %}
21+
{% if "navigation.tabs" in features %}
22+
{% set class = class ~ " md-nav--lifted" %}
23+
{% endif %}
24+
{% if "toc.integrate" in features %}
25+
{% set class = class ~ " md-nav--integrated" %}
26+
{% endif %}
27+
28+
29+
<nav class="{{ class }}" aria-label="{{ lang.t('nav') }}" data-md-level="0">
30+
31+
<label class="md-nav__title" for="__drawer">
32+
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="{{ config.site_name | e }}" class="logo-link" aria-label="{{ config.site_name }}" data-md-component="logo">
33+
<img src="{{ 'image/header/logo-mobile.svg' | url }}" alt="" class="logo">
34+
</a>
35+
</label>
36+
37+
{% if config.repo_url %}
38+
<div class="md-nav__source">
39+
{% include "partials/source.html" %}
40+
</div>
41+
{% endif %}
42+
43+
<ul class="md-nav__list" data-md-scrollfix>
44+
{% for nav_item in nav %}
45+
{% set path = "__nav_" ~ loop.index %}
46+
{{ item.render(nav_item, path, 1) }}
47+
{% endfor %}
48+
49+
<li class="btn-group">
50+
<a href="#" class="btn btn-red">
51+
Get started
52+
</a>
53+
</li>
54+
55+
</ul>
56+
</nav>

0 commit comments

Comments
 (0)