-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TBD Proposal cards animation #4996
base: main
Are you sure you want to change the base?
Changes from 16 commits
3ee6669
849a1cc
15ce62d
109cbdd
4baba06
5ad2fe1
ccc0613
9f04837
624b135
458379f
ae132c8
768e9ef
060a2b1
8396b56
c590525
1b20e0d
bcce0b4
94d205e
5226be1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,11 @@ | |
import { Principal } from "@dfinity/principal"; | ||
import type { Universe } from "$lib/types/universe"; | ||
import type { Readable } from "svelte/store"; | ||
import { PROPOSAL_CARD_ANIMATION_DELAY_IN_MILLISECOND } from "$lib/constants/constants"; | ||
|
||
export let universe: Universe; | ||
export let proposals: ProposalData[]; | ||
export let cardIndex = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about |
||
|
||
let rootCanisterId: RootCanisterIdText; | ||
$: rootCanisterId = universe.canisterId; | ||
|
@@ -27,9 +29,13 @@ | |
|
||
<TestIdWrapper testId="actionable-sns-proposals-component"> | ||
{#if nonNullish(nsFunctions)} | ||
<UniverseWithActionableProposals {universe}> | ||
{#each proposals as proposalData (fromNullable(proposalData.id)?.id)} | ||
<UniverseWithActionableProposals | ||
{universe} | ||
delay={cardIndex * PROPOSAL_CARD_ANIMATION_DELAY_IN_MILLISECOND} | ||
> | ||
{#each proposals as proposalData, index (fromNullable(proposalData.id)?.id)} | ||
<SnsProposalCard | ||
index={cardIndex + index} | ||
actionable | ||
fromActionablePage | ||
{proposalData} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,20 @@ | ||
<script lang="ts"> | ||
import TestIdWrapper from "$lib/components/common/TestIdWrapper.svelte"; | ||
import { | ||
type ActionableSnsProposalsByUniverseData, | ||
actionableSnsProposalsByUniverseStore, | ||
} from "$lib/derived/actionable-proposals.derived"; | ||
import ActionableSnsProposals from "$lib/components/proposals/ActionableSnsProposals.svelte"; | ||
|
||
export let cardIndex = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
let actionableUniverses: ActionableSnsProposalsByUniverseData[] = []; | ||
$: actionableUniverses = $actionableSnsProposalsByUniverseStore.filter( | ||
({ proposals }) => proposals.length > 0 | ||
); | ||
</script> | ||
|
||
<TestIdWrapper testId="actionable-snses-component"> | ||
<div data-tid="actionable-snses-component"> | ||
{#each actionableUniverses as { universe, proposals } (universe.canisterId)} | ||
<ActionableSnsProposals {universe} {proposals} /> | ||
<ActionableSnsProposals {universe} {proposals} {cardIndex} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't |
||
{/each} | ||
</TestIdWrapper> | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
<script lang="ts"> | ||
import { i18n } from "$lib/stores/i18n"; | ||
import { fade } from "svelte/transition"; | ||
</script> | ||
|
||
<p class="description" data-tid="no-proposals-msg"> | ||
<p class="description" data-tid="no-proposals-msg" in:fade|global> | ||
{$i18n.voting.nothing_found} | ||
</p> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,12 +9,22 @@ | |
import { i18n } from "$lib/stores/i18n"; | ||
import Countdown from "./Countdown.svelte"; | ||
import { nowInSeconds } from "$lib/utils/date.utils"; | ||
import { nonNullish } from "@dfinity/utils"; | ||
import { isNullish, nonNullish } from "@dfinity/utils"; | ||
import { shortenWithMiddleEllipsis } from "$lib/utils/format.utils"; | ||
import { PROPOSER_ID_DISPLAY_SPLIT_LENGTH } from "$lib/constants/proposals.constants"; | ||
import type { UniversalProposalStatus } from "$lib/types/proposals"; | ||
import ProposalStatusTag from "$lib/components/ui/ProposalStatusTag.svelte"; | ||
|
||
import { fly, type FlyParams } from "svelte/transition"; | ||
import { | ||
PROPOSAL_CARD_ANIMATION_DELAY_IN_MILLISECOND, | ||
PROPOSAL_CARD_ANIMATION_DURATION_IN_MILLISECOND, | ||
PROPOSAL_CARD_ANIMATION_EASING, | ||
PROPOSAL_CARD_ANIMATION_Y, | ||
} from "$lib/constants/constants"; | ||
import { isNode } from "$lib/utils/dev.utils"; | ||
import { isHtmlElementInViewport } from "$lib/utils/utils"; | ||
|
||
export let index = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use a more specific name? Something like |
||
export let hidden = false; | ||
export let actionable = false; | ||
export let status: UniversalProposalStatus | undefined; | ||
|
@@ -25,9 +35,41 @@ | |
export let proposer: string | undefined; | ||
export let deadlineTimestampSeconds: bigint | undefined; | ||
export let href: string; | ||
|
||
let element: HTMLElement; | ||
|
||
let inViewport: boolean = false; | ||
$: inViewport = | ||
isNode() || isNullish(element) ? true : isHtmlElementInViewport(element); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why exactly do we call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I read the logic correctly, we treat an element that is |
||
|
||
// A short delay to wait when the cards are being rendered. | ||
// This process takes some time on FF and Safari, which makes the animation look not perfect. | ||
const CARD_ANIMATION_DELAY = 250; | ||
// Apply sequential fly animation to only first cards: | ||
// 1. to not waist resources on not visible animation; | ||
// 2. to make the proposal lazy loading still looks good. | ||
const TOP_MAX_ANIMATED_CARDS = 18; | ||
let topCards = false; | ||
$: topCards = index < TOP_MAX_ANIMATED_CARDS; | ||
let flyAnimation: FlyParams = {}; | ||
$: flyAnimation = { | ||
duration: topCards ? PROPOSAL_CARD_ANIMATION_DURATION_IN_MILLISECOND : 0, | ||
delay: topCards | ||
? index * PROPOSAL_CARD_ANIMATION_DELAY_IN_MILLISECOND + | ||
CARD_ANIMATION_DELAY | ||
: // Adjust the animation start time for cards other than the first ones, | ||
// so they appear right after the first cards becomes visible. | ||
TOP_MAX_ANIMATED_CARDS * PROPOSAL_CARD_ANIMATION_DELAY_IN_MILLISECOND + | ||
CARD_ANIMATION_DELAY + | ||
PROPOSAL_CARD_ANIMATION_DURATION_IN_MILLISECOND / 2, | ||
// Do not apply any animation to the cards that are not in the viewport. | ||
y: inViewport ? PROPOSAL_CARD_ANIMATION_Y : 0, | ||
opacity: inViewport ? 0 : 1, | ||
easing: PROPOSAL_CARD_ANIMATION_EASING, | ||
}; | ||
</script> | ||
|
||
<li class:hidden> | ||
<li bind:this={element} class:hidden in:fly|global={flyAnimation}> | ||
<Card testId="proposal-card" {href}> | ||
<div class="container"> | ||
<div> | ||
|
@@ -95,6 +137,7 @@ | |
|
||
li { | ||
list-style: none; | ||
will-change: transform, opacity; | ||
} | ||
|
||
.container { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,24 @@ | |
import type { Universe } from "$lib/types/universe"; | ||
import { InfiniteScroll } from "@dfinity/gix-components"; | ||
import UniversePageSummary from "$lib/components/universe/UniversePageSummary.svelte"; | ||
import { fade } from "svelte/transition"; | ||
import { SVELTE_DEFAULT_ANIMATION_DURATION_IN_MILLISECOND } from "$lib/constants/constants"; | ||
|
||
export let universe: Universe; | ||
export let delay = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use a clearer name. Something like |
||
export let noAnimation = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this prop? Just leaving the |
||
</script> | ||
|
||
<div class="container" data-tid="universe-with-actionable-proposals-component"> | ||
<div class="title"> | ||
<div | ||
in:fade|global={{ | ||
delay, | ||
duration: noAnimation | ||
? 0 | ||
: SVELTE_DEFAULT_ANIMATION_DURATION_IN_MILLISECOND, | ||
}} | ||
class="title" | ||
> | ||
<UniversePageSummary {universe} /> | ||
</div> | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
import { cubicOut } from "svelte/easing"; | ||
|
||
export const DEFAULT_LIST_PAGINATION_LIMIT = 100; | ||
export const MAX_ACTIONABLE_REQUEST_COUNT = 5; | ||
// Use a different limit for Icrc transactions | ||
|
@@ -22,3 +24,12 @@ export const DAYS_IN_NON_LEAP_YEAR = 365; | |
|
||
export const NANO_SECONDS_IN_MILLISECOND = 1_000_000; | ||
export const NANO_SECONDS_IN_MINUTE = NANO_SECONDS_IN_MILLISECOND * 1_000 * 60; | ||
|
||
// Animation constants | ||
export const SVELTE_DEFAULT_ANIMATION_DURATION_IN_MILLISECOND = 400; | ||
export const PROPOSAL_CARD_ANIMATION_DURATION_IN_MILLISECOND = | ||
SVELTE_DEFAULT_ANIMATION_DURATION_IN_MILLISECOND; | ||
// Maximum 10 card animations at a time | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this comment refer to? And should it be 18 instead of 10? The PR description says 18. Or is that something else? |
||
export const PROPOSAL_CARD_ANIMATION_DELAY_IN_MILLISECOND = 40; | ||
export const PROPOSAL_CARD_ANIMATION_Y = 50; | ||
export const PROPOSAL_CARD_ANIMATION_EASING = cubicOut; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really want the proposal on the SNS page to slide in while the other 2 cards don't?