Add pagination and game cards to about page
This commit is contained in:
1 parent
cc085be17a
commit
5d04df8d54
5 files changed
+207
-45
No files matched your search
@@ -0,0 +1,115 @@
|
||||
<script lang="ts">
|
||||
import Icon from '@iconify/svelte';
|
||||
import type { Game } from '#lib/content';
|
||||
|
||||
let { game }: { game: Game } = $props();
|
||||
|
||||
const storeNames: Record<string, { label: string; icon: string }> = {
|
||||
'store.steampowered.com': { label: 'Steam', icon: 'mdi:steam' }
|
||||
};
|
||||
|
||||
const store = $derived.by(() => {
|
||||
const host = new URL(game.url).hostname;
|
||||
return storeNames[host] ?? { label: host.replace(/^www\./, ''), icon: 'mdi:web' };
|
||||
});
|
||||
</script>
|
||||
|
||||
<a class="game-card" href={game.url} target="_blank" rel="noopener noreferrer">
|
||||
<div class="cover">
|
||||
<img src={game.image} alt="" loading="lazy" />
|
||||
<span class="play"><Icon icon="mdi:play" width="16" /> Play</span>
|
||||
</div>
|
||||
<div class="details">
|
||||
<span class="name">{game.name}</span>
|
||||
<span class="store"><Icon icon={store.icon} width="14" />{store.label}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.game-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.45rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cover {
|
||||
position: relative;
|
||||
aspect-ratio: 16 / 9;
|
||||
overflow: hidden;
|
||||
background: var(--dark-background);
|
||||
border: 1px solid color-mix(in srgb, var(--foreground) 20%, transparent);
|
||||
transition: border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.game-card:hover .cover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.cover img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.game-card:hover .cover img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.play {
|
||||
position: absolute;
|
||||
right: 0.5rem;
|
||||
bottom: 0.5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.1rem 0.55rem;
|
||||
background: var(--accent);
|
||||
color: var(--background);
|
||||
font-size: 0.8rem;
|
||||
opacity: 0;
|
||||
transform: translateY(4px);
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
transform 0.2s ease;
|
||||
}
|
||||
|
||||
.game-card:hover .play,
|
||||
.game-card:focus-visible .play {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
overflow: hidden;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.store {
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
color: var(--muted);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.cover img,
|
||||
.play {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user