mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-28 04:59:50 +01:00
feat: discord plug
This commit is contained in:
1 parent
8ef355c574
commit
3d940f4b47
7 files changed
+250
-4
No files matched your search
@@ -824,6 +824,12 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"home": {
|
"home": {
|
||||||
|
"discord": {
|
||||||
|
"join_short": "Join cool people!",
|
||||||
|
"join_long": "Join super duper cool people!",
|
||||||
|
"action": "Discord"
|
||||||
|
},
|
||||||
|
|
||||||
"hero": {
|
"hero": {
|
||||||
"credit": "By %s1 ❤️"
|
"credit": "By %s1 ❤️"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function BlitzKitTheme({
|
|||||||
}: BlitzKitThemeProps) {
|
}: BlitzKitThemeProps) {
|
||||||
return (
|
return (
|
||||||
<Theme
|
<Theme
|
||||||
style={{ minHeight: 'unset', ...style }}
|
style={{ minHeight: 'unset', display: 'contents', ...style }}
|
||||||
className={`blitzkit-theme ${className}`}
|
className={`blitzkit-theme ${className}`}
|
||||||
grayColor="mauve"
|
grayColor="mauve"
|
||||||
appearance="dark"
|
appearance="dark"
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
:root {
|
||||||
|
--scroll-time: 80s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroller-0 {
|
||||||
|
animation: move-1 var(--scroll-time) linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroller-1 {
|
||||||
|
animation-delay: var(--scroll-time);
|
||||||
|
animation: move-1 var(--scroll-time) linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move-1 {
|
||||||
|
from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
import { assertSecret } from '@blitzkit/core';
|
||||||
|
import { CaretRightIcon } from '@radix-ui/react-icons';
|
||||||
|
import { Box, Button, Flex, Link, Text } from '@radix-ui/themes';
|
||||||
|
import { times } from 'lodash-es';
|
||||||
|
import { getStrings } from '../../core/i18n/getStrings';
|
||||||
|
import { Var } from '../../core/radix/var';
|
||||||
|
import type { LocaleAcceptorProps } from '../../hooks/useLocale';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
export interface DiscordWidget {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
instant_invite: string;
|
||||||
|
channels: any[];
|
||||||
|
members: Member[];
|
||||||
|
presence_count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Member {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
discriminator: string;
|
||||||
|
avatar: null;
|
||||||
|
status: Status;
|
||||||
|
avatar_url: string;
|
||||||
|
game?: Game;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Game {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Status {
|
||||||
|
DND = 'dnd',
|
||||||
|
Idle = 'idle',
|
||||||
|
Online = 'online',
|
||||||
|
}
|
||||||
|
|
||||||
|
const COLUMN_COUNT = 3;
|
||||||
|
|
||||||
|
const discordServerId = assertSecret(import.meta.env.PUBLIC_DISCORD_SERVER_ID);
|
||||||
|
const widget = await fetch(
|
||||||
|
`https://discord.com/api/guilds/${discordServerId}/widget.json`,
|
||||||
|
).then((response) => response.json() as Promise<DiscordWidget>);
|
||||||
|
const filteredMembers = widget.members
|
||||||
|
.filter((member) => {
|
||||||
|
const isPrivateUsername =
|
||||||
|
member.username.length === 4 && member.username.endsWith('...');
|
||||||
|
return !isPrivateUsername;
|
||||||
|
})
|
||||||
|
.sort(() => Math.random() - 0.5);
|
||||||
|
|
||||||
|
const columnSize = Math.floor(filteredMembers.length / COLUMN_COUNT);
|
||||||
|
const columns = times(COLUMN_COUNT, (index) => {
|
||||||
|
const start = index * columnSize;
|
||||||
|
const end = start + columnSize;
|
||||||
|
return filteredMembers.slice(start, end);
|
||||||
|
});
|
||||||
|
|
||||||
|
function Member({ id, avatar_url, username, status }: Member) {
|
||||||
|
let statusColor: string;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case Status.DND:
|
||||||
|
statusColor = Var('red-9');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Status.Idle:
|
||||||
|
statusColor = Var('amber-9');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Status.Online:
|
||||||
|
statusColor = Var('jade-9');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
maxWidth: '8rem',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
color="gray"
|
||||||
|
>
|
||||||
|
<Flex key={id} align="center" gap="2" flexShrink="0">
|
||||||
|
<Box width="1.5em" height="1.5em" flexShrink="0" position="relative">
|
||||||
|
<img
|
||||||
|
src={avatar_url}
|
||||||
|
alt={`${username} profile picture`}
|
||||||
|
style={{ width: '100%', height: '100%', borderRadius: '50%' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
width="0.5em"
|
||||||
|
height="0.5em"
|
||||||
|
position="absolute"
|
||||||
|
bottom="0"
|
||||||
|
right="0"
|
||||||
|
style={{ borderRadius: '50%', backgroundColor: statusColor }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{username}
|
||||||
|
</Flex>
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Scroller({ index }: { index: number }) {
|
||||||
|
return (
|
||||||
|
<Flex gap="6" className={`scroller-${index}`} pt="2">
|
||||||
|
{columns.map((column) => (
|
||||||
|
<Flex direction="column" gap="2">
|
||||||
|
{column.map((member) => (
|
||||||
|
<Member key={member.id} {...member} />
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DiscordPlug({ locale }: LocaleAcceptorProps) {
|
||||||
|
const strings = getStrings(locale);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex justify="center" flexGrow="1" flexShrink="0">
|
||||||
|
<Link
|
||||||
|
style={{ display: 'contents' }}
|
||||||
|
href="https://discord.gg/nDt7AjGJQH"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
maxWidth="26rem"
|
||||||
|
overflow="hidden"
|
||||||
|
style={{
|
||||||
|
borderRadius: Var('radius-2'),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
height="5rem"
|
||||||
|
style={{
|
||||||
|
perspective: '32rem',
|
||||||
|
background: `linear-gradient(90deg, ${Var('indigo-2')}, ${Var('blue-2')}, ${Var('purple-2')})`,
|
||||||
|
}}
|
||||||
|
position="relative"
|
||||||
|
overflow="hidden"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
top="-250%"
|
||||||
|
position="absolute"
|
||||||
|
direction="column"
|
||||||
|
width="fit-content"
|
||||||
|
height="32rem"
|
||||||
|
flexGrow="1"
|
||||||
|
overflow="hidden"
|
||||||
|
style={{
|
||||||
|
transform: 'rotateX(60deg) rotateZ(-20deg)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Scroller index={0} />
|
||||||
|
<Scroller index={1} />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Flex
|
||||||
|
align="center"
|
||||||
|
justify="between"
|
||||||
|
p="3"
|
||||||
|
gap="4"
|
||||||
|
style={{
|
||||||
|
background: `linear-gradient(90deg, ${Var('indigo-3')}, ${Var('blue-3')}, ${Var('purple-3')})`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box display={{ initial: 'block', xs: 'none' }}>
|
||||||
|
<Text color="gray" highContrast>
|
||||||
|
{strings.website.home.discord.join_short}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={{ initial: 'none', xs: 'block' }}>
|
||||||
|
<Text color="gray" highContrast>
|
||||||
|
{strings.website.home.discord.join_long}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Button color="iris">
|
||||||
|
{strings.website.home.discord.action}
|
||||||
|
<CaretRightIcon />
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Link>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -10,7 +10,14 @@ export function HomeLocaleSwitcher({
|
|||||||
}: LocaleAcceptorProps) {
|
}: LocaleAcceptorProps) {
|
||||||
return (
|
return (
|
||||||
<BlitzKitTheme>
|
<BlitzKitTheme>
|
||||||
<Flex justify="center" mt="4" py="6" align="center" gap="3">
|
<Flex
|
||||||
|
flexGrow="2"
|
||||||
|
flexShrink="0"
|
||||||
|
justify="center"
|
||||||
|
mt="4"
|
||||||
|
align="center"
|
||||||
|
gap="3"
|
||||||
|
>
|
||||||
<Text size="5" trim="end" color="gray">
|
<Text size="5" trim="end" color="gray">
|
||||||
<GlobeIcon width="1em" height="1em" />
|
<GlobeIcon width="1em" height="1em" />
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ function Content() {
|
|||||||
const { locale, strings } = useLocale();
|
const { locale, strings } = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" pt="4" pb="8">
|
<Flex direction="column" pt="4">
|
||||||
<Heading align="center" size="5">
|
<Heading align="center" size="5">
|
||||||
{strings.website.home.hot_tanks.title}
|
{strings.website.home.hot_tanks.title}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { literals } from '@blitzkit/i18n/src/literals';
|
|||||||
import { Box, Flex, Heading, Link } from '@radix-ui/themes';
|
import { Box, Flex, Heading, Link } from '@radix-ui/themes';
|
||||||
import type { GetStaticPaths } from 'astro';
|
import type { GetStaticPaths } from 'astro';
|
||||||
import { AesonPlug } from '../../components/AesonPlug';
|
import { AesonPlug } from '../../components/AesonPlug';
|
||||||
|
import { DiscordPlug } from '../../components/Discord';
|
||||||
import { HomeLocaleSwitcher } from '../../components/Home/HomeLocaleSwitcher';
|
import { HomeLocaleSwitcher } from '../../components/Home/HomeLocaleSwitcher';
|
||||||
import HomeHero from '../../components/HomeHero.astro';
|
import HomeHero from '../../components/HomeHero.astro';
|
||||||
import { HomePageHotTanks } from '../../components/HomePageHotTanks';
|
import { HomePageHotTanks } from '../../components/HomePageHotTanks';
|
||||||
@@ -45,7 +46,19 @@ export const getStaticPaths = (() => {
|
|||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
<HomeHero />
|
<HomeHero />
|
||||||
|
|
||||||
<HomeLocaleSwitcher {locale} client:load />
|
<Flex justify="center" py="6" px="4" justify="center">
|
||||||
|
<Flex
|
||||||
|
wrap="wrap"
|
||||||
|
justify="between"
|
||||||
|
maxWidth="64rem"
|
||||||
|
gap="6"
|
||||||
|
align="center"
|
||||||
|
flexGrow="1"
|
||||||
|
>
|
||||||
|
<HomeLocaleSwitcher {locale} client:load />
|
||||||
|
<DiscordPlug {locale} />
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
{
|
{
|
||||||
locale !== DEFAULT_LOCALE && (
|
locale !== DEFAULT_LOCALE && (
|
||||||
|
|||||||
Reference in new issue
Block a user