Skip to content

Commit

Permalink
Bootstrap 5 Renderer (#100)
Browse files Browse the repository at this point in the history
* Add Bootstrap 5 Rendering

* Fix active dropdown class

* fix dropdown position

* Fix some flake8

* More flake8 fixes

* Move examples, add bootstrap5 example, remove all the flag bits that aren't needed
  • Loading branch information
coolacid authored Mar 12, 2024
1 parent 1640e0a commit 900b6c8
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 0 deletions.
File renamed without changes.
File renamed without changes.
12 changes: 12 additions & 0 deletions example/bootstrap5/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<title>{{msg|default('example page')}}</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
{{nav.top.render(id='top-navbar', renderer='bootstrap5')}}
<h1>{{msg|default('Welcome')}}</h1>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>
45 changes: 45 additions & 0 deletions example/simple/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from flask import Flask, render_template

from flask_nav3 import Nav
from flask_nav3.elements import Link, Navbar, Separator, Subgroup, Text, View

nav = Nav()

# registers the "top" menubar
nav.register_element(
"top",
Navbar(
View("Widgits, Inc.", "index"),
View("Our Mission", "about"),
Subgroup(
"Products",
View("Wg240-Series", "products", product="wg240"),
View("Wg250-Series", "products", product="wg250"),
Separator(),
Text("Discontinued Products"),
View("Wg10X", "products", product="wg10x"),
),
Link("Tech Support", "http://techsupport.invalid/widgits_inc"),
),
)


def create_app(configfile=None):
"""Creates the application."""
app = Flask(__name__)
nav.init_app(app)

# not good style, but like to keep our examples short
@app.route("/")
def index():
return render_template("index.html")

@app.route("/products/<product>/")
def products(product):
return render_template("index.html", msg="Buy our {0}".format(product))

@app.route("/about-us/")
def about():
return render_template("index.html")

return app
32 changes: 32 additions & 0 deletions example/simple/static/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
nav.navbar a {
text-decoration: none;
color: blue;
font-weight: normal;
}

nav.navbar .active {
font-weight: bold;
}

nav.navbar > ul {
list-style: none;
}

nav.navbar ul li {
display: block;
width: 150px;
margin-right: 20px;
float: left;
}

nav.navbar ul > li > a:hover {
background-color: #eeeecc;
}

nav.navbar ul .subgroup {
padding-left: 0px;
}

h1 {
clear: both;
}
File renamed without changes.
2 changes: 2 additions & 0 deletions flask_nav3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ def __init__(self, app=None):

# per default, register the simple renderer
simple = "{0}.renderers".format(__name__), "SimpleRenderer"
bootstrap5 = "{0}.renderers".format(__name__), "BootStrap5Renderer"
self._renderers = [
("simple", simple),
("bootstrap5", bootstrap5),
(None, simple, False),
]

Expand Down
75 changes: 75 additions & 0 deletions flask_nav3/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,78 @@ def visit_Separator(self, node):
def visit_Text(self, node):
"""Returns nav-label spans."""
return tags.span(node.text, _class="nav-label")


class BootStrap5Renderer(Renderer):
"""A very basic Bootstrap 5 renderer.
Renders a navigational structure using ``<nav>`` and ``<ul>`` tags that
can be styled using modern CSS.
:param kwargs: Additional attributes to pass on to the root ``<nav>``-tag.
"""

def __init__(self, **kwargs):
"""Constructor for ``SimpleRenderer``."""
self.kwargs = kwargs

def visit_Link(self, node):
"""Returns arefs matching url."""
return tags.a(node.text, href=node.get_url(), _class="nav-link")

def visit_Navbar(self, node):
"""Returns navbar classes."""
kwargs = self.kwargs.copy()

addclass = []
if "class" in self.kwargs:
addclass = kwargs["class"].split(" ")

kwargs["class"] = " ".join(addclass + ["navbar", "navbar-expand-lg"])

cont = tags.nav(**kwargs)
ul = cont.add(tags.ul(_class=" ".join(addclass + ["nav"])))

for item in node.items:
ul.add(tags.li(self.visit(item), _class="nav-item"))

return cont

def visit_View(self, node):
"""Returns arefs."""
kwargs = {"class": "nav-link"}
if node.active:
kwargs["_class"] = "nav-link active"
return tags.a(
node.text,
href=node.get_url(),
title=node.text,
**kwargs,
) # noqa: WPS221

def visit_Subgroup(self, node):
"""Returns subgroup divs."""
group = tags.ul(_class="dropdown-menu")
kwargs = {"data-bs-toggle": "dropdown"}
title = tags.a(
node.title,
href="#",
_class="nav-link dropdown-toggle",
**kwargs,
)

if node.active:
title.attributes["class"] = "nav-link dropdown-toggle active"

for item in node.items:
group.add(tags.li(self.visit(item), _class="dropdown-item"))

return tags.div(title, group, _class="dropdown")

def visit_Separator(self, node):
"""Returns separator hrs."""
return tags.hr(_class="dropdown-divider")

def visit_Text(self, node):
"""Returns nav-label spans."""
return tags.a(node.text, _class="nav-link disabled")

0 comments on commit 900b6c8

Please sign in to comment.