Flowbite-Based Jinja Components
Project description
Flowbite-Based Jinja Components
A collection of Flowbite component developed as Jinja Layout Templates and Macros.
Getting Started for Flask
For a pre-configured starter repo both web and desktop app, goto: https://github.com/schaveyt/jinja-flowbite-web-desktop-demo
Otherwise start from scratch following the steps below:
-
Add the
jinja-flowbite
package to your python environment- Option 1: Add it to your
requirements.txt
- Option 2: Add it to your
pyproject.toml
if you are usingpoetry
- Option 3: Install to your global packages:
pip install jinja-flowbite
- Option 1: Add it to your
-
Register the
jinja_flowbite
package to the Flask runtimefrom flask import Flask import jinja2 app = Flask(__name__,) app.jinja_env.auto_reload = True enhanced_loader = jinja2.ChoiceLoader([ jinja2.PackageLoader("jinja_flowbite", ""), app.jinja_loader ]) app.jinja_loader = template_loader
-
Register the
jinja-flowbite
source file with Tailwind configurationsNOTE: Below is a standard flowbite setup with the key addition of adding the
jinja-flowbite
package .jinja files to thecontent
section./** @type {import('tailwindcss').Config} */ module.exports = { content: [ ".your_app_folder/templates/**/*.{html,jinja}", "./src/static/js/**/*.js", "./node_modules/flowbite/**/*.js", "./venv/Lib/site-packages/jinja_flowbite/**/*.{html,jinja}", ], darkMode: 'class', theme: { extend: { colors: { primary: { "50": "#eff6ff", "100": "#dbeafe", "200": "#bfdbfe", "300": "#93c5fd", "400": "#60a5fa", "500": "#3b82f6", "600": "#2563eb", "700": "#1d4ed8", "800": "#1e40af", "900": "#1e3a8a", "950": "#172554" } }, maxHeight: { 'table-xl': '60rem', } }, fontFamily: { 'body': [ 'Inter', 'ui-sans-serif', 'system-ui', '-apple-system', 'system-ui', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', 'sans-serif', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji' ], 'sans': [ 'Inter', 'ui-sans-serif', 'system-ui', '-apple-system', 'system-ui', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', 'sans-serif', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji' ], 'mono': [ 'ui-monospace', 'SFMono-Regular', 'MesloLGL Nerd Font Mono', 'Cascadia Mono', 'Courier New' ] } }, plugins: [ require('flowbite/plugin') ], }
-
In your HTML template, import the Components and use as Jinja macros
{% import "jinja_flowbite/controls/button.jinja" as Button %} {% import 'jinja_flowbite/controls/card.jinja' as Card %} <div class="flex flex-col items-center space-y-6"> {{ Card.render(title="This is a card") }} {{ Button.render(text="Click me") }} <div>
-
IMPORTANT - Rebuild the application's css file
-
For example:
npx tailwindcss -i ./{{ FLASK_APP_DIR_NAME }}/static/css/app.css -o ./{{ FLASK_APP_DIR_NAME }}/static/css/app.min.css"
-
Create an Full Application Shell (Flask)
-
Perform all the above getting started setup steps.
-
Create a directory structure something like this:
_ my_app/ |_ static/ |_ css |_ app.css # contains tailwindcss instructions and your custom classes |_ app.min.css # generated by tailwindcss npm tool |_ js |_ jinja-flowbite-app.js # will contain dark mode toggle logic |_ templates/ |_ components/ |_ footer.jinja # your custom footer content |_ sidebar.jinja # your custom side bar content |_ layouts/ |_ main_layout.html # layout with header, sidebar, and footer |_ pages/ |_ index.html # template for the / route |_ index.py # code for the / route
-
In the
jinja-flowbite-app.js
, add the following code:// HANDLE DARK MODE ---------------------------------------------------------------------------- var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon'); var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon'); // Change the icons inside the button based on previous settings if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { themeToggleLightIcon.classList.remove('hidden'); } else { themeToggleDarkIcon.classList.remove('hidden'); } var themeToggleBtn = document.getElementById('theme-toggle'); themeToggleBtn.addEventListener('click', function() { // toggle icons inside button themeToggleDarkIcon.classList.toggle('hidden'); themeToggleLightIcon.classList.toggle('hidden'); // if set via local storage previously if (localStorage.getItem('color-theme')) { if (localStorage.getItem('color-theme') === 'light') { document.documentElement.classList.add('dark'); localStorage.setItem('color-theme', 'dark'); } else { document.documentElement.classList.remove('dark'); localStorage.setItem('color-theme', 'light'); } // if NOT set via local storage previously } else { if (document.documentElement.classList.contains('dark')) { document.documentElement.classList.remove('dark'); localStorage.setItem('color-theme', 'light'); } else { document.documentElement.classList.add('dark'); localStorage.setItem('color-theme', 'dark'); } } });
-
In the
templates/layout/main_layout.html
add the following content:{% import 'jinja_flowbite/icons/flowbite_logo.jinja' as flowbite_flowbite_icon %} {% import 'jinja_flowbite/controls/dark_mode_toggle.jinja' as flowbite_dark_mode_toggle %} {% extends "jinja_flowbite/layouts/main_layout.jinja" %} {% block flowbite_head_app_css_links_outlet %} <link href="{{url_for('static',filename='css/app.min.css')}}" rel="stylesheet" /> {% endblock %} {% block flowbite_head_scripts_outlet %} <script src="{{url_for('static',filename='js/htmx.2.0.1.min.js')}}"></script> {% endblock %} {% block flowbite_body_scripts_outlet %} <script src="https://cdn.jsdelivr.net/npm/flowbite@2.4.1/dist/flowbite.min.js"></script> <script src="{{url_for('static',filename='js/jinja-flowbite-app.js')}}"></script> {% endblock %} {% block flowbite_header_content_left_outlet %} <!-- Application Title --> <a class="flex items-center ml-2 sm:ml-0" data-enhance-nav="false"> {{ flowbite_flowbite_icon.render(width_css_class="w-8", width_css_class="h-8", class="text-primary-500 mr-3" ) }} <a href="/" class="self-center text-2xl font-semibold whitespace-nowrap text-white"> Application Title </a> </a> {% endblock %} {% block flowbite_header_content_right_outlet %} {{ flowbite_dark_mode_toggle.render(class="mr-1" ) }} {% endblock %} {% block flowbite_page_sidebar_outlet %} {% include "components/sidebar_content.jinja" %} {% endblock %} {% block flowbite_footer_content_outlet %} {% include "components/footer_content.jinja" %} {% endblock %} {% block flowbite_page_body_outlet %} {% block page_body %}{% endblock %} {% endblock %}
-
In the
templates/components/footer.jinja
add the following content:<!-- left side footer --> <div role="footer-left-controls" class="flex items-center"> <p> Left side text</p> </div> <!-- right side footer --> <div> <div id="app-version" class="text-sm mr-2 flex space-x-2 items-center"> <span>Application Title</span> <span>v0.1</span> </div> </div>
-
In the
templates/components/footer.jinja
add the following content:<!-- left side footer --> <div role="footer-left-controls" class="flex items-center"> <p> Left side text</p> </div> <!-- right side footer --> <div> <div id="app-version" class="text-sm mr-2 flex space-x-2 items-center"> <span>Application Title</span> <span>v0.1</span> </div> </div>
-
In the
templates/components/sidebar.jinja
add the following content:{% set inactive_classes = "hover:bg-gray-100 dark:hover:bg-gray-700" %} {% set active_classes = "bg-primary-300 dark:bg-primary-800" %} <div class="py-5 px-3"> <ul class="pt-5 mt-5 space-y-2 border-t border-gray-200 dark:border-gray-700"> <!-- Home NavItem --> <li> {% set nav_active_classes = active_classes if 'home' in request.endpoint else inactive_classes %} <a href="/home" class="flex items-center p-2 text-base font-medium text-gray-900 rounded-lg transition duration-75 dark:text-white group {{ nav_active_classes }}"> <svg aria-hidden="true" class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"></path> <path fill-rule="evenodd" d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 4a1 1 0 000 2h.01a1 1 0 100-2H7zm3 0a1 1 0 000 2h3a1 1 0 100-2h-3zm-3 4a1 1 0 100 2h.01a1 1 0 100-2H7zm3 0a1 1 0 100 2h3a1 1 0 100-2h-3z" clip-rule="evenodd"></path> </svg> <span class="ml-3">Home</span> </a> </li> <!-- Help NavItem --> <li> {% set nav_active_classes = active_classes if 'help' in request.endpoint else inactive_classes %} <a href="/help" class="flex items-center p-2 text-base font-medium text-gray-900 rounded-lg transition duration-75 dark:text-white group {{ nav_active_classes }}"> <svg aria-hidden="true" class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-2 0c0 .993-.241 1.929-.668 2.754l-1.524-1.525a3.997 3.997 0 00.078-2.183l1.562-1.562C15.802 8.249 16 9.1 16 10zm-5.165 3.913l1.58 1.58A5.98 5.98 0 0110 16a5.976 5.976 0 01-2.516-.552l1.562-1.562a4.006 4.006 0 001.789.027zm-4.677-2.796a4.002 4.002 0 01-.041-2.08l-.08.08-1.53-1.533A5.98 5.98 0 004 10c0 .954.223 1.856.619 2.657l1.54-1.54zm1.088-6.45A5.974 5.974 0 0110 4c.954 0 1.856.223 2.657.619l-1.54 1.54a4.002 4.002 0 00-2.346.033L7.246 4.668zM12 10a2 2 0 11-4 0 2 2 0 014 0z" clip-rule="evenodd"></path> </svg> <span class="ml-3">Help</span> </a> </li> </ul> </div>
-
In the
templates/pages/home_page.html
add the following content:{% extends "layouts/main_layout.html" %} {% block page_body %} <p class="text-3xl">Home</p> {% endblock %}
-
In the
templates/pages/home_page.py
add the following content:from flask import render_template from my_app.webapp import app @app.route("/") def index_page(): return render_template("pages/home_page.html", page_title="Home")
-
In the
templates/pages/help_page.html
add the following content:{% extends "layouts/main_layout.html" %} {% block page_body %} <p class="text-3xl">Help</p> {% endblock %}
-
In the
templates/pages/help_page.py
add the following content:from flask import render_template from my_app.webapp import app @app.route("/") def index_page(): return render_template("pages/help_page.html", page_title="Help")
-
Run the application and one should see the following:
- custom header
- custom footer
- custom sidebar
- the sidebar highlights the active page
END OF DOCUMENT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
File details
Details for the file jinja_flowbite-0.4.dev5-py3-none-any.whl
.
File metadata
- Download URL: jinja_flowbite-0.4.dev5-py3-none-any.whl
- Upload date:
- Size: 46.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.11.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f6df7fc507ae01931bfa2b11924ebef7a74ccf510018d4cefdc1bb21f554f0cb |
|
MD5 | a94f43aad477f5f357af57179c4deeb2 |
|
BLAKE2b-256 | 223e34978e20f3d7dc41dd2f6587eba360f3d01df19efdc5fc226410f9e4648f |