Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Use anchors on home view for better accesibility
Thomas Scholtes committed 9 months ago
commit 0936d7f9ff2630e9713bd4f41f5c65a7611aece0
parent 1a5e702
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()}`;
+
}