Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Prevent layout shifts when selecting an item in lists
Rūdolfs Ošiņš committed 1 year ago
commit 5845bf3cd19a66731ec7a5ab930730c1d920c27e
parent f777284
9 files changed +128 -117
modified public/index.css
@@ -111,6 +111,30 @@ body {
    0 calc(100% - 2px)
  );

+
  --1px-top-corner-fill: polygon(
+
    0 2px,
+
    2px 2px,
+
    2px 0,
+
    calc(100% - 2px) 0,
+
    calc(100% - 2px) 2px,
+
    100% 2px,
+
    100% calc(100% - 2px),
+
    100% 4px,
+
    100% 100%,
+
    0 100%
+
  );
+

+
  --1px-bottom-corner-fill: polygon(
+
    0 0,
+
    100% 0,
+
    100% calc(100% - 2px),
+
    calc(100% - 2px) calc(100% - 2px),
+
    calc(100% - 2px) 100%,
+
    2px 100%,
+
    2px calc(100% - 2px),
+
    0 calc(100% - 2px)
+
  );
+

  --2px-corner-fill: polygon(
    0 4px,
    2px 4px,
modified src/components/IssueSecondColumn.svelte
@@ -71,13 +71,7 @@
    display: flex;
    align-items: center;
    min-height: 2.5rem;
-
  }
-
  .issue-list {
-
    margin-top: 1rem;
-
    display: flex;
-
    flex-direction: column;
-
    gap: 2px;
-
    padding-bottom: 1rem;
+
    margin-bottom: 1rem;
  }
</style>

@@ -218,10 +212,17 @@
  </div>
{/if}

-
<div class="issue-list">
+
<Border
+
  variant={searchResults.length === 1 && searchInput !== ""
+
    ? "secondary"
+
    : "float"}
+
  styleFlexDirection="column"
+
  styleOverflow="hidden"
+
  styleGap="2px"
+
  styleAlignItems="center"
+
  styleJustifyContent="center">
  {#each searchResults as result}
    <IssueTeaser
-
      focussed={searchResults.length === 1 && searchInput !== ""}
      compact
      issue={result.obj.issue}
      {status}
@@ -230,24 +231,19 @@
  {/each}

  {#if searchResults.length === 0}
-
    <Border
-
      styleMinWidth="25rem"
-
      variant="ghost"
-
      styleAlignItems="center"
-
      styleJustifyContent="center">
-
      <div
-
        class="global-flex"
-
        style:height="74px"
-
        style:justify-content="center">
-
        <div class="txt-missing txt-small global-flex" style:gap="0.25rem">
-
          <Icon name="none" />
-
          {#if issues.length > 0 && searchResults.length === 0}
-
            No matching issues.
-
          {:else}
-
            No {status === "all" ? "" : status} issues.
-
          {/if}
-
        </div>
+
    <div
+
      class="global-flex"
+
      style:height="74px"
+
      style:justify-content="center"
+
      style:min-width="405px">
+
      <div class="txt-missing txt-small global-flex" style:gap="0.25rem">
+
        <Icon name="none" />
+
        {#if issues.length > 0 && searchResults.length === 0}
+
          No matching issues.
+
        {:else}
+
          No {status === "all" ? "" : status} issues.
+
        {/if}
      </div>
-
    </Border>
+
    </div>
  {/if}
-
</div>
+
</Border>
modified src/components/IssueTeaser.svelte
@@ -42,6 +42,7 @@
    align-items: center;
    gap: 0.25rem;
    min-height: 5rem;
+
    min-width: 405px;
    background-color: var(--color-background-float);
    padding: 1rem;
    cursor: pointer;
@@ -60,13 +61,13 @@
    margin-right: 1rem;
  }
  .issue-teaser:first-of-type {
-
    clip-path: var(--3px-top-corner-fill);
+
    clip-path: var(--1px-top-corner-fill);
  }
  .issue-teaser:last-of-type {
-
    clip-path: var(--3px-bottom-corner-fill);
+
    clip-path: var(--1px-bottom-corner-fill);
  }
  .issue-teaser:only-of-type {
-
    clip-path: var(--3px-corner-fill);
+
    clip-path: var(--1px-corner-fill);
  }
</style>

modified src/components/PatchTeaser.svelte
@@ -47,6 +47,7 @@
    justify-content: space-between;
    gap: 0.25rem;
    min-height: 5rem;
+
    min-width: 440px;
    background-color: var(--color-background-float);
    padding: 1rem;
    cursor: pointer;
@@ -65,13 +66,13 @@
    margin-right: 1rem;
  }
  .patch-teaser:first-of-type {
-
    clip-path: var(--3px-top-corner-fill);
+
    clip-path: var(--1px-top-corner-fill);
  }
  .patch-teaser:last-of-type {
-
    clip-path: var(--3px-bottom-corner-fill);
+
    clip-path: var(--1px-bottom-corner-fill);
  }
  .patch-teaser:only-of-type {
-
    clip-path: var(--3px-corner-fill);
+
    clip-path: var(--1px-corner-fill);
  }
</style>

modified src/views/repo/Issues.svelte
@@ -62,11 +62,6 @@
  .container {
    padding: 1rem 1rem 1rem 0;
  }
-
  .list {
-
    display: flex;
-
    flex-direction: column;
-
    gap: 2px;
-
  }
  .header {
    font-weight: var(--font-weight-medium);
    font-size: var(--font-size-medium);
@@ -141,35 +136,34 @@
      </div>
    </div>

-
    <div class="list">
+
    <Border
+
      variant={searchResults.length === 1 && searchInput !== ""
+
        ? "secondary"
+
        : "float"}
+
      styleFlexDirection="column"
+
      styleOverflow="hidden"
+
      styleGap="2px"
+
      styleAlignItems="center"
+
      styleJustifyContent="center">
      {#each searchResults as result}
-
        <IssueTeaser
-
          focussed={searchResults.length === 1 && searchInput !== ""}
-
          issue={result.obj.issue}
-
          rid={repo.rid}
-
          {status} />
+
        <IssueTeaser issue={result.obj.issue} rid={repo.rid} {status} />
      {/each}

      {#if searchResults.length === 0}
-
        <Border
-
          variant="ghost"
-
          styleAlignItems="center"
-
          styleJustifyContent="center">
-
          <div
-
            class="global-flex"
-
            style:height="74px"
-
            style:justify-content="center">
-
            <div class="txt-missing txt-small global-flex" style:gap="0.25rem">
-
              <Icon name="none" />
-
              {#if issues.length > 0 && searchResults.length === 0}
-
                No matching issues.
-
              {:else}
-
                No {status === "all" ? "" : status} issues.
-
              {/if}
-
            </div>
+
        <div
+
          class="global-flex"
+
          style:height="74px"
+
          style:justify-content="center">
+
          <div class="txt-missing txt-small global-flex" style:gap="0.25rem">
+
            <Icon name="none" />
+
            {#if issues.length > 0 && searchResults.length === 0}
+
              No matching issues.
+
            {:else}
+
              No {status === "all" ? "" : status} issues.
+
            {/if}
          </div>
-
        </Border>
+
        </div>
      {/if}
-
    </div>
+
    </Border>
  </div>
</Layout>
modified src/views/repo/Patch.svelte
@@ -325,13 +325,6 @@
    height: 2.5rem;
    width: 2.5rem;
  }
-
  .patch-list {
-
    margin-top: 1rem;
-
    display: flex;
-
    flex-direction: column;
-
    gap: 2px;
-
    padding-bottom: 1rem;
-
  }
  .content {
    padding: 1rem 1rem 1rem 0;
  }
@@ -389,7 +382,10 @@
  {/snippet}

  {#snippet secondColumn()}
-
    <div class="txt-regular txt-semibold global-flex" style:min-height="2.5rem">
+
    <div
+
      class="txt-regular txt-semibold global-flex"
+
      style:min-height="2.5rem"
+
      style:margin-bottom="1rem">
      <div class="global-flex" style:gap="4px">
        {project.data.name}
        <Icon name="chevron-right" />
@@ -502,10 +498,17 @@
        {/if}
      </div>
    {/if}
-
    <div class="patch-list">
+
    <Border
+
      variant={searchResults.length === 1 && searchInput !== ""
+
        ? "secondary"
+
        : "float"}
+
      styleFlexDirection="column"
+
      styleOverflow="hidden"
+
      styleGap="2px"
+
      styleAlignItems="center"
+
      styleJustifyContent="center">
      {#each searchResults as teaser}
        <PatchTeaser
-
          focussed={searchResults.length === 1 && searchInput !== ""}
          compact
          loadPatch={async (id: string) => {
            review = undefined;
@@ -518,27 +521,22 @@
      {/each}

      {#if searchResults.length === 0}
-
        <Border
-
          styleMinWidth="25rem"
-
          variant="ghost"
-
          styleAlignItems="center"
-
          styleJustifyContent="center">
-
          <div
-
            class="global-flex"
-
            style:height="74px"
-
            style:justify-content="center">
-
            <div class="txt-missing txt-small global-flex" style:gap="0.25rem">
-
              <Icon name="none" />
-
              {#if patchTeasers.length > 0 && searchResults.length === 0}
-
                No matching patches.
-
              {:else}
-
                No {status === undefined ? "" : status} patches.
-
              {/if}
-
            </div>
+
        <div
+
          class="global-flex"
+
          style:height="74px"
+
          style:min-width="440px"
+
          style:justify-content="center">
+
          <div class="txt-missing txt-small global-flex" style:gap="0.25rem">
+
            <Icon name="none" />
+
            {#if patchTeasers.length > 0 && searchResults.length === 0}
+
              No matching patches.
+
            {:else}
+
              No {status === undefined ? "" : status} patches.
+
            {/if}
          </div>
-
        </Border>
+
        </div>
      {/if}
-
    </div>
+
    </Border>
  {/snippet}

  {#if review}
modified src/views/repo/Patches.svelte
@@ -174,19 +174,20 @@
    </div>

    <div class="list">
-
      {#each searchResults as result}
-
        <PatchTeaser
-
          focussed={searchResults.length === 1 && searchInput !== ""}
-
          patch={result.obj.patch}
-
          rid={repo.rid}
-
          {status} />
-
      {/each}
-

-
      {#if searchResults.length === 0}
-
        <Border
-
          variant="ghost"
-
          styleAlignItems="center"
-
          styleJustifyContent="center">
+
      <Border
+
        variant={searchResults.length === 1 && searchInput !== ""
+
          ? "secondary"
+
          : "float"}
+
        styleFlexDirection="column"
+
        styleOverflow="hidden"
+
        styleGap="2px"
+
        styleAlignItems="center"
+
        styleJustifyContent="center">
+
        {#each searchResults as result}
+
          <PatchTeaser patch={result.obj.patch} rid={repo.rid} {status} />
+
        {/each}
+

+
        {#if searchResults.length === 0}
          <div
            class="global-flex"
            style:height="74px"
@@ -200,8 +201,8 @@
              {/if}
            </div>
          </div>
-
        </Border>
-
      {/if}
+
        {/if}
+
      </Border>
    </div>
  </div>
</Layout>
modified tests/e2e/repo/issue.spec.ts
@@ -10,9 +10,7 @@ test("navigate single issue", async ({ page }) => {
test("correct order of threads", async ({ page }) => {
  await page.goto("/repos");
  await page.getByRole("button", { name: "cobs" }).click();
-
  await page
-
    .getByRole("button", { name: "This title has **markdown**" })
-
    .click();
+
  await page.getByText("This title has **markdown**").click();
  const body = page.locator(".issue-body");
  await expect(body.getByText("This is a description")).toBeVisible();

@@ -43,10 +41,10 @@ test("creation of top level comments", async ({ page }) => {
    );
  await page.getByRole("button", { name: "icon-checkmark" }).click();
  await expect(
-
    page.getByText("Make sure that comment creation is working").last(),
-
  ).toBeVisible();
-
  await expect(
-
    page.getByRole("button", { name: "icon-issue Make sure that" }),
+
    page.getByRole("button", {
+
      name: "icon-issue Make sure that comment creation is working avatar palm opened 8faf9dc 6 months ago",
+
      exact: true,
+
    }),
  ).toBeVisible();
  await expect(
    page
modified tests/e2e/repos.spec.ts
@@ -3,9 +3,7 @@ import { expect, test } from "@tests/support/fixtures.js";
test("navigate to repo issues", async ({ page }) => {
  await page.goto("/repos");
  await page.getByRole("button", { name: "cobs" }).click();
-
  await page
-
    .getByRole("button", { name: "This title has **markdown**" })
-
    .click();
+
  await page.getByText("This title has **markdown**").click();
  await expect(
    page.getByText("This title has **markdown**").nth(1),
  ).toBeVisible();