mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-15 19:30:38 +08:00
Implement new landing page
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
| "foreground"
|
||||
| "background"
|
||||
| "outline"
|
||||
| "yellowOutline"
|
||||
| "yellow"
|
||||
| "neutral"
|
||||
| "negative"
|
||||
| "positive"
|
||||
@@ -50,10 +50,9 @@
|
||||
color: var(--color-foreground-match-background);
|
||||
background-color: var(--color-fill-secondary);
|
||||
}
|
||||
.yellow-outline {
|
||||
border: 1px solid var(--color-foreground-yellow);
|
||||
color: var(--color-foreground-yellow);
|
||||
background-color: transparent;
|
||||
.yellow {
|
||||
color: var(--color-foreground-black);
|
||||
background-color: var(--color-fill-yellow);
|
||||
}
|
||||
.outline {
|
||||
border: 1px solid var(--color-border-hint);
|
||||
@@ -112,7 +111,7 @@
|
||||
class:small={size === "small"}
|
||||
class:medium={size === "medium"}
|
||||
class:caution={variant === "caution"}
|
||||
class:yellow-outline={variant === "yellowOutline"}
|
||||
class:yellow={variant === "yellow"}
|
||||
class:outline={variant === "outline"}
|
||||
class:background={variant === "background"}
|
||||
class:foreground={variant === "foreground"}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<script>
|
||||
import { api, httpdStore } from "@app/lib/httpd";
|
||||
import Command from "./Command.svelte";
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.divider {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: var(--color-fill-separator);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-regular);
|
||||
margin-bottom: 0.75rem;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
{#if $httpdStore.state === "running"}
|
||||
<div class="label">Authenticate with your local node to make changes.</div>
|
||||
<Command
|
||||
fullWidth
|
||||
command={`rad web ${window.origin} --connect ${api.hostname}:${api.port}`} />
|
||||
{:else}
|
||||
<div class="heading">Connect & Authenticate</div>
|
||||
<div class="label">
|
||||
Connect to your local node to browse projects on your local machine,
|
||||
create issues, and participate in discussions.
|
||||
</div>
|
||||
<Command fullWidth command={`rad web ${window.origin}`} />
|
||||
|
||||
<div class="divider" />
|
||||
<div class="heading">New to Radicle?</div>
|
||||
<div class="label">
|
||||
Run the following command and follow the instructions to install Radicle
|
||||
and get started.
|
||||
</div>
|
||||
<Command fullWidth command="sh <(curl -sSf https://radicle.xyz/install)" />
|
||||
{/if}
|
||||
</div>
|
||||
@@ -17,7 +17,6 @@
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-regular);
|
||||
color: var(--color-foreground-contrast);
|
||||
height: 2rem;
|
||||
}
|
||||
.item.disabled {
|
||||
color: var(--color-foreground-disabled);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
| "no-issues"
|
||||
| "no-patches"
|
||||
| "patch"
|
||||
| "plus"
|
||||
| "review"
|
||||
| "sun";
|
||||
export let size: "24" | "48" = "24";
|
||||
@@ -384,7 +385,6 @@
|
||||
d="M12 18C12.5523 18 13 17.5523 13 17C13 16.4477 12.5523 16 12 16C11.4477
|
||||
16 11 16.4477 11 17C11 17.5523 11.4477 18 12 18Z" />
|
||||
{:else if name === "face"}
|
||||
.only
|
||||
<path
|
||||
d="M8.3 13.1C8.07908 12.9343 7.76568 12.9791 7.6 13.2C7.43431 13.4209
|
||||
7.47908 13.7343 7.7 13.9L8.1 14.2C10.4111 15.9333 13.5889 15.9333 15.9
|
||||
@@ -718,6 +718,11 @@
|
||||
16.5ZM18 16.5C17.1716 16.5 16.5 17.1716 16.5 18C16.5 18.8284 17.1716 19.5
|
||||
18 19.5C18.8284 19.5 19.5 18.8284 19.5 18C19.5 17.1716 18.8284 16.5 18
|
||||
16.5Z" />
|
||||
{:else if name === "plus"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12.5 5.97656C12.5 5.70042 12.2761 5.47656 12 5.47656C11.7239 5.47656 11.5 5.70042 11.5 5.97656V12.4766H5C4.72386 12.4766 4.5 12.7004 4.5 12.9766C4.5 13.2527 4.72386 13.4766 5 13.4766H11.5V19.9766C11.5 20.2527 11.7239 20.4766 12 20.4766C12.2761 20.4766 12.5 20.2527 12.5 19.9766V13.4766L19 13.4766C19.2761 13.4766 19.5 13.2527 19.5 12.9766C19.5 12.7004 19.2761 12.4766 19 12.4766L12.5 12.4766V5.97656Z" />
|
||||
{:else if name === "review"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
| "activity"
|
||||
| "arrow-box-up-right"
|
||||
| "arrow-reply"
|
||||
| "badge"
|
||||
| "branch"
|
||||
| "broadcasting"
|
||||
| "brush"
|
||||
@@ -85,6 +86,15 @@
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M2.87128 8.85806C2.89568 8.91703 2.93185 8.97228 2.97979 9.02022L6.31312 12.3536C6.50839 12.5488 6.82497 12.5488 7.02023 12.3536C7.21549 12.1583 7.21549 11.8417 7.02023 11.6464L4.54045 9.16667H12C12.6443 9.16667 13.1667 8.64433 13.1667 8V4C13.1667 3.72386 12.9428 3.5 12.6667 3.5C12.3905 3.5 12.1667 3.72386 12.1667 4V8C12.1667 8.09205 12.0921 8.16667 12 8.16667H4.54045L7.02023 5.68689C7.21549 5.49162 7.21549 5.17504 7.02023 4.97978C6.82497 4.78452 6.50839 4.78452 6.31312 4.97978L2.97979 8.31311C2.88292 8.40998 2.83411 8.53671 2.83335 8.66367C2.83335 8.66467 2.83334 8.66567 2.83334 8.66667C2.83334 8.66767 2.83335 8.66867 2.83335 8.66967C2.83374 8.73637 2.8472 8.79997 2.87128 8.85806Z" />
|
||||
{:else if name === "badge"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M10.0435 6.41199C10.0435 7.51656 9.14803 8.41199 8.04346 8.41199C6.93889 8.41199 6.04346 7.51656 6.04346 6.41199C6.04346 5.30742 6.93889 4.41199 8.04346 4.41199C9.14803 4.41199 10.0435 5.30742 10.0435 6.41199ZM9.04346 6.41199C9.04346 6.96427 8.59574 7.41199 8.04346 7.41199C7.49117 7.41199 7.04346 6.96427 7.04346 6.41199C7.04346 5.8597 7.49117 5.41199 8.04346 5.41199C8.59574 5.41199 9.04346 5.8597 9.04346 6.41199Z" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M8.70235 1.76514L9.06964 2.13244C9.25591 2.31871 9.50857 2.42335 9.77201 2.42335H11.0548C11.6034 2.42335 12.0481 2.86806 12.0481 3.41663V4.69945C12.0481 4.9629 12.1528 5.21555 12.3391 5.40182L12.8168 5.87958C13.2047 6.26748 13.2047 6.89641 12.8168 7.28428L12.3391 7.76207C12.1528 7.94834 12.0481 8.20099 12.0481 8.46441V9.43104C12.0481 9.78994 11.8577 10.1044 11.5725 10.2789L12.6676 12.9387C12.7421 13.1197 12.7034 13.3277 12.5686 13.4697C12.4338 13.6117 12.2281 13.6612 12.0435 13.5962L10.7832 13.1526L10.082 14.2898C9.98071 14.454 9.79344 14.5447 9.60178 14.5224C9.41011 14.5001 9.24873 14.3687 9.18792 14.1856L8.33941 11.6302C8.12056 11.7095 7.87942 11.7095 7.66057 11.6301L6.81206 14.1856C6.75125 14.3687 6.58987 14.5001 6.3982 14.5224C6.20654 14.5447 6.01927 14.454 5.91799 14.2898L5.21675 13.1526L3.95651 13.5962C3.77184 13.6612 3.5662 13.6117 3.4314 13.4697C3.2966 13.3277 3.25783 13.1197 3.33237 12.9387L4.44826 10.2286C4.20486 10.0475 4.04717 9.75769 4.04717 9.43104V8.55968C4.04717 8.29627 3.9425 8.04361 3.75623 7.85734L3.1832 7.28428C2.7953 6.89641 2.7953 6.26748 3.1832 5.87958L3.75623 5.30655C3.9425 5.12028 4.04717 4.86762 4.04717 4.60418V3.41663C4.04717 2.86806 4.49185 2.42335 5.04045 2.42335H6.228C6.49142 2.42335 6.74407 2.31871 6.93034 2.13244L7.29764 1.76514C7.68554 1.37724 8.31447 1.37724 8.70235 1.76514ZM8.00001 2.46748L8.3673 2.83478C8.73984 3.20732 9.24515 3.41663 9.77201 3.41663H11.0548V4.69945C11.0548 5.22634 11.2641 5.73162 11.6367 6.10416L12.1145 6.58194L11.6367 7.0597C11.2641 7.43227 11.0548 7.93755 11.0548 8.46441V9.43104H10.0882C9.56134 9.43104 9.05606 9.64032 8.68352 10.0129L8.00001 10.6964L7.31649 10.0129C6.94392 9.64032 6.43864 9.43104 5.91178 9.43104H5.04045V8.55968C5.04045 8.03282 4.83114 7.52754 4.4586 7.15497L3.88554 6.58194L4.4586 6.00889C4.83114 5.63635 5.04045 5.13107 5.04045 4.60418V3.41663H6.228C6.75486 3.41663 7.26014 3.20732 7.63271 2.83478L8.00001 2.46748ZM5.44185 10.4243L4.6733 12.2909L5.26446 12.0827C5.48483 12.0052 5.72948 12.0917 5.8521 12.2905L6.20478 12.8625L6.84207 10.9432L6.61412 10.7152C6.42785 10.529 6.17523 10.4243 5.91178 10.4243H5.44185ZM9.15791 10.9432L9.7952 12.8625L10.1479 12.2905C10.2705 12.0917 10.5152 12.0052 10.7355 12.0827L11.3267 12.2909L10.5581 10.4243H10.0882C9.82479 10.4243 9.57213 10.529 9.38586 10.7152L9.15791 10.9432Z" />
|
||||
{:else if name === "branch"}
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
export let popoverPositionRight: string | undefined = undefined;
|
||||
export let popoverPositionTop: string | undefined = undefined;
|
||||
|
||||
let expanded = false;
|
||||
export let expanded = false;
|
||||
let thisComponent: HTMLDivElement;
|
||||
|
||||
function clickOutside(ev: MouseEvent | TouchEvent) {
|
||||
|
||||
+162
-119
@@ -1,162 +1,205 @@
|
||||
<script lang="ts">
|
||||
import type { WeeklyActivity } from "@app/lib/commit";
|
||||
import type { BaseUrl } from "@httpd-client";
|
||||
|
||||
import capitalize from "lodash/capitalize";
|
||||
import { formatCommit, twemoji } from "@app/lib/utils";
|
||||
import type { WeeklyActivity } from "@app/lib/commit";
|
||||
import { formatTimestamp, twemoji } from "@app/lib/utils";
|
||||
|
||||
import ActivityDiagram from "@app/components/ActivityDiagram.svelte";
|
||||
import Badge from "@app/components/Badge.svelte";
|
||||
import IconSmall from "@app/components/IconSmall.svelte";
|
||||
import Link from "@app/components/Link.svelte";
|
||||
|
||||
export let compact = false;
|
||||
|
||||
export let activity: WeeklyActivity[];
|
||||
export let compact = false;
|
||||
export let description: string;
|
||||
export let head: string;
|
||||
export let visibility: "public" | "private" = "public";
|
||||
export let baseUrl: BaseUrl;
|
||||
|
||||
export let numberOfIssues: number;
|
||||
export let numberOfPatches: number;
|
||||
|
||||
export let isDelegate: boolean;
|
||||
export let isSeeding: boolean;
|
||||
export let isPrivate: boolean;
|
||||
|
||||
export let lastUpdatedTimestamp: number;
|
||||
|
||||
$: lastUpdated = formatTimestamp(lastUpdatedTimestamp);
|
||||
|
||||
export let id: string;
|
||||
export let name: string;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.project {
|
||||
.project-card {
|
||||
height: 10rem;
|
||||
border: 1px solid var(--color-border-default);
|
||||
border-radius: var(--border-radius-small);
|
||||
background-color: var(--color-background-float);
|
||||
padding: 0.75rem 1rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
box-shadow: 0 0 0 1px var(--color-border-hint);
|
||||
border-radius: var(--border-radius-small);
|
||||
min-width: 36rem;
|
||||
cursor: pointer;
|
||||
background: var(--color-background-float);
|
||||
}
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
overflow: hidden;
|
||||
}
|
||||
.left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 50%;
|
||||
|
||||
.project-card.compact {
|
||||
height: 8rem;
|
||||
}
|
||||
.description {
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.compact {
|
||||
min-width: 16rem;
|
||||
height: 9rem;
|
||||
}
|
||||
.compact .left {
|
||||
width: 100%;
|
||||
}
|
||||
.compact .right {
|
||||
display: none;
|
||||
}
|
||||
.compact .description {
|
||||
white-space: nowrap;
|
||||
|
||||
.project-card:hover {
|
||||
background-color: var(--color-fill-float-hover);
|
||||
}
|
||||
|
||||
.activity {
|
||||
width: 100%;
|
||||
max-width: 14rem;
|
||||
margin-top: 0.5rem;
|
||||
position: absolute;
|
||||
bottom: 1.5rem;
|
||||
right: 0;
|
||||
width: calc(100% - 3rem);
|
||||
max-width: 24rem;
|
||||
}
|
||||
.compact .activity {
|
||||
|
||||
.activity > .fadeout-overlay {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
var(--color-background-float) 20%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
}
|
||||
.project:hover {
|
||||
box-shadow: 0 0 0 2px var(--color-border-focus);
|
||||
}
|
||||
.description {
|
||||
font-size: var(--font-size-small);
|
||||
|
||||
.project-card:hover .fadeout-overlay {
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
var(--color-fill-float-hover) 20%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
font-size: var(--font-size-medium);
|
||||
font-weight: var(--font-weight-medium);
|
||||
flex-direction: column;
|
||||
gap: 0.125rem;
|
||||
position: relative;
|
||||
}
|
||||
.name {
|
||||
font-weight: var(--font-weight-semibold);
|
||||
|
||||
.title * {
|
||||
line-clamp: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.rid {
|
||||
visibility: hidden;
|
||||
color: var(--color-fill-secondary);
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-tiny);
|
||||
|
||||
.title p {
|
||||
color: var(--color-foreground-dim);
|
||||
}
|
||||
.project:hover .rid {
|
||||
visibility: visible;
|
||||
|
||||
.headline-and-badges {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.text {
|
||||
|
||||
.badges {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.badge-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h4,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
height: 1.5rem;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="project" class:compact>
|
||||
<div class="left">
|
||||
<div class="text">
|
||||
<div class="title">
|
||||
<span class="name txt-overflow" title={name}>
|
||||
{name}
|
||||
</span>
|
||||
{#if visibility === "private"}
|
||||
{#if compact}
|
||||
<div title="Private" style:color="var(--color-foreground-yellow)">
|
||||
<Link
|
||||
route={{
|
||||
resource: "project.source",
|
||||
project: id,
|
||||
node: baseUrl,
|
||||
}}>
|
||||
<div class="project-card" class:compact>
|
||||
<div class="activity">
|
||||
<div class="fadeout-overlay" />
|
||||
<ActivityDiagram
|
||||
{id}
|
||||
viewBoxHeight={200}
|
||||
styleColor="var(--color-foreground-primary"
|
||||
{activity} />
|
||||
</div>
|
||||
<div class="title">
|
||||
<div class="headline-and-badges">
|
||||
<h4 use:twemoji>{name}</h4>
|
||||
<div class="badges">
|
||||
{#if isPrivate}
|
||||
<div title="Private" class="badge">
|
||||
<div
|
||||
class="badge-background"
|
||||
style:background-color="var(--color-fill-yellow)" />
|
||||
<IconSmall name="lock" />
|
||||
</div>
|
||||
{:else}
|
||||
<Badge variant="yellowOutline" size="tiny">
|
||||
{capitalize(visibility)}
|
||||
</Badge>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="description" use:twemoji>{description}</div>
|
||||
<div class="global-commit">
|
||||
{#if compact}
|
||||
{formatCommit(head)}
|
||||
{:else}
|
||||
{head}
|
||||
{/if}
|
||||
{#if isDelegate}
|
||||
<div title="Delegate" class="badge">
|
||||
<div
|
||||
class="badge-background"
|
||||
style:background-color="var(--color-foreground-primary)" />
|
||||
<IconSmall name="badge" />
|
||||
</div>
|
||||
{/if}
|
||||
{#if isSeeding}
|
||||
<div title="Seeding" class="badge">
|
||||
<div
|
||||
class="badge-background"
|
||||
style:background-color="var(--color-fill-secondary)" />
|
||||
<IconSmall name="network" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<p class="txt-small" use:twemoji>{description}</p>
|
||||
</div>
|
||||
<div class="stats-row txt-tiny" style:color="var(--color-foreground-dim)">
|
||||
<IconSmall name="issue" />
|
||||
{numberOfIssues} ·
|
||||
<IconSmall name="patch" />
|
||||
<span style:overflow="hidden" style:text-overflow="ellipsis">
|
||||
{numberOfPatches} · Updated {lastUpdated}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{#if compact}
|
||||
<div class="activity">
|
||||
<ActivityDiagram
|
||||
{id}
|
||||
{activity}
|
||||
viewBoxHeight={70}
|
||||
styleColor={visibility === "private"
|
||||
? "var(--color-foreground-yellow)"
|
||||
: "var(--color-foreground-primary)"} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if !compact}
|
||||
<div class="right">
|
||||
<div class="id">
|
||||
<span class="rid">{id}</span>
|
||||
</div>
|
||||
<div class="activity">
|
||||
<ActivityDiagram
|
||||
{id}
|
||||
{activity}
|
||||
viewBoxHeight={100}
|
||||
styleColor={visibility === "private"
|
||||
? "var(--color-foreground-yellow)"
|
||||
: "var(--color-foreground-primary)"} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
<script lang="ts">
|
||||
import type { Tweened } from "svelte/motion";
|
||||
|
||||
import { onMount } from "svelte";
|
||||
import { cubicInOut } from "svelte/easing";
|
||||
import { tweened } from "svelte/motion";
|
||||
|
||||
// Force a height of 0, and optionally apply `negativeMarginWhileCollapsed`.
|
||||
export let collapsed = false;
|
||||
|
||||
// If true, all content height changes are transitioned. If false, only
|
||||
// collapsing and expanding the content is transitioned.
|
||||
export let transitionHeightChanges = false;
|
||||
|
||||
// Force a negative margin while collapsed. This is useful when you use
|
||||
// `transitionedHeight` in the context of some layout where there's further
|
||||
// content below.
|
||||
export let negativeMarginWhileCollapsed: string | undefined = undefined;
|
||||
|
||||
let contentContainerElem: HTMLDivElement;
|
||||
let fitContent = !collapsed;
|
||||
|
||||
let containerHeight: Tweened<number> | undefined;
|
||||
onMount(() => {
|
||||
if (collapsed) {
|
||||
containerHeight = tweened(0);
|
||||
} else {
|
||||
containerHeight = tweened(
|
||||
contentContainerElem.getBoundingClientRect().height,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let animating = false;
|
||||
let zeroHeight = collapsed;
|
||||
let previouslyCollapsed = collapsed;
|
||||
|
||||
async function updateHeight() {
|
||||
if (!containerHeight) return;
|
||||
|
||||
const newHeight = collapsed
|
||||
? 0
|
||||
: contentContainerElem.getBoundingClientRect().height;
|
||||
|
||||
const collapsedChanged = previouslyCollapsed !== collapsed;
|
||||
|
||||
const shouldTransition = transitionHeightChanges || collapsedChanged;
|
||||
|
||||
if (collapsed && !collapsedChanged) return;
|
||||
|
||||
// Setting fitContent to false so that we can smoothly animate the
|
||||
// container height.
|
||||
if (shouldTransition) {
|
||||
fitContent = false;
|
||||
animating = true;
|
||||
}
|
||||
|
||||
void containerHeight.set(
|
||||
newHeight,
|
||||
shouldTransition ? { duration: 300, easing: cubicInOut } : undefined,
|
||||
);
|
||||
|
||||
if (shouldTransition && !collapsed) {
|
||||
setTimeout(() => {
|
||||
fitContent = true;
|
||||
animating = false;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
zeroHeight = newHeight === 0;
|
||||
|
||||
previouslyCollapsed = collapsed;
|
||||
}
|
||||
$: {
|
||||
collapsed;
|
||||
void updateHeight();
|
||||
}
|
||||
|
||||
let sizeObserver: ResizeObserver | undefined;
|
||||
onMount(() => {
|
||||
sizeObserver = new ResizeObserver(updateHeight);
|
||||
sizeObserver.observe(contentContainerElem);
|
||||
|
||||
return () => sizeObserver?.disconnect();
|
||||
});
|
||||
|
||||
$: heightStyleString = fitContent ? "fit-content" : `${$containerHeight}px`;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.transitioned-height {
|
||||
width: 100%;
|
||||
transition: margin-bottom 0.3s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.animating,
|
||||
.zero-height {
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div
|
||||
class="transitioned-height"
|
||||
class:animating
|
||||
class:zero-height={zeroHeight}
|
||||
style:margin-bottom={negativeMarginWhileCollapsed && zeroHeight === true
|
||||
? negativeMarginWhileCollapsed
|
||||
: undefined}
|
||||
style:height={heightStyleString}>
|
||||
<div class="inner" bind:this={contentContainerElem}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user