Skip to content

Commit

Permalink
feat: creates CollectionsGallery and CollectionsGalleryItem (#2395)
Browse files Browse the repository at this point in the history
* feat: creates CollectionsGallery and CollectionsGalleryItem

* enhancement: NftGalleryItem

* refactor: removes duplicated css

* fix: stack border radius

* fix: change NFT count Pill's color

* fix: placeholder width

---------

Co-authored-by: Mark Nardi <[email protected]>
  • Loading branch information
jeeanribeiro and MarkNerdi authored Apr 30, 2024
1 parent 66c07d0 commit c898e89
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script lang="ts">
import CollectionsGalleryItem from './CollectionsGalleryItem.svelte'
import { Collection, Collections } from '@core/nfts'
import VirtualList from '@sveltejs/svelte-virtual-list'
import { breakpoint } from '@core/app/stores'
export let collections: Collections
$: collectionsArray = Object.values(collections)
const COLLECTIONS_PER_CHUNK_FOR_SCREEN_SIZE = {
sm: 2,
md: 3,
lg: 3,
xl: 4,
'2xl': 5,
}
let rowDivElement: HTMLDivElement
$: rowDivHeight = getRowDivHeight(rowDivElement?.clientHeight)
function getRowDivHeight(clientHeight: number | undefined) {
if (!clientHeight) {
return rowDivHeight
}
if (!rowDivElement) {
return clientHeight
}
if (Math.abs(clientHeight - rowDivHeight) > 200) {
return rowDivHeight
}
return clientHeight
}
let collectionChunks: (Collection | undefined)[][] = []
$: collectionChunks = Array.from(
{ length: Math.ceil(collectionsArray.length / COLLECTIONS_PER_CHUNK_FOR_SCREEN_SIZE[$breakpoint]) },
(_, i) => {
return Array.from(
{ length: COLLECTIONS_PER_CHUNK_FOR_SCREEN_SIZE[$breakpoint] },
(_, j) => collectionsArray[i * COLLECTIONS_PER_CHUNK_FOR_SCREEN_SIZE[$breakpoint] + j]
)
}
)
</script>

<VirtualList items={collectionChunks} let:item itemHeight={rowDivHeight}>
<div
bind:this={rowDivElement}
class="grid sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-3 2xl:gap-4 pb-3 2xl:pb-4"
>
{#each item as collection}
{#if collection}
<CollectionsGalleryItem {collection} />
{:else}
<div />
{/if}
{/each}
</div>
</VirtualList>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script lang="ts">
import { Collection } from '@core/nfts'
import { AssetPillsForNft, MediaPlaceholder, NetworkAvatar, NftMedia } from '@ui'
import { Pill, Text } from '@bloomwalletio/ui'
import { downloadingNftId } from '@core/nfts/stores'
import { localize } from '@core/i18n'
export let collection: Collection
function onCollectionClick(): void {
return
}
</script>

<button type="button" on:click={onCollectionClick}>
<div class="container">
<div class="flex-1 flex relative bg-surface-2 dark:bg-surface-2-dark rounded-t-[0.9rem] overflow-hidden">
<!-- TODO: change media to collection URI instead of first NFT URI -->
<NftMedia nft={collection.nfts[0]} classes="min-w-full min-h-full object-cover" loop muted>
<MediaPlaceholder
type={collection.nfts[0]?.type}
downloading={$downloadingNftId === collection.nfts[0]?.id}
size="md"
slot="placeholder"
/>
</NftMedia>
</div>
<div class="w-full flex flex-col gap-2 p-3">
<nft-name class="w-full flex flex-row items-center gap-2 overflow-hidden">
<Text type="body2" truncate>{collection.name}</Text>
</nft-name>
<nft-pills class="flex flex-row items-center gap-2">
<NetworkAvatar networkId={collection.nfts[0].networkId} size="sm" showTooltip />
<AssetPillsForNft nft={collection.nfts[0]} />
<Pill compact color="brand">{localize('general.nfts', { count: collection.nfts.length })}</Pill>
</nft-pills>
</div>
</div>
</button>

<style lang="postcss">
.container {
@apply relative w-full flex flex-col mt-4;
@apply divide-y divide-solid divide-stroke dark:divide-stroke-dark;
@apply rounded-2xl border-2 border-solid border-stroke dark:border-stroke-dark;
@apply bg-surface-1 dark:bg-surface-1-dark;
@apply duration-300 z-[2];
transition-property: background-color, border-color, box-shadow;
aspect-ratio: 3 / 4;
&:hover,
&:focus {
@apply shadow-lg dark:shadow-violet-900/25;
@apply border-2 border-brand-500;
@apply bg-surface dark:bg-surface-dark;
}
}
button {
@apply relative;
&::after,
&::before {
@apply content-[''] absolute block left-0 right-0 z-[1];
@apply rounded-2xl border-t-2 border-x-2 border-solid border-stroke dark:border-stroke-dark;
@apply bg-surface-1 dark:bg-surface-1-dark;
aspect-ratio: 3 / 4;
}
&::after {
@apply top-2.5 mx-2;
}
&::before {
@apply top-[0.2rem] mx-4 blur-[1px];
}
}
</style>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as CollectiblesTabs } from './CollectiblesTabs.svelte'
export { default as CollectionsGallery } from './CollectionsGallery.svelte'
export { default as Erc721CollectibleDetails } from './Erc721CollectibleDetails.svelte'
export { default as Irc27CollectibleDetails } from './Irc27CollectibleDetails.svelte'
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { PopupId, openPopup } from '@desktop/auxiliary/popup'
import features from '@features/features'
import { SearchInput } from '@ui'
import { CollectiblesTabs } from '../components'
import { CollectiblesTabs, CollectionsGallery } from '../components'
import { collectionsSearchTerm, selectedAccountCollections } from '@core/nfts/stores'
import { Collections, isVisibleCollection } from '@core/nfts'
Expand Down Expand Up @@ -48,10 +48,7 @@
</header>
{#if hasCollections}
{#if Object.keys(queriedCollections).length > 0}
<!-- <CollectionsGallery collections={queriedCollections} /> -->
{#each Object.keys(queriedCollections) as collection}
<Text>{queriedCollections[collection].name}</Text>
{/each}
<CollectionsGallery collections={queriedCollections} />
{:else}
<div class="w-full h-full flex flex-col items-center justify-center">
<EmptyListPlaceholder
Expand Down
109 changes: 48 additions & 61 deletions packages/shared/src/components/molecules/NftGalleryItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
export let nft: Nft
let nftWrapperClientWidth: number
let anchor: HTMLElement
$: placeHolderColor = nft.downloadMetadata?.error
Expand Down Expand Up @@ -38,73 +37,61 @@
}
</script>

<button type="button" on:click={onNftClick} class="nft-gallery-item w-full">
<container>
<div
class="w-full flex relative bg-surface-2 dark:bg-surface-2-dark"
bind:clientWidth={nftWrapperClientWidth}
style="height: {nftWrapperClientWidth}px; "
>
<NftMedia {nft} classes="min-w-full min-h-full object-cover" loop muted>
<MediaPlaceholder
type={nft?.type}
textColor={placeHolderColor}
downloading={$downloadingNftId === nft?.id}
size="md"
slot="placeholder"
/>
</NftMedia>
<error-container bind:this={anchor}>
{#if nft.isScam}
<Pill color="warning">{localize('general.warning')}</Pill>
{:else if nft.downloadMetadata?.error || nft.downloadMetadata?.warning}
<Pill color={nft.downloadMetadata?.error ? 'danger' : 'warning'}>
{localize('general.' + (nft.downloadMetadata?.error ? 'error' : 'warning'))}
</Pill>
{/if}
</error-container>
<Tooltip
{anchor}
placement="bottom"
event="hover"
text={nft.isScam ? localize('error.nft.scamNft.short') : getAlertText(nft.downloadMetadata)}
<button type="button" on:click={onNftClick}>
<div class="flex-1 w-full flex relative bg-surface-2 dark:bg-surface-2-dark">
<NftMedia {nft} classes="min-w-full min-h-full object-cover" loop muted>
<MediaPlaceholder
type={nft?.type}
textColor={placeHolderColor}
downloading={$downloadingNftId === nft?.id}
size="md"
slot="placeholder"
/>
</div>
<div class="flex flex-col gap-2 p-3">
<nft-name class="w-full flex flex-row items-center justify-between gap-2">
<Text type="body2" truncate>{nft.name}</Text>
</nft-name>
<nft-pills class="flex flex-row items-center gap-2">
<NetworkAvatar networkId={nft.networkId} size="sm" showTooltip />
<AssetPillsForNft {nft} />
<AsyncPillsForNft {nft} />
</nft-pills>
</div>
</container>
</NftMedia>
<error-container bind:this={anchor} class="absolute left-3 top-3">
{#if nft.isScam}
<Pill color="warning">{localize('general.warning')}</Pill>
{:else if nft.downloadMetadata?.error || nft.downloadMetadata?.warning}
<Pill color={nft.downloadMetadata?.error ? 'danger' : 'warning'}>
{localize('general.' + (nft.downloadMetadata?.error ? 'error' : 'warning'))}
</Pill>
{/if}
</error-container>
<Tooltip
{anchor}
placement="bottom"
event="hover"
text={nft.isScam ? localize('error.nft.scamNft.short') : getAlertText(nft.downloadMetadata)}
/>
</div>
<div class="flex flex-col gap-2 p-3">
<nft-name class="w-full flex flex-row items-center justify-between gap-2">
<Text type="body2" truncate>{nft.name}</Text>
</nft-name>
<nft-pills class="flex flex-row items-center gap-2">
<NetworkAvatar networkId={nft.networkId} size="sm" showTooltip />
<AssetPillsForNft {nft} />
<AsyncPillsForNft {nft} />
</nft-pills>
</div>
</button>

<style lang="postcss">
.nft-gallery-item {
container {
@apply w-full overflow-hidden flex flex-col divide-y divide-solid divide-stroke dark:divide-stroke-dark;
@apply border border-solid border-stroke dark:border-stroke-dark;
@apply bg-surface-1 dark:bg-surface-1-dark;
@apply rounded-2xl;
@apply duration-300;
transition-property: background-color, border-color, box-shadow;
}
button {
@apply w-full overflow-hidden flex flex-col;
@apply divide-y divide-solid divide-stroke dark:divide-stroke-dark;
@apply border-2 border-solid border-stroke dark:border-stroke-dark;
@apply bg-surface-1 dark:bg-surface-1-dark;
@apply rounded-2xl;
@apply duration-300;
transition-property: background-color, border-color, box-shadow;
aspect-ratio: 3 / 4;
&:hover,
&:focus {
container {
@apply shadow-lg dark:shadow-violet-900/25;
@apply border-2 border-brand-500;
@apply bg-surface dark:bg-surface-dark;
}
@apply shadow-lg dark:shadow-violet-900/25;
@apply border-2 border-brand-500;
@apply bg-surface dark:bg-surface-dark;
}
}
error-container {
@apply absolute left-3 top-3;
}
</style>
1 change: 1 addition & 0 deletions packages/shared/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,7 @@
"token": "Token",
"unknownToken": "Unknown Token",
"nft": "NFT",
"nfts": "{count, plural, one {# NFT} other {# NFTs}}",
"type": "Type",
"immutableIssuer": "Immutable Issuer",
"magicContract": "Magic Contract",
Expand Down

0 comments on commit c898e89

Please sign in to comment.