Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Make all popover and drop-down buttons consistent
Rūdolfs Ošiņš committed 11 months ago
commit ac7189a1e962d603d31b0dcaf3574c6455a4ffe4
parent 7d977f2
23 files changed +209 -55
modified src/components/Button.svelte
@@ -31,7 +31,8 @@
      `--button-color-3: var(--color-fill-${variant}-shade);` +
      // The ghost colors are called --color-fill-counter and --color-fill-counter-emphasized.
      `--button-color-4: var(--color-fill${variant === "ghost" ? "" : `-${variant}`}-counter);` +
-
      `--text-color: ${variant === "ghost" ? "var(--color-foreground-contrast)" : "var(--color-foreground-white)"}`,
+
      `--text-color: ${variant === "ghost" ? "var(--color-foreground-contrast)" : "var(--color-foreground-white)"};` +
+
      `--text-color-active: ${variant === "ghost" ? "var(--color-foreground-emphasized)" : "var(--color-foreground-white)"};`,
  );
</script>

@@ -119,7 +120,7 @@
    color: var(--color-foreground-disabled);
  }
  .container.active:not(.disabled) {
-
    color: var(--color-foreground-emphasized);
+
    color: var(--text-color-active);
  }

  .disabled .p1-3,
modified src/components/Changes.svelte
@@ -118,10 +118,15 @@
<div
  class="txt-semibold global-flex"
  style:margin-bottom={hideChanges ? undefined : "1rem"}>
-
  <NakedButton variant="ghost" onclick={() => (hideChanges = !hideChanges)}>
-
    <Icon name={hideChanges ? "chevron-right" : "chevron-down"} />
+
  <div class="global-flex">
+
    <NakedButton
+
      variant="ghost"
+
      onclick={() => (hideChanges = !hideChanges)}
+
      stylePadding="0 4px">
+
      <Icon name={hideChanges ? "chevron-right" : "chevron-down"} />
+
    </NakedButton>
    <div class="txt-semibold global-flex txt-regular">Changes</div>
-
  </NakedButton>
+
  </div>
  {#if !hideChanges}
    <div style:margin-left="auto">
      <NakedButton
modified src/components/CheckoutPatchButton.svelte
@@ -22,12 +22,21 @@
      return `rad patch checkout ${formatOid(patchId)}`;
    }
  });
+

+
  let popoverExpanded: boolean = $state(false);
</script>

-
<Popover popoverPositionRight="0" popoverPositionTop="3rem">
+
<Popover
+
  popoverPositionRight="0"
+
  popoverPositionTop="3rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
-
    <Button styleHeight="2.5rem" variant="secondary" {onclick}>
-
      <Icon name="checkout" />Checkout patch<Icon name="chevron-down" />
+
    <Button
+
      styleHeight="2.5rem"
+
      variant="secondary"
+
      {onclick}
+
      active={popoverExpanded}>
+
      <Icon name="checkout" />Checkout patch
    </Button>
  {/snippet}
  {#snippet popover()}
modified src/components/CheckoutRepoButton.svelte
@@ -10,12 +10,21 @@
  }

  const { rid }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

-
<Popover popoverPositionRight="0" popoverPositionTop="3rem">
+
<Popover
+
  popoverPositionRight="0"
+
  popoverPositionTop="3rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
-
    <Button styleHeight="2.5rem" variant="secondary" {onclick}>
-
      <Icon name="checkout" />Checkout repo<Icon name="chevron-down" />
+
    <Button
+
      styleHeight="2.5rem"
+
      variant="secondary"
+
      {onclick}
+
      active={popoverExpanded}>
+
      <Icon name="checkout" />Checkout repo
    </Button>
  {/snippet}

modified src/components/ConfirmClear.svelte
@@ -13,14 +13,21 @@
    subject: string;
  }

-
  /* eslint-disable prefer-const */
-
  let { clear, subject }: Props = $props();
-
  /* eslint-enable prefer-const */
+
  const { clear, subject }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

-
<Popover popoverPositionRight="0" popoverPositionTop="2.5rem">
+
<Popover
+
  popoverPositionRight="0"
+
  popoverPositionTop="2.5rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
-
    <NakedButton stylePadding="0 0.25rem" variant="ghost" {onclick}>
+
    <NakedButton
+
      stylePadding="0 0.25rem"
+
      variant="ghost"
+
      {onclick}
+
      active={popoverExpanded}>
      <Icon name="broom-double" />
    </NakedButton>
  {/snippet}
modified src/components/Discussion.svelte
@@ -94,12 +94,19 @@

<div style:margin={hideDiscussion ? "1.5rem 0" : "1.5rem 0 2.5rem 0"}>
  <div class="global-flex">
-
    <NakedButton
-
      variant="ghost"
-
      disabled={commentThreads.length === 0}
-
      onclick={() => (hideDiscussion = !hideDiscussion)}>
-
      <Icon name={hideDiscussion ? "chevron-right" : "chevron-down"} />
-
      <div class="txt-semibold global-flex txt-regular">
+
    <div class="global-flex">
+
      <NakedButton
+
        variant="ghost"
+
        stylePadding="0 4px"
+
        disabled={commentThreads.length === 0}
+
        onclick={() => (hideDiscussion = !hideDiscussion)}>
+
        <Icon name={hideDiscussion ? "chevron-right" : "chevron-down"} />
+
      </NakedButton>
+
      <div
+
        class="txt-semibold global-flex txt-regular"
+
        style:color={commentThreads.length === 0
+
          ? "var(--color-foreground-disabled)"
+
          : undefined}>
        Discussion <span style:font-weight="var(--font-weight-regular)">
          {sum(
            commentThreads.map(t => {
@@ -108,10 +115,11 @@
          )}
        </span>
      </div>
-
    </NakedButton>
+
    </div>
    <div style:margin-left="auto">
      <NakedButton
        variant="ghost"
+
        active={topLevelReplyOpen}
        onclick={async () => {
          if (hideDiscussion) {
            hideDiscussion = false;
modified src/components/Header.svelte
@@ -85,6 +85,7 @@
      <div class="global-flex" style:gap="0.25rem">
        <NakedButton
          variant="ghost"
+
          active={$activeRouteStore.resource === "home"}
          onclick={() => {
            void router.push({ resource: "home" });
          }}
modified src/components/Icon.svelte
@@ -23,6 +23,7 @@
      | "checkout"
      | "chevron-down"
      | "chevron-right"
+
      | "chevron-up"
      | "clock"
      | "collapse"
      | "collapse-panel"
@@ -298,6 +299,17 @@
    <path d="M7 10L8 10L8 11L7 11L7 10Z" />
    <path d="M9 8L10 8V9L9 9V8Z" />
    <path d="M8 9H9V10H8L8 9Z" />
+
  {:else if name === "chevron-up"}
+
    <path d="M7 6.5L7 5.5L8 5.5L8 6.5L7 6.5Z" />
+
    <path d="M6 7.5L6 6.5L7 6.5V7.5L6 7.5Z" />
+
    <path d="M5 8.5L5 7.5L6 7.5L6 8.5L5 8.5Z" />
+
    <path d="M4 9.5L4 8.5L5 8.5L5 9.5L4 9.5Z" />
+
    <path d="M3 10.5L3 9.5L4 9.5L4 10.5H3Z" />
+
    <path d="M12 10.5V9.5H13V10.5H12Z" />
+
    <path d="M11 9.5L11 8.5L12 8.5L12 9.5L11 9.5Z" />
+
    <path d="M10 8.5V7.5L11 7.5V8.5L10 8.5Z" />
+
    <path d="M8 6.5L8 5.5L9 5.5L9 6.5L8 6.5Z" />
+
    <path d="M9 7.5V6.5L10 6.5L10 7.5L9 7.5Z" />
  {:else if name === "clock"}
    <path d="M6 13H8V14H6V13Z" />
    <path d="M10 13H8V14H10V13Z" />
modified src/components/InfoButton.svelte
@@ -17,6 +17,8 @@
    config: Config;
  }
  const { config }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

<style>
@@ -35,10 +37,15 @@
  popoverId="popover-guide"
  popoverPadding="0"
  popoverPositionTop="2.5rem"
+
  bind:expanded={popoverExpanded}
  popoverPositionRight="-9.3rem">
  {#snippet toggle(onclick)}
-
    <NakedButton variant="ghost" {onclick} stylePadding="0 4px">
-
      <Icon name="info" />
+
    <NakedButton
+
      variant="ghost"
+
      {onclick}
+
      stylePadding="0 4px"
+
      active={popoverExpanded}>
+
      <Icon name="info" /> Guide
    </NakedButton>
  {/snippet}
  {#snippet popover()}
modified src/components/IssueStateButton.svelte
@@ -19,6 +19,8 @@
  }

  const { selectedState, onSelect }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

<style>
@@ -39,7 +41,11 @@
  }
</style>

-
<Popover popoverPadding="0" popoverPositionTop="2rem" popoverPositionLeft="0">
+
<Popover
+
  popoverPadding="0"
+
  popoverPositionTop="2rem"
+
  popoverPositionLeft="0"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
    <button {onclick}>
      <span
@@ -54,7 +60,7 @@
            : `issue-${selectedState.status}`} />
        {capitalize(selectedState.status)}
        {selectedState.status === "closed" ? `as ${selectedState.reason}` : ""}
-
        <Icon name="chevron-down" />
+
        <Icon name={popoverExpanded ? "chevron-up" : "chevron-down"} />
      </span>
    </button>
  {/snippet}
modified src/components/IssueStateFilterButton.svelte
@@ -21,6 +21,8 @@
  }

  const { changeFilter, counters, status }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

{#snippet iconSnippet(status: IssueStatus)}
@@ -41,13 +43,20 @@
  </div>
{/snippet}

-
<Popover popoverPositionLeft="0" popoverPositionTop="3rem">
+
<Popover
+
  popoverPositionLeft="0"
+
  popoverPositionTop="3rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
-
    <OutlineButton variant="ghost" {onclick} styleHeight="2.5rem">
+
    <OutlineButton
+
      variant="ghost"
+
      {onclick}
+
      styleHeight="2.5rem"
+
      active={popoverExpanded}>
      {@render iconSnippet(status)}
      {capitalize(status)}
      {@render counterSnippet(status)}
-
      <Icon name="chevron-down" />
+
      <Icon name={popoverExpanded ? "chevron-up" : "chevron-down"} />
    </OutlineButton>
  {/snippet}

modified src/components/NakedButton.svelte
@@ -207,6 +207,10 @@
    background-color: var(--button-color-1);
  }

+
  .container.active:not(.disabled) {
+
    color: var(--color-foreground-emphasized);
+
  }
+

  .container.disabled {
    color: var(--color-foreground-disabled);
    cursor: inherit;
modified src/components/NewPatchButton.svelte
@@ -12,17 +12,30 @@
  }

  const { outline = false, rid }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

-
<Popover popoverPositionRight="0" popoverPositionTop="3rem">
+
<Popover
+
  popoverPositionRight="0"
+
  popoverPositionTop="3rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
    {#if outline}
-
      <OutlineButton styleHeight="2.5rem" variant="ghost" {onclick}>
-
        <Icon name="add" />New patch<Icon name="chevron-down" />
+
      <OutlineButton
+
        styleHeight="2.5rem"
+
        variant="ghost"
+
        {onclick}
+
        active={popoverExpanded}>
+
        <Icon name="add" />New patch
      </OutlineButton>
    {:else}
-
      <Button styleHeight="2.5rem" variant="secondary" {onclick}>
-
        <Icon name="add" />New patch<Icon name="chevron-down" />
+
      <Button
+
        styleHeight="2.5rem"
+
        variant="secondary"
+
        {onclick}
+
        active={popoverExpanded}>
+
        <Icon name="add" />New patch
      </Button>
    {/if}
  {/snippet}
modified src/components/NodeStatusButton.svelte
@@ -5,14 +5,17 @@
  import Icon from "@app/components/Icon.svelte";
  import NakedButton from "@app/components/NakedButton.svelte";
  import Popover from "@app/components/Popover.svelte";
+

+
  let popoverExpanded: boolean = $state(false);
</script>

<Popover
  popoverPadding="0"
  popoverPositionTop="2.5rem"
+
  bind:expanded={popoverExpanded}
  popoverPositionRight="0">
  {#snippet toggle(onclick)}
-
    <NakedButton variant="ghost" {onclick}>
+
    <NakedButton variant="ghost" {onclick} active={popoverExpanded}>
      {#if $nodeRunning}
        <Icon name="online" />
        Online
modified src/components/OutlineButton.svelte
@@ -229,6 +229,10 @@
    background-color: var(--button-color-1);
  }

+
  .container.active:not(.disabled) {
+
    color: var(--color-foreground-emphasized);
+
  }
+

  .container.disabled {
    color: var(--color-foreground-disabled);
  }
modified src/components/PatchStateButton.svelte
@@ -18,6 +18,8 @@
  }

  const { selectedState, onSelect }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

<style>
@@ -42,7 +44,11 @@
  }
</style>

-
<Popover popoverPadding="0" popoverPositionTop="2rem" popoverPositionLeft="0">
+
<Popover
+
  popoverPadding="0"
+
  popoverPositionTop="2rem"
+
  popoverPositionLeft="0"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
    <button disabled={selectedState.status === "merged"} {onclick}>
      <span
@@ -57,7 +63,7 @@
            : `patch-${selectedState.status}`} />
        {capitalize(selectedState.status)}
        {#if selectedState.status !== "merged"}
-
          <Icon name="chevron-down" />
+
          <Icon name={popoverExpanded ? "chevron-up" : "chevron-down"} />
        {/if}
      </span>
    </button>
modified src/components/PatchStateFilterButton.svelte
@@ -22,6 +22,8 @@
  }

  const { status, select, counters }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

{#snippet iconSnippet(status: PatchStatus | undefined)}
@@ -43,13 +45,20 @@
  </div>
{/snippet}

-
<Popover popoverPositionLeft="0" popoverPositionTop="3rem">
+
<Popover
+
  popoverPositionLeft="0"
+
  popoverPositionTop="3rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
-
    <OutlineButton variant="ghost" {onclick} styleHeight="2.5rem">
+
    <OutlineButton
+
      variant="ghost"
+
      {onclick}
+
      styleHeight="2.5rem"
+
      active={popoverExpanded}>
      {@render iconSnippet(status)}
      {status ? capitalize(status) : "All"}
      {@render counterSnippet(status)}
-
      <Icon name="chevron-down" />
+
      <Icon name={popoverExpanded ? "chevron-up" : "chevron-down"} />
    </OutlineButton>
  {/snippet}

modified src/components/Popover.svelte
@@ -32,6 +32,7 @@
    popoverPositionLeft?: string;
    popoverPositionRight?: string;
    popoverPositionTop?: string;
+
    expanded?: boolean;
  }

  /* eslint-disable prefer-const */
@@ -45,6 +46,7 @@
    popoverPositionLeft,
    popoverPositionRight,
    popoverPositionTop,
+
    expanded = $bindable(false),
  }: Props = $props();
  /* eslint-enable prefer-const */

@@ -74,6 +76,10 @@
      }
    }
  }
+

+
  $effect(() => {
+
    expanded = focused?.element === thisComponent;
+
  });
</script>

<style>
@@ -96,7 +102,7 @@
  style:min-width={popoverContainerMinWidth}>
  {@render toggle(toggleFn)}

-
  {#if focused?.element === thisComponent}
+
  {#if expanded}
    <div
      class="popover"
      style:bottom={popoverPositionBottom}
modified src/components/ReviewButton.svelte
@@ -43,13 +43,19 @@
        ),
    ),
  );
+

+
  let popoverExpanded: boolean = $state(false);
</script>

-
<Popover popoverPositionRight="0" popoverPositionTop="2.5rem">
+
<Popover
+
  popoverPositionRight="0"
+
  popoverPositionTop="2.5rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
    <NakedButton
      variant="ghost"
      disabled={hasOwnReview}
+
      active={popoverExpanded}
      {onclick}
      title={hasOwnReview ? "You already published a review" : undefined}>
      <Icon name="add" />
modified src/components/Reviews.svelte
@@ -69,17 +69,26 @@

<div style:margin={hideReviews ? "1.5rem 0" : "1.5rem 0 2.5rem 0"}>
  <div class="global-flex">
-
    <NakedButton
-
      disabled={revision.reviews === undefined || revision.reviews.length === 0}
-
      variant="ghost"
-
      onclick={() => (hideReviews = !hideReviews)}>
-
      <Icon name={hideReviews ? "chevron-right" : "chevron-down"} />
-
      <div class="txt-semibold global-flex txt-regular">
+
    <div class="global-flex">
+
      <NakedButton
+
        stylePadding="0 4px"
+
        disabled={revision.reviews === undefined ||
+
          revision.reviews.length === 0}
+
        variant="ghost"
+
        onclick={() => (hideReviews = !hideReviews)}>
+
        <Icon name={hideReviews ? "chevron-right" : "chevron-down"} />
+
      </NakedButton>
+
      <div
+
        class="txt-semibold global-flex txt-regular"
+
        style:color={revision.reviews === undefined ||
+
        revision.reviews.length === 0
+
          ? "var(--color-foreground-disabled)"
+
          : undefined}>
        Reviews <span style:font-weight="var(--font-weight-regular)">
          {revision.reviews?.length ?? 0}
        </span>
      </div>
-
    </NakedButton>
+
    </div>

    <div class="global-flex" style:margin-left="auto">
      <ReviewButton
modified src/components/RevisionSelector.svelte
@@ -43,6 +43,8 @@
      ["desc"],
    ),
  );
+

+
  let popoverExpanded: boolean = $state(false);
</script>

<style>
@@ -54,9 +56,14 @@
  }
</style>

-
<Popover popoverPadding="0" popoverPositionTop="37px" popoverPositionLeft="0">
+
<Popover
+
  popoverPadding="0"
+
  popoverPositionTop="37px"
+
  popoverPositionLeft="0"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
    <NakedButton
+
      active={popoverExpanded}
      variant="ghost"
      onclick={(e: MouseEvent) => {
        e.stopPropagation();
modified src/components/Settings.svelte
@@ -30,11 +30,18 @@
    styleHeight = "2.5rem",
    popoverProps,
  }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

-
<Popover {...popoverProps}>
+
<Popover {...popoverProps} bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
-
    <NakedButton title="Settings" variant="ghost" {onclick} {styleHeight}>
+
    <NakedButton
+
      title="Settings"
+
      variant="ghost"
+
      {onclick}
+
      {styleHeight}
+
      active={popoverExpanded}>
      <Icon name="settings" />
      {#if !compact}
        Settings
modified src/components/VerdictButton.svelte
@@ -20,6 +20,8 @@
  }

  const { onSelect, summaryMissing, selectedVerdict }: Props = $props();
+

+
  let popoverExpanded: boolean = $state(false);
</script>

<style>
@@ -47,11 +49,15 @@
  }
</style>

-
<Popover popoverPadding="0" popoverPositionLeft="0" popoverPositionTop="2rem">
+
<Popover
+
  popoverPadding="0"
+
  popoverPositionLeft="0"
+
  popoverPositionTop="2rem"
+
  bind:expanded={popoverExpanded}>
  {#snippet toggle(onclick)}
    <button {onclick}>
      <VerdictBadge verdict={selectedVerdict} hoverable>
-
        <Icon name="chevron-down" />
+
        <Icon name={popoverExpanded ? "chevron-up" : "chevron-down"} />
      </VerdictBadge>
    </button>
  {/snippet}