feat(ui): mejorar estilos y estructura de componentes en el dashboard

Se ajustan los estilos y la estructura de varios componentes en el dashboard, incluyendo ExportDropdown, ResearcherCard, SwordProfileSelect y SyncButton, para mejorar la presentación y la responsividad. Se añade soporte para clases personalizadas en SyncButton y se integra el nuevo sistema de exportación en GroupResultsPage.
This commit is contained in:
Alexis
2026-06-02 10:44:51 +02:00
parent ddab663d50
commit 6603ddfe23
6 changed files with 51 additions and 54 deletions
@@ -49,19 +49,20 @@ export function ExportDropdown({
}
return (
<div className="flex flex-wrap items-center justify-end gap-2 sm:flex-nowrap">
<div className="mx-auto flex w-full max-w-[440px] flex-col items-stretch gap-2 sm:mx-0 sm:w-auto sm:max-w-none sm:flex-row sm:items-center sm:justify-end">
<SwordProfileSelect
id="dashboard-export-destination"
value={exportDestination}
onChange={onExportDestinationChange}
includeZip
className="w-full"
/>
<button
type="button"
onClick={handleDownload}
disabled={isBusy || nothingToDownload}
className="inline-flex items-center gap-2 rounded-lg border border-surface-border-strong bg-surface-primary px-[18px] py-2.5 text-sm font-medium text-ink-primary transition-colors enabled:hover:bg-surface-secondary disabled:cursor-not-allowed disabled:opacity-70"
className="inline-flex w-full items-center justify-center gap-2 rounded-lg border border-surface-border-strong bg-surface-primary px-[18px] py-2.5 text-sm font-medium text-ink-primary transition-colors enabled:hover:bg-surface-secondary disabled:cursor-not-allowed disabled:opacity-70 sm:w-auto"
>
{isBusy ? (
<Spinner size={15} />
@@ -44,7 +44,7 @@ export function ResearcherCard({ researcher, actions = null }) {
</div>
{actions && (
<div className="ml-auto flex shrink-0 flex-col items-end gap-2.5">
<div className="flex w-full flex-col items-stretch gap-2.5 md:ml-auto md:w-auto md:shrink-0 md:items-end">
{actions}
</div>
)}
@@ -48,28 +48,32 @@ export function SwordProfileSelect({
return (
<div
ref={rootRef}
className={`flex items-center gap-2 text-sm ${className}`.trim()}
className={`flex w-full flex-col items-start gap-1.5 text-sm sm:w-auto sm:flex-row sm:items-center sm:gap-2 ${className}`.trim()}
>
<span className="whitespace-nowrap text-ink-tertiary">Destino:</span>
<div className="relative">
<span className="w-full whitespace-nowrap text-center text-ink-tertiary sm:w-auto sm:text-left">
Destino:
</span>
<div className="relative w-full sm:w-auto sm:flex-none">
<button
type="button"
id={id}
aria-haspopup="listbox"
aria-expanded={open}
onClick={() => setOpen((o) => !o)}
className="inline-flex min-w-44 items-center gap-2 rounded-lg border border-surface-border-strong bg-surface-primary px-3 py-2.5 text-sm font-medium text-ink-primary transition-colors hover:bg-surface-secondary"
className="relative inline-flex w-full min-w-44 items-center justify-center rounded-lg border border-surface-border-strong bg-surface-primary px-3 py-2.5 pr-10 text-sm font-medium text-ink-primary transition-colors hover:bg-surface-secondary sm:w-auto"
>
<ExportProfileIcon profile={selected.value} size={20} />
<span className="truncate">{selected.label}</span>
<ChevronDownIcon className="ml-auto shrink-0" />
<span className="inline-flex min-w-0 items-center gap-2">
<ExportProfileIcon profile={selected.value} size={20} />
<span className="truncate text-center">{selected.label}</span>
</span>
<ChevronDownIcon className="pointer-events-none absolute right-3 top-1/2 shrink-0 -translate-y-1/2" />
</button>
{open && (
<div
role="listbox"
aria-labelledby={id}
className="absolute left-0 top-[calc(100%+6px)] z-50 min-w-80 overflow-hidden rounded-xl border border-surface-border-strong bg-surface-primary shadow-lg"
className="absolute left-0 top-[calc(100%+6px)] z-50 w-full min-w-0 overflow-hidden rounded-xl border border-surface-border-strong bg-surface-primary shadow-lg sm:min-w-80"
>
{options.map(({ value: optionValue, label, desc }, idx) => (
<button
@@ -91,7 +95,7 @@ export function SwordProfileSelect({
<div className="text-sm font-medium text-ink-primary">
{label}
</div>
<div className="whitespace-nowrap text-xs text-ink-tertiary">
<div className="text-xs text-ink-tertiary sm:whitespace-nowrap">
{desc}
</div>
</div>
@@ -5,7 +5,7 @@ import { Spinner } from "../ui/Spinner";
* Primary action button on the dashboard. Swaps icon + colour scheme
* depending on the sync lifecycle (idle → loading → success flash).
*/
export function SyncButton({ onClick, status = "idle" }) {
export function SyncButton({ onClick, status = "idle", className = "" }) {
const isLoading = status === "loading";
const isSuccess = status === "success";
@@ -20,7 +20,7 @@ export function SyncButton({ onClick, status = "idle" }) {
type="button"
onClick={onClick}
disabled={isLoading}
className={`inline-flex items-center gap-2 rounded-lg px-[18px] py-2.5 text-sm font-medium transition-colors disabled:cursor-not-allowed ${palette}`}
className={`inline-flex items-center justify-center gap-2 rounded-lg px-[18px] py-2.5 text-sm font-medium transition-colors disabled:cursor-not-allowed ${palette} ${className}`.trim()}
>
{isLoading ? (
<Spinner size={15} />