Skip to content

Commit

Permalink
carousel
Browse files Browse the repository at this point in the history
  • Loading branch information
almeidx committed May 21, 2024
1 parent c4e8104 commit 10d3e5c
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 48 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"@next/third-parties": "^14.2.3",
"@sindresorhus/slugify": "^2.2.1",
"clsx": "^2.1.1",
"embla-carousel-auto-scroll": "^8.1.3",
"embla-carousel-react": "^8.1.3",
"jwt-decode": "^4.0.0",
"match-sorter": "^6.3.4",
"next": "^14.2.3",
Expand Down
40 changes: 40 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions src/app/featured-guilds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"use client";

import discoverableSvg from "@/assets/guild-badges/discoverable.svg";
import partnerSvg from "@/assets/guild-badges/partner.svg";
import verifiedSvg from "@/assets/guild-badges/verified.svg";
import { ImageWithFallback } from "@/components/ImageWithFallback.tsx";
import { type Snowflake, guildIcon } from "@/utils/discord-cdn.ts";
import { formatToNearestOrderOfMagnitude } from "@/utils/format-to-nearest-order-of-magnitude.ts";
import AutoScroll from "embla-carousel-auto-scroll";
import useEmblaCarousel from "embla-carousel-react";
import Image from "next/image";

export function FeaturedGuilds({ guilds, startDelay = 0 }: FeaturedGuildsProps) {
const [emblaRef] = useEmblaCarousel({ loop: true, dragFree: true }, [AutoScroll({ speed: 0.75, startDelay })]);

return (
<div className="overflow-hidden relative" ref={emblaRef}>
<div className="flex">
{guilds.map((guild) => (
<div
className="basis-full sm:basis-1/2 lg:basis-1/3 xl:basis-1/4 shrink-0 min-w-0 mr-4"
key={`featured-${guild.id}`}
>
<FeaturedGuild key={guild.id} {...guild} />
</div>
))}
</div>

<div className="absolute left-0 inset-y-0 right-[90%] bg-gradient-to-l from-transparent to-background" />
<div className="absolute right-0 inset-y-0 left-[90%] bg-gradient-to-r from-transparent to-background" />
</div>
);
}

function FeaturedGuild({ id, icon, name, memberCount, partner, verified }: FeaturedGuild) {
const iconSrc = verified ? verifiedSvg : partner ? partnerSvg : discoverableSvg;
const alt = verified ? "Verified guild badge" : partner ? "Partner guild badge" : "Discoverable guild badge";

return (
<div className="flex items-center gap-4 md:gap-6 bg-darker px-3 py-2 border border-white/25 rounded-lg select-none">
<ImageWithFallback
alt={`${name}'s icon`}
className="rounded-full size-14 md:size-16 no-drag"
height={64}
src={guildIcon(id, icon, { format: "webp", size: 64 })}
priority
width={64}
/>

<div className="flex flex-col">
<p className="flex items-center gap-2 text-xl md:text-2xl font-bold text-ellipsis" title={name}>
<Image src={iconSrc} alt={alt} width={20} height={20} className="size-5 rounded-full no-drag" />
{name}
</p>
<p className="text-md md:text-lg text-white/50">
{formatToNearestOrderOfMagnitude(memberCount).toLocaleString("en")} members
</p>
</div>
</div>
);
}

interface FeaturedGuildsProps {
readonly guilds: readonly FeaturedGuild[];
readonly startDelay?: number;
}

export interface FeaturedGuild {
id: Snowflake;
name: string;
icon: string | null;
memberCount: number;
verified: boolean;
partner: boolean;
}
12 changes: 12 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,15 @@ img {
*::placeholder {
@apply !text-white/50;
}

.no-drag {
-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
user-drag: none;
}

.slick-slide {
@apply mx-4;
}
2 changes: 1 addition & 1 deletion src/app/guilds/guild-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function DashboardGuildList({ guilds }: { readonly guilds: GuildInfo[] })
<div className="mt-12 flex items-center gap-4">
<input
type="text"
placeholder="Enter a server name of id…"
placeholder="Enter a server name or id…"
className="h-10 w-72 rounded-lg bg-light-gray px-4 py-3 shadow-sm md:w-96"
value={term}
onChange={(event) => setTerm(event.target.value)}
Expand Down
61 changes: 14 additions & 47 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import discoverableSvg from "@/assets/guild-badges/discoverable.svg";
import partnerSvg from "@/assets/guild-badges/partner.svg";
import verifiedSvg from "@/assets/guild-badges/verified.svg";
import { type FeaturedGuild, FeaturedGuilds } from "@/app/featured-guilds.tsx";
import logoImg from "@/assets/logo.png";
import importImg from "@/assets/showcases/import.png";
import levelingImg from "@/assets/showcases/leveling.png";
Expand All @@ -9,11 +7,8 @@ import premiumImg from "@/assets/showcases/premium.png";
import rankCardsImg from "@/assets/showcases/rank-cards.png";
import roleRewardsImg from "@/assets/showcases/role-rewards.png";
import { ExternalLink } from "@/components/ExternalLink.tsx";
import { ImageWithFallback } from "@/components/ImageWithFallback.tsx";
import { Showcase } from "@/components/Showcase";
import { type Snowflake, guildIcon } from "@/utils/discord-cdn.ts";
import { formatNumber } from "@/utils/format-number.ts";
import { formatToNearestOrderOfMagnitude } from "@/utils/format-to-nearest-order-of-magnitude.ts";
import { makeApiRequest } from "@/utils/make-api-request.ts";
import { AttachMoney, Brush, CloudDownload, Launch, MilitaryTech, Speed, TrendingUp } from "@mui/icons-material";
import Image from "next/image";
Expand All @@ -26,6 +21,10 @@ export default async function Homepage() {
featured,
} = await getData();

const half = Math.ceil(featured.length / 2);
const featured1 = featured.slice(0, half);
const featured2 = featured.slice(half);

return (
<div className="flex flex-col items-center gap-10 mb-8 py-4">
<div className="flex flex-col items-center gap-4 xl:gap-0">
Expand Down Expand Up @@ -90,10 +89,15 @@ export default async function Homepage() {
Trusted by Discord Servers <span className="italic">you</span> know!
</p>

<div className="container flex flex-row flex-wrap gap-y-4 gap-x-6 justify-center mb-4 mx-4 md:mx-0">
{featured.map((guild) => (
<FeaturedGuild key={guild.id} {...guild} />
))}
<div className="container flex flex-col space-y-4">
{featured.length > 8 ? (
<>
<FeaturedGuilds guilds={featured1} />
<FeaturedGuilds guilds={featured2} />
</>
) : (
<FeaturedGuilds guilds={featured} />
)}
</div>
</>
) : null}
Expand Down Expand Up @@ -190,34 +194,6 @@ function ShowcaseSeparator() {
return <div className="my-4 h-6 w-[2px] bg-gradient-radial" />;
}

function FeaturedGuild({ id, icon, name, memberCount, partner, verified }: FeaturedGuild) {
const iconSrc = verified ? verifiedSvg : partner ? partnerSvg : discoverableSvg;
const alt = verified ? "Verified guild badge" : partner ? "Partner guild badge" : "Discoverable guild badge";

return (
<div className="flex items-center gap-4 md:gap-6 bg-darker px-3 py-2 border border-white/25 rounded-lg">
<ImageWithFallback
alt={`${name}'s icon`}
className="rounded-full size-14 md:size-16"
height={64}
src={guildIcon(id, icon, { format: "webp", size: 64 })}
priority
width={64}
/>

<div className="flex flex-col">
<p className="flex items-center gap-2 text-xl md:text-2xl font-bold text-ellipsis" title={name}>
<Image src={iconSrc} alt={alt} width={20} height={20} className="size-5 rounded-full" />
{name}
</p>
<p className="text-md md:text-lg text-white/50">
{formatToNearestOrderOfMagnitude(memberCount).toLocaleString("en")} members
</p>
</div>
</div>
);
}

async function getData() {
const [statsResponse, featuredResponse] = await Promise.allSettled([
makeApiRequest("/stats", null, {
Expand Down Expand Up @@ -253,12 +229,3 @@ interface StatsResponse {
messageCount: number;
uptime: number;
}

interface FeaturedGuild {
id: Snowflake;
name: string;
icon: string | null;
memberCount: number;
verified: boolean;
partner: boolean;
}

0 comments on commit 10d3e5c

Please sign in to comment.