search: pagination and scroll, add range counter, mobile version

This commit is contained in:
Pontoporeia
2026-07-03 16:53:16 +02:00
parent e607833b2e
commit 880d169e72
8 changed files with 378 additions and 116 deletions
+18 -10
View File
@@ -27,34 +27,42 @@ $paginationUrl = static function(int $targetPage) use ($baseParams): string {
$atFirst = $page <= 1;
$atLast = $page >= $totalPages;
/** Build HTMX attributes for a non-disabled pagination link. */
$hxAttrs = static function(string $url): string {
return 'hx-get="' . htmlspecialchars($url) . '"'
. ' hx-target="#search-results"'
. ' hx-swap="outerHTML"'
. ' hx-push-url="' . htmlspecialchars($url) . '"';
};
?>
<nav class="pagination-wrap" aria-label="Pagination">
<ul>
<li>
<a href="<?= $paginationUrl(1) ?>"
<li class="pagination-edge">
<a href="<?= $firstUrl = $paginationUrl(1) ?>"
class="pagination-btn<?= $atFirst ? ' disabled' : '' ?>"
<?= $atFirst ? 'aria-disabled="true" tabindex="-1"' : '' ?>
<?= $atFirst ? 'aria-disabled="true" tabindex="-1"' : $hxAttrs($firstUrl) ?>
aria-label="Première page">«</a>
</li>
<li>
<a href="<?= $paginationUrl(max(1, $page - 1)) ?>"
<a href="<?= $prevUrl = $paginationUrl(max(1, $page - 1)) ?>"
class="pagination-btn<?= $atFirst ? ' disabled' : '' ?>"
<?= $atFirst ? 'aria-disabled="true" tabindex="-1"' : '' ?>
<?= $atFirst ? 'aria-disabled="true" tabindex="-1"' : $hxAttrs($prevUrl) ?>
aria-label="Page précédente"></a>
</li>
<li class="pagination-info" aria-current="page">
<span class="page-current"><?= $page ?></span> / <?= $totalPages ?>
</li>
<li>
<a href="<?= $paginationUrl(min($totalPages, $page + 1)) ?>"
<a href="<?= $nextUrl = $paginationUrl(min($totalPages, $page + 1)) ?>"
class="pagination-btn<?= $atLast ? ' disabled' : '' ?>"
<?= $atLast ? 'aria-disabled="true" tabindex="-1"' : '' ?>
<?= $atLast ? 'aria-disabled="true" tabindex="-1"' : $hxAttrs($nextUrl) ?>
aria-label="Page suivante"></a>
</li>
<li>
<a href="<?= $paginationUrl($totalPages) ?>"
<li class="pagination-edge">
<a href="<?= $lastUrl = $paginationUrl($totalPages) ?>"
class="pagination-btn<?= $atLast ? ' disabled' : '' ?>"
<?= $atLast ? 'aria-disabled="true" tabindex="-1"' : '' ?>
<?= $atLast ? 'aria-disabled="true" tabindex="-1"' : $hxAttrs($lastUrl) ?>
aria-label="Dernière page">»</a>
</li>
</ul>
+63
View File
@@ -0,0 +1,63 @@
<?php
/**
* Search results fragment
*
* Renders the results header, grid, and pagination.
* Used both for the initial page load and for HTMX pagination swaps.
*
* Required variables:
* array $results
* int $totalItems
* int $totalPages
* int $page
* array $baseParams
* array $coverMap
* ?string $validationError
*/
?>
<div id="search-results">
<?php if ($validationError): ?>
<div class="search-error">⚠ <?= htmlspecialchars($validationError) ?></div>
<?php endif; ?>
<?php
$perPage = 15;
$from = ($page - 1) * $perPage + 1;
$to = min($page * $perPage, $totalItems);
?>
<output class="search-results-header" role="status">
<?php if ($totalItems > 0): ?>
<span class="search-results-range"><?= $from ?><?= $to ?> sur <?= $totalItems ?> résultat<?= $totalItems > 1 ? 's' : '' ?></span>
<span class="search-results-range--compact"><?= $from ?><?= $to ?> / <?= $totalItems ?></span>
<?php else: ?>
<span>0 résultat</span>
<?php endif; ?>
</output>
<?php if (!empty($results)): ?>
<ul class="results-grid">
<?php foreach ($results as $item): ?>
<?php $thumb = $coverMap[$item['id']] ?? null; ?>
<li><a href="/tfe?id=<?= (int)$item['id'] ?>" class="result-card">
<?php if ($thumb): ?>
<figure class="result-card__cover">
<img src="/media?path=<?= urlencode($thumb) ?>"
alt="Couverture — <?= htmlspecialchars($item['title']) ?>"
loading="lazy">
</figure>
<?php else: ?>
<div class="result-card__gradient"></div>
<?php endif; ?>
<span class="result-card__authors"><?= htmlspecialchars($item['authors'] ?? '') ?></span>
<span class="result-card__title"><?= htmlspecialchars($item['title']) ?></span>
<small class="result-card__meta"><?= htmlspecialchars($item['year']) ?><?php if (!empty($item['orientation'])): ?> · <?= htmlspecialchars($item['orientation']) ?><?php endif; ?></small>
</a></li>
<?php endforeach; ?>
</ul>
<?php include APP_ROOT . '/templates/partials/pagination.php'; ?>
<?php else: ?>
<p class="search-empty">Aucun résultat pour cette recherche.</p>
<?php endif; ?>
</div>