Radish alpha
r
Radicle desktop app
Radicle
Git (anonymous pull)
Log in to clone via SSH
Use anchors on home view for better accesibility
Thomas Scholtes committed 10 months ago
commit 0936d7f9ff2630e9713bd4f41f5c65a7611aece0
parent 1a5e702158332e15efa9d4ecc4895560e1197710
4 files changed +106 -41
modified public/index.css
@@ -22,6 +22,27 @@ body {
  background-color: var(--color-background-default);
}

+
a,
+
a:link,
+
a:visited,
+
a:hover,
+
a:active,
+
a:focus {
+
  color: inherit;
+
  text-decoration: none;
+
  background: transparent;
+
  cursor: pointer;
+
}
+

+
a {
+
  display: inline;
+
  font-weight: inherit;
+
  font-style: inherit;
+
  font-size: inherit;
+
  line-height: inherit;
+
  font-family: inherit;
+
}
+

::selection {
  background: var(--color-fill-yellow);
  color: var(--color-foreground-black);
modified src/components/HomeSidebar.svelte
@@ -27,7 +27,6 @@
    align-items: center;
    gap: 0.5rem;
    background-color: var(--color-background-float);
-
    clip-path: var(--1px-corner-fill);
    display: flex;
    font-size: var(--font-size-small);
    justify-content: space-between;
@@ -54,65 +53,58 @@
      styleFlexDirection="column"
      styleGap="2px"
      styleBackgroundColor="var(--color-background-float)">
-
      <!-- svelte-ignore a11y_click_events_have_key_events -->
-
      <!-- svelte-ignore a11y_no_static_element_interactions -->
-
      <div
+
      <a
+
        tabindex="0"
        class="tab txt-small"
        class:active={activeTab === "all"}
-
        onclick={() => router.push({ resource: "home", activeTab: "all" })}>
+
        href={router.routeToPath({
+
          resource: "home",
+
          activeTab: "all",
+
        })}>
        <div class="global-flex"><Icon name="repo" />Repositories</div>
        <div class="global-counter">
          {repoCount.total}
        </div>
-
      </div>
-
      <!-- svelte-ignore a11y_click_events_have_key_events -->
-
      <!-- svelte-ignore a11y_no_static_element_interactions -->
-
      <div
+
      </a>
+
      <a
        class="tab"
        class:active={activeTab === "delegate"}
-
        onclick={() =>
-
          router.push({
-
            resource: "home",
-
            activeTab: "delegate",
-
          })}>
+
        href={router.routeToPath({
+
          resource: "home",
+
          activeTab: "delegate",
+
        })}>
        <div class="global-flex">
          <Icon name="delegate" />
          <div>Delegate</div>
        </div>
        <div class="global-counter">{repoCount.delegate}</div>
-
      </div>
-
      <!-- svelte-ignore a11y_click_events_have_key_events -->
-
      <!-- svelte-ignore a11y_no_static_element_interactions -->
-
      <div
+
      </a>
+
      <a
        class="tab"
        class:active={activeTab === "contributor"}
-
        onclick={() =>
-
          router.push({
-
            resource: "home",
-
            activeTab: "contributor",
-
          })}>
+
        href={router.routeToPath({
+
          resource: "home",
+
          activeTab: "contributor",
+
        })}>
        <div class="global-flex">
          <Icon name="user" />
          <div>Contributor</div>
        </div>
        <div class="global-counter">{repoCount.contributor}</div>
-
      </div>
-
      <!-- svelte-ignore a11y_click_events_have_key_events -->
-
      <!-- svelte-ignore a11y_no_static_element_interactions -->
-
      <div
+
      </a>
+
      <a
        class="tab"
        class:active={activeTab === "private"}
-
        onclick={() =>
-
          router.push({
-
            resource: "home",
-
            activeTab: "private",
-
          })}>
+
        href={router.routeToPath({
+
          resource: "home",
+
          activeTab: "private",
+
        })}>
        <div class="global-flex">
          <Icon name="lock" />
          <div>Private</div>
        </div>
        <div class="global-counter">{repoCount.private}</div>
-
      </div>
+
      </a>
    </Border>
  </div>

modified src/lib/router.ts
@@ -1,4 +1,9 @@
+
import {
+
  homeRouteToPath as homeRouteToPath,
+
  homeUrlToRoute,
+
} from "@app/views/home/router";
import { repoRouteToPath, repoUrlToRoute } from "@app/views/repo/router";
+
import { on } from "svelte/events";
import { get, writable } from "svelte/store";

import * as mutexExecutor from "@app/lib/mutexExecutor";
@@ -50,7 +55,27 @@ async function navigateToUrl(
  }
}

-
window.addEventListener("popstate", () => loadFromLocation());
+
const offPopstate = on(window, "popstate", () => loadFromLocation());
+

+
const offNavigateAnchor = on(document, "click", e => {
+
  const [anchor] = e
+
    .composedPath()
+
    .flatMap(target => (target instanceof HTMLAnchorElement ? [target] : []));
+
  if (anchor && anchor.getAttribute("href")?.startsWith("/")) {
+
    e.preventDefault();
+
    void navigateToUrl(
+
      "push",
+
      new URL(anchor.getAttribute("href") ?? "", window.location.href),
+
    );
+
  }
+
});
+

+
if (import.meta.hot) {
+
  import.meta.hot.dispose(() => {
+
    offPopstate();
+
    offNavigateAnchor();
+
  });
+
}

const loadExecutor = mutexExecutor.create();

@@ -100,13 +125,12 @@ function urlToRoute(url: URL): Route | null {
  const segments = url.pathname.substring(1).split("/");
  const resource = segments.shift();

+
  const homeRoute = homeUrlToRoute(url);
+
  if (homeRoute) {
+
    return homeRoute;
+
  }
+

  switch (resource) {
-
    case "": {
-
      return {
-
        resource: "home",
-
        activeTab: "all",
-
      };
-
    }
    case "repos": {
      return repoUrlToRoute(segments, url.searchParams);
    }
@@ -118,7 +142,7 @@ function urlToRoute(url: URL): Route | null {

export function routeToPath(route: Route): string {
  if (route.resource === "home") {
-
    return "/";
+
    return homeRouteToPath(route);
  } else if (
    route.resource === "repo.home" ||
    route.resource === "repo.createIssue" ||
modified src/views/home/router.ts
@@ -2,10 +2,19 @@ import type { Config } from "@bindings/config/Config";
import type { RepoCount } from "@bindings/repo/RepoCount";
import type { RepoInfo } from "@bindings/repo/RepoInfo";

+
import z from "zod";
+

import { invoke } from "@app/lib/invoke";

export type HomeReposTab = "all" | "delegate" | "private" | "contributor";

+
const homeReposTabSchema = z.union([
+
  z.literal("all"),
+
  z.literal("delegate"),
+
  z.literal("private"),
+
  z.literal("contributor"),
+
]);
+

export interface HomeRoute {
  resource: "home";
  activeTab: HomeReposTab;
@@ -56,3 +65,22 @@ export async function loadHome(route: HomeRoute): Promise<LoadedHomeRoute> {
    },
  };
}
+

+
export function homeUrlToRoute(url: URL): HomeRoute | undefined {
+
  if (url.pathname === "/") {
+
    return {
+
      resource: "home",
+
      activeTab: homeReposTabSchema
+
        .catch(() => "all" as const)
+
        .parse(url.searchParams.get("tab")),
+
    };
+
  }
+
}
+

+
export function homeRouteToPath(route: HomeRoute): string {
+
  const searchParams = new URLSearchParams();
+
  if (route.activeTab !== "all") {
+
    searchParams.append("tab", route.activeTab);
+
  }
+
  return `/?${searchParams.toString()}`;
+
}