Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Add expand, collapse, expand all and collapse all buttons
Merged rudolfs opened 1 year ago

check check-e2e

๐Ÿ‘‰ Workflow runs ๐Ÿ‘‰ Branch on GitHub

5 files changed +122 -22 c4bef0e9 โ†’ 924130ce
modified src/components/Changeset.svelte
@@ -6,9 +6,10 @@
  interface Props {
    diff: Diff;
    repoId: string;
+
    expanded?: boolean;
  }

-
  const { diff }: Props = $props();
+
  const { diff, expanded = true }: Props = $props();
</script>

<style>
@@ -26,6 +27,7 @@
  {#each diff.files as file}
    <div class="diff">
      <FileDiff
+
        {expanded}
        filePath={"path" in file ? file.path : file.newPath}
        oldFilePath={"oldPath" in file ? file.oldPath : undefined}
        fileDiff={file.diff}
modified src/components/Changeset/FileDiff.svelte
@@ -11,6 +11,7 @@
    oldFilePath?: string | undefined;
    fileDiff: DiffContent;
    headerBadgeCaption: FileDiff["status"];
+
    expanded: boolean;
  }

  const {
@@ -18,6 +19,7 @@
    oldFilePath = undefined,
    fileDiff,
    headerBadgeCaption,
+
    expanded,
  }: Props = $props();

  function lineNumberR(line: Modification): string | number {
@@ -199,28 +201,46 @@
    padding-left: 0.5rem;
    color: var(--color-foreground-dim);
  }
+
  .added {
+
    color: var(--color-foreground-success);
+
    background-color: var(--color-fill-diff-green-light);
+
  }
+
  .deleted {
+
    color: var(--color-foreground-red);
+
    background-color: var(--color-fill-diff-red-light);
+
  }
+
  .moved,
+
  .copied {
+
    color: var(--color-foreground-dim);
+
    background: var(--color-fill-ghost);
+
  }
</style>

-
<File>
+
{#snippet styledPath(fullPath: string)}
+
  <!-- prettier-ignore -->
+
  <span class="txt-small" style:white-space="nowrap"><span style:color="var(--color-fill-gray)" style:font-weight="var(--font-weight-regular)">{fullPath.match(/^.*\/|/)?.values().next().value}</span><span style:font-weight="var(--font-weight-semibold)">{fullPath.split("/").slice(-1)}</span></span>
+
{/snippet}
+

+
<File {expanded}>
  {#snippet leftHeader()}
    {#if (headerBadgeCaption === "moved" || headerBadgeCaption === "copied") && oldFilePath}
      <span style="display: flex; align-items: center; flex-wrap: wrap;">
-
        {oldFilePath}
+
        {@render styledPath(filePath)}
        <span style:padding="0 0.5rem">โ†’</span>
-
        {filePath}
+
        {@render styledPath(filePath)}
      </span>
    {:else}
-
      {filePath}
+
      {@render styledPath(filePath)}
    {/if}

    {#if headerBadgeCaption === "added"}
-
      added
+
      <span class="global-counter added">added</span>
    {:else if headerBadgeCaption === "deleted"}
-
      deleted
+
      <span class="global-counter deleted">deleted</span>
    {:else if headerBadgeCaption === "moved"}
-
      moved
+
      <span class="global-counter moved">moved</span>
    {:else if headerBadgeCaption === "copied"}
-
      copied
+
      <span class="global-counter copied">copied</span>
    {/if}
  {/snippet}

modified src/components/File.svelte
@@ -1,13 +1,23 @@
<script lang="ts">
  import type { Snippet } from "svelte";

+
  import { tick } from "svelte";
+

+
  import Icon from "./Icon.svelte";
+
  import NakedButton from "./NakedButton.svelte";
+

  interface Props {
    sticky?: boolean;
    leftHeader: Snippet;
    children: Snippet;
+
    expanded: boolean;
  }

-
  const { sticky = true, leftHeader, children }: Props = $props();
+
  /* eslint-disable prefer-const */
+
  let { sticky = true, leftHeader, children, expanded }: Props = $props();
+
  /* eslint-enable prefer-const */
+

+
  let header: HTMLElement | undefined = $state();
</script>

<style>
@@ -15,7 +25,7 @@
    display: flex;
    align-items: center;
    height: 2.5rem;
-
    padding-left: 1rem;
+
    padding-left: 0.5rem;
    z-index: 2;
    font-size: var(--font-size-small);
    background-color: var(--color-background-default);
@@ -31,6 +41,9 @@
    top: 0;
    left: 0;
  }
+
  .header.collapsed {
+
    clip-path: var(--2px-corner-fill);
+
  }

  .sticky {
    position: sticky;
@@ -62,12 +75,26 @@
  }
</style>

-
<div class="header" class:sticky>
+
<div class="header" class:sticky class:collapsed={!expanded} bind:this={header}>
  <div class="left">
+
    <NakedButton
+
      stylePadding="0 4px"
+
      variant="ghost"
+
      onclick={async () => {
+
        expanded = !expanded;
+
        if (!expanded && header) {
+
          await tick();
+
          header.scrollIntoView({ behavior: "smooth", block: "nearest" });
+
        }
+
      }}>
+
      <Icon name={expanded ? "chevron-down" : "chevron-right"} />
+
    </NakedButton>
    {@render leftHeader()}
  </div>
</div>

-
<div class="container">
-
  {@render children()}
-
</div>
+
{#if expanded}
+
  <div class="container">
+
    {@render children()}
+
  </div>
+
{/if}
modified src/components/Icon.svelte
@@ -19,6 +19,7 @@
      | "chevron-down"
      | "chevron-right"
      | "clock"
+
      | "collapse"
      | "collapse-panel"
      | "comment"
      | "comment-checkmark"
@@ -28,6 +29,7 @@
      | "dashboard"
      | "delegate"
      | "diff"
+
      | "expand"
      | "expand-panel"
      | "eye"
      | "face"
@@ -256,6 +258,20 @@
    <path d="M7 7H8V8L7 8V7Z" />
    <path d="M6 6H7V7L6 7V6Z" />
    <path d="M5 5H6V6H5V5Z" />
+
  {:else if name === "collapse"}
+
    <path d="M7 5.5L8 5.5L8 4.5L7 4.5L7 5.5Z" />
+
    <path d="M6 4.5L7 4.5L7 3.5L6 3.5L6 4.5Z" />
+
    <path d="M9 4.5L9 1.5L7 1.5L7 4.5L9 4.5Z" />
+
    <path d="M11 3.5L11 2.5L5 2.5L5 3.5L11 3.5Z" />
+
    <path d="M10 4.5L10 3.5L9 3.5L9 4.5L10 4.5Z" />
+
    <path d="M9 5.5L9 4.5L8 4.5L8 5.5L9 5.5Z" />
+
    <path d="M9 10.5L8 10.5L8 11.5L9 11.5L9 10.5Z" />
+
    <path d="M10 11.5L9 11.5L9 12.5L10 12.5L10 11.5Z" />
+
    <path d="M7 11.5L7 14.5L9 14.5L9 11.5L7 11.5Z" />
+
    <path d="M5 12.5L5 13.5L11 13.5L11 12.5L5 12.5Z" />
+
    <path d="M6 11.5L6 12.5L7 12.5L8 12.5L8 11.5L7 11.5L6 11.5Z" />
+
    <path d="M7 10.5L7 11.5L8 11.5L8 10.5L7 10.5Z" />
+
    <path d="M2 7.5H14V8.5H2V7.5Z" />
  {:else if name === "collapse-panel"}
    <path d="M2 3.00002H3V13H2V3.00002Z" />
    <path d="M13 3.00002H14V6.00002H13V3.00002Z" />
@@ -416,6 +432,20 @@
    <path d="M7 4H8V9H7V4Z" />
    <path d="M5 6H10V7H5V6Z" />
    <path d="M5 10H10V11H5V10Z" />
+
  {:else if name === "expand"}
+
    <path d="M9 1.5H8V2.5H9V1.5Z" />
+
    <path d="M10 2.5H9V3.5H10V2.5Z" />
+
    <path d="M7 2.5V5.5H9V2.5H7Z" />
+
    <path d="M5 3.5V4.5H11V3.5H5Z" />
+
    <path d="M6 2.5V3.5H7V2.5H6Z" />
+
    <path d="M7 1.5V2.5H8V1.5H7Z" />
+
    <path d="M7 14.5H8V13.5H7V14.5Z" />
+
    <path d="M6 13.5H7V12.5H6V13.5Z" />
+
    <path d="M9 13.5V10.5H7V13.5H9Z" />
+
    <path d="M11 12.5V11.5H5V12.5H11Z" />
+
    <path d="M10 13.5V12.5H9H8V13.5H9H10Z" />
+
    <path d="M9 14.5V13.5H8V14.5H9Z" />
+
    <path d="M2 7.5H14V8.5H2V7.5Z" />
  {:else if name === "expand-panel"}
    <path d="M2 3.00002H3V13H2V3.00002Z" />
    <path d="M13 3.00002H14V5.00002H13V3.00002Z" />
modified src/components/Revision.svelte
@@ -28,6 +28,7 @@
  import NodeId from "@app/components/NodeId.svelte";
  import ThreadComponent from "@app/components/Thread.svelte";
  import Markdown from "./Markdown.svelte";
+
  import NakedButton from "./NakedButton.svelte";

  interface Props {
    rid: string;
@@ -48,6 +49,7 @@
  let hideDiscussion = $state(false);
  let hideReviews = $state(false);
  let topLevelReplyOpen = $state(false);
+
  let filesExpanded = $state(true);

  const threads = $derived(
    ((revision.discussion &&
@@ -385,18 +387,37 @@

<!-- svelte-ignore a11y_click_events_have_key_events -->
<div
-
  role="button"
-
  tabindex="0"
  class="txt-semibold global-flex"
-
  style:margin-bottom={hideChanges ? undefined : "1rem"}
-
  style:cursor="pointer"
-
  onclick={() => (hideChanges = !hideChanges)}>
-
  <Icon name={hideChanges ? "chevron-right" : "chevron-down"} />Changes
+
  style:margin-bottom={hideChanges ? undefined : "1rem"}>
+
  <div
+
    style:cursor="pointer"
+
    style:min-height="2rem"
+
    class="global-flex"
+
    role="button"
+
    tabindex="0"
+
    onclick={() => (hideChanges = !hideChanges)}>
+
    <Icon name={hideChanges ? "chevron-right" : "chevron-down"} />Changes
+
  </div>
+
  {#if !hideChanges}
+
    <div style:margin-left="auto">
+
      <NakedButton
+
        variant="ghost"
+
        onclick={() => (filesExpanded = !filesExpanded)}>
+
        {#if filesExpanded === true}
+
          <Icon name="collapse" />
+
          Collapse all
+
        {:else}
+
          <Icon name="expand" />
+
          Expand all
+
        {/if}
+
      </NakedButton>
+
    </div>
+
  {/if}
</div>
<div class:hide={hideChanges}>
  {#await loadHighlightedDiff(rid, revision.base, revision.head)}
    <span class="txt-small">Loadingโ€ฆ</span>
  {:then diff}
-
    <Changeset {diff} repoId={rid} />
+
    <Changeset {diff} repoId={rid} expanded={filesExpanded} />
  {/await}
</div>