{# ================================================================================ Page Hero Macros (Pure Definitions) - Kida-Native v2 ================================================================================ All hero variants as pure macro definitions. No side effects, safe to import. USAGE: {% from 'partials/page-hero/_macros.html' import hero_editorial, hero_element %} {{ hero_editorial(page, params, theme) }} VARIANTS: - hero_editorial: Clean magazine layout (default for single pages) - hero_magazine: Editorial with container/background styling - hero_overview: Section index with page count - hero_classic: Traditional action-bar + header (two-piece layout) - hero_element: Autodoc elements (modules, classes, commands) - hero_section: Autodoc section indexes INTERNAL HELPERS (prefixed with _): - _get_page_url: URL with fallback chain - _share_dropdown: LLM share button with popover (data-driven) - _breadcrumb_eyebrow: Breadcrumbs as eyebrow - _hero_metadata: Unified metadata row (DRY extraction) - _element_badges: DocElement badges (pattern-matched) - _element_stats: DocElement stats KIDA FEATURES USED: - Data-driven loops for AI assistant rendering - {% match %} for element badge dispatching - {% with %} for nil-resilient metadata sections - {% let %} for scoped variable binding - {% capture %} for string building - Pipeline operators (|>) for cleaner filter chains - Optional chaining (?.) and null coalescing (??) For automatic routing based on hero_style, use: {% include 'partials/page-hero.html' %} ================================================================================ #} {% from 'partials/navigation-components.html' import breadcrumbs %} {# ============================================================================= HELPER MACROS (internal) ============================================================================= #} {# Get page URL with fallback chain #} {% def _get_page_url(page) -%} {{ (page?._path ?? page?.href ?? '/') | trim }} {%- end %} {# ============================================================================= AI ASSISTANTS DATA (data-driven configuration) Extracted for maintainability - add new AI assistants here. ============================================================================= #} {% let AI_ASSISTANTS = [ {'id': 'claude', 'name': 'Claude', 'url': 'https://claude.ai/new', 'icon': 'ai-claude'}, {'id': 'chatgpt', 'name': 'ChatGPT', 'url': 'https://chatgpt.com/', 'icon': 'ai-chatgpt'}, {'id': 'gemini', 'name': 'Gemini', 'url': 'https://gemini.google.com/app', 'icon': 'ai-gemini'}, {'id': 'copilot', 'name': 'Copilot', 'url': 'https://copilot.microsoft.com/', 'icon': 'ai-copilot'} ] %} {# ============================================================================= SHARE DROPDOWN MACRO (internal) Renders the LLM share button with popover menu. PATTERN: POPOVER - browser handles show/hide, light dismiss, escape key KIDA FEATURES: - Data-driven AI assistant loop (no repetition) - {% let %} for URL computation - Pipeline operators for clean encoding ============================================================================= #} {% def _share_dropdown(page) %} {% let page_url = canonical_url(_get_page_url(page)) %} {% let llm_txt_url = ensure_trailing_slash(page_url) ~ 'index.txt' %} {% let share_prompt = "Please help me understand this documentation: " ~ llm_txt_url %}
{% end %} {# ============================================================================= BREADCRUMB EYEBROW MACRO (internal) Renders breadcrumbs as eyebrow, excluding current page (it's the H1). KIDA FEATURES: - {% with %} for nil-resilient breadcrumb access - {% spaceless %} for clean HTML output ============================================================================= #} {% def _breadcrumb_eyebrow(page) %} {% with get_breadcrumbs(page) as breadcrumb_items %} {% if breadcrumb_items | length > 1 %} {% end %} {% end %} {% end %} {# ============================================================================= HERO METADATA ROW (internal - DRY extraction) Unified metadata rendering for editorial/magazine variants. Avoids code duplication between hero types. KIDA FEATURES: - Data-driven metadata items - {% with %} for nil-resilient feature check - Conditional rendering based on available data NOTE: Uses page.word_count and page.reading_time computed properties instead of filters for better performance (cached on first access). ============================================================================= #} {% def _hero_metadata(page, params, theme, show_reading_time=true) %} {% let has_word_count = (page?.word_count ?? none) %} {% let has_date = (page?.date ?? none) or (params?.lastmod ?? none) %} {% if has_word_count or has_date %}
{# Reading Time - conditionally shown based on theme features #} {% with theme?.features as features %} {% if has_word_count and show_reading_time and features and 'content.reading_time' in features %} {{ icon("clock", size=16) }} {{ t('meta.reading_time', {'time': page.reading_time}, default='{time} min read') }} {% end %} {% end %} {# Word Count #} {% if has_word_count %} {{ icon("file-text", size=16) }} {{ t('meta.word_count', {'count': page.word_count}, default='{count} words') }} {% end %} {# Last Updated / Date #} {% with params?.lastmod ?? page?.date as display_date %} {% if display_date %} {{ icon("arrow-clockwise", size=16) }} {{ display_date |> time_ago }} {% end %} {% end %}
{% end %} {% end %} {# ============================================================================= ELEMENT BADGES MACRO (internal) Renders badges for DocElements (modules, classes, functions, commands). KIDA FEATURES: - {% match %} for clean element type dispatching - Data-driven badge rendering with metadata flags - Nil-resilient metadata access ============================================================================= #} {% def _element_badges(element) %} {% with element?.metadata ?? {} as meta %} {% with element?.element_type ?? '' as elem_type %}
{% match elem_type %} {% case 'module' %} Module {% if meta?.is_dataclass %}dataclass{% end %} {% case 'class' %} {# Class badges - order matters for visual hierarchy #} {% for badge_key, badge_label in [('is_mixin', 'Mixin'), ('is_dataclass', 'dataclass'), ('is_abstract', 'abstract')] %} {% if meta[badge_key] %}{{ badge_label }}{% end %} {% end %} {% case 'function' %} {% if meta?.is_async %}async{% end %} {% case 'method' %} {# Method badges - data-driven for extensibility #} {% for badge_key, badge_label in [('is_async', 'async'), ('is_classmethod', 'classmethod'), ('is_staticmethod', 'staticmethod'), ('is_property', 'property')] %} {% if meta[badge_key] %}{{ badge_label }}{% end %} {% end %} {% case 'command' %} Command {% case 'command-group' %} Command Group {% end %}
{% end %} {% end %} {% end %} {# ============================================================================= ELEMENT STATS MACRO (internal) Renders stats (counts of children by type) for a DocElement. Uses the get_element_stats filter. KIDA FEATURES: - {% with %} for nil-resilient stats access - {% spaceless %} for clean HTML in stats row ============================================================================= #} {% def _element_stats(element) %} {% with element |> get_element_stats as stats %} {% if stats | length > 0 %} {% spaceless %}
{% for stat in stats %} {{ stat.value }} {{ stat.label }} {% end %}
{% end %} {% end %} {% end %} {% end %} {# ============================================================================= VARIANT MACROS (public API) ============================================================================= #} {# ----------------------------------------------------------------------------- EDITORIAL VARIANT Clean magazine-style layout without container styling. Default for single documentation pages. KIDA FEATURES: - Uses _hero_metadata for DRY metadata rendering - Nil-resilient page/params access ----------------------------------------------------------------------------- #} {% def hero_editorial(page, params, theme) %} {% with page?.title ?? 'Untitled' as page_title %}
{# Top row: Breadcrumbs (left) + Actions (right) #}
{{ _breadcrumb_eyebrow(page) }} {{ _share_dropdown(page) }}
{# Title #}

{{ page_title }}

{# Description #} {% with (params?.description ?? none) as desc %} {% if desc %}

{{ desc }}

{% end %} {% end %} {# Unified Metadata Row (DRY) #} {{ _hero_metadata(page, params, theme) }}
{% end %} {% end %} {# ----------------------------------------------------------------------------- MAGAZINE VARIANT Editorial-style with container/background styling. KIDA FEATURES: - Uses _hero_metadata for DRY metadata rendering - Identical structure to editorial for consistency ----------------------------------------------------------------------------- #} {% def hero_magazine(page, params, theme) %} {% with page?.title ?? 'Untitled' as page_title %}
{# Top row: Breadcrumbs (left) + Actions (right) #}
{{ _breadcrumb_eyebrow(page) }} {{ _share_dropdown(page) }}
{# Title #}

{{ page_title }}

{# Description #} {% with (params?.description ?? none) as desc %} {% if desc %}

{{ desc }}

{% end %} {% end %} {# Unified Metadata Row (DRY) #} {{ _hero_metadata(page, params, theme) }}
{% end %} {% end %} {# ----------------------------------------------------------------------------- OVERVIEW VARIANT For section index pages - wayfinding focused with page count. KIDA FEATURES: - {% let %} for computed counts - {% match %} for singular/plural dispatching - Nil-resilient list access with ?? [] ----------------------------------------------------------------------------- #} {% def hero_overview(page, params, posts, subsections) %} {% with page?.title ?? 'Section' as page_title %} {% let page_count = (posts ?? []) | length %} {% let subsection_count = (subsections ?? []) | length %} {% let total_count = page_count + subsection_count %}
{# Top row: Breadcrumbs (left) + Actions (right) #}
{{ _breadcrumb_eyebrow(page) }} {{ _share_dropdown(page) }}
{# Title #}

{{ page_title }}

{# Description #} {% with (params?.description ?? none) as desc %} {% if desc %}

{{ desc }}

{% end %} {% end %} {# Section Stats - page count with smart pluralization #} {% if total_count > 0 %}
{{ icon('file-text', size=16) }} {% match total_count %} {% case 1 %}1 page in this section {% case n %}{{ n }} pages in this section {% end %}
{% end %}
{% end %} {% end %} {# ----------------------------------------------------------------------------- CLASSIC VARIANT Traditional two-piece layout with separate action bar and page header. Useful for pages that need the action bar above the fold. ----------------------------------------------------------------------------- #} {% def hero_classic(page, params) %} {# Action Bar: Breadcrumbs + Share #} {% include 'partials/action-bar.html' %} {# Page Header #} {% end %} {# ----------------------------------------------------------------------------- ELEMENT VARIANT (API) For DocElement pages: modules, classes, functions, commands. Includes badges, code-style title, source link, and stats. KIDA FEATURES: - {% with %} for nil-resilient element access - {% capture %} for building source URL - {% let %} for scoped URL computation ----------------------------------------------------------------------------- #} {% def hero_element(element, page, config) %} {% let raw_name = element?.qualified_name ?? element?.name ?? 'Element' %} {% let is_cli_elem = element?.element_type in ['command', 'command-group'] %} {% with (raw_name | replace('.', ' ') if is_cli_elem else raw_name) as display_name %} {% let source_file = element?.display_source_file ?? element?.source_file %}
{# Top row: Breadcrumbs (left) + Actions (right) #}
{{ _breadcrumb_eyebrow(page) }} {{ _share_dropdown(page) }}
{# Badges - delegated to helper #} {{ _element_badges(element) }} {# Title - qualified name for elements #}

{{ display_name }}

{# Description from element #} {% with element?.description as desc %} {% if desc %}
{{ desc |> markdownify |> safe }}
{% end %} {% end %} {# Footer: Source link + stats #}
{% end %} {% end %} {# ----------------------------------------------------------------------------- SECTION VARIANT (API) For section-index pages: API packages, CLI groups. Shows subsection and page counts. KIDA FEATURES: - {% match %} for section type dispatching (CLI vs API) - {% let %} for computed counts - Data-driven stats rendering - Nil-resilient chaining throughout ----------------------------------------------------------------------------- #} {# STAT LABELS - data-driven for extensibility #} {% let SECTION_LABELS = { 'cli': {'subsection': 'Group', 'page': 'Command'}, 'api': {'subsection': 'Package', 'page': 'Module'} } %} {% def hero_section(section, page, hero_context) %} {# Determine section type from explicit context, page type, or URL (fallback) #} {% let is_cli = (hero_context?.is_cli ?? false) or (page?.type == 'autodoc-cli') or (page?.href and '/cli' in page.href) or false %} {% let section_type = 'cli' if is_cli else 'api' %} {% let labels = SECTION_LABELS[section_type] %} {# Computed values with nil-resilience #} {% let display_title = section?.title ?? page?.title ?? 'Section' %} {% let section_desc = section?.metadata?.description %} {% let subsections = (section?.sorted_subsections ?? []) |> list %} {% let pages = section?.regular_pages ?? [] %} {% let sub_count = subsections | length %} {% let page_count = pages | length %}
{# Top row: Breadcrumbs (left) + Actions (right) #}
{{ _breadcrumb_eyebrow(page) }} {{ _share_dropdown(page) }}
{# Title #}

{{ display_title }}

{# Description from section metadata #} {% if section_desc %}
{{ section_desc |> markdownify |> safe }}
{% end %} {# Footer: Stats from section children #} {% if sub_count > 0 or page_count > 0 %} {% end %}
{% end %}