Skip to content

Commit

Permalink
feat: improve highlight card by adding variants (#110)
Browse files Browse the repository at this point in the history
* feat: improve highlight card by adding variants

* perf: switch to css transitions

* fix: icon z index

* chore: duplicate highlight card component

* chore: fix props for story

* feat: add testing page for highlight card

* refactor: improve transitions and classes

* chore: remove unused component

* chore: revert app.svelte
  • Loading branch information
VmMad authored Apr 25, 2024
1 parent 9b670b5 commit 1c74e47
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 29 deletions.
19 changes: 8 additions & 11 deletions src/lib/components/atoms/animation/animation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,19 @@
let player: HTMLElement
let animation: AnimationItem | undefined
$: if (playOnHover) {
isHovered ? void animation?.play() : animation?.pause()
}
$: if (animation) {
animation.setSpeed(speed)
animation.setDirection(direction)
}
$: if (playOnHover && animation) {
if (isHovered) {
animation?.play()
} else {
animation?.pause()
}
}
onMount(() => {
animation = Lottie.loadAnimation({
renderer,
Expand All @@ -63,12 +67,6 @@
path: src,
})
})
function onMouseLeave(): void {
if (playOnHover) {
animation?.pause()
}
}
</script>

<dotlottie-player
Expand All @@ -79,7 +77,6 @@
autoplay={isMobileDevice() || (!playOnHover && autoplay)}
{loop}
role="img"
on:mouseleave={onMouseLeave}
/>

<style lang="postcss">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum HighlightCardVariant {
Static = 'static',
Hover = 'hover',
}
55 changes: 48 additions & 7 deletions src/lib/components/molecules/highlight-card/highlight-card.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import { Position, Align } from '$lib/enums'
import { isMobileDevice } from '$lib/utils'
import { MediaManager, type Media } from '../media-manager'
import { HighlightCardVariant } from './highlight-card.enums'
import {
ALIGNMENT_WITH_ICON,
CONTENT_ALIGNMENT,
Expand Down Expand Up @@ -46,7 +48,7 @@
export let link: string | null = null
/**
* The media to display
* The media to display in the background
* @type {Media}
*/
export let backgroundMedia: Media | null = null
Expand Down Expand Up @@ -74,6 +76,11 @@
*/
export let isExternal: boolean = false
/**
* The variant of the card
*/
export let variant: HighlightCardVariant = HighlightCardVariant.Static
let isHovered: boolean = false
$: itemsAlignClass = icon ? ALIGNMENT_WITH_ICON : ITEMS_ALIGNMENT_CLASSES[align]
Expand All @@ -86,6 +93,7 @@
target: isExternal ? '_blank' : null,
rel: isExternal ? 'noopener noreferrer' : null,
}
$: isHoverVariant = variant === HighlightCardVariant.Hover
function handleMouseEnter(): void {
if (!isMobileDevice()) {
Expand All @@ -105,11 +113,12 @@
on:mouseenter={handleMouseEnter}
on:mouseleave={handleMouseLeave}
class="highlight-card flex flex-col {backgroundColor} {itemsAlignClass}"
class:variant--hover={isHoverVariant}
{...link ? { ...externalLinkProps, href: link, role: 'link', tabindex: 0 } : {}}
>
{#if backgroundMedia}
<media-wrapper class="absolute inset-0 z-0 text-2xl">
<MediaManager media={backgroundMedia} pointerEventsNone playOnHover {isHovered} />
<media-wrapper class="absolute inset-0 z-0 text-2xl pointer-events-none">
<MediaManager media={backgroundMedia} {isHovered} playOnHover={isHoverVariant} />
</media-wrapper>
{/if}
{#if link}
Expand All @@ -122,11 +131,13 @@
</icon-link-wrapper>
{/if}
{#if icon}
<span class="text-white flex" class:justify-center={position === Position.Center}>
<span class="text-white flex z-[1]" class:justify-center={position === Position.Center}>
<Icon {icon} width={48} height={48} currentColor />
</span>
{/if}
<content-wrapper class="flex flex-col space-y-6 z-[1] {alignmentClass} {justifyClass}">
<content-wrapper
class="flex flex-col space-y-6 z-[1] overflow-hidden {alignmentClass} {justifyClass}"
>
<title-wrapper class="flex flex-col space-y-6">
<div
class="flex flex-col font-medium space-y-6"
Expand All @@ -148,7 +159,9 @@
</div>
</title-wrapper>
{#if description}
<p class="text-white/80">{description}</p>
<description class="text-white/80">
{description}
</description>
{/if}
</content-wrapper>
</svelte:element>
Expand All @@ -157,8 +170,36 @@
.highlight-card {
min-width: 312px;
max-width: 800px;
min-height: 480px;
aspect-ratio: 4/3;
@apply flex flex-col w-full relative p-12 rounded-xl overflow-hidden;
&.variant--hover {
description {
@apply max-h-0 opacity-0;
@apply mt-0;
transition:
max-height 300ms,
opacity 400ms,
margin-top 400ms;
@apply ease-in-out;
}
media-wrapper {
@apply opacity-0;
@apply duration-300 ease-in-out;
transition-property: opacity;
}
&:hover {
description {
@apply max-h-[500px] opacity-100;
@apply mt-6;
}
media-wrapper {
@apply opacity-100;
}
}
}
}
</style>
2 changes: 2 additions & 0 deletions src/lib/components/molecules/highlight-card/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default as HighlightCard } from './highlight-card.svelte'

export { HighlightCardVariant } from './highlight-card.enums'
13 changes: 5 additions & 8 deletions src/lib/components/molecules/media-manager/media-manager.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@
}
}
$: if (playOnHover) {
isHovered ? void videoElement?.play() : videoElement?.pause()
}
function onMouseLeave(): void {
if (playOnHover) {
isHovered = false
$: if (playOnHover && videoElement) {
if (isHovered) {
void videoElement.play()
} else {
videoElement.pause()
}
}
</script>
Expand All @@ -49,7 +47,6 @@
{poster}
class={objectFit}
class:pointer-events-none={pointerEventsNone}
on:mouseleave={onMouseLeave}
>
<source {src} type="video/mp4" />
</video>
Expand Down
30 changes: 27 additions & 3 deletions src/stories/molecules/highlight-card.stories.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,21 @@
type: 'boolean',
},
},
variant: {
control: {
type: 'select',
labels: getEnumLabels(HighlightCardVariant),
},
options: Object.values(HighlightCardVariant),
},
},
} satisfies Meta<HighlightCardComponent>
</script>

<script lang="ts">
import { Story, Template } from '@storybook/addon-svelte-csf'
import type { Meta } from '@storybook/svelte'
import { MediaType } from '$molecules'
import { HighlightCardVariant, MediaType } from '$molecules'
import { IconEnum } from '$components'
import { Align, Position } from '$lib/enums'
import { getEnumLabels } from '$storybook/utils/map-enum-labels'
Expand All @@ -84,11 +91,28 @@
subtitle: 'Subtitle',
icon: IconEnum.Atom,
backgroundMedia: {
src: 'https://lottie.host/f7277c23-b529-4c2a-ae08-0358068e792d/gbUnU4pWbh.json',
type: MediaType.Animation,
src: 'https://files.iota.org/media/ui-kit/cards/black/compressed/IOTA_card_black_6.mp4',
type: MediaType.Video,
},
link: 'https://iota.org',
description:
'Allowing the EVM chain to communicate outside of the chain and interact, through the IOTA/Shimmer layer, with other chains and even non-EVM chain smart contracts',
}}
/>

<Story
name="Hoverable Highlight Card"
args={{
title: 'Send IOTA Tokens with Javascript',
overline: 'Overline',
subtitle: 'Subtitle',
icon: IconEnum.Atom,
variant: HighlightCardVariant.Hover,
backgroundMedia: {
src: 'https://files.iota.org/media/ui-kit/cards/black/compressed/IOTA_card_black_6.mp4',
type: MediaType.Video,
},
description:
'Allowing the EVM chain to communicate outside of the chain and interact, through the IOTA/Shimmer layer, with other chains and even non-EVM chain smart contracts',
}}
/>

0 comments on commit 1c74e47

Please sign in to comment.