fix(web): better alignment on mobile for table views
This commit is contained in:
parent
32c0935124
commit
ff8f0c781e
6 changed files with 89 additions and 36 deletions
|
|
@ -97,7 +97,7 @@
|
||||||
{% call table::pagination_header(bags, navigator, "#bag-list") %}
|
{% call table::pagination_header(bags, navigator, "#bag-list") %}
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
<table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
||||||
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
||||||
<tr>
|
<tr>
|
||||||
{% call table::sortable_header("Roaster", "roaster", navigator, "#bag-list") %} {%
|
{% call table::sortable_header("Roaster", "roaster", navigator, "#bag-list") %} {%
|
||||||
|
|
@ -110,13 +110,13 @@
|
||||||
<tbody class="divide-y divide-amber-200/70">
|
<tbody class="divide-y divide-amber-200/70">
|
||||||
{% for bag in bags.items %}
|
{% for bag in bags.items %}
|
||||||
<tr class="bg-amber-50/40 transition hover:bg-amber-50">
|
<tr class="bg-amber-50/40 transition hover:bg-amber-50">
|
||||||
<td class="px-4 py-3 whitespace-nowrap font-medium text-stone-600">
|
<td data-label="Roaster" class="px-4 py-3 whitespace-nowrap font-medium text-stone-600">
|
||||||
{{ bag.roaster_name }}
|
{{ bag.roaster_name }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ bag.roast_name }}</td>
|
<td data-label="Roast" class="px-4 py-3 whitespace-nowrap">{{ bag.roast_name }}</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ bag.amount }}g</td>
|
<td data-label="Weight" class="px-4 py-3 whitespace-nowrap">{{ bag.amount }}g</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ bag.created_at }}</td>
|
<td data-label="Added" class="px-4 py-3 whitespace-nowrap">{{ bag.created_at }}</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ bag.finished_at }}</td>
|
<td data-label="Finished" class="px-4 py-3 whitespace-nowrap">{{ bag.finished_at }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
{% call table::pagination_header(brews, navigator, "#brew-list") %}
|
{% call table::pagination_header(brews, navigator, "#brew-list") %}
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
<table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
||||||
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" class="px-4 py-3">Coffee</th>
|
<th scope="col" class="px-4 py-3">Coffee</th>
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
<tbody class="divide-y divide-amber-200/70">
|
<tbody class="divide-y divide-amber-200/70">
|
||||||
{% for brew in brews.items %}
|
{% for brew in brews.items %}
|
||||||
<tr class="bg-amber-50/40 transition hover:bg-amber-50">
|
<tr class="bg-amber-50/40 transition hover:bg-amber-50">
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Coffee" class="px-4 py-3 whitespace-nowrap">
|
||||||
<div class="font-medium text-stone-800">
|
<div class="font-medium text-stone-800">
|
||||||
<a href="/roasters/{{ brew.roaster_slug }}/roasts/{{ brew.roast_slug }}" class="hover:text-amber-700 hover:underline">
|
<a href="/roasters/{{ brew.roaster_slug }}/roasts/{{ brew.roast_slug }}" class="hover:text-amber-700 hover:underline">
|
||||||
{{ brew.roast_name }}
|
{{ brew.roast_name }}
|
||||||
|
|
@ -34,24 +34,24 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Grind" class="px-4 py-3 whitespace-nowrap">
|
||||||
<div>{{ brew.grind_setting }}</div>
|
<div>{{ brew.grind_setting }}</div>
|
||||||
<div class="text-xs text-stone-500">{{ brew.grinder_name }}</div>
|
<div class="text-xs text-stone-500">{{ brew.grinder_name }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Recipe" class="px-4 py-3 whitespace-nowrap">
|
||||||
<div>{{ brew.coffee_weight }} / {{ brew.water_volume }}</div>
|
<div>{{ brew.coffee_weight }} / {{ brew.water_volume }}</div>
|
||||||
<div class="text-xs text-stone-500 font-mono">{{ brew.ratio }}</div>
|
<div class="text-xs text-stone-500 font-mono">{{ brew.ratio }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ brew.water_temp }}</td>
|
<td data-label="Temp" class="px-4 py-3 whitespace-nowrap">{{ brew.water_temp }}</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Brewer" class="px-4 py-3 whitespace-nowrap">
|
||||||
<div>{{ brew.brewer_name }}</div>
|
<div>{{ brew.brewer_name }}</div>
|
||||||
{% if let Some(fp_name) = brew.filter_paper_name %}
|
{% if let Some(fp_name) = brew.filter_paper_name %}
|
||||||
<div class="text-xs text-stone-500">{{ fp_name }}</div>
|
<div class="text-xs text-stone-500">{{ fp_name }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap text-stone-500">{{ brew.created_at }}</td>
|
<td data-label="Date" class="px-4 py-3 whitespace-nowrap text-stone-500">{{ brew.created_at }}</td>
|
||||||
{% if is_authenticated %}
|
{% if is_authenticated %}
|
||||||
<td class="px-4 py-3 text-right">
|
<td data-label="" class="px-4 py-3 text-right">
|
||||||
<form class="inline" data-on:submit="@post('/api/v1/brews?{{ navigator.query() }}', {contentType: 'form', responseOverrides: {selector: '#brew-list', mode: 'replace'}})">
|
<form class="inline" data-on:submit="@post('/api/v1/brews?{{ navigator.query() }}', {contentType: 'form', responseOverrides: {selector: '#brew-list', mode: 'replace'}})">
|
||||||
<input type="hidden" name="bag_id" value="{{ brew.bag_id }}" />
|
<input type="hidden" name="bag_id" value="{{ brew.bag_id }}" />
|
||||||
<input type="hidden" name="coffee_weight" value="{{ brew.coffee_weight_raw }}" />
|
<input type="hidden" name="coffee_weight" value="{{ brew.coffee_weight_raw }}" />
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
{% call table::pagination_header(gear, navigator, "#gear-list") %}
|
{% call table::pagination_header(gear, navigator, "#gear-list") %}
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
<table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
||||||
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
||||||
<tr>
|
<tr>
|
||||||
{% call table::sortable_header("Category", "category", navigator, "#gear-list") %}
|
{% call table::sortable_header("Category", "category", navigator, "#gear-list") %}
|
||||||
|
|
@ -28,22 +28,22 @@
|
||||||
<tbody class="divide-y divide-amber-200/70">
|
<tbody class="divide-y divide-amber-200/70">
|
||||||
{% for item in gear.items %}
|
{% for item in gear.items %}
|
||||||
<tr class="bg-amber-50/40 transition hover:bg-amber-50">
|
<tr class="bg-amber-50/40 transition hover:bg-amber-50">
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Category" class="px-4 py-3 whitespace-nowrap">
|
||||||
<span class="inline-flex rounded-full bg-amber-100 px-2 py-1 text-xs font-medium text-amber-800">
|
<span class="inline-flex rounded-full bg-amber-100 px-2 py-1 text-xs font-medium text-amber-800">
|
||||||
{{ item.category_label }}
|
{{ item.category_label }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap font-medium text-stone-600">
|
<td data-label="Make" class="px-4 py-3 whitespace-nowrap font-medium text-stone-600">
|
||||||
{{ item.make }}
|
{{ item.make }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Model" class="px-4 py-3 whitespace-nowrap">
|
||||||
{{ item.model }}
|
{{ item.model }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td data-label="Added" class="px-4 py-3 whitespace-nowrap">
|
||||||
{{ item.created_at }}
|
{{ item.created_at }}
|
||||||
</td>
|
</td>
|
||||||
{% if is_authenticated %}
|
{% if is_authenticated %}
|
||||||
<td class="px-4 py-3 text-right">
|
<td data-label="" class="px-4 py-3 text-right">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-flex h-8 w-8 items-center justify-center rounded-md text-stone-500 transition hover:text-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
|
class="inline-flex h-8 w-8 items-center justify-center rounded-md text-stone-500 transition hover:text-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<section class="rounded-lg border border-amber-300 bg-amber-100/80 shadow-sm">
|
<section class="rounded-lg border border-amber-300 bg-amber-100/80 shadow-sm">
|
||||||
{% call table::pagination_header(roasts, navigator, "#roast-list") %}
|
{% call table::pagination_header(roasts, navigator, "#roast-list") %}
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
<table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
||||||
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
||||||
<tr>
|
<tr>
|
||||||
{% call table::sortable_header("Added", "created-at", navigator, "#roast-list") %} {%
|
{% call table::sortable_header("Added", "created-at", navigator, "#roast-list") %} {%
|
||||||
|
|
@ -36,10 +36,10 @@
|
||||||
data-sort-producer="{{ roast.producer }}"
|
data-sort-producer="{{ roast.producer }}"
|
||||||
class="bg-amber-50/40 transition hover:bg-amber-50"
|
class="bg-amber-50/40 transition hover:bg-amber-50"
|
||||||
>
|
>
|
||||||
<td class="whitespace-nowrap px-4 py-3 text-xs font-medium text-stone-600">
|
<td data-label="Added" class="whitespace-nowrap px-4 py-3 text-xs font-medium text-stone-600">
|
||||||
{{ roast.created_at }}
|
{{ roast.created_at }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3">
|
<td data-label="Roast" class="px-4 py-3">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<a
|
<a
|
||||||
href="{{ roast.detail_path }}"
|
href="{{ roast.detail_path }}"
|
||||||
|
|
@ -48,10 +48,10 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ roast.roaster_label }}</td>
|
<td data-label="Roaster" class="px-4 py-3 whitespace-nowrap">{{ roast.roaster_label }}</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ roast.origin }}</td>
|
<td data-label="Origin" class="px-4 py-3 whitespace-nowrap">{{ roast.origin }}</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ roast.producer }}</td>
|
<td data-label="Producer" class="px-4 py-3 whitespace-nowrap">{{ roast.producer }}</td>
|
||||||
<td class="px-4 py-3">
|
<td data-label="Notes" class="px-4 py-3">
|
||||||
{% if roast.tasting_notes.is_empty() %}
|
{% if roast.tasting_notes.is_empty() %}
|
||||||
<span class="text-xs text-stone-500">No tasting notes yet.</span>
|
<span class="text-xs text-stone-500">No tasting notes yet.</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% if is_authenticated %}
|
{% if is_authenticated %}
|
||||||
<td class="px-4 py-3 text-right">
|
<td data-label="" class="px-4 py-3 text-right">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-flex h-8 w-8 items-center justify-center rounded-md text-stone-500 transition hover:text-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
|
class="inline-flex h-8 w-8 items-center justify-center rounded-md text-stone-500 transition hover:text-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<section class="rounded-lg border border-amber-300 bg-amber-100/80 shadow-sm">
|
<section class="rounded-lg border border-amber-300 bg-amber-100/80 shadow-sm">
|
||||||
{% call table::pagination_header(roasters, navigator, "#roaster-list") %}
|
{% call table::pagination_header(roasters, navigator, "#roaster-list") %}
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
<table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
|
||||||
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
|
||||||
<tr>
|
<tr>
|
||||||
{% call table::sortable_header("Added", "created-at", navigator, "#roaster-list") %} {%
|
{% call table::sortable_header("Added", "created-at", navigator, "#roaster-list") %} {%
|
||||||
|
|
@ -37,19 +37,19 @@
|
||||||
data-sort-city="{{ roaster.city }}"
|
data-sort-city="{{ roaster.city }}"
|
||||||
class="bg-amber-50/40 transition hover:bg-amber-50"
|
class="bg-amber-50/40 transition hover:bg-amber-50"
|
||||||
>
|
>
|
||||||
<td class="whitespace-nowrap px-4 py-3 text-xs font-medium text-stone-600">
|
<td data-label="Added" class="whitespace-nowrap px-4 py-3 text-xs font-medium text-stone-600">
|
||||||
{{ roaster.created_at }}
|
{{ roaster.created_at }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3">
|
<td data-label="Name" class="px-4 py-3">
|
||||||
<a
|
<a
|
||||||
href="{{ roaster.detail_path }}"
|
href="{{ roaster.detail_path }}"
|
||||||
class="font-semibold text-amber-800 hover:text-amber-600"
|
class="font-semibold text-amber-800 hover:text-amber-600"
|
||||||
>{{ roaster.name }}</a
|
>{{ roaster.name }}</a
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ roaster.country }}</td>
|
<td data-label="Country" class="px-4 py-3 whitespace-nowrap">{{ roaster.country }}</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">{{ roaster.city }}</td>
|
<td data-label="City" class="px-4 py-3 whitespace-nowrap">{{ roaster.city }}</td>
|
||||||
<td class="px-4 py-3">
|
<td data-label="Homepage" class="mobile-hidden px-4 py-3">
|
||||||
{% if roaster.has_homepage %}
|
{% if roaster.has_homepage %}
|
||||||
<a
|
<a
|
||||||
class="inline-flex items-center justify-center rounded-md border border-amber-400 bg-amber-200/50 p-2 text-amber-800 transition hover:border-amber-500 hover:text-amber-900"
|
class="inline-flex items-center justify-center rounded-md border border-amber-400 bg-amber-200/50 p-2 text-amber-800 transition hover:border-amber-500 hover:text-amber-900"
|
||||||
|
|
@ -73,9 +73,9 @@
|
||||||
<span class="text-stone-400">—</span>
|
<span class="text-stone-400">—</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-sm text-stone-600">{{ roaster.notes }}</td>
|
<td data-label="Notes" class="mobile-hidden px-4 py-3 text-sm text-stone-600">{{ roaster.notes }}</td>
|
||||||
{% if is_authenticated %}
|
{% if is_authenticated %}
|
||||||
<td class="px-4 py-3 text-right">
|
<td data-label="" class="px-4 py-3 text-right">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-flex h-8 w-8 items-center justify-center rounded-md text-stone-500 transition hover:text-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
|
class="inline-flex h-8 w-8 items-center justify-center rounded-md text-stone-500 transition hover:text-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,59 @@ a {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Responsive tables: convert rows to cards on mobile */
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.responsive-table thead {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table tbody {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table tr {
|
||||||
|
display: block;
|
||||||
|
padding: 1rem;
|
||||||
|
border-bottom: 1px solid rgba(217, 169, 55, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table tr:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table td {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
white-space: normal;
|
||||||
|
font-size: 0.875rem; /* normalize all values to text-sm */
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table td::before {
|
||||||
|
content: attr(data-label);
|
||||||
|
flex-shrink: 0;
|
||||||
|
min-width: 5.5rem;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #78350f; /* amber-900 */
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table td[data-label=""]::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table td[data-label=""] {
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-table td.mobile-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Desktop: alternating cards with central line */
|
/* Desktop: alternating cards with central line */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.timeline-heading {
|
.timeline-heading {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue