Skip to content

Instantly share code, notes, and snippets.

@arvidkahl
Created February 3, 2024 14:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arvidkahl/587fa2ff60e48ef2058d252438283538 to your computer and use it in GitHub Desktop.
Save arvidkahl/587fa2ff60e48ef2058d252438283538 to your computer and use it in GitHub Desktop.
Podscan's Card Stack
<template>
<div class="bg-white">
<div
@mouseenter="paused = true"
@mouseleave="paused = false"
@mouseover="paused = true"
@click="continueRotation()"
class="cardstack mt-24 xs:mt-28 sm:mt-24 mb-24 m-auto max-w-screen-sm grid grid-cols-1 grid-rows-1 select-none">
<article v-for="card in cards"
:key="card.name"
class="overflow-hidden border border-zinc-300 rounded rounded-4xl shadow-2xl shadow-black/[14%] backdrop-blur-md bg-white/50 transition-all duration-[400ms] hover:-top-1.5 row-start-1 col-start-1 flex flex-col">
<div
class="rounded-[inherit] shadow-inner-glow shadow-white/50 mix-blend-overlay absolute inset-0 -z-10"></div>
<header
class="cursor-pointer bg-gradient-to-b from-zinc-50/50 to-zinc-100/50 overflow-hidden shadow-subtle-lg border-b border-b-white/75 rounded-t-[inherit] h-[3.6rem] text-zinc-800">
<div
class="topbar | h-full flex gap-3 justify-between md:grid grid-cols-1fr-auto-1fr items-baseline py-3 px-6 ">
<div class="flex flex-row gap-x-1 text-sm pt-2 font-bold">
Your keyword <span
class="mx-1 border border-zinc-800 px-1.5 py-0 leading-5 rounded-md bg-white text-zinc-800 whitespace-nowrap text-xs">{{ card.keyword }}</span> was mentioned on a
{{ card.podcastType }} podcast.
</div>
</div>
</header>
<div class="CardContent flex flex-col md:flex-row justify-between grow w-full">
<div class="py-4 px-6 w-full">
<div>
<div class="flex justify-between ">
<img :src="card.image" class="w-12 h-12 mr-3 border border-zinc-800" alt="">
<div class="grow text-left">
<h2 class="text-zinc-500">on <span class="text-xl font-bold text-zinc-800">{{ card.podcast }}</span></h2>
<p class="text-sm text-zinc-500">{{ card.episodeNumber }}: <span class="text-zinc-800 font-bold">{{ card.episode }}</span></p>
</div>
<span class="block text-sm text-zinc-500 leading-4 text-right">
<span class="text-sm">published</span>
<span class="font-bold block text-zinc-800">{{ card.published }}</span>
</span>
</div>
<p class="text-sm text-zinc-500 mt-4 italic" v-html="card.fragment"/>
</div>
</div>
</div>
</article>
</div>
</div>
</template>
<script setup>
import {ref} from "vue";
let paused = ref(false);
let cards = ref([
{
name: 'Example 1',
image: '/images/tjre.webp',
keyword: 'sponsored by acquire.com',
podcast: 'Joe Rogan Experience',
episode: 'The Power of Influence',
episodeNumber: 'Episode 221',
podcastType: 'popular',
published: 'just now',
fragment: '…shoutout to our sponsor, acquire.com. And because this episode is <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">sponsored by acquire.com</span>, you get to use code ROGAN for 10% off your acquisition…',
},
{
name: 'Industry Trends',
keyword: 'using AI to automate my business',
image: '/images/mw.webp',
podcast: 'Morning Wire',
episode: 'The Future of Business',
episodeNumber: 'Episode 245',
podcastType: 'trending',
published: '23min ago',
fragment: '...the latest trend everyone is talking about is artificial intelligence. I want to start <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">using AI to automate my business</span>, but I have no clue where to start...',
},
{
name: 'Influencer Insights',
keyword: 'Sam Altman',
image: '/images/hibt.webp',
podcast: 'How I Built This',
episode: 'Disrupting Industries',
episodeNumber: 'Episode 329',
podcastType: 'trending',
published: 'last hour',
fragment: '...today we have a special guest, <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">Sam Altman</span>. He’s sharing his insights —and a few closely guarded secrets— on how AI will innovate and disrupt industries...',
},
{
name: 'Conversational Themes',
keyword: 'Mental Health in the Workplace',
image: '/images/ttd.webp',
podcast: 'TED Talks Daily',
episode: 'The Importance of Mental Health',
episodeNumber: 'Episode 210',
podcastType: 'popular',
published: '45min ago',
fragment: '...data shows that the importance of <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">mental health in the workplace</span> is more impactful than ever. And there are quire a few startups out there trying to...',
},
{
name: 'Competitor Analysis',
keyword: 'HubSpot',
image: '/images/ra.webp',
podcast: 'Reply All',
episode: 'The Tech Wars — Interview with HubSpot\'s Biggest Competitor',
episodeNumber: 'Episode 135',
podcastType: 'new',
published: '2h ago',
fragment: '...just noticed the other day that our competitor, <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">HubSpot</span>, has launched their new product just this week, and we plan to outmaneuver them by...',
},
{
name: 'Potential Partnerships',
keyword: 'partnered with myBrand',
image: '/images/tdrs.webp',
podcast: 'The Dave Ramsey Show',
episode: 'Saving the Planet',
episodeNumber: 'Episode 132',
podcastType: 'viral',
published: '5h ago',
fragment: '...as no surprise that we’ve <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">partnered with myBrand</span> to make this happen. They’re doing great things in the eco-friendly space, and I believe they still have a lot of capacity. So why not…',
},
{
name: 'Keyword Optimization',
keyword: 'blockchain tech*',
podcast: 'Freakonomics Radio',
image: '/images/fr.webp',
episode: 'How Blockchain Might Change Everything',
episodeNumber: 'Episode 210',
podcastType: 'popular',
published: '20min ago',
fragment: '...and as we spoke to him in his Florida mansion, it dawned on me just how quickly <span class="bg-zinc-800 px-1 py-0.5 mr-1 rounded-md text-white whitespace-nowrap">blockchain technology</span> is poised to revolutionize finance as we know it...',
},
])
// shuffle the cards
cards.value = cards.value.sort(() => Math.random() - 0.5)
function continueRotation() {
cards.value.unshift(cards.value.pop())
}
// every 3 seconds, move the last card to the front
setInterval(() => {
if (paused.value) return;
continueRotation()
}, 5000)
</script>
<style scoped>
.cardstack {
--card-offset: 2.35rem;
--scale-factor: .07;
--opacity-factor: .23;
}
.cardstack > article {
will-change: transform, opacity;
transform: translateY(calc(var(--index) * -1 * var(--card-offset))) scale(calc(1 - var(--index) * var(--scale-factor)));
opacity: calc(1 - var(--index) * var(--opacity-factor));
transition: transform .5s ease-in-out, opacity .5s ease-in-out;
transition-property: all;
}
.cardstack > article:hover {
opacity: calc(1 - var(--index) * var(--opacity-factor) + .3)
}
.cardstack > article .CardContent {
opacity: 0
}
.cardstack > article:nth-child(5) .CardContent, .cardstack > article:nth-child(6) .CardContent, .cardstack > article:nth-child(7) .CardContent {
opacity: 1
}
.cardstack > article:nth-child(-n+4) {
-webkit-backdrop-filter: none;
backdrop-filter: none
}
.cardstack > article:nth-child(1) {
--index: 5
}
.cardstack > article:nth-child(2) {
--index: 4
}
.cardstack > article:nth-child(3) {
--index: 3
}
.cardstack > article:nth-child(4) {
--index: 2
}
.cardstack > article:nth-child(5) {
--index: 1
}
.cardstack > article:nth-child(6) {
--index: 0
}
.cardstack > article:nth-child(7) {
transition: transform .3s ease-in, opacity .3s ease-in;
transform: translateY(var(--card-offset)) scale(1.1);
opacity: 0;
pointer-events: none
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment