Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Add repository search, list pagination, and theme/a11y polish

5cab7b18548e5263c01549cb61415fd7777d1758 · Keenan Nemetz · 15d ago · parent 0b26547e

Add repository search, list pagination, and theme/a11y polish

The chrome and the index page search repository names and descriptions after the same read filter, so a private repository cannot appear. Issues and changes paginate at 25 rows with filters and HTMX navigation preserved.

Polish from the UI plan: a light token block follows prefers-color-scheme, a skip link and focus-visible outlines help keyboard users, panels scroll horizontally on narrow screens, and the empty index/search states explain what is visible. Also fixes a flaky key assertion in the admin users test.

server/web/static/vole.css +70

@@ -1633,3 +1633,73 @@ form.htmx-request .label-tokens { opacity: 0.6; }
1633 1633 .danger-zone h3 { margin: 14px 0 4px; }
1634 1634 .state.active { color: var(--good); }
1635 1635 .state.retired { color: var(--fg-faint); }
1636
1637 /* Global repository search lives in the chrome on wide screens; the index page
1638 keeps its own visible form so the control is still reachable on mobile. */
1639 .topsearch { margin-left: auto; }
1640 .topsearch input[type="search"] { width: 12rem; max-width: 28vw; }
1641 .topright { margin-left: 0; }
1642 @media (max-width: 720px) {
1643 .topsearch { display: none; }
1644 .topright { margin-left: auto; }
1645 }
1646
1647 /* Keyboard users get out of the chrome before the tabs. */
1648 .skip-link {
1649 position: absolute;
1650 left: -999px;
1651 top: 8px;
1652 z-index: 100;
1653 padding: 6px 10px;
1654 background: var(--bg-raised);
1655 border: 1px solid var(--accent);
1656 border-radius: var(--radius);
1657 }
1658 .skip-link:focus { left: 12px; }
1659
1660 a:focus-visible,
1661 button:focus-visible,
1662 select:focus-visible,
1663 input:focus-visible,
1664 textarea:focus-visible {
1665 outline: 2px solid var(--accent);
1666 outline-offset: 2px;
1667 }
1668
1669 @media (prefers-reduced-motion: reduce) {
1670 *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
1671 }
1672
1673 @media (max-width: 720px) {
1674 .panel { overflow-x: auto; }
1675 .panel > table { min-width: 34rem; }
1676 }
1677
1678 /* A light theme is the same layout with a second set of tokens. It follows the
1679 operating system until a real theme switch exists. */
1680 @media (prefers-color-scheme: light) {
1681 :root {
1682 color-scheme: light;
1683 --bg: #f7f7f8;
1684 --bg-panel: #ffffff;
1685 --bg-raised: #f1f2f4;
1686 --bg-hover: #eceef2;
1687 --bg-active: #e4e7ec;
1688 --border: #dfe2e7;
1689 --border-strong: #c7ccd5;
1690 --fg: #1b1e23;
1691 --fg-muted: #5d646e;
1692 --fg-faint: #858c96;
1693 --accent: #4f5bd5;
1694 --accent-fg: #ffffff;
1695 --accent-soft: rgba(79, 91, 213, 0.12);
1696 --good: #247f55;
1697 --good-soft: rgba(36, 127, 85, 0.12);
1698 --bad: #bd3b3b;
1699 --bad-soft: rgba(189, 59, 59, 0.10);
1700 --warn: #946200;
1701 --warn-soft: rgba(148, 98, 0, 0.12);
1702 }
1703 }
1704 .pager { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 12px 0; }
1705 .pager .button { font-size: 12px; }