{# ============================================================ APEP Macro Showcase - Part 1 breadcrumb, btn, checkbox, date_picker, download_btn, dropdown, faq, faq_list, file_upload, footer_nav, header_banner, hero_btn, image, image_gallery, logo_scroller, nav ============================================================ #} {# ================================================================ 1. breadcrumb ================================================================ #}

breadcrumb

breadcrumb(items, separator="/")

default separator "/"

{{ apep.macros.breadcrumb([ {"label": "Home", "url": "/"}, {"label": "Blog", "url": "/blog"}, {"label": "Article"} ]) }}

separator "›"

{{ apep.macros.breadcrumb([ {"label": "Home", "url": "/"}, {"label": "Products", "url": "/products"}, {"label": "Widget"} ], separator="›") }}

two levels only

{{ apep.macros.breadcrumb([ {"label": "Home", "url": "/"}, {"label": "Contact"} ]) }}

deep path + separator "»"

{{ apep.macros.breadcrumb([ {"label": "Home", "url": "/"}, {"label": "Docs", "url": "/docs"}, {"label": "API", "url": "/docs/api"}, {"label": "Macros", "url": "/docs/api/macros"}, {"label": "breadcrumb"} ], separator="»") }}
{# ================================================================ 2. btn ================================================================ #}

btn

btn(label, variant, size, url, disabled)

all variants - md

{{ apep.macros.btn("Primary", variant="primary") }} {{ apep.macros.btn("Secondary", variant="secondary") }} {{ apep.macros.btn("Ghost", variant="ghost") }} {{ apep.macros.btn("Danger", variant="danger") }}

primary - sm / md / lg

{{ apep.macros.btn("Small", variant="primary", size="sm") }} {{ apep.macros.btn("Medium", variant="primary", size="md") }} {{ apep.macros.btn("Large", variant="primary", size="lg") }}

as anchor (url set)

{{ apep.macros.btn("Visit Docs", variant="secondary", url="/docs") }}

disabled states

{{ apep.macros.btn("Disabled Primary", variant="primary", disabled=True) }} {{ apep.macros.btn("Disabled Ghost", variant="ghost", disabled=True) }} {{ apep.macros.btn("Disabled Danger", variant="danger", disabled=True) }}
{# ================================================================ 3. checkbox ================================================================ #}

checkbox

checkbox(name, options, hidden_name)

basic - none checked

{{ apep.macros.checkbox("fruits", [ {"label": "Apple"}, {"label": "Banana"}, {"label": "Cherry"} ]) }}

pre-checked items

{{ apep.macros.checkbox("langs", [ {"label": "Python", "checked": True}, {"label": "JavaScript", "checked": False}, {"label": "Rust", "checked": True} ]) }}

with hidden_name

{{ apep.macros.checkbox("colors", [ {"label": "Red", "value": "red"}, {"label": "Green", "value": "green"}, {"label": "Blue", "value": "blue", "checked": True} ], hidden_name="colors_csv") }}

label ≠ value pairs

{{ apep.macros.checkbox("roles", [ {"label": "Administrator", "value": "admin"}, {"label": "Editor", "value": "edit", "checked": True}, {"label": "Viewer", "value": "view"} ]) }}
{# ================================================================ 4. date_picker ================================================================ #}

date_picker

date_picker(name, id, format, display, value, required, min_date, max_date, placeholder)

default format yyyy.mm.dd

{{ apep.macros.date_picker(name="birth_date") }}

prefilled value

{{ apep.macros.date_picker(name="start_date", value="2025.06.01") }}

required + custom placeholder

{{ apep.macros.date_picker(name="deadline", required=True, placeholder="Pick a deadline") }}

min/max range

{{ apep.macros.date_picker(name="booking", min_date="2025.01.01", max_date="2025.12.31") }}
{# ================================================================ 5. download_btn ================================================================ #}

download_btn

download_btn(label, file_path, variant)

variant="default"

{{ apep.macros.download_btn("Download Report", "report_q3.pdf") }}

variant="icon"

{{ apep.macros.download_btn("Download CSV", "data.csv", variant="icon") }}

variant="minimal"

{{ apep.macros.download_btn("Download Slides", "slides.pptx", variant="minimal") }}
{# ================================================================ 6. dropdown ================================================================ #}

dropdown

dropdown(name, label, options, selected, required)

basic

{{ apep.macros.dropdown("country", "Country", [ {"label": "Germany"}, {"label": "France"}, {"label": "Spain"} ]) }}

pre-selected

{{ apep.macros.dropdown("size", "Size", [ {"label": "Small", "value": "s"}, {"label": "Medium", "value": "m"}, {"label": "Large", "value": "l"} ], selected="m") }}

required

{{ apep.macros.dropdown("plan", "Subscription Plan", [ {"label": "Free", "value": "free"}, {"label": "Pro", "value": "pro"}, {"label": "Enterprise", "value": "ent"} ], required=True) }}
{# ================================================================ 7. faq (single item) ================================================================ #}

faq

faq(question, answer, open)

closed (default)

{{ apep.macros.faq( "What is APEP?", "APEP is a macro-driven component system for Jinja2 templates." ) }}

open=True

{{ apep.macros.faq( "Why use macros instead of components?", "Macros keep logic server-side. No client-side JS is needed for rendering.", open=True ) }}

HTML in answer

{{ apep.macros.faq( "How do I pass HTML inside an answer?", "

The answer param supports raw HTML.

  • Lists work
  • Links work
" ) }}
{# ================================================================ 8. faq_list ================================================================ #}

faq_list

faq_list(items, open_all)

all closed (default)

{{ apep.macros.faq_list([ {"question": "Is Jinja2 server-side?", "answer": "Yes, it renders on the server."}, {"question": "Does APEP require Python?", "answer": "Yes, via Flask or similar backends."}, {"question": "Can I extend macros?", "answer": "Not directly, but you can compose them."} ]) }}

open_all=True

{{ apep.macros.faq_list([ {"question": "What does open_all do?", "answer": "It expands every item on page load."}, {"question": "Can I still close them?", "answer": "Yes, via the toggle button per item."} ], open_all=True) }}

individual open states mixed

{{ apep.macros.faq_list([ {"question": "First - starts open", "answer": "This one starts open.", "open": True}, {"question": "Second - starts closed", "answer": "This one starts closed."}, {"question": "Third - starts open", "answer": "This one also starts open.", "open": True} ]) }}
{# ================================================================ 9. file_upload ================================================================ #}

file_upload

file_upload(name, label, url, mode, accept, multiple, max_size, required, hint)

mode="direct"

{{ apep.macros.file_upload("avatar", "Profile Picture", url="/upload/avatar") }}

mode="cache"

{{ apep.macros.file_upload("attachment", "Attachment", mode="cache") }}

accept + multiple + required + hint

{{ apep.macros.file_upload( "docs", "Supporting Documents", url="/upload/docs", accept=".pdf,.docx", multiple=True, required=True, hint="Max 3 files. PDF or DOCX only." ) }}

images only + max_size

{{ apep.macros.file_upload( "gallery_img", "Gallery Image", url="/upload/gallery", accept="image/*", max_size=5242880 ) }}
{# ================================================================ 10. footer_nav ================================================================ #}

footer_nav

footer_nav(links, variant)

variant="blocks" - grouped columns

{{ apep.macros.footer_nav({ "Company": {"About": "/about", "Careers": "/careers", "Press": "/press"}, "Product": {"Features": "/features", "Pricing": "/pricing", "Changelog": "/changelog"}, "Support": {"Docs": "/docs", "Status": "/status", "Contact": "/contact"} }) }}

variant="blocks" - Mixed with title and none)

{{ apep.macros.footer_nav({ "Imprint": "/imprint", "GDPR": {"Privacy": "/privacy"}, "Terms": "/terms" }) }}

variant="inline"

{{ apep.macros.footer_nav({ "Imprint": "/imprint", "Privacy": "/privacy", "Terms": "/terms", "Cookies": "/cookies" }, variant="inline") }}
{# ================================================================ 11. header_banner ================================================================ #}

header_banner

header_banner(company_name, subtitle, url)

name only

{{ apep.macros.header_banner("APEP") }}

name + subtitle

{{ apep.macros.header_banner("APEP", subtitle="Component Library") }}

linked (url set)

{{ apep.macros.header_banner("APEP", subtitle="Go to homepage", url="/") }}
{# ================================================================ 12. hero_btn ================================================================ #}

hero_btn

hero_btn(label, url, subtitle, variant)

variant="primary"

{{ apep.macros.hero_btn("Get Started", url="/signup") }}

variant="secondary"

{{ apep.macros.hero_btn("Learn More", url="/docs", variant="secondary") }}

primary + subtitle

{{ apep.macros.hero_btn("Start Free Trial", url="/trial", subtitle="No credit card required") }}

secondary + subtitle

{{ apep.macros.hero_btn("Watch Demo", url="/demo", variant="secondary", subtitle="3-minute overview") }}
{# ================================================================ 13. image ================================================================ #}

image

image(src, alt, url, on_click, protected, width, height, downloadable)

basic path - protected=True (default)

{{ apep.macros.image("/apep-static/images/examples/unsplash1.svg", alt="Sample landscape", width="280px", height="180px") }}

linked - protected=False

{{ apep.macros.image("/apep-static/images/examples/unsplash2.svg", alt="Linked image", url="https://example.com", protected=False, width="280px", height="180px") }}

downloadable=True

{{ apep.macros.image("/apep-static/images/examples/unsplash3.svg", alt="Downloadable image", downloadable=True, width="280px", height="180px") }}

inline SVG src

{% set _svg_demo %} inline SVG {% endset %} {{ apep.macros.image(_svg_demo, alt="Demo SVG", downloadable=True) }}

raw <img> tag as src

{{ apep.macros.image('', alt="Raw img tag") }}
{# ================================================================ 14. image_gallery ================================================================ #}

image_gallery

image_gallery(images, downloadable)

9 images - downloadable=False - mix of short, long and missing captions - click to open overlay

{{ apep.macros.image_gallery([ {"src": "/apep-static/images/examples/unsplash1.svg", "alt": "Landscape 1", "caption": "Mountain at dawn"}, {"src": "/apep-static/images/examples/unsplash2.svg", "alt": "Landscape 2", "caption": "Forest path in autumn - taken during a three-day hiking trip through the Bavarian Alps, early October, just after sunrise when the mist was still sitting in the valley below"}, {"src": "/apep-static/images/examples/unsplash3.svg", "alt": "Landscape 3", "caption": "Ocean view"}, {"src": "/apep-static/images/examples/unsplash4.svg", "alt": "Landscape 4"}, {"src": "/apep-static/images/examples/unsplash5.svg", "alt": "Landscape 5", "caption": "Desert dunes - this shot required waking up at 4am, driving two hours into the Sahara, and waiting another hour for the light to hit the sand at exactly the right angle. Completely worth it."}, {"src": "/apep-static/images/examples/unsplash6.svg", "alt": "Landscape 6", "caption": "Frozen lake"}, {"src": "/apep-static/images/examples/unsplash7.svg", "alt": "Landscape 7"}, {"src": "/apep-static/images/examples/unsplash8.svg", "alt": "Landscape 8", "caption": "Coastal cliffs"}, {"src": "/apep-static/images/examples/unsplash9.svg", "alt": "Landscape 9", "caption": "Night sky - Milky Way core visible, 25 second exposure at f/2.8, ISO 3200. No editing beyond white balance correction."} ]) }}

9 images - downloadable=True - mix of path + inline SVG

{% set _gallery_svg_1 %} Inline A SVG from template {% endset %} {% set _gallery_svg_2 %} Inline B {% endset %} {% set _gallery_svg_3 %} Inline C {% endset %} {{ apep.macros.image_gallery([ {"src": "/apep-static/images/examples/unsplash1.svg", "alt": "Download 1", "caption": "Waterfall"}, {"src": "/apep-static/images/examples/unsplash2.svg", "alt": "Download 2", "caption": "Summit view - an extremely long caption to test how the overlay handles text that goes well beyond a single line, potentially wrapping across multiple rows in the lightbox caption area"}, {"src": "/apep-static/images/examples/unsplash3.svg", "alt": "Download 3", "caption": "City lights"}, {"src": "/apep-static/images/examples/unsplash4.svg", "alt": "Download 4"}, {"src": "/apep-static/images/examples/unsplash5.svg", "alt": "Download 5", "caption": "River delta"}, {"src": _gallery_svg_1, "alt": "Inline SVG A", "caption": "Generated inline - this SVG was constructed directly in the Jinja2 template using a set block, no file required"}, {"src": _gallery_svg_2, "alt": "Inline SVG B"}, {"src": _gallery_svg_3, "alt": "Inline SVG C", "caption": "Also inline"}, {"src": "/apep-static/images/examples/unsplash6.svg", "alt": "Download 9", "caption": "Glacier"} ], downloadable=True) }}
{# ================================================================ 15. logo_scroller ================================================================ #}

logo_scroller

logo_scroller(logos, speed, logo_height, width, height)

default speed=30, logo_height=40 - 9 logos

{{ apep.macros.logo_scroller([ {"src": "/apep-static/images/examples/unsplash1.svg", "alt": "Partner A"}, {"src": "/apep-static/images/examples/unsplash2.svg", "alt": "Partner B"}, {"src": "/apep-static/images/examples/unsplash3.svg", "alt": "Partner C"}, {"src": "/apep-static/images/examples/unsplash4.svg", "alt": "Partner D"}, {"src": "/apep-static/images/examples/unsplash5.svg", "alt": "Partner E"}, {"src": "/apep-static/images/examples/unsplash6.svg", "alt": "Partner F"}, {"src": "/apep-static/images/examples/unsplash7.svg", "alt": "Partner G"}, {"src": "/apep-static/images/examples/unsplash8.svg", "alt": "Partner H"}, {"src": "/apep-static/images/examples/unsplash9.svg", "alt": "Partner I"} ]) }}

speed=8 (fast), logo_height=60 - 9 linked logos

{{ apep.macros.logo_scroller([ {"src": "/apep-static/images/examples/unsplash1.svg", "alt": "Partner A", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash2.svg", "alt": "Partner B", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash3.svg", "alt": "Partner C", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash4.svg", "alt": "Partner D", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash5.svg", "alt": "Partner E", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash6.svg", "alt": "Partner F", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash7.svg", "alt": "Partner G", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash8.svg", "alt": "Partner H", "url": "https://example.com"}, {"src": "/apep-static/images/examples/unsplash9.svg", "alt": "Partner I", "url": "https://example.com"} ], speed=8, logo_height=60) }}
{# ================================================================ 16. nav ================================================================ #}

nav

nav(items, variant) - flying navs omitted, not suitable for inline showcase

variant="top" - flat links only

{{ apep.macros.nav({ "Home": "/", "Features": "/features", "Pricing": "/pricing", "About": "/about", "Contact": "/contact" }) }}

variant="top" - with dropdown children

{{ apep.macros.nav({ "Home": "/", "Products": { "Widget Pro": "/products/widget-pro", "Widget Lite": "/products/widget-lite", "Add-ons": "/products/addons" }, "Docs": { "Getting Started": "/docs/start", "API Reference": "/docs/api", "Changelog": "/docs/changelog" }, "Pricing": "/pricing", "Blog": "/blog" }) }}

variant="left" - with dropdown

{{ apep.macros.nav({ "Dashboard": "/dashboard", "Analytics": { "Overview": "/analytics/overview", "Reports": "/analytics/reports", "Exports": "/analytics/exports" }, "Reports": "/reports", "Settings": "/settings", "Logout": "/logout" }, variant="left") }}

variant="right" - with dropdown

{{ apep.macros.nav({ "Dashboard": "/dashboard", "Users": { "All Users": "/users", "Roles": "/users/roles", "Invites": "/users/invites" }, "Settings": "/settings" }, variant="right") }}