{# Tungsten UI kit — the small building blocks every page reuses. Import with: {% import "tungsten/components/ui.html" as ui %} #} {# ---------------------------------------------------------------- buttons #} {% macro button_classes(color='primary', style='button', size='md', outlined=false) -%} {%- set sizes = {'sm': 'px-2.5 py-1.5 text-xs', 'md': 'px-3 py-2 text-sm', 'lg': 'px-4 py-2.5 text-sm'} -%} {%- if style == 'link' -%} inline-flex items-center gap-1.5 text-sm font-semibold {{ colors.pick(colors.LINK, color) }} {%- elif style == 'icon' -%} inline-flex h-9 w-9 items-center justify-center rounded-full bg-white ring-1 ring-gray-950/10 transition dark:bg-white/5 dark:ring-white/10 {{ colors.pick(colors.ICON_BUTTON, color if color != 'primary' else 'gray') }} {%- elif style == 'soft' -%} tw-btn {{ sizes.get(size, sizes.md) }} {{ colors.pick(colors.SOFT_BUTTON, color) }} {%- elif style == 'dropdown' -%} flex w-full items-center gap-2 rounded-xl px-2.5 py-2 text-start text-sm transition hover:bg-gray-50 dark:hover:bg-white/5 {{ colors.pick(colors.TEXT, color) if color not in ('primary', 'gray') else 'text-gray-700 dark:text-gray-200' }} {%- elif outlined -%} tw-btn {{ sizes.get(size, sizes.md) }} bg-white ring-1 ring-gray-950/10 dark:bg-transparent dark:ring-white/20 {{ colors.pick(colors.LINK, color) }} {%- else -%} tw-btn {{ sizes.get(size, sizes.md) }} {{ colors.pick(colors.BUTTON, color) }} {%- endif -%} {%- endmacro %} {% macro button(label, color='primary', icon_name=None, href=None, type='button', style='button', size='md', attrs_='', outlined=false) %} {% set label = __(label) %} {% if href %} {{ icon(icon_name, 'h-4 w-4' if size != 'lg' else 'h-5 w-5') }}{{ label }} {% else %} {% endif %} {% endmacro %} {% macro icon_button(icon_name, label, color='gray', href=None, attrs_='', bordered=true) %} {% set label = __(label) %} {% set cls = button_classes(color, 'icon') if bordered else 'tw-icon-btn ' ~ colors.pick(colors.ICON_BUTTON, color) %} {% if href %} {{ icon(icon_name, 'h-4 w-4') }} {% else %} {% endif %} {% endmacro %} {# ---------------------------------------------------------------- badges #} {% macro badge(text, color='gray', icon_name=None, size='sm') %} {{ icon(icon_name, 'h-3.5 w-3.5') }}{{ text }} {% endmacro %} {% macro count_pill(n, color='primary', tooltip=none) %} {% if n is not none and n != '' %} {{ n }} {% endif %} {% endmacro %} {# ---------------------------------------------------------------- avatar #} {% macro avatar(name, url=None, size='h-9 w-9', text='text-sm') %} {% if url %} {{ name }} {% else %} {% set parts = (name or '?').split() %} {% set tones = ['bg-primary-100 text-primary-700 dark:bg-primary-500/20 dark:text-primary-300', 'bg-info-100 text-info-700 dark:bg-info-500/20 dark:text-info-300', 'bg-success-100 text-success-700 dark:bg-success-500/20 dark:text-success-300', 'bg-purple-100 text-purple-700 dark:bg-purple-500/20 dark:text-purple-300', 'bg-pink-100 text-pink-700 dark:bg-pink-500/20 dark:text-pink-300', 'bg-teal-100 text-teal-700 dark:bg-teal-500/20 dark:text-teal-300', 'bg-warning-100 text-warning-700 dark:bg-warning-500/20 dark:text-warning-300'] %} {% set ns = namespace(h=0) %}{% for ch in (name or '?') %}{% set ns.h = ns.h + ch | string | length * loop.index * (ch | ord_value) %}{% endfor %} {{- (parts[0][0] ~ (parts[-1][0] if parts | length > 1 else '')) | upper -}} {% endif %} {% endmacro %} {# ---------------------------------------------------------------- cards #} {# Card title block: optional icon tile, heading and a muted line under it. #} {% macro card_heading(heading, description=None, icon_name=None, icon_color='primary') %}
{% if icon_name %}{{ icon(icon_name, 'h-5 w-5') }}{% endif %}

{{ heading }}

{% if description %}

{{ description }}

{% endif %}
{% endmacro %} {% macro card_link(url, label='View all') %} {{ __(label) }}{{ icon('arrow-right', 'h-4 w-4') }} {% endmacro %} {% macro card(heading=None, description=None, padding='p-6', classes='', link=None, link_label='View all', icon_name=None, icon_color='primary') %}
{% if heading %}
{{ card_heading(heading, description, icon_name, icon_color) }} {% if link %}{{ card_link(link, link_label) }}{% endif %}
{% endif %}
{{ caller() }}
{% endmacro %} {# ---------------------------------------------------------------- dropdown #} {# twDropdown (tungsten.js) floats the open panel next to its trigger, so a table's scroll box can't cut it off. Picking a link or button in the panel closes it. #} {% macro dropdown(align='end', width='w-56', classes='') %}
{{ caller('trigger') }}
{{ caller('panel') }}
{% endmacro %} {# ---------------------------------------------------------------- headers #} {% macro breadcrumbs(items) %} {% if items %} {% endif %} {% endmacro %} {% macro empty_state(heading, description=None, icon_name='inbox') %}
{{ icon(icon_name, 'h-6 w-6') }}

{{ heading }}

{% if description %}

{{ description }}

{% endif %} {% if caller %}
{{ caller() }}
{% endif %}
{% endmacro %} {# ---------------------------------------------------------------- stat card #} {% macro trend(value, direction='up', color=None, suffix='vs last month') %} {% set c = color or ('success' if direction == 'up' else 'danger') %}

{{ icon('arrow-up' if direction == 'up' else 'arrow-down', 'h-4 w-4') }}{{ value }} {% if suffix %}{{ suffix }}{% endif %}

{% endmacro %} {% macro sparkline(points, color='primary', id='spark') %} {% if points and points | length > 1 %} {% set lo = points | min %}{% set hi = points | max %}{% set span = (hi - lo) or 1 %} {% set n = points | length - 1 %} {% set ns = namespace(d='') %} {% for p in points %} {% set x = (loop.index0 / n * 100) | round(2) %}{% set y = (36 - (p - lo) / span * 32) | round(2) %} {% set ns.d = ns.d ~ ('M' if loop.first else ' L') ~ x ~ ' ' ~ y %} {% endfor %} {% endif %} {% endmacro %} {% macro stat_card(label, value, icon_name=None, color='primary', description=None, trend_value=None, trend_direction='up', trend_color=None, chart=None, url=None, id='stat', variant='default') %} {% set tag = 'a' if url else 'div' %} {% set description = description or (__('vs last month') if trend_value else none) %} {% set filled = variant in ('brand', 'dark') %} <{{ tag }} {% if url %}href="{{ url }}"{% endif %} class="{{ 'tw-card-brand' if variant == 'brand' else ('tw-card-dark relative overflow-hidden' if variant == 'dark' else 'tw-card') }} group relative block overflow-hidden p-5 {{ 'tw-card-hover' if url }}" data-tw-stat="{{ variant }}"> {% if filled %}{% endif %}

{{ label }}

{% if icon_name %} {{ icon(icon_name, 'h-5 w-5') }} {% endif %}

{{ value }}

{% if trend_value %} {% set c = trend_color or ('success' if trend_direction == 'up' else 'danger') %} {{ icon('arrow-up' if trend_direction == 'up' else 'arrow-down', 'h-3 w-3') }}{{ trend_value }} {% endif %}
{% if description %}

{{ description }}

{% else %}{% endif %} {% if chart %}
{{ sparkline(chart, trend_color or color, id) }}
{% endif %}
{% endmacro %} {# ---------------------------------------------------------------- toolbar input #} {% macro search_input(name, value='', placeholder=None, id=None, attrs_='', shortcut=None) %} {% set placeholder = placeholder or __('Search...') %} {% endmacro %} {# ================================================================ modern components Small building blocks in the style of the dashboard: pills, chips, rings, gauges, bars and lists. Every macro works in light and dark mode. See docs/ui-components.md. #} {# A trend pill on its own: ui.trend_pill('12%', 'up') #} {% macro trend_pill(value, direction='up', color=None) %} {% set c = color or ('success' if direction == 'up' else 'danger') %} {{ icon('arrow-up' if direction == 'up' else 'arrow-down', 'h-3 w-3') }}{{ value }} {% endmacro %} {# A colored dot: ui.dot('success') #} {% macro dot(color='primary') %}{% endmacro %} {# A small rounded label, optionally with an icon or a colored dot: ui.chip('June 2025', 'calendar') #} {% macro chip(text, icon_name=None, dot_color=None, href=None) %} {% set tag = 'a' if href else 'span' %} <{{ tag }} {% if href %}href="{{ href }}"{% endif %} class="tw-chip {{ 'transition hover:bg-gray-50 dark:hover:bg-white/10' if href }}"> {% if dot_color %}{{ dot(dot_color) }}{% endif %}{{ icon(icon_name, 'h-3.5 w-3.5') }}{{ text }} {% endmacro %} {# A keyboard key: ui.kbd('⌘K') #} {% macro kbd(text) %}{{ text }}{% endmacro %} {# A thin line with an optional label in the middle. #} {% macro divider(label=None) %} {% endmacro %} {# Grey loading placeholder lines. #} {% macro skeleton(lines=3) %} {% endmacro %} {# Pill navigation. items: list of dicts {label, url, active, icon, badge}. muted=true gives a grey bar. #} {% macro pill_tabs(items, muted=false, label='Tabs') %} {% endmacro %} {# A segmented control that posts with the form: ui.segmented('period', {'7': '7 days', '30': '30 days'}, '30') #} {% macro segmented(name, options, value=None) %}
{% for v, text in options.items() %} {% endfor %}
{% endmacro %} {# An on/off switch for forms (a styled checkbox). #} {% macro switch(name, checked=false, label=None, description=None, value='1') %} {% endmacro %} {# A ring that fills to `percent`, with text in the middle. #} {% macro progress_ring(percent, color='primary', size=96, stroke=10, label=None, value=None) %} {% set r = (size - stroke) / 2 %}{% set c = 2 * 3.14159265 * r %} {% set p = [[percent or 0, 0] | max, 100] | min %} {% endmacro %} {# A half-circle gauge. on_dark=true draws it for a dark or brand card. #} {% macro gauge(percent, color='primary', value=None, caption=None, label=None, on_dark=false) %} {% set p = [[percent or 0, 0] | max, 100] | min %} {% set len = 3.14159265 * 80 %} {% endmacro %} {# A labelled bar: ui.meter('Enterprise deals', 12, 'danger', '12%') #} {% macro meter(label, percent, color='primary', value=None) %} {% set p = [[percent or 0, 0] | max, 100] | min %}
{{ label }} {{ value if value is not none else (p | round | int ~ '%') }}
{% endmacro %} {# Overlapping avatars. people: list of dicts {name, avatar}. #} {% macro avatar_group(people, max=4, size='h-9 w-9') %}
{% for person in people[:max] %}{{ avatar(person.name, person.avatar, size, 'text-xs') }}{% endfor %} {% if people | length > max %}+{{ people | length - max }}{% endif %}
{% endmacro %} {# One row in a list: an avatar or icon, a title and muted text, and a value at the end. #} {% macro list_row(title, description=None, value=None, icon_name=None, color='primary', avatar_url=None, avatar_name=None, href=None, badge_text=None, badge_color='gray') %} {% set tag = 'a' if href else 'div' %} <{{ tag }} {% if href %}href="{{ href }}"{% endif %} class="flex items-center gap-3 rounded-2xl px-2 py-2 {{ 'transition hover:bg-gray-50 dark:hover:bg-white/5' if href }}"> {% if avatar_name or avatar_url %}{{ avatar(avatar_name or title, avatar_url) }} {% elif icon_name %}{{ icon(icon_name, 'h-4 w-4') }}{% endif %}

{{ title }}

{% if description %}

{{ description }}

{% endif %}
{% if badge_text %}{{ badge(badge_text, badge_color) }}{% endif %} {% if value is not none %}{{ value }}{% endif %} {% endmacro %} {# One timeline entry (use inside
    ). last=true hides the line below. #} {% macro timeline_item(title, description=None, time=None, icon_name='circle', color='primary', last=false, href=None) %}
  1. {% if not last %}{% endif %} {{ icon(icon_name, 'h-4 w-4') }}
    {% if href %}{{ title }}{% else %}

    {{ title }}

    {% endif %} {% if time %}{{ time }}{% endif %}
    {% if description %}

    {{ description }}

    {% endif %}
  2. {% endmacro %} {# Rounded columns, one highlighted. columns: list of dicts {label, display, height (0-100), active}. #} {% macro columns(cols, color='primary', height='12rem') %}
    {% for col in cols %}
    {% if col.active %}{{ col.display }}{% endif %}
    {% if col.active %}{% endif %}
    {{ col.label }}
    {% endfor %}
    {% endmacro %} {# A colored banner card. variant: soft | brand | dark #} {% macro banner(heading, text=None, button_label=None, button_url=None, eyebrow=None, variant='soft', color='primary', button_icon='arrow-up-right') %} {% set filled = variant in ('brand', 'dark') %}
    {% if eyebrow %}{{ eyebrow }}{% endif %}

    {{ heading }}

    {% if text %}

    {{ text }}

    {% endif %}
    {% if button_label %} {% endif %}
    {% endmacro %} {# The current week as a strip of days. days: list of dicts {name, day, today}. #} {% macro week_strip(days) %}
    {% for d in days %}
    {{ d.name[:2] if d.name | length > 3 else d.name }} {{ d.day }}
    {% endfor %}
    {% endmacro %} {# A message box. color: info | success | warning | danger | primary | gray #} {% macro alert(heading, text=None, color='info', icon_name=None) %} {% set icons = {'info': 'info', 'success': 'circle-check', 'warning': 'triangle-alert', 'danger': 'circle-x'} %}
    {{ icon(icon_name or icons.get(color, 'info'), 'h-5 w-5') }}

    {{ heading }}

    {% if text %}

    {{ text }}

    {% endif %}
    {% endmacro %} {# A compact number with a label and optional trend, for use inside cards. #} {% macro kpi(label, value, trend_value=None, trend_direction='up', color=None, accent=None) %}

    {{ label }}

    {{ value }} {% if trend_value %}{{ trend_pill(trend_value, trend_direction, color) }}{% endif %}
    {% endmacro %}