mirror of
https://github.com/PretendoNetwork/website.git
synced 2026-08-24 09:36:43 -05:00
feat(page): set up home (showcase, faq) & components
This commit is contained in:
44
components/Faq/Faq.js
Normal file
44
components/Faq/Faq.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { CaretRight } from 'phosphor-react';
|
||||
|
||||
import styles from './Faq.module.css';
|
||||
|
||||
export default function Faq(ctx) {
|
||||
const { questionObject } = ctx;
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
|
||||
const questions = {
|
||||
odd: questionObject.filter((_, i) => i % 2 === 0),
|
||||
even: questionObject.filter((_, i) => i % 2 !== 0),
|
||||
};
|
||||
|
||||
// reusable question component
|
||||
const QnA = ({ question, i, selected }) => (
|
||||
<div className={styles.question}>
|
||||
<h3 className={classNames({ [styles.selected]: selected })} onClick={() => setSelectedIndex(i)}>
|
||||
<CaretRight size={24} weight="bold" className={styles.chevron} />
|
||||
{question.question}
|
||||
</h3>
|
||||
<p style={{ display: selected ? 'block' : 'none' }} dangerouslySetInnerHTML={{ __html: question.answer }} />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={styles.faq}>
|
||||
<div>
|
||||
{questions.odd.map((question, i) => {
|
||||
const selected = selectedIndex === i;
|
||||
return <QnA key={i} question={question} selected={selected} i={i} />;
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
{questions.even.map((question, i) => {
|
||||
const index = i + questions.odd.length;
|
||||
const selected = selectedIndex === index;
|
||||
return <QnA key={i} question={question} selected={selected} i={index} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
45
components/Faq/Faq.module.css
Normal file
45
components/Faq/Faq.module.css
Normal file
@@ -0,0 +1,45 @@
|
||||
.faq {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.question h3 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 300;
|
||||
margin: 0;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-shade-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.question h3:hover {
|
||||
color: var(--text-shade-3);
|
||||
text-decoration: underline;
|
||||
}
|
||||
.question h3.selected {
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
|
||||
.question p {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
margin-left: -6px;
|
||||
}
|
||||
|
||||
.selected .chevron {
|
||||
transform: rotate(90deg);
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 840px) {
|
||||
.faq {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
}
|
||||
}
|
||||
28
components/Section/Section.js
Normal file
28
components/Section/Section.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
import styles from './Section.module.css';
|
||||
|
||||
/**
|
||||
* A reusable component for sections.
|
||||
*
|
||||
* @param {import('react').ComponentClass} className - Custom classes to apply to the section.
|
||||
* @param {import('react').ComponentClass} contentClassName - Custom styles to apply to the content.
|
||||
* @param {string} style - Custom styles to apply to the section.
|
||||
* @param {string} id - The id of the section.
|
||||
*
|
||||
* @example
|
||||
* <Section className={styles.showcaseTail} contentClassName={styles.content}>
|
||||
* <Title>Hello</Title>
|
||||
* </Section>
|
||||
*
|
||||
*/
|
||||
|
||||
export default function Section(ctx) {
|
||||
const { id, style, children, className, contentClassName } = ctx;
|
||||
|
||||
return (
|
||||
<section className={classNames(styles.sectionWrapper, className)} id={id} style={style}>
|
||||
<div className={classNames(styles.content, contentClassName)}>{children}</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
16
components/Section/Section.module.css
Normal file
16
components/Section/Section.module.css
Normal file
@@ -0,0 +1,16 @@
|
||||
.sectionWrapper {
|
||||
display: flex;
|
||||
padding: 180px 0;
|
||||
}
|
||||
|
||||
.sectionWrapper .content {
|
||||
width: 100%;
|
||||
max-width: var(--maxwidth);
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 840px) {
|
||||
.sectionWrapper {
|
||||
padding: 90px 0;
|
||||
}
|
||||
}
|
||||
23
components/ShowcaseSection/ShowcaseSection.js
Normal file
23
components/ShowcaseSection/ShowcaseSection.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import styles from './ShowcaseSection.module.css';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import Image from 'next/image';
|
||||
|
||||
import Section from '../Section/Section';
|
||||
import Title from '../Title/Title';
|
||||
|
||||
export default function ShowcaseSection(ctx) {
|
||||
const { title, caption, image, isOdd } = ctx;
|
||||
return (
|
||||
<Section
|
||||
className={classNames(styles.sectionWrapper, { [styles.odd]: isOdd })}
|
||||
contentClassName={styles.content}
|
||||
>
|
||||
<div className={styles.text}>
|
||||
<Title>{title}</Title>
|
||||
<p className={styles.caption}>{caption}</p>
|
||||
</div>
|
||||
<Image src={image} alt="" className={styles.image} quality={100} sizes="(max-width: 840px) 100vw, 700px" />
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
55
components/ShowcaseSection/ShowcaseSection.module.css
Normal file
55
components/ShowcaseSection/ShowcaseSection.module.css
Normal file
@@ -0,0 +1,55 @@
|
||||
.content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: min(10vw, 200px);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
max-width: var(--maxwidth);
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.odd.sectionWrapper {
|
||||
background: var(--bg-shade-0);
|
||||
}
|
||||
|
||||
.odd .text {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.odd .image {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 840px) {
|
||||
.content {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 42px;
|
||||
}
|
||||
|
||||
.text,
|
||||
.image,
|
||||
.odd .text,
|
||||
.odd .image {
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.text,
|
||||
.odd .text {
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.image,
|
||||
.odd .image {
|
||||
margin: auto;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -79,24 +79,23 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"showcase": {
|
||||
"title": "What we make",
|
||||
"text": "Our project has many components. Here are some of them.",
|
||||
"cards": [
|
||||
{
|
||||
"title": "Game servers",
|
||||
"caption": "Bringing back your favorite games and content using custom servers."
|
||||
},
|
||||
{
|
||||
"title": "Juxtaposition",
|
||||
"caption": "A re-imagining of Miiverse, as if it were made in the modern era."
|
||||
},
|
||||
{
|
||||
"title": "Cemu support",
|
||||
"caption": "Play your favorite Wii U titles even without a console!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"showcase" : [
|
||||
{
|
||||
"title": "Online play.",
|
||||
"caption": "Dash down Mount Wario on Wii U, [some 3DS stuff we have implemented], upload a course to Mario Maker on CEMU and more, online with Pretendo Network!",
|
||||
"image": "network"
|
||||
},
|
||||
{
|
||||
"title": "Juxtaposition.",
|
||||
"caption": "Juxtaposition is our reimagining of Miiverse for the modern era. With a refreshingly modern design and in-game posting support, insert text insert text insert text insert text insert text!",
|
||||
"image": "juxt"
|
||||
},
|
||||
{
|
||||
"title": "Emulators.",
|
||||
"caption": "See you later, emulator! I wish I had something to put here instead of dummy text, and yet...",
|
||||
"image": "pcmouse"
|
||||
}
|
||||
],
|
||||
"credits": {
|
||||
"title": "The team",
|
||||
"text": "Meet the team behind the project",
|
||||
|
||||
845
package-lock.json
generated
845
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -2,6 +2,7 @@
|
||||
"name": "pretendo",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
@@ -9,10 +10,17 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@next/font": "^13.0.1",
|
||||
"chalk": "^5.1.2",
|
||||
"classnames": "^2.3.2",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"next": "13.0.1",
|
||||
"phosphor-react": "^1.4.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"react-dom": "18.2.0",
|
||||
"sharp": "^0.31.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,85 @@
|
||||
export default function Home() {
|
||||
return <p>bandwidth my beloved</p>;
|
||||
import { getLocale } from '../utils/locale';
|
||||
|
||||
import Button from '../components/Button/Button';
|
||||
import Title from '../components/Title/Title';
|
||||
import Section from '../components/Section/Section';
|
||||
import ShowcaseSection from '../components/ShowcaseSection/ShowcaseSection';
|
||||
import Faq from '../components/Faq/Faq';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
import styles from './index.module.css';
|
||||
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import juxtImage from '../public/assets/images/showcase/juxt.png';
|
||||
import networkImage from '../public/assets/images/showcase/network.png';
|
||||
import pcmouseImage from '../public/assets/images/showcase/pcmouse.png';
|
||||
import wiiuchatImage from '../public/assets/images/showcase/wiiuchat.png';
|
||||
|
||||
const showcaseImages = {
|
||||
juxt: juxtImage,
|
||||
network: networkImage,
|
||||
pcmouse: pcmouseImage,
|
||||
wiiuchat: wiiuchatImage,
|
||||
};
|
||||
|
||||
export async function getServerSideProps(ctx) {
|
||||
const locale = getLocale(ctx.locale);
|
||||
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function Home({ locale }) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<main>
|
||||
<div id="showcase">
|
||||
{locale.showcase.map((element, i) => {
|
||||
return (
|
||||
<ShowcaseSection
|
||||
title={element.title}
|
||||
caption={element.caption}
|
||||
image={showcaseImages[element.image]}
|
||||
isOdd={i % 2 !== 0}
|
||||
key={i}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Section className={styles.showcaseTail} contentClassName={styles.content}>
|
||||
<Image
|
||||
src={wiiuchatImage}
|
||||
className={styles.image}
|
||||
alt=""
|
||||
quality={100}
|
||||
sizes="(max-width: 840px) 100vw, 700px"
|
||||
/>
|
||||
<div className={styles.text}>
|
||||
<Title>And much more!</Title>
|
||||
<p className={styles.caption}>
|
||||
Check out our progress page for an extensive list of our current progress and goals!
|
||||
</p>
|
||||
<Button
|
||||
isPrimary={true}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
router.push('/progress');
|
||||
}}
|
||||
>
|
||||
Check progress
|
||||
</Button>
|
||||
</div>
|
||||
</Section>
|
||||
<Section>
|
||||
<Title id="faq">Frequently Asked Questions.</Title>
|
||||
<p className={styles.caption}>{locale.faq.text}</p>
|
||||
<Faq questionObject={locale.faq.QAs} />
|
||||
</Section>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
47
pages/index.module.css
Normal file
47
pages/index.module.css
Normal file
@@ -0,0 +1,47 @@
|
||||
.caption {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
max-width: 66%;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.showcaseTail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--bg-shade-0);
|
||||
padding: 180px 0;
|
||||
}
|
||||
|
||||
.showcaseTail .content {
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
max-width: var(--maxwidth);
|
||||
margin: auto;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.showcaseTail .image {
|
||||
max-width: min(600px, 50%);
|
||||
height: auto;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.showcaseTail .text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.showcaseTail .caption {
|
||||
margin: 1rem auto 2rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 840px) {
|
||||
.showcaseTail {
|
||||
padding: 90px 0;
|
||||
}
|
||||
|
||||
.showcaseTail .image {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
BIN
public/assets/images/showcase/juxt.png
Normal file
BIN
public/assets/images/showcase/juxt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 678 KiB |
BIN
public/assets/images/showcase/network.png
Normal file
BIN
public/assets/images/showcase/network.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
public/assets/images/showcase/pcmouse.png
Normal file
BIN
public/assets/images/showcase/pcmouse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
public/assets/images/showcase/wiiuchat.png
Normal file
BIN
public/assets/images/showcase/wiiuchat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -1,6 +1,9 @@
|
||||
:root {
|
||||
/* 1 is the base color, <1 are darker variations and >1 are lighter */
|
||||
|
||||
--width: 1400px;
|
||||
--maxwidth: min(var(--width), 90%);
|
||||
|
||||
/* 1 is the base color, <1 are darker variations and >1 are lighter */
|
||||
--bg-shade-0: #131733;
|
||||
--bg-shade-1: #1B1F3B;
|
||||
--bg-shade-2: #23274A;
|
||||
@@ -23,8 +26,6 @@
|
||||
--green-shade-1: #59c9a5;
|
||||
|
||||
--red-shade-1: #a9375b;
|
||||
|
||||
--border: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -34,12 +35,20 @@ body {
|
||||
body {
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
height: 100vh;
|
||||
max-height: 100%;
|
||||
position: relative; /* This fixes overflow-x not hiding on Safari on mobile */
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
margin: 0;
|
||||
color: var(--text-shade-3);
|
||||
color: var(--text-shade-1);
|
||||
justify-content: center;
|
||||
font-family: Poppins, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--accent-shade-1);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Scrollbar styling 'cause it's fancy */
|
||||
|
||||
Reference in New Issue
Block a user