fix: apply accordion to personal/work project variants

The homepage uses cv-projects-personal.njk, not cv-projects.njk.
Apply the same collapsible accordion pattern to both personal
and work project section variants.
This commit is contained in:
Ricardo
2026-02-24 16:07:18 +01:00
parent b8b1ebcdf4
commit 20f7823ee1
2 changed files with 146 additions and 76 deletions
@@ -1,5 +1,6 @@
{# {#
CV Personal Projects Section - filters projects by projectType == "personal" (or unset) CV Personal Projects Section - collapsible project cards (accordion)
Filters projects by projectType == "personal" (or unset)
Data fetched from /cv/data.json via homepage plugin Data fetched from /cv/data.json via homepage plugin
#} #}
@@ -17,18 +18,24 @@
{% endif %} {% endif %}
{% if personalProjects.length %} {% if personalProjects.length %}
<section class="mb-8 sm:mb-12" id="personal-projects"> <section class="mb-8 sm:mb-12" id="personal-projects" x-data="{ expanded: {} }">
<h2 class="text-xl sm:text-2xl font-bold text-surface-900 dark:text-surface-100 mb-4 sm:mb-6"> <h2 class="text-xl sm:text-2xl font-bold text-surface-900 dark:text-surface-100 mb-4 sm:mb-6">
{{ sectionConfig.title or "Personal Projects" }} {{ sectionConfig.title or "Personal Projects" }}
</h2> </h2>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
{% for item in personalProjects | head(maxItems) %} {% for item in personalProjects | head(maxItems) %}
<div class="p-4 bg-white dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 hover:border-primary-400 dark:hover:border-primary-600 transition-colors"> <div class="bg-white dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 hover:border-primary-400 dark:hover:border-primary-600 transition-colors overflow-hidden">
<div class="flex items-start justify-between gap-2 mb-1"> {# Summary row — always visible, clickable #}
<h3 class="font-semibold text-surface-900 dark:text-surface-100"> <button
class="w-full p-4 flex items-center justify-between gap-2 cursor-pointer text-left hover:bg-surface-50 dark:hover:bg-surface-700/50 transition-colors"
@click="expanded[{{ loop.index0 }}] = !expanded[{{ loop.index0 }}]"
:aria-expanded="expanded[{{ loop.index0 }}] ? 'true' : 'false'"
>
<div class="flex items-center gap-2 min-w-0 flex-1">
<h3 class="font-semibold text-surface-900 dark:text-surface-100 truncate">
{% if item.url %} {% if item.url %}
<a href="{{ item.url }}" class="hover:text-primary-600 dark:hover:text-primary-400">{{ item.name }}</a> <a href="{{ item.url }}" class="hover:text-primary-600 dark:hover:text-primary-400" @click.stop>{{ item.name }}</a>
{% else %} {% else %}
{{ item.name }} {{ item.name }}
{% endif %} {% endif %}
@@ -43,9 +50,36 @@
</span> </span>
{% endif %} {% endif %}
</div> </div>
<div class="flex items-center gap-2 shrink-0">
{% if item.startDate %} {% if item.startDate %}
<p class="text-xs text-surface-500 mb-1"> <span class="text-xs text-surface-500 hidden sm:inline">
{{ item.startDate }}{% if item.endDate %} {{ item.endDate }}{% else %} Present{% endif %}
</span>
{% endif %}
<svg
class="w-4 h-4 text-surface-400 transition-transform duration-200"
:class="expanded[{{ loop.index0 }}] && 'rotate-180'"
fill="none" stroke="currentColor" viewBox="0 0 24 24"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
</button>
{# Detail section — collapsible #}
<div
x-show="expanded[{{ loop.index0 }}]"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 -translate-y-1"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 -translate-y-1"
x-cloak
class="px-4 pb-4"
>
{% if item.startDate %}
<p class="text-xs text-surface-500 mb-1 sm:hidden">
{{ item.startDate }}{% if item.endDate %} {{ item.endDate }}{% else %} Present{% endif %} {{ item.startDate }}{% if item.endDate %} {{ item.endDate }}{% else %} Present{% endif %}
</p> </p>
{% endif %} {% endif %}
@@ -64,6 +98,7 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div>
{% endfor %} {% endfor %}
</div> </div>
</section> </section>
@@ -1,5 +1,6 @@
{# {#
CV Work Projects Section - filters projects by projectType == "work" CV Work Projects Section - collapsible project cards (accordion)
Filters projects by projectType == "work"
Data fetched from /cv/data.json via homepage plugin Data fetched from /cv/data.json via homepage plugin
#} #}
@@ -17,18 +18,24 @@
{% endif %} {% endif %}
{% if workProjects.length %} {% if workProjects.length %}
<section class="mb-8 sm:mb-12" id="work-projects"> <section class="mb-8 sm:mb-12" id="work-projects" x-data="{ expanded: {} }">
<h2 class="text-xl sm:text-2xl font-bold text-surface-900 dark:text-surface-100 mb-4 sm:mb-6"> <h2 class="text-xl sm:text-2xl font-bold text-surface-900 dark:text-surface-100 mb-4 sm:mb-6">
{{ sectionConfig.title or "Work Projects" }} {{ sectionConfig.title or "Work Projects" }}
</h2> </h2>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
{% for item in workProjects | head(maxItems) %} {% for item in workProjects | head(maxItems) %}
<div class="p-4 bg-white dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 hover:border-primary-400 dark:hover:border-primary-600 transition-colors"> <div class="bg-white dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 hover:border-primary-400 dark:hover:border-primary-600 transition-colors overflow-hidden">
<div class="flex items-start justify-between gap-2 mb-1"> {# Summary row — always visible, clickable #}
<h3 class="font-semibold text-surface-900 dark:text-surface-100"> <button
class="w-full p-4 flex items-center justify-between gap-2 cursor-pointer text-left hover:bg-surface-50 dark:hover:bg-surface-700/50 transition-colors"
@click="expanded[{{ loop.index0 }}] = !expanded[{{ loop.index0 }}]"
:aria-expanded="expanded[{{ loop.index0 }}] ? 'true' : 'false'"
>
<div class="flex items-center gap-2 min-w-0 flex-1">
<h3 class="font-semibold text-surface-900 dark:text-surface-100 truncate">
{% if item.url %} {% if item.url %}
<a href="{{ item.url }}" class="hover:text-primary-600 dark:hover:text-primary-400">{{ item.name }}</a> <a href="{{ item.url }}" class="hover:text-primary-600 dark:hover:text-primary-400" @click.stop>{{ item.name }}</a>
{% else %} {% else %}
{{ item.name }} {{ item.name }}
{% endif %} {% endif %}
@@ -43,9 +50,36 @@
</span> </span>
{% endif %} {% endif %}
</div> </div>
<div class="flex items-center gap-2 shrink-0">
{% if item.startDate %} {% if item.startDate %}
<p class="text-xs text-surface-500 mb-1"> <span class="text-xs text-surface-500 hidden sm:inline">
{{ item.startDate }}{% if item.endDate %} {{ item.endDate }}{% else %} Present{% endif %}
</span>
{% endif %}
<svg
class="w-4 h-4 text-surface-400 transition-transform duration-200"
:class="expanded[{{ loop.index0 }}] && 'rotate-180'"
fill="none" stroke="currentColor" viewBox="0 0 24 24"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
</button>
{# Detail section — collapsible #}
<div
x-show="expanded[{{ loop.index0 }}]"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 -translate-y-1"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 -translate-y-1"
x-cloak
class="px-4 pb-4"
>
{% if item.startDate %}
<p class="text-xs text-surface-500 mb-1 sm:hidden">
{{ item.startDate }}{% if item.endDate %} {{ item.endDate }}{% else %} Present{% endif %} {{ item.startDate }}{% if item.endDate %} {{ item.endDate }}{% else %} Present{% endif %}
</p> </p>
{% endif %} {% endif %}
@@ -64,6 +98,7 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div>
{% endfor %} {% endfor %}
</div> </div>
</section> </section>