Merge conference sections into a single table so columns align

Replace three separate <table> elements with one shared table. The
conf_table macro becomes conf_rows which emits only <tr> elements;
Current/Future/Past section boundaries are dark header rows inside
the same <tbody>. With one colgroup the browser uses one shared
column-width calculation so all headings line up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2026-03-14 11:22:43 +00:00
parent e36a326739
commit 1dfef38128

View file

@ -68,6 +68,15 @@ tr.conf-hl > td {
} }
/* Conference table */ /* Conference table */
.conf-section-row td {
background: #343a40 !important;
color: #fff;
font-weight: 700;
font-size: 0.85em;
padding-top: 0.5rem;
padding-bottom: 0.4rem;
border-bottom: none;
}
.conf-month-row td { .conf-month-row td {
background: #e9ecef !important; background: #e9ecef !important;
font-weight: 600; font-weight: 600;
@ -121,94 +130,74 @@ tr.conf-hl > td {
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro conf_table(heading, item_list, badge) %} {% macro conf_rows(heading, item_list, badge) %}
{% if item_list %} {% if item_list %}
{% set count = item_list | length %} {% set count = item_list | length %}
<h2>{{ heading }} <small class="text-muted fs-6 fw-normal">{{ count }} conference{{ "" if count == 1 else "s" }}</small></h2> <tr class="conf-section-row">
<table class="table table-sm table-hover align-middle mb-4"> <td colspan="6">{{ heading }} <span class="fw-normal opacity-75">{{ count }} conference{{ "" if count == 1 else "s" }}</span></td>
<colgroup> </tr>
<col style="width: 9rem"> {% set ns = namespace(prev_month="") %}
<col> {% for item in item_list %}
<col style="width: 18rem"> {% set month_label = item.start_date.strftime("%B %Y") %}
<col style="width: 14rem"> {% if month_label != ns.prev_month %}
<col style="width: 7rem"> {% set ns.prev_month = month_label %}
<col style="width: 10rem"> <tr class="conf-month-row">
</colgroup> <td colspan="6">{{ month_label }}</td>
<thead class="table-light">
<tr>
<th>Dates</th>
<th>Conference</th>
<th>Topic</th>
<th>Location</th>
<th>CFP ends</th>
<th>Price</th>
</tr> </tr>
</thead> {% endif %}
<tbody> <tr{% if item.going %} class="conf-going"{% endif %} data-conf-key="{{ item.start_date.isoformat() }}|{{ item.name }}">
{% set ns = namespace(prev_month="") %} <td class="text-nowrap text-muted small">
{% for item in item_list %} {%- if item.start_date == item.end_date -%}
{% set month_label = item.start_date.strftime("%B %Y") %} {{ item.start_date.strftime("%-d %b %Y") }}
{% if month_label != ns.prev_month %} {%- elif item.start_date.year == item.end_date.year and item.start_date.month == item.end_date.month -%}
{% set ns.prev_month = month_label %} {{ item.start_date.strftime("%-d") }}{{ item.end_date.strftime("%-d %b %Y") }}
<tr class="conf-month-row"> {%- else -%}
<td colspan="6">{{ month_label }}</td> {{ item.start_date.strftime("%-d %b") }}{{ item.end_date.strftime("%-d %b %Y") }}
</tr> {%- endif -%}
</td>
<td>
{% if item.url %}<a href="{{ item.url }}">{{ item.name }}</a>
{% else %}{{ item.name }}{% endif %}
{% if item.going and not (item.accommodation_booked or item.travel_booked) %}
<span class="badge text-bg-primary ms-1">{{ badge }}</span>
{% endif %} {% endif %}
<tr{% if item.going %} class="conf-going"{% endif %} data-conf-key="{{ item.start_date.isoformat() }}|{{ item.name }}"> {% if item.accommodation_booked %}
<td class="text-nowrap text-muted small"> <span class="badge text-bg-success ms-1">accommodation</span>
{%- if item.start_date == item.end_date -%} {% endif %}
{{ item.start_date.strftime("%-d %b %Y") }} {% if item.transport_booked %}
{%- elif item.start_date.year == item.end_date.year and item.start_date.month == item.end_date.month -%} <span class="badge text-bg-success ms-1">transport</span>
{{ item.start_date.strftime("%-d") }}{{ item.end_date.strftime("%-d %b %Y") }} {% endif %}
{%- else -%} {% if item.linked_trip %}
{{ item.start_date.strftime("%-d %b") }}{{ item.end_date.strftime("%-d %b %Y") }} {% set trip = item.linked_trip %}
{%- endif -%} <a href="{{ url_for('trip_page', start=trip.start.isoformat()) }}"
</td> class="text-muted ms-1 text-decoration-none"
<td> title="Trip: {{ trip.title }}">
{% if item.url %}<a href="{{ item.url }}">{{ item.name }}</a> 🧳{% if trip.title != item.name %} {{ trip.title }}{% endif %}
{% else %}{{ item.name }}{% endif %} </a>
{% if item.going and not (item.accommodation_booked or item.travel_booked) %} {% endif %}
<span class="badge text-bg-primary ms-1">{{ badge }}</span> </td>
{% endif %} <td class="text-muted small">{{ item.topic }}</td>
{% if item.accommodation_booked %} <td class="text-nowrap">
<span class="badge text-bg-success ms-1">accommodation</span> {% set country = get_country(item.country) if item.country else None %}
{% endif %} {% if country %}{{ country.flag }} {{ item.location }}
{% if item.transport_booked %} {% elif item.online %}💻 Online
<span class="badge text-bg-success ms-1">transport</span> {% else %}{{ item.location }}{% endif %}
{% endif %} </td>
{% if item.linked_trip %} <td class="text-nowrap text-muted small">
{% set trip = item.linked_trip %} {% if item.cfp_end %}{{ item.cfp_end.strftime("%-d %b %Y") }}{% endif %}
<a href="{{ url_for('trip_page', start=trip.start.isoformat()) }}" </td>
class="text-muted ms-1 text-decoration-none" <td>
title="Trip: {{ trip.title }}"> {% if item.price and item.currency %}
🧳{% if trip.title != item.name %} {{ trip.title }}{% endif %} <span class="badge bg-info text-nowrap">{{ "{:,d}".format(item.price | int) }} {{ item.currency }}</span>
</a> {% if item.currency != "GBP" and item.currency in fx_rate %}
{% endif %} <span class="badge bg-info text-nowrap">{{ "{:,.0f}".format(item.price / fx_rate[item.currency]) }} GBP</span>
</td> {% endif %}
<td class="text-muted small">{{ item.topic }}</td> {% elif item.free %}
<td class="text-nowrap"> <span class="badge bg-success text-nowrap">free</span>
{% set country = get_country(item.country) if item.country else None %} {% endif %}
{% if country %}{{ country.flag }} {{ item.location }} </td>
{% elif item.online %}💻 Online </tr>
{% else %}{{ item.location }}{% endif %} {% endfor %}
</td>
<td class="text-nowrap text-muted small">
{% if item.cfp_end %}{{ item.cfp_end.strftime("%-d %b %Y") }}{% endif %}
</td>
<td>
{% if item.price and item.currency %}
<span class="badge bg-info text-nowrap">{{ "{:,d}".format(item.price | int) }} {{ item.currency }}</span>
{% if item.currency != "GBP" and item.currency in fx_rate %}
<span class="badge bg-info text-nowrap">{{ "{:,.0f}".format(item.price / fx_rate[item.currency]) }} GBP</span>
{% endif %}
{% elif item.free %}
<span class="badge bg-success text-nowrap">free</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
@ -219,9 +208,31 @@ tr.conf-hl > td {
{{ render_timeline(timeline) }} {{ render_timeline(timeline) }}
{{ conf_table("Current", current, "attending") }} <table class="table table-sm table-hover align-middle">
{{ conf_table("Future", future, "going") }} <colgroup>
{{ conf_table("Past", past|reverse|list, "went") }} <col style="width: 9rem">
<col>
<col style="width: 18rem">
<col style="width: 14rem">
<col style="width: 7rem">
<col style="width: 10rem">
</colgroup>
<thead class="table-light">
<tr>
<th>Dates</th>
<th>Conference</th>
<th>Topic</th>
<th>Location</th>
<th>CFP ends</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{{ conf_rows("Current", current, "attending") }}
{{ conf_rows("Future", future, "going") }}
{{ conf_rows("Past", past|reverse|list, "went") }}
</tbody>
</table>
</div> </div>
<script> <script>