Skip to content

Commit 1cdaecc

Browse files
committed
Updated for gamepad support, added new ControllerIcon component, and added a help view for gamepads
1 parent 6492fcd commit 1cdaecc

11 files changed

Lines changed: 331 additions & 49 deletions

File tree

src/app/layout.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
"use client";
2-
31
import React from "react";
4-
import { useState } from "react";
52
import type { Metadata, Viewport } from 'next';
63
import { Inter } from "next/font/google";
74
import { config } from '@fortawesome/fontawesome-svg-core';
85
import '@fortawesome/fontawesome-svg-core/styles.css';
96
import "./globals.css";
107
import Head from 'next/head';
11-
import { useGamepads } from 'awesome-react-gamepads';
128

139
config.autoAddCss = false;
1410

@@ -17,6 +13,9 @@ const inter = Inter({ subsets: ["latin"] });
1713
export const metadata: Metadata = {
1814
title: 'Trey | Social, Games, and More Links',
1915
description: 'Profiles for gaming, social media, development, and more.',
16+
category: "Personal Website",
17+
publisher: "@syntax-tm",
18+
creator: "@syntax-tm",
2019
};
2120

2221
export const viewport: Viewport = {
@@ -30,19 +29,13 @@ export default function RootLayout({
3029
}: Readonly<{
3130
children: React.ReactNode;
3231
}>) {
33-
const [secret, setSecret] = useState(false);
34-
useGamepads({
35-
onKonamiSuccess: () => {
36-
setSecret(true);
37-
}
38-
});
3932
return (
4033
<html lang="en">
4134
<Head>
4235
<meta name="keywords" content={'gundwn, gundwn.gg, steam, xbox, syntax-tm, github, git, xmb, links, social, profile, games'} />
4336
<meta name="twitter:site" content="@gundwnsrc" />
4437
</Head>
45-
<body className={`${inter.className} text-white ${secret ? 'secret' : ''}`}>{children}</body>
38+
<body className={`${inter.className} text-white`}>{children}</body>
4639
</html>
4740
);
4841
}

src/components/background/background.css

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,44 @@ body {
22
margin: auto;
33
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
44
overflow: auto;
5-
/*background: linear-gradient(240deg, rgb(114, 25, 108) 3%, rgb(27, 83, 139) 38%, rgb(22, 153, 144) 68%, rgb(92, 27, 27) 98%);*/
6-
/*background: rgb(74,185,176);*/
7-
/*background: linear-gradient(90deg, rgba(74,185,176,1) 23%, rgba(50,109,208,1) 47%, rgba(210,63,63,1) 71%, rgba(126,68,241,1) 100%);*/
8-
/* background: linear-gradient(315deg, rgba(101,0,94,1) 3%, rgba(60,132,206,1) 38%, rgba(48,238,226,1) 68%, rgba(255,25,25,1) 98%); */
9-
background: rgb(20,36,80);
10-
background: linear-gradient(60deg, rgba(20,36,80,1) 27%, rgba(37,22,91,1) 47%, rgba(66,30,85,1) 68%);
11-
animation: gradient 15s ease infinite;
12-
background-size: 400% 400%;
13-
background-attachment: fixed;
145
}
156

16-
body.secret {
7+
.background {
178
background: rgb(20,36,80);
18-
background: linear-gradient(60deg, rgb(61, 91, 105) 27%, rgb(92, 74, 173) 47%, rgb(50, 104, 57) 68%);
19-
animation: gradient 15s ease infinite;
20-
background-size: 400% 400%;
9+
background: linear-gradient(60deg, rgba(20,36,80,1) 27%, rgba(37,22,91,1) 47%, rgb(38, 30, 85) 68%);
10+
-webkit-animation: gradient 10s ease infinite;
11+
-moz-animation: gradient 10s ease infinite;
12+
animation: gradient 10s ease infinite;
13+
background-size: 600% 600%;
2114
background-attachment: fixed;
15+
position: absolute;
16+
width: 100%;
17+
height: 100%;
2218
}
2319

20+
.background:has(.secret) {
21+
background: rgb(54, 54, 54);
22+
background: linear-gradient(60deg, rgb(41, 116, 54) 27%, rgb(69, 143, 165) 47%, rgb(43, 80, 128) 68%);
23+
animation: gradient 5s ease infinite;
24+
}
25+
26+
@-webkit-keyframes gradient {
27+
0%{background-position:0% 86%}
28+
50%{background-position:100% 15%}
29+
100%{background-position:0% 86%}
30+
}
31+
@-moz-keyframes gradient {
32+
0%{background-position:0% 86%}
33+
50%{background-position:100% 15%}
34+
100%{background-position:0% 86%}
35+
}
2436
@keyframes gradient {
37+
0%{background-position:0% 86%}
38+
50%{background-position:100% 15%}
39+
100%{background-position:0% 86%}
40+
}
41+
42+
/* @keyframes gradient {
2543
0% {
2644
background-position: 0% 0%;
2745
}
@@ -31,7 +49,7 @@ body.secret {
3149
100% {
3250
background-position: 0% 0%;
3351
}
34-
}
52+
} */
3553

3654
.wave {
3755
background: rgb(255 255 255 / 25%);
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
import React from 'react';
2+
import Secret from '@components/secret/Secret';
13
import './background.css';
24

35
export default function Background() {
46
return (
5-
<div className="absolute overflow-hidden h-dvh -z-50">
7+
<>
8+
<div className="background absolute overflow-hidden h-dvh -z-50">
9+
<Secret />
610
<div className='wave' />
711
<div className='wave' />
812
<div className='wave' />
913
</div>
14+
</>
1015
)
1116
};
1217

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"use client";
2+
3+
import React from "react";
4+
import Image from "next/image";
5+
6+
type ControllerButton =
7+
| "a"
8+
| "b"
9+
| "d_pad_down"
10+
| "d_pad_left"
11+
| "d_pad_right"
12+
| "d_pad_up"
13+
| "d_pad"
14+
| "home"
15+
| "left_bumper"
16+
| "left_stick_all"
17+
| "left_stick_click"
18+
| "left_stick_down"
19+
| "left_stick_left_right"
20+
| "left_stick_left"
21+
| "left_stick_right"
22+
| "left_stick_up_down"
23+
| "left_stick_up"
24+
| "left_stick"
25+
| "left_trigger"
26+
| "menu"
27+
| "right_bumper"
28+
| "right_stick_all"
29+
| "right_stick_click"
30+
| "right_stick_down"
31+
| "right_stick_left_right"
32+
| "right_stick_left"
33+
| "right_stick_right"
34+
| "right_stick_up_down"
35+
| "right_stick_up"
36+
| "right_stick"
37+
| "right_trigger"
38+
| "share"
39+
| "view"
40+
| "x"
41+
| "y";
42+
43+
type ControllerIconStyle = "white" | "black";
44+
45+
interface ControllerIconProps {
46+
style?: ControllerIconStyle;
47+
icon: ControllerButton;
48+
className?: string;
49+
width?: number;
50+
height?: number;
51+
styleProps?: React.CSSProperties;
52+
}
53+
54+
export default function ControllerIcon({
55+
style = "white",
56+
icon,
57+
className = "",
58+
width = 200,
59+
height = 200,
60+
styleProps = {},
61+
}: ControllerIconProps) {
62+
return (
63+
<>
64+
<Image
65+
src={`/svg/xbox_${style}/${icon}.svg`}
66+
alt={`${style} ${icon}`}
67+
className={className}
68+
width={width}
69+
height={height}
70+
/>
71+
</>
72+
);
73+
}

src/components/modal/Modal.tsx

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
11
"use client"
22

3+
import React from "react";
34
import { ReadonlyURLSearchParams, useRouter, useSearchParams } from "next/navigation";
45
import { useRef, useState } from "react";
5-
import { HelpView, MobileHelpView } from "./views/help";
6+
import { GamepadView, HelpView, MobileHelpView } from "./views/help";
67
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
78
import { faClose } from "@fortawesome/free-solid-svg-icons";
89
import useKeyboard, { KeyPressAction } from "@hooks/useKeyboard";
910
import useMobileDetect from "@hooks/useMobileDetect";
1011
import useQuery from "@hooks/useQuery";
11-
import { useWindowSize } from "@uidotdev/usehooks";
1212
import Link from "next/link";
1313
import { CopyView } from "./views/copy";
1414
import accounts from "@/config/accounts.json";
1515
import "./modal.css";
1616
import { AboutView } from "./views/about";
17+
import { useGamepads } from 'awesome-react-gamepads';
18+
import ControllerIcon from "@components/icons/ControllerIcon";
1719

1820
export default function Modal() {
1921
const searchParams = useSearchParams();
2022
const modalParam = searchParams.get("modal");
2123
const audioRef = useRef<HTMLAudioElement | null>(null);
2224
const router = useRouter();
23-
const size = useWindowSize();
2425
const mobileDetect = useMobileDetect();
2526

27+
28+
const [gamepadConnected, setGamepadConnected] = useState(false);
29+
useGamepads({
30+
onConnect: (gamepad) => {
31+
console.log("Gamepad connected:", gamepad);
32+
setGamepadConnected(true);
33+
},
34+
onDisconnect: (gamepad) => {
35+
console.log("Gamepad disconnected:", gamepad);
36+
setGamepadConnected(false);
37+
}
38+
})
39+
2640
const [modal, setModal] = useState<string | null>(modalParam);
2741

2842
const play = () => {
@@ -59,7 +73,9 @@ export default function Modal() {
5973

6074
if (modal === 'help') {
6175
title = 'Help';
62-
if (mobileDetect.isMobile()) {
76+
if (gamepadConnected) {
77+
view = <GamepadView />;
78+
} else if (mobileDetect.isMobile()) {
6379
view = <MobileHelpView />;
6480
} else {
6581
view = <HelpView />;
@@ -76,9 +92,6 @@ export default function Modal() {
7692
<>
7793
{modal && (
7894
<div className="absolute left-0 top-0 w-full h-screen overflow-clip block z-1">
79-
{/* <div className="right-0 top-0 absolute w-[30px] m-5 aspect-square z-[200]">
80-
<FontAwesomeIcon icon={faClose} className="w-full h-full" />
81-
</div> */}
8295
<dialog className="flex flex-col w-screen h-screen bg-black/75 z-100 overflow-none backdrop-blur">
8396
<div className="w-full h-[15%] relative">
8497
<audio ref={audioRef} src='/audio/nav.mp3' />
@@ -98,20 +111,28 @@ export default function Modal() {
98111
<div className="grid justify-center">
99112
<span className="text-white mt-[1em] ml-[0.5em] text-center modal-action object-center mx-auto">
100113
{/* need to set the href so that the user can close modal by clicking on the buttton */}
101-
<Link href={'/'}>
102-
{mobileDetect.isMobile() && (
114+
<Link href="/">
115+
{gamepadConnected && (
116+
<div className="text-xl items-center justify-items-center align-items-center inline-flex">
117+
<div className="relative max-w-10">
118+
<ControllerIcon icon="b" className="m-2" />
119+
</div>
120+
<span className="mx-2 my-auto">close</span>
121+
</div>
122+
)
123+
}
124+
{!gamepadConnected && mobileDetect.isMobile() && (
103125
<div className="text-xl items-center justify-items-center align-items-center inline-flex">
104126
<FontAwesomeIcon icon={faClose} className="w-7 h-7 aspect-square inline-flex my-auto modal-action" />
105127
<span className="mx-2 my-auto">close</span>
106128
</div>
107129
)}
108-
{mobileDetect.isDesktop() && (
130+
{!gamepadConnected && mobileDetect.isDesktop() && (
109131
<div className="justify-between w-auto mt-4 text-lg hover:animate-pulse">
110132
<kbd className="px-2 py-1.5 text-gray-800 bg-gray-100 mx-[3px] border border-gray-200 rounded-lg dark:bg-gray-400/25 dark:text-white dark:border-gray-500/25">Esc</kbd>
111133
<span className="mx-2 my-auto">close</span>
112134
</div>
113135
)}
114-
115136
</Link>
116137
</span>
117138
</div>

src/components/modal/views/about.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React from "react";
12
import { loadEnvConfig } from '@next/env'
23
import { faInfo, faInfoCircle } from "@fortawesome/free-solid-svg-icons";
34
import useMobileDetect from "@hooks/useMobileDetect";

src/components/modal/views/help.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tr > :first-child {
1+
tr:not(.content-center) > :first-child {
22
text-align: right;
33
display: flex;
44
justify-content: end;

0 commit comments

Comments
 (0)