Bootstrap 4 & 5 helper for Flask projects providing Jinja macros for forms, tables, navigation, and utilities.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Navigation and breadcrumb components with Bootstrap styling, supporting badges, active state management, and flexible link generation for creating consistent navigation elements.
Render navigation items with Bootstrap styling and optional badge indicators.
def render_nav_item(endpoint, text, _badge='', _use_li=False, _badge_classes=''):
"""
Render a navigation item with Bootstrap styling.
Args:
endpoint (str): Flask endpoint name for URL generation
text (str): Display text for the navigation item
_badge (str): Optional badge text to display
_use_li (bool): Wrap in <li> element for nav lists
_badge_classes (str): CSS classes for badge styling
Returns:
Rendered HTML navigation item with optional badge
Bootstrap Versions:
- Bootstrap 4: Uses 'badge badge-light' default classes
- Bootstrap 5: Uses 'badge text-bg-light' default classes
Active State:
- Automatically adds 'active' class if current endpoint matches
- Uses Flask's request.endpoint for comparison
"""Render individual breadcrumb navigation items for hierarchical navigation.
def render_breadcrumb_item(endpoint, text):
"""
Render a breadcrumb navigation item.
Args:
endpoint (str): Flask endpoint name for URL generation
text (str): Display text for the breadcrumb item
Returns:
Rendered HTML breadcrumb item
Usage:
- Used within Bootstrap breadcrumb navigation
- Automatically handles active state for current page
- Generates proper Bootstrap breadcrumb markup
"""Simple navigation links without list wrappers:
{% from 'bootstrap5/nav.html' import render_nav_item %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="/">My App</a>
<div class="navbar-nav">
{{ render_nav_item('home', 'Home') }}
{{ render_nav_item('about', 'About') }}
{{ render_nav_item('contact', 'Contact') }}
</div>
</div>
</nav>Navigation items wrapped in list elements:
<ul class="nav nav-tabs">
{{ render_nav_item('dashboard', 'Dashboard', _use_li=True) }}
{{ render_nav_item('users', 'Users', _use_li=True) }}
{{ render_nav_item('settings', 'Settings', _use_li=True) }}
</ul>Navigation items displaying badge indicators:
<nav class="nav nav-pills flex-column">
{{ render_nav_item('messages', 'Messages', _badge='5', _badge_classes='badge bg-primary') }}
{{ render_nav_item('notifications', 'Notifications', _badge='12', _badge_classes='badge bg-warning') }}
{{ render_nav_item('tasks', 'Tasks', _badge='new', _badge_classes='badge bg-success') }}
</nav>Hierarchical breadcrumb navigation:
{% from 'base/nav.html' import render_breadcrumb_item %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
{{ render_breadcrumb_item('home', 'Home') }}
</li>
<li class="breadcrumb-item">
{{ render_breadcrumb_item('admin', 'Admin') }}
</li>
<li class="breadcrumb-item">
{{ render_breadcrumb_item('users', 'Users') }}
</li>
<li class="breadcrumb-item active" aria-current="page">
Edit User
</li>
</ol>
</nav>{% from 'bootstrap5/nav.html' import render_nav_item %}
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="{{ url_for('home') }}">My App</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<div class="navbar-nav me-auto">
{{ render_nav_item('home', 'Home') }}
{{ render_nav_item('products', 'Products') }}
{{ render_nav_item('services', 'Services') }}
{{ render_nav_item('contact', 'Contact') }}
</div>
<div class="navbar-nav">
{% if current_user.is_authenticated %}
{{ render_nav_item('profile', 'Profile') }}
{{ render_nav_item('logout', 'Logout') }}
{% else %}
{{ render_nav_item('login', 'Login') }}
{{ render_nav_item('register', 'Register') }}
{% endif %}
</div>
</div>
</div>
</nav><div class="d-flex">
<nav class="bg-light sidebar">
<div class="nav flex-column">
<h6 class="nav-header">Dashboard</h6>
{{ render_nav_item('admin.dashboard', 'Overview') }}
{{ render_nav_item('admin.analytics', 'Analytics') }}
<h6 class="nav-header">Management</h6>
{{ render_nav_item('admin.users', 'Users', _badge=user_count) }}
{{ render_nav_item('admin.orders', 'Orders', _badge=pending_orders,
_badge_classes='badge bg-warning') }}
{{ render_nav_item('admin.products', 'Products') }}
<h6 class="nav-header">Settings</h6>
{{ render_nav_item('admin.config', 'Configuration') }}
{{ render_nav_item('admin.logs', 'System Logs') }}
</div>
</nav>
<main class="flex-grow-1 p-4">
<!-- Main content -->
</main>
</div><ul class="nav nav-tabs mb-3">
{{ render_nav_item('user.profile', 'Profile', _use_li=True) }}
{{ render_nav_item('user.settings', 'Settings', _use_li=True) }}
{{ render_nav_item('user.security', 'Security', _use_li=True) }}
{{ render_nav_item('user.billing', 'Billing', _use_li=True) }}
</ul>
<div class="tab-content">
<!-- Tab content here -->
</div><nav class="nav nav-pills nav-justified">
{{ render_nav_item('inbox', 'Inbox', _badge='15', _badge_classes='badge bg-primary ms-1') }}
{{ render_nav_item('sent', 'Sent') }}
{{ render_nav_item('drafts', 'Drafts', _badge='3', _badge_classes='badge bg-secondary ms-1') }}
{{ render_nav_item('trash', 'Trash') }}
</nav>{% from 'base/nav.html' import render_breadcrumb_item %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
{{ render_breadcrumb_item('home', 'Home') }}
</li>
<li class="breadcrumb-item">
{{ render_breadcrumb_item('blog', 'Blog') }}
</li>
<li class="breadcrumb-item">
{{ render_breadcrumb_item('blog.category', 'Technology', category='tech') }}
</li>
<li class="breadcrumb-item active" aria-current="page">
{{ post.title }}
</li>
</ol>
</nav>{% from 'bootstrap4/nav.html' import render_nav_item %}
<!-- Bootstrap 4 badge classes -->
{{ render_nav_item('messages', 'Messages', _badge='5',
_badge_classes='badge badge-primary') }}{% from 'bootstrap5/nav.html' import render_nav_item %}
<!-- Bootstrap 5 badge classes -->
{{ render_nav_item('messages', 'Messages', _badge='5',
_badge_classes='badge text-bg-primary') }}<!-- Show different navigation based on user role -->
{% if current_user.is_admin %}
<div class="nav flex-column">
{{ render_nav_item('admin.dashboard', 'Admin Dashboard') }}
{{ render_nav_item('admin.users', 'Manage Users') }}
{{ render_nav_item('admin.settings', 'System Settings') }}
</div>
{% elif current_user.is_authenticated %}
<div class="nav flex-column">
{{ render_nav_item('user.dashboard', 'My Dashboard') }}
{{ render_nav_item('user.profile', 'My Profile') }}
{{ render_nav_item('user.orders', 'My Orders') }}
</div>
{% else %}
<div class="nav flex-column">
{{ render_nav_item('home', 'Home') }}
{{ render_nav_item('about', 'About') }}
{{ render_nav_item('login', 'Login') }}
</div>
{% endif %}# View function
@app.route('/dashboard')
def dashboard():
unread_messages = Message.query.filter_by(
user_id=current_user.id, read=False
).count()
pending_tasks = Task.query.filter_by(
user_id=current_user.id, status='pending'
).count()
return render_template('dashboard.html',
unread_messages=unread_messages,
pending_tasks=pending_tasks)<!-- Template with dynamic badges -->
<nav class="nav nav-pills">
{{ render_nav_item('messages', 'Messages',
_badge=unread_messages if unread_messages > 0 else '',
_badge_classes='badge bg-danger') }}
{{ render_nav_item('tasks', 'Tasks',
_badge=pending_tasks if pending_tasks > 0 else '',
_badge_classes='badge bg-warning') }}
</nav>Navigation components automatically handle active states:
request.endpoint with nav item endpointactive class to matching navigation items<!-- If current page is 'users' endpoint -->
{{ render_nav_item('users', 'Users') }}
<!-- Renders as: -->
<a class="nav-link active" href="/users">Users</a>
<!-- Other endpoints render without active class -->
{{ render_nav_item('settings', 'Settings') }}
<!-- Renders as: -->
<a class="nav-link" href="/settings">Settings</a>Install with Tessl CLI
npx tessl i tessl/pypi-bootstrap-flask