feat(ui): mejorar la responsividad y estructura de PublicationsTable

Se ajustan los estilos en PublicationsTable para mejorar la responsividad en dispositivos móviles. Se modifica la estructura del componente para incluir un mensaje de estado cuando no se encuentran publicaciones y se optimizan los estilos de los elementos de entrada y botones.
This commit is contained in:
Alexis
2026-06-02 10:58:43 +02:00
parent 6603ddfe23
commit 35eef2ff90
@@ -258,7 +258,7 @@ export function PublicationsTable({
)}
</p>
</div>
<div className="flex flex-wrap items-center gap-2">
<div className="flex w-full flex-wrap items-center gap-2 sm:w-auto">
<button
type="button"
onClick={() => setFiltersOpen((o) => !o)}
@@ -282,7 +282,7 @@ export function PublicationsTable({
className={`transition-transform ${filtersOpen ? "rotate-180" : ""}`}
/>
</button>
<div className="relative">
<div className="relative w-full sm:w-auto">
<input
type="text"
placeholder="Filtrar publicaciones..."
@@ -291,7 +291,7 @@ export function PublicationsTable({
setFilter(e.target.value);
setPage(1);
}}
className="w-[220px] rounded-lg border border-surface-border-strong bg-surface-secondary py-2 pl-9 pr-3.5 text-[13px] text-ink-primary outline-none focus:border-brand-accent"
className="w-full rounded-lg border border-surface-border-strong bg-surface-secondary py-2 pl-9 pr-3.5 text-[13px] text-ink-primary outline-none focus:border-brand-accent sm:w-[220px]"
/>
<span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-ink-tertiary/70">
<SearchIcon />
@@ -366,7 +366,100 @@ export function PublicationsTable({
) : loading ? (
<LoadingState />
) : (
<table className="w-full border-collapse">
<>
<div className="md:hidden">
{filtered.length === 0 ? (
<p className="p-8 text-center text-sm text-ink-tertiary">
No se encontraron publicaciones con los filtros aplicados.
</p>
) : (
<>
<div className="border-b border-surface-border/60 bg-surface-secondary px-4 py-2.5">
<TriStateCheckbox
checked={pageSelectionStats.allChecked}
indeterminate={pageSelectionStats.anyChecked}
onChange={toggleCurrentPage}
ariaLabel="Seleccionar todas las publicaciones de esta página"
/>
</div>
<div>
{pageRows.map((pub, i) => {
const isSelected = selectedIds.has(pub.id);
return (
<article
key={pub.id}
className={`px-4 py-3.5 transition-colors ${
isSelected
? "bg-tag-article-bg/70 hover:bg-tag-article-bg"
: "hover:bg-surface-secondary/70"
} ${
i < pageRows.length - 1
? "border-b border-surface-border/60"
: ""
}`}
>
<div className="mb-2 flex items-start gap-2.5">
<TriStateCheckbox
checked={isSelected}
onChange={() => toggleRow(pub.id)}
ariaLabel={`Seleccionar publicación ${pub.title}`}
/>
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-start gap-1.5">
{isAuthenticated && pub.downloaded_by_me === false && (
<span
title="No descargada aún por ti"
className="mt-0.5 inline-flex shrink-0 items-center gap-0.5 rounded-full bg-brand-accent/10 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-brand-accent"
>
<SparkleIcon size={9} />
Nuevo
</span>
)}
<p className="text-[14px] font-medium leading-relaxed text-ink-primary">
{pub.title}
</p>
</div>
</div>
</div>
<div className="space-y-1.5 pl-6.5 text-[12px] text-ink-secondary">
<p>
<span className="font-medium text-ink-primary">Revista:</span>{" "}
{pub.journal || "—"}
</p>
<p>
<span className="font-medium text-ink-primary">Año:</span>{" "}
{pub.publication_year ?? "—"}
</p>
<p>
<span className="font-medium text-ink-primary">DOI:</span>{" "}
{pub.doi ? (
<a
href={`https://doi.org/${pub.doi}`}
target="_blank"
rel="noopener noreferrer"
className="break-all font-mono text-[11px] text-brand-accent hover:underline"
>
{pub.doi}
</a>
) : (
<span className="font-mono text-[11px] text-ink-tertiary">
</span>
)}
</p>
<div>
<Badge type={pub.type} />
</div>
</div>
</article>
);
})}
</div>
</>
)}
</div>
<table className="hidden w-full border-collapse md:table">
<thead>
<tr className="bg-surface-secondary">
<th
@@ -483,6 +576,7 @@ export function PublicationsTable({
)}
</tbody>
</table>
</>
)}
</div>