Skip to content

Commit

Permalink
Add hover transitions and partners page, update NumberTicker componen…
Browse files Browse the repository at this point in the history
…t and stats on homepage, and refactor img-src directive (#147)

This pull request includes several changes:

- The "refactor: Add hover transitions" commit adds hover transitions to a Svelte component.

- The "feat: add partners page" commit adds a new page to display partnerships with other communities.

- The "feat: Add NumberTicker component" commit adds a new Svelte component called NumberTicker.

- The "feat: add stats to homepage" commit adds statistics to the homepage.

- The "refactor: Update img-src directive in svelte.config.js" commit updates the img-src directive in the svelte.config.js file.

- The "chore: Update npm dependencies to latest versions" commit updates the npm dependencies to their latest versions.

These changes improve the user experience by adding hover transitions, a new partners page, a NumberTicker component, and statistics on the homepage. The img-src directive in the svelte.config.js file is also updated for better security.
  • Loading branch information
DarthGigi authored Aug 20, 2024
2 parents 32c44fe + 2d48e55 commit 81d5969
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 251 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
},
"devDependencies": {
"@eslint/js": "^9.9.0",
"@jill64/universal-sanitizer": "^1.3.0",
"@jill64/universal-sanitizer": "^1.3.1",
"@lucia-auth/adapter-prisma": "4.0.1",
"@sveltejs/adapter-vercel": "^5.4.3",
"@sveltejs/kit": "^2.5.22",
"@sveltejs/kit": "^2.5.24",
"@sveltejs/vite-plugin-svelte": "^3.1.1",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.7",
"@types/cookie": "^0.6.0",
"@types/node": "^22.4.0",
"@types/node": "^22.4.1",
"@vercel/analytics": "^1.3.1",
"autoprefixer": "^10.4.20",
"date-fns-tz": "^3.1.3",
Expand All @@ -42,7 +42,7 @@
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.6",
"prettier-plugin-tailwindcss": "^0.6.6",
"shiki": "^1.13.0",
"shiki": "^1.14.1",
"svelte": "^4.2.18",
"svelte-check": "^3.8.5",
"svelte-headless-table": "^0.18.2",
Expand All @@ -52,14 +52,14 @@
"tailwindcss": "^3.4.10",
"tslib": "^2.6.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0",
"vite": "^5.4.1"
"typescript-eslint": "^8.2.0",
"vite": "^5.4.2"
},
"type": "module",
"dependencies": {
"@node-rs/argon2": "^1.8.3",
"@oslojs/oauth2": "^0.5.0",
"@oslojs/webauthn": "^0.6.3",
"@oslojs/webauthn": "^0.6.4",
"@prisma/client": "5.18.0",
"@prisma/extension-accelerate": "^1.1.0",
"@sentry/svelte": "^8.26.0",
Expand Down
466 changes: 233 additions & 233 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/lib/components/magicui/number-ticker.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import { cn } from "$lib/utils";
import { onMount } from "svelte";
import { cubicOut } from "svelte/easing";
import { tweened } from "svelte/motion";
export let value = 100;
export let initial = 0;
export let duration = 6000;
let num = tweened(initial, {
duration: duration,
easing: cubicOut
});
let className: string = "";
export { className as class };
onMount(() => {
num.set(value);
});
</script>

<div class={cn("inline-block tracking-normal", className)} {...$$restProps}>
{$num.toFixed(0)}
</div>
21 changes: 13 additions & 8 deletions src/lib/layouts/Navbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import CircleHelp from "lucide-svelte/icons/circle-help";
import Code from "lucide-svelte/icons/code";
import Cog from "lucide-svelte/icons/cog";
import Handshake from "lucide-svelte/icons/handshake";
import House from "lucide-svelte/icons/house";
import Info from "lucide-svelte/icons/info";
import LayoutDashboard from "lucide-svelte/icons/layout-dashboard";
Expand All @@ -33,35 +34,39 @@
<div class="flex h-16 flex-row justify-between">
<div class="flex flex-shrink-0 items-center">
<DropdownMenu.Root bind:open={menuDropdownOpen}>
<DropdownMenu.Trigger class="flex items-center gap-2 rounded-md px-4 py-2 hover:bg-popover">
<DropdownMenu.Trigger class="flex items-center gap-2 rounded-md px-4 py-2 transition-colors duration-300 hover:bg-popover">
<img class="pointer-events-none block h-8 w-auto transition-transform duration-300 ease-in-out" src="/favicon.png" alt="Minion AH" class:rotate-45={menuDropdownOpen} class:max-md:-rotate-45={menuDropdownOpen} />
<h1>MinionAH<span class="sr-only">: The Auction House for SkyBlock Minions</span></h1>
<ChevronDown class="h-4 w-4" />
</DropdownMenu.Trigger>
<DropdownMenu.Content class="w-44 border-border bg-popover" transitionConfig={{ duration: 300 }}>
<DropdownMenu.Group>
<DropdownMenu.Item class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="/">
<DropdownMenu.Item class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="/">
<House class="size-4" />Home
</DropdownMenu.Item>
<DropdownMenu.Separator class="bg-border" />
<DropdownMenu.Item target="_blank" class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com">
<DropdownMenu.Item target="_blank" class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com">
<Newspaper class="size-4" />Newsroom
</DropdownMenu.Item>
<DropdownMenu.Item target="_blank" class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="https://discord.minionah.com">
<DropdownMenu.Item target="_blank" class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="https://discord.minionah.com">
<Users class="size-4" />Community
</DropdownMenu.Item>
<DropdownMenu.Separator class="bg-border" />
<DropdownMenu.Item target="_blank" class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com/minionah/">
<DropdownMenu.Item class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="/partners">
<Handshake class="size-4" />Partners
</DropdownMenu.Item>
<DropdownMenu.Separator class="bg-border" />
<DropdownMenu.Item target="_blank" class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com/minionah/">
<CircleHelp class="size-4" />About
</DropdownMenu.Item>
<DropdownMenu.Item target="_blank" class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="https://github.com/DarthGigi/MinionAH">
<DropdownMenu.Item target="_blank" class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="https://github.com/DarthGigi/MinionAH">
<Code class="size-4" /> GitHub
</DropdownMenu.Item>
<DropdownMenu.Separator class="bg-border" />
<DropdownMenu.Item target="_blank" class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com/privacy-policy">
<DropdownMenu.Item target="_blank" class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com/privacy-policy">
<Scale class="size-4" />Privacy Policy
</DropdownMenu.Item>
<DropdownMenu.Item target="_blank" class="gap-1.5 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com/terms-of-service">
<DropdownMenu.Item target="_blank" class="gap-1.5 transition-colors duration-300 hover:cursor-pointer data-[highlighted]:bg-background" href="https://newsroom.minionah.com/terms-of-service">
<Scale class="size-4" />Terms of Service
</DropdownMenu.Item>
</DropdownMenu.Group>
Expand Down
33 changes: 32 additions & 1 deletion src/routes/(main)/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const load = (async () => {
}
}
},
// @ts-expect-error - This isn't typed yet
cacheStrategy: {
ttl: 30,
swr: 60
Expand All @@ -40,6 +41,7 @@ export const load = (async () => {
orderBy: {
generator: "asc"
},
// @ts-expect-error - This isn't typed yet
cacheStrategy: {
ttl: 2629746 // 1 month
}
Expand All @@ -49,13 +51,42 @@ export const load = (async () => {
id: true,
username: true
},
// @ts-expect-error - This isn't typed yet
cacheStrategy: {
ttl: 86400, // 1 day
swr: 60 // 1 minute
},
orderBy: {
loggedInAt: "desc"
}
})
}),
stats: {
users: prisma.user.count({
// @ts-expect-error - This isn't typed yet
cacheStrategy: {
ttl: 86400, // 1 day
swr: 60 // 1 minute
}
}),
auctions: prisma.auction.count({
// @ts-expect-error - This isn't typed yet
cacheStrategy: {
ttl: 30,
swr: 60
}
}),
chats: prisma.chat.count({
where: {
messages: {
some: {}
}
},
// @ts-expect-error - This isn't typed yet
cacheStrategy: {
ttl: 43200, // 12 hours
swr: 60
}
})
}
};
}) as PageServerLoad;
50 changes: 49 additions & 1 deletion src/routes/(main)/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@
import { MinionCard } from "$lib/components/card";
import { GradualSpacing } from "$lib/components/magicui";
import AnimatedShinyText from "$lib/components/magicui/animated-shiny-text.svelte";
import NumberTicker from "$lib/components/magicui/number-ticker.svelte";
import { Button } from "$lib/components/ui/button";
import * as Card from "$lib/components/ui/card";
import { Label } from "$lib/components/ui/label";
import { internalPreferences, preferences } from "$lib/stores/preferences";
import { searchSignal } from "$lib/stores/signals";
import type { Seller } from "$lib/types";
import { cn } from "$lib/utils";
import ArrowRight from "lucide-svelte/icons/arrow-right";
import ChevronsUpDown from "lucide-svelte/icons/chevrons-up-down";
import LayoutGrid from "lucide-svelte/icons/layout-grid";
import MessagesSquare from "lucide-svelte/icons/messages-square";
import Users from "lucide-svelte/icons/users";
import { onMount } from "svelte";
import { infiniteScrollAction } from "svelte-legos";
import SvelteSeo from "svelte-seo";
Expand Down Expand Up @@ -241,6 +246,7 @@
}} />

<h2 class="sr-only">MinionAH - The Auction House for SkyBlock Minions</h2>

<div class="mt-8 h-10 md:mt-20 md:h-20">
<GradualSpacing class="text-center text-4xl font-bold tracking-[-0.1em] text-white md:text-7xl md:leading-[5rem]" text="MinionAH" />
</div>
Expand All @@ -251,8 +257,50 @@
</AnimatedShinyText>
</Button>

<div class="mx-auto mt-[1.375rem] flex gap-1 px-1 md:max-w-2xl md:gap-2 md:px-2">
<Card.Root class="w-full border-border bg-transparent">
<Card.Header class="flex flex-row items-center justify-center gap-2 space-y-0 pb-2">
<Users class="h-4 w-4 text-muted-foreground" />
<Card.Title class="text-sm font-medium">Users</Card.Title>
</Card.Header>
<Card.Content>
{#await data.stats.users}
<div class="h-12 w-20 animate-pulse rounded-lg bg-background"></div>
{:then users}
<NumberTicker class="w-full text-center text-3xl font-bold md:text-5xl" value={users} />
{/await}
</Card.Content>
</Card.Root>
<Card.Root class="w-full border-border bg-transparent">
<Card.Header class="flex flex-row items-center justify-center gap-2 space-y-0 pb-2">
<LayoutGrid class="h-4 w-4 text-muted-foreground" />
<Card.Title class="text-sm font-medium">Auctions</Card.Title>
</Card.Header>
<Card.Content>
{#await data.stats.auctions}
<div class="h-12 w-20 animate-pulse rounded-lg bg-background"></div>
{:then auctions}
<NumberTicker class="w-full text-center text-3xl font-bold md:text-5xl" value={auctions} />
{/await}
</Card.Content>
</Card.Root>
<Card.Root class="w-full border-border bg-transparent">
<Card.Header class="flex flex-row items-center justify-center gap-2 space-y-0 pb-2">
<MessagesSquare class="h-4 w-4 text-muted-foreground" />
<Card.Title class="text-sm font-medium">Chats</Card.Title>
</Card.Header>
<Card.Content>
{#await data.stats.chats}
<div class="h-12 w-20 animate-pulse rounded-lg bg-background"></div>
{:then chats}
<NumberTicker class="w-full text-center text-3xl font-bold md:text-5xl" value={chats} />
{/await}
</Card.Content>
</Card.Root>
</div>

<div class="mx-auto w-fit">
<div class="flex flex-col items-start justify-center gap-4 px-4 pt-8 sm:flex-row sm:items-end sm:px-6 sm:py-20 lg:px-8">
<div class="flex flex-col items-start justify-center gap-4 px-4 pt-8 sm:flex-row sm:items-end sm:px-6 sm:pt-20 lg:px-8">
<div class="flex flex-col justify-center space-y-2">
<Label>Search</Label>

Expand Down
17 changes: 17 additions & 0 deletions src/routes/(misc)/partners/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import PartnerCard from "./partner-card.svelte";
import { partners } from "./partners";
</script>

<div class="relative mx-auto flex w-full max-w-sm flex-col items-center justify-center gap-3">
<h2 class="text-center text-6xl font-semibold leading-none text-foreground">Partnerships</h2>
<p class="text-center text-xs text-accent">We are proud to be partnered with the following communities. <br /> If you are interested in partnering with us, please reach out to us.</p>
</div>

<div class="py-8 max-md:pb-20">
<div class="mx-auto flex max-w-7xl flex-wrap items-center justify-center gap-6 px-4 sm:px-6 lg:px-8">
{#each partners as partner}
<PartnerCard cardData={partner} />
{/each}
</div>
</div>
56 changes: 56 additions & 0 deletions src/routes/(misc)/partners/partner-card.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script lang="ts">
import * as Avatar from "$lib/components/ui/avatar";
import * as Card from "$lib/components/ui/card";
import * as Tooltip from "$lib/components/ui/tooltip";
import Earth from "lucide-svelte/icons/earth";
import type { CardData } from "./partners";
export let cardData: CardData;
</script>

<Card.Root class="max-w-[32rem] border-border bg-background">
<Card.Header class="flex flex-col items-center justify-center space-y-0 max-md:gap-6 md:flex-row md:justify-between">
<a href={cardData.links[0].url} target="_blank" rel="noopener noreferrer" class="group flex flex-row items-center justify-start gap-2">
<Avatar.Root class="pointer-events-none select-none">
<Avatar.Image src={cardData.image} alt={cardData.title} class="transition-all duration-300 group-hover:brightness-150" />
<Avatar.Fallback class="transition-all duration-300 group-hover:brightness-150">{cardData.title.slice(0, 2).toUpperCase()}</Avatar.Fallback>
</Avatar.Root>
<div class="flex flex-col">
<Card.Title>{cardData.title}</Card.Title>
{#if cardData.subTitle}
<Card.Description>{cardData.subTitle}</Card.Description>
{/if}
</div>
</a>
<div class="flex flex-row-reverse flex-wrap items-center justify-center gap-2">
{#each cardData.links as link}
<Tooltip.Root openDelay={100} closeDelay={0} group="links" closeOnPointerDown={true} closeOnEscape={true}>
<Tooltip.Trigger asChild let:builder class="group">
<a href={link.url} target="_blank" rel="noopener noreferrer" class="group" use:builder.action {...builder} title={link.url}>
<Avatar.Root class="size-7 select-none">
<Avatar.Image class="pointer-events-none h-full w-full rounded-full bg-accent p-0.5 transition-all duration-300 group-hover:p-0" src={`/api/internal/favicon/${encodeURIComponent(link.url.toString())}`} alt="Favicon" />
<Avatar.Fallback class="pointer-events-none h-full w-full rounded-full bg-accent p-0.5 transition-all duration-300 group-hover:p-0">
<Earth />
</Avatar.Fallback>
</Avatar.Root>
</a>
</Tooltip.Trigger>
<Tooltip.Content class="border-border bg-popover">
<p>{link.name}</p>
</Tooltip.Content>
</Tooltip.Root>
{/each}
</div>
</Card.Header>
<Card.Content class="text-sm">
<p>{cardData.description}</p>
</Card.Content>
<Card.Footer class="flex flex-1 items-center justify-center">
<Avatar.Root asChild>
<a href={cardData.links[0].url} target="_blank" rel="noopener noreferrer" class="group relative flex aspect-video h-auto w-full shrink-0 overflow-hidden rounded-xl border border-border shadow-sm">
<Avatar.Image src={cardData.banner} alt={cardData.title} class="pointer-events-none select-none transition-all duration-300 group-hover:brightness-150" />
<Avatar.Fallback class="pointer-events-none select-none rounded-xl transition-all duration-300 group-hover:brightness-150">{cardData.title.slice(0, 2).toUpperCase()}</Avatar.Fallback>
</a>
</Avatar.Root>
</Card.Footer>
</Card.Root>
31 changes: 31 additions & 0 deletions src/routes/(misc)/partners/partners.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export type CardData = {
image: string;
title: string;
subTitle?: string;
description: string;
banner?: string;
links: {
name: string;
url: string;
}[];
};

export const partners: CardData[] = [
{
image: "https://res.cloudinary.com/minionah/image/upload/v1/partners/icons/skyblock%20university",
title: "Skyblock University",
subTitle: "@sbuni",
description: "Skyblock University was founded with one goal in mind: to help brand new, early, and mid-game Hypixel Skyblock players by empowering them and equipping them with the tools, resources, and mentors they need to continually grow, learn, and progress.",
banner: "https://res.cloudinary.com/minionah/image/upload/v1/partners/banners/skyblock%20university%20banner",
links: [
{
name: "Discord",
url: "https://discord.gg/sbuni"
},
{
name: "Hypixel Forums",
url: "https://hypixel.net/threads/skyblock-university-helping-early-and-mid-game-players-no-reqs-friendly-and-welcoming-community-5-3k-member-discord-9-guilds.5730713/"
}
]
}
];
2 changes: 1 addition & 1 deletion svelte.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const config = {
directives: {
"script-src": ["self", "unsafe-eval", "https://*.vercel-scripts.com", "https://*.vercel.app", "https://*.pusher.com", "sha256-y2WkUILyE4eycy7x+pC0z99aZjTZlWfVwgUAfNc1sY8="],
"worker-src": ["self", "blob:", "https://*.minionah.com"],
"img-src": ["self", "data:", "https://*.vercel.app", "https://*.vercel-scripts.com", "https://*.imgur.com", "https://*.imgbb.com", "https://*.vgy.me", "https://*.gyazo.com", "https://*.prnt.sc", "https://*.prntscr.com", "https://*.tenor.com", "https://*.giphy.com", "https://*.gfycat.com", "https://*.discordapp.net", "https://*.discordapp.com", "https://*.discord.com", "https://*.minionah.com", "https://*.cloudinary.com"],
"img-src": ["self", "data:", "https://*.vercel.app", "https://*.vercel-scripts.com", "https://*.imgur.com", "https://*.imgbb.com", "https://*.vgy.me", "https://*.gyazo.com", "https://*.prnt.sc", "https://*.prntscr.com", "https://*.tenor.com", "https://*.giphy.com", "https://*.gfycat.com", "https://*.discordapp.net", "https://*.discordapp.com", "https://*.discord.com", "https://*.minionah.com", "https://*.cloudinary.com", "https://*.hypixel.net"],
"style-src": ["self", "unsafe-inline"]
},
mode: "auto"
Expand Down

0 comments on commit 81d5969

Please sign in to comment.