commit
6099a0b337
@ -0,0 +1,47 @@ |
||||
.card { |
||||
display: flex; |
||||
flex-direction: row; |
||||
max-width: calc(1000rem / 16); |
||||
box-sizing: border-box; |
||||
padding: calc(24rem / 16); |
||||
} |
||||
|
||||
.card aside { |
||||
flex: 0 0 calc(144rem / 16); |
||||
margin-right: calc(24rem / 16); |
||||
} |
||||
|
||||
.card aside img { |
||||
width: 100%; |
||||
margin-bottom: 1rem; |
||||
} |
||||
|
||||
.spacer { |
||||
margin-top: calc(76rem / 16); |
||||
} |
||||
|
||||
.registerButton { |
||||
width: 100%; |
||||
} |
||||
|
||||
.content > h1 { |
||||
font-size: calc(24rem / 16); |
||||
font-weight: 700; |
||||
font-style: normal; |
||||
margin-top: 0; |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
.content, |
||||
.content > h2 { |
||||
color: var(--purple-2); |
||||
font-weight: 400; |
||||
font-style: normal; |
||||
margin-top: 0; |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
.content > h2 { |
||||
font-size: 1rem; |
||||
margin-bottom: calc(14rem / 16); |
||||
} |
@ -0,0 +1,48 @@ |
||||
import React, { ReactNode } from "react"; |
||||
import styles from "./EventCard.module.css"; |
||||
|
||||
import { EventSetting } from "./EventSetting"; |
||||
import { Image } from "./Image"; |
||||
|
||||
interface EventCardProps { |
||||
name: string; |
||||
short: string; |
||||
date: Date; |
||||
online: boolean; |
||||
location: string; |
||||
poster?: string; |
||||
registerLink?: string; |
||||
children: ReactNode; |
||||
} |
||||
|
||||
export function EventCard({ |
||||
name, |
||||
date, |
||||
online, |
||||
location, |
||||
poster, |
||||
registerLink, |
||||
children, |
||||
}: EventCardProps) { |
||||
return ( |
||||
<article className={styles.card}> |
||||
<aside> |
||||
{poster && <Image alt={name} src={poster} />} |
||||
{!poster && <div className={styles.spacer}></div>} |
||||
{/* TODO: use the <Button /> component */} |
||||
{registerLink && ( |
||||
<button className={styles.registerButton}> |
||||
<a href={registerLink}>Register</a> |
||||
</button> |
||||
)} |
||||
</aside> |
||||
<section className={styles.content}> |
||||
<h1>{name}</h1> |
||||
<h2> |
||||
<EventSetting date={date} online={online} location={location} /> |
||||
</h2> |
||||
<div>{children}</div> |
||||
</section> |
||||
</article> |
||||
); |
||||
} |
@ -0,0 +1,63 @@ |
||||
.card { |
||||
display: flex; |
||||
box-sizing: border-box; |
||||
max-width: calc(540rem / 16); |
||||
padding: calc(24rem / 16); |
||||
border-radius: calc(4rem / 16); |
||||
background-color: white; |
||||
} |
||||
|
||||
.poster { |
||||
width: calc(150rem / 16); |
||||
height: calc(150rem / 16); |
||||
margin-right: calc(20rem / 16); |
||||
} |
||||
|
||||
.details { |
||||
position: relative; |
||||
width: 100%; |
||||
} |
||||
|
||||
.name { |
||||
color: var(--purple-2); |
||||
font-weight: bolder; |
||||
font-size: calc(18rem / 16); |
||||
line-height: calc(27rem / 16); |
||||
margin: 0; |
||||
} |
||||
|
||||
.desc { |
||||
color: var(--purple-2); |
||||
margin-top: calc(12rem / 16); |
||||
} |
||||
|
||||
.spacer { |
||||
height: calc(35rem / 16); |
||||
} |
||||
|
||||
.button { |
||||
position: absolute; |
||||
bottom: 0; |
||||
left: 0; |
||||
} |
||||
|
||||
.logo { |
||||
width: calc(30rem / 16); |
||||
position: absolute; |
||||
bottom: 0; |
||||
right: 0; |
||||
} |
||||
|
||||
.setting { |
||||
margin: 0; |
||||
color: var(--blue-1); |
||||
font-weight: bolder; |
||||
font-size: calc(14rem / 16); |
||||
} |
||||
|
||||
@media only screen and (max-width: calc(768rem / 16)) { |
||||
.card { |
||||
padding: 0; |
||||
background-color: #e1eefa; |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
import React, { ReactNode } from "react"; |
||||
// import { Button } from "./Button";
|
||||
import { Image } from "./Image"; |
||||
import { EventSetting } from "./EventSetting"; |
||||
import styles from "./EventDescriptionCard.module.css"; |
||||
|
||||
interface Props { |
||||
name: string; |
||||
online: boolean; |
||||
location: string; |
||||
date: Date; |
||||
poster?: string; |
||||
registerLink?: string; |
||||
children: ReactNode; |
||||
} |
||||
|
||||
function getPlatformURL(platform: string) { |
||||
switch (platform) { |
||||
case "Twitch": |
||||
return "https://www.twitch.tv/uwcsclub"; |
||||
case "Discord": |
||||
return "https://discord.gg/pHfYBCg"; |
||||
case "Facebook": |
||||
return "https://www.facebook.com/uw.computerscienceclub"; |
||||
case "Instagram": |
||||
return "https://www.instagram.com/uwcsclub/"; |
||||
default: |
||||
return; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @remarks |
||||
* - Child elements will display as the event's description |
||||
* - Assuming date prop is in EST |
||||
* - poster is the event's image name, including file ending (.jpg/.png/etc) |
||||
* - If event is online, location will be the platform, with capital first letter and no trailing spaces |
||||
* - ie. location="Discord" |
||||
* @todo |
||||
* get Link component |
||||
*/ |
||||
export function EventDescriptionCard({ |
||||
location, |
||||
poster, |
||||
name, |
||||
date, |
||||
online, |
||||
registerLink, |
||||
children, |
||||
}: Props) { |
||||
const platformURL = getPlatformURL(location); |
||||
|
||||
return ( |
||||
<article className={styles.card}> |
||||
{poster && <Image className={styles.poster} src={poster} alt={name} />} |
||||
|
||||
<div className={styles.details}> |
||||
<h1 className={styles.name}>{name}</h1> |
||||
<h2 className={styles.setting}> |
||||
<EventSetting date={date} online={online} location={location} /> |
||||
</h2> |
||||
<div className={styles.desc}>{children}</div> |
||||
<div className={styles.spacer}></div> |
||||
|
||||
<footer> |
||||
{registerLink && ( |
||||
<div className={styles.button}> |
||||
<button> |
||||
<a href={registerLink}>Register</a> |
||||
</button> |
||||
</div> |
||||
)} |
||||
{online && platformURL && ( |
||||
<a target="_blank" href={platformURL} rel="noreferrer"> |
||||
<Image |
||||
className={styles.logo} |
||||
alt={location} |
||||
src={"logos/" + location + ".png"} |
||||
/> |
||||
</a> |
||||
)} |
||||
</footer> |
||||
</div> |
||||
</article> |
||||
); |
||||
} |
@ -0,0 +1,27 @@ |
||||
import React from "react"; |
||||
|
||||
interface Props { |
||||
date: Date; |
||||
online: boolean; |
||||
location: string; |
||||
} |
||||
|
||||
export function EventSetting(props: Props) { |
||||
const date = props.date.toLocaleDateString("en-US", { |
||||
day: "numeric", |
||||
month: "long", |
||||
year: "numeric", |
||||
}); |
||||
const time = props.date.toLocaleTimeString("en-US", { |
||||
hour: "numeric", |
||||
minute: "numeric", |
||||
}); |
||||
const location = props.online ? `Online - ${props.location}` : props.location; |
||||
|
||||
return ( |
||||
<div> |
||||
<time dateTime={props.date.toISOString()}>{`${date} | ${time}`}</time> |
||||
{` | ${location}`} |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,16 @@ |
||||
import React, { ImgHTMLAttributes } from "react"; |
||||
|
||||
export function Image(props: ImgHTMLAttributes<HTMLImageElement>) { |
||||
const { src: relativeSrc = "" } = props; |
||||
|
||||
let absoluteSrc = process.env.BASE_PATH ?? "/"; |
||||
if (absoluteSrc.endsWith("/") && relativeSrc.startsWith("/")) { |
||||
absoluteSrc += relativeSrc.slice(1); |
||||
} else if (absoluteSrc.endsWith("/") || relativeSrc.startsWith("/")) { |
||||
absoluteSrc += relativeSrc; |
||||
} else { |
||||
absoluteSrc += "/" + relativeSrc; |
||||
} |
||||
|
||||
return <img {...props} src={absoluteSrc} />; |
||||
} |
@ -0,0 +1,151 @@ |
||||
.navbar { |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
|
||||
background-color: var(--white); |
||||
} |
||||
|
||||
.navContent { |
||||
display: flex; |
||||
flex-direction: row; |
||||
flex-wrap: none; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
|
||||
width: stretch; |
||||
max-width: calc(1440rem / 16); |
||||
height: auto; |
||||
padding: calc(28rem / 16) calc(136rem / 16); |
||||
} |
||||
|
||||
.logo { |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.logo:hover { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.logo img { |
||||
width: calc(96rem / 16); |
||||
} |
||||
|
||||
.navMenu { |
||||
display: inline-flex; |
||||
flex-direction: row; |
||||
flex-wrap: none; |
||||
justify-content: space-between; |
||||
align-items: baseline; |
||||
|
||||
margin: 0; |
||||
padding: 0; |
||||
|
||||
width: calc(512rem / 16); |
||||
} |
||||
|
||||
.navMenu li { |
||||
list-style: none; |
||||
text-align: center; |
||||
} |
||||
|
||||
.navMenu a { |
||||
color: var(--purple-2); |
||||
text-decoration: none; |
||||
} |
||||
|
||||
.navMenu a.currentPage { |
||||
color: var(--blue-2); |
||||
} |
||||
|
||||
.navMenu > li:hover > a { |
||||
color: var(--blue-2); |
||||
font-weight: 600; |
||||
} |
||||
|
||||
/* Prevents the menu items from shifting when made bold on hover */ |
||||
.navMenu > li > a::before { |
||||
display: block; |
||||
content: attr(title); |
||||
font-weight: 600; |
||||
height: 0; |
||||
overflow: hidden; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
.navMenu > li > a { |
||||
padding: 1rem; |
||||
} |
||||
|
||||
.dropdownWrapper { |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: flex-start; |
||||
align-items: center; |
||||
} |
||||
|
||||
.dropdown { |
||||
visibility: visible; |
||||
|
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: space-evenly; |
||||
align-items: center; |
||||
|
||||
position: absolute; |
||||
|
||||
margin: 0; |
||||
margin-top: calc(48rem / 16); |
||||
padding: 0; |
||||
|
||||
border-radius: calc(8rem / 16); |
||||
background-color: var(--white); |
||||
box-shadow: 0 calc(8rem / 16) 1rem var(--blue-1-20); |
||||
|
||||
font-size: calc(14rem / 16); |
||||
} |
||||
|
||||
.dropdown > li { |
||||
width: 100%; |
||||
} |
||||
|
||||
.dropdown > li > a { |
||||
padding: calc(8rem / 16); |
||||
width: 100%; |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
.dropdown > li:hover > a, |
||||
.dropdown > li > a:focus { |
||||
background-color: var(--blue-1-20); |
||||
} |
||||
|
||||
.dropdown > li:first-child > a { |
||||
padding-top: 1rem; |
||||
border-radius: calc(8rem / 16) calc(8rem / 16) 0 0; |
||||
} |
||||
|
||||
.dropdown > li:last-child > a { |
||||
padding-bottom: 1rem; |
||||
border-radius: 0 0 calc(8rem / 16) calc(8rem / 16); |
||||
} |
||||
|
||||
.navMenu > li .dropdown { |
||||
visibility: hidden; |
||||
} |
||||
|
||||
.navMenu > li:hover .dropdown, |
||||
.navMenu > li:focus-within .dropdown { |
||||
visibility: visible; |
||||
} |
||||
|
||||
/* On a smaller desktop screen, keep the same navbar layout but decrease the |
||||
* horizontal padding so it still fits |
||||
*/ |
||||
@media screen and (max-width: calc(960rem / 16)) { |
||||
.navContent { |
||||
padding: calc(28rem / 16) calc(64rem / 16); |
||||
} |
||||
} |
@ -0,0 +1,120 @@ |
||||
import React from "react"; |
||||
import Link from "next/link"; |
||||
import { useRouter } from "next/router"; |
||||
import { Image } from "./Image"; |
||||
import styles from "./Navbar.module.css"; |
||||
|
||||
interface NavLink { |
||||
name: string; |
||||
route: string; |
||||
submenu?: { |
||||
name: string; |
||||
route: string; |
||||
}[]; |
||||
} |
||||
|
||||
const menu: NavLink[] = [ |
||||
{ |
||||
name: "Home", |
||||
route: "/", |
||||
}, |
||||
{ |
||||
name: "About", |
||||
route: "/about", |
||||
submenu: [ |
||||
{ |
||||
name: "About Us", |
||||
route: "/about", |
||||
}, |
||||
{ |
||||
name: "Meet the Team", |
||||
route: "/about/team", |
||||
}, |
||||
{ |
||||
name: "Constitution", |
||||
route: "/about/constitution", |
||||
}, |
||||
{ |
||||
name: "Code of Conduct", |
||||
route: "/about/code-of-conduct", |
||||
}, |
||||
], |
||||
}, |
||||
{ |
||||
name: "Get Involved", |
||||
route: "/get-involved", |
||||
}, |
||||
{ |
||||
name: "Events", |
||||
route: "/events", |
||||
}, |
||||
{ |
||||
name: "Resources", |
||||
route: "/resources", |
||||
}, |
||||
]; |
||||
|
||||
function NavItem(props: NavLink) { |
||||
const router = useRouter(); |
||||
return ( |
||||
<> |
||||
<Link href={props.route}> |
||||
<a |
||||
title={props.name} |
||||
className={ |
||||
router.pathname === props.route || |
||||
((props.submenu?.length ?? 0) > 0 && |
||||
router.pathname.startsWith(props.route)) |
||||
? styles.currentPage |
||||
: "" |
||||
} |
||||
onClick={() => { |
||||
if (document.activeElement instanceof HTMLElement) { |
||||
document.activeElement.blur(); |
||||
} |
||||
}} |
||||
> |
||||
{props.name} |
||||
</a> |
||||
</Link> |
||||
{(props.submenu?.length ?? 0) > 0 ? ( |
||||
<ul className={styles.dropdown}> |
||||
{props.submenu?.map((item) => { |
||||
return ( |
||||
<li className={styles.dropdownWrapper} key={item.name}> |
||||
<NavItem name={item.name} route={item.route} /> |
||||
</li> |
||||
); |
||||
})} |
||||
</ul> |
||||
) : null} |
||||
</> |
||||
); |
||||
} |
||||
|
||||
export function Navbar() { |
||||
return ( |
||||
<nav className={styles.navbar}> |
||||
<div className={styles.navContent}> |
||||
<Link href="/"> |
||||
<a className={styles.logo}> |
||||
<Image src="/images/logo-icon.png" alt="CSC Logo" /> |
||||
</a> |
||||
</Link> |
||||
<ul className={styles.navMenu}> |
||||
{menu.map((item) => { |
||||
return ( |
||||
<li className={styles.dropdownWrapper} key={item.name}> |
||||
<NavItem |
||||
name={item.name} |
||||
route={item.route} |
||||
submenu={item.submenu} |
||||
/> |
||||
</li> |
||||
); |
||||
})} |
||||
</ul> |
||||
</div> |
||||
</nav> |
||||
); |
||||
} |
@ -0,0 +1,32 @@ |
||||
.card { |
||||
padding: calc(27rem / 16) calc(39rem / 16); |
||||
max-width: calc(524rem / 16); |
||||
background-color: white; |
||||
} |
||||
|
||||
.date { |
||||
color: var(--purple-2); |
||||
font-size: calc(18rem / 16); |
||||
font-weight: bold; |
||||
line-height: calc(27rem / 16); |
||||
} |
||||
|
||||
.author { |
||||
color: var(--purple-1); |
||||
font-style: normal; |
||||
line-height: calc(21rem / 16); |
||||
font-size: calc(14rem / 16); |
||||
margin: calc(5rem / 16) 0 calc(7rem / 16) 0; |
||||
} |
||||
|
||||
.content { |
||||
line-height: calc(21rem / 16); |
||||
color: var(--purple-2); |
||||
} |
||||
|
||||
@media only screen and (max-width: calc(768rem / 16)) { |
||||
.card { |
||||
padding: 0; |
||||
background-color: transparent; |
||||
} |
||||
} |
@ -0,0 +1,30 @@ |
||||
import React, { ReactNode } from "react"; |
||||
import styles from "./NewsCard.module.css"; |
||||
|
||||
interface NewsCardProps { |
||||
date: Date; |
||||
author: string; |
||||
children: ReactNode; |
||||
} |
||||
|
||||
export const NewsCard: React.FC<NewsCardProps> = ({ |
||||
date, |
||||
author, |
||||
children, |
||||
}) => { |
||||
return ( |
||||
<article className={styles.card}> |
||||
<h3> |
||||
<time className={styles.date} dateTime={date.toISOString()}> |
||||
{date.toLocaleDateString("en-US", { |
||||
year: "numeric", |
||||
month: "long", |
||||
day: "numeric", |
||||
})} |
||||
</time> |
||||
</h3> |
||||
<address className={styles.author}>{author}</address> |
||||
<div className={styles.content}>{children}</div> |
||||
</article> |
||||
); |
||||
}; |
@ -0,0 +1,28 @@ |
||||
.container { |
||||
max-width: calc(126rem / 16); |
||||
display: flex; |
||||
flex-direction: column; |
||||
margin: 0; |
||||
} |
||||
|
||||
.img { |
||||
width: 100%; |
||||
border-radius: 50%; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.caption { |
||||
text-align: center; |
||||
margin-top: calc(24rem / 16); |
||||
} |
||||
|
||||
.name { |
||||
font-weight: bold; |
||||
color: var(--blue-1); |
||||
} |
||||
|
||||
.role { |
||||
font-weight: 600; |
||||
color: var(--purple-2); |
||||
line-height: 1.875; |
||||
} |
@ -0,0 +1,29 @@ |
||||
import React from "react"; |
||||
import styles from "./TeamMember.module.css"; |
||||
import { Image } from "./Image"; |
||||
|
||||
interface TeamMemberProps { |
||||
name: string; |
||||
role: string; |
||||
image?: string; |
||||
} |
||||
|
||||
export const TeamMember: React.FC<TeamMemberProps> = ({ |
||||
name, |
||||
role, |
||||
image, |
||||
}) => { |
||||
return ( |
||||
<div className={styles.container}> |
||||
<Image |
||||
className={styles.img} |
||||
src={image ?? "/images/team-member-placeholder.svg"} |
||||
alt={`Picture of ${name}`} |
||||
/> |
||||
<div className={styles.caption}> |
||||
<div className={styles.name}>{name}</div> |
||||
<div className={styles.role}>{role}</div> |
||||
</div> |
||||
</div> |
||||
); |
||||
}; |
@ -0,0 +1,112 @@ |
||||
.card { |
||||
display: grid; |
||||
grid-template-columns: calc(126rem / 16) auto; |
||||
grid-template-areas: |
||||
"picture name" |
||||
"picture role" |
||||
"picture description"; |
||||
column-gap: calc(32rem / 16); |
||||
row-gap: 0; |
||||
justify-items: start; |
||||
align-items: start; |
||||
|
||||
max-width: calc(847rem / 16); |
||||
} |
||||
|
||||
.picture { |
||||
grid-area: picture; |
||||
justify-self: center; |
||||
|
||||
max-width: calc(126rem / 16); |
||||
max-height: calc(126rem / 16); |
||||
|
||||
clip-path: circle(50%); |
||||
} |
||||
|
||||
.image { |
||||
width: 100%; |
||||
} |
||||
|
||||
.name { |
||||
grid-area: name; |
||||
margin: 0; |
||||
|
||||
color: var(--blue-1); |
||||
font-size: calc(36rem / 16); |
||||
line-height: 1.1; |
||||
font-weight: 700; |
||||
} |
||||
|
||||
.role { |
||||
grid-area: role; |
||||
margin: 0; |
||||
|
||||
color: var(--purple-2); |
||||
font-size: calc(24rem / 16); |
||||
line-height: 1.7; |
||||
font-weight: 600; |
||||
} |
||||
|
||||
.description { |
||||
grid-area: description; |
||||
margin: 0; |
||||
|
||||
line-height: 1.875; |
||||
} |
||||
|
||||
@media screen and (max-width: calc(768rem / 16)) { |
||||
.card { |
||||
grid-template-columns: calc(90rem / 16) auto; |
||||
column-gap: calc(22rem / 16); |
||||
|
||||
max-width: calc(460rem / 16); |
||||
} |
||||
|
||||
.picture { |
||||
max-width: calc(90rem / 16); |
||||
max-height: calc(90rem / 16); |
||||
} |
||||
|
||||
.name, |
||||
.role, |
||||
.description { |
||||
line-height: 1.5; |
||||
} |
||||
} |
||||
|
||||
/* TODO: Use the correct mobile styles from figma |
||||
@media only screen and (max-width: calc(375rem / 16)) { |
||||
.card { |
||||
grid-template-columns: calc(70rem / 16) auto; |
||||
grid-template-rows: auto calc(calc(14rem / 16) * 1.5 + calc(12rem / 16)) auto; |
||||
grid-template-areas: |
||||
"picture name" |
||||
"picture role" |
||||
"description description"; |
||||
column-gap: 1.4375rem; |
||||
align-items: end; |
||||
|
||||
max-width: calc(190rem / 16); |
||||
} |
||||
|
||||
.picture { |
||||
max-width: calc(70rem / 16); |
||||
max-height: calc(70rem / 16); |
||||
} |
||||
|
||||
.name, |
||||
.role, |
||||
.description { |
||||
line-height: 1.5; |
||||
} |
||||
|
||||
.role { |
||||
margin-bottom: calc(12rem / 16); |
||||
} |
||||
|
||||
.description { |
||||
justify-self: top; |
||||
margin-top: calc(12rem / 16); |
||||
margin-left: calc(12rem / 16); |
||||
} |
||||
} */ |
@ -0,0 +1,27 @@ |
||||
import React from "react"; |
||||
import { Image } from "./Image"; |
||||
import styles from "./TeamMemberCard.module.css"; |
||||
|
||||
interface TeamMemberCardProps { |
||||
name: string; |
||||
role: string; |
||||
image?: string; // path to image of person, relative to public directory
|
||||
children: React.ReactNode; |
||||
} |
||||
|
||||
export function TeamMemberCard(props: TeamMemberCardProps) { |
||||
return ( |
||||
<article className={styles.card}> |
||||
<div className={styles.picture}> |
||||
<Image |
||||
className={styles.image} |
||||
src={props.image ?? "/images/team-member-placeholder.svg"} |
||||
alt={`Picture of ${props.name}`} |
||||
/> |
||||
</div> |
||||
<h1 className={styles.name}>{props.name}</h1> |
||||
<h2 className={styles.role}>{props.role}</h2> |
||||
<div className={styles.description}>{props.children}</div> |
||||
</article> |
||||
); |
||||
} |
@ -1,3 +1,93 @@ |
||||
.miniEventCardDemo > *:nth-child(odd) { |
||||
background: #E1EEFA; |
||||
} |
||||
background: #e1eefa; |
||||
} |
||||
|
||||
.newsDemo { |
||||
padding: calc(50rem / 16); |
||||
background-color: var(--off-white); |
||||
display: inline-block; |
||||
} |
||||
|
||||
.newsTitle { |
||||
font-style: normal; |
||||
font-weight: bold; |
||||
color: var(--purple-2); |
||||
font-size: calc(24rem / 16); |
||||
line-height: calc(36rem / 16); |
||||
margin-bottom: calc(14rem / 16); |
||||
} |
||||
|
||||
.newsDesc { |
||||
font-style: normal; |
||||
font-weight: normal; |
||||
font-size: calc(14rem / 16); |
||||
line-height: calc(21rem / 16); |
||||
white-space: pre-line; |
||||
color: var(--purple-2); |
||||
vertical-align: baseline; |
||||
} |
||||
|
||||
.news > hr { |
||||
border: none; |
||||
height: calc(1rem / 16); |
||||
background-color: var(--purple-2); |
||||
margin: 0 0 calc(13rem / 16) 0; |
||||
} |
||||
|
||||
.eventDescriptionCardDemo { |
||||
padding: calc(50rem / 16) 0; |
||||
background-color: var(--off-white); |
||||
display: inline-block; |
||||
} |
||||
|
||||
.eventDescriptionCardDemo > * { |
||||
margin: calc(12rem / 16) calc(50rem / 16); |
||||
} |
||||
|
||||
.eventDescriptionCardDemo > *:first-child { |
||||
margin-top: 0; |
||||
} |
||||
|
||||
.eventDescriptionCardDemo > *:last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
.teamMemberDemo { |
||||
padding: calc(10rem / 16) calc(50rem / 16) calc(30rem / 16) calc(50rem / 16); |
||||
max-width: calc(847rem / 16); |
||||
} |
||||
|
||||
.committee { |
||||
margin: 0; |
||||
color: var(--purple-2); |
||||
font-weight: 600; |
||||
font-size: calc(24rem / 16); |
||||
line-height: calc(36rem / 16); |
||||
} |
||||
|
||||
.teamMemberDemo > hr { |
||||
border: none; |
||||
height: calc(1rem / 16); |
||||
background-color: var(--blue-2); |
||||
width: 100%; |
||||
margin-top: calc(24rem / 16); |
||||
margin-bottom: calc(46rem / 16); |
||||
} |
||||
|
||||
.teamMembers { |
||||
display: grid; |
||||
grid-template-columns: repeat(auto-fill, minmax(calc(100rem / 16), 1fr)); |
||||
row-gap: calc(43rem / 16); |
||||
column-gap: calc(53rem / 16); |
||||
} |
||||
|
||||
@media only screen and (max-width: calc(768rem / 16)) { |
||||
.newsDemo, |
||||
.eventDescriptionCardDemo { |
||||
background-color: #e1eefa; |
||||
} |
||||
|
||||
.eventDescriptionCardDemo > * { |
||||
margin: calc(50rem / 16); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,14 @@ |
||||
export const metadata = { |
||||
name: "Alt-Tab", |
||||
short: "CSC is proud to present to you Alt-Tab!", |
||||
date: new Date("March 25, 2021 19:00:00"), |
||||
online: true, |
||||
location: "Twitch", |
||||
poster: "/images/playground/alt-tab.jpg", |
||||
}; |
||||
|
||||
CSC is proud to present to you Alt-Tab! Join us in a lightning tech talk series presented to you by our very own students. Alt-Tab consists of 10 to 15-minute talks about anything related to tech. Learn more about exciting topics that range from competitive programming to cryptography! |
||||
|
||||
We will have four incredible presenters that are eager to share their insights with you. Stay tuned as we'll be introducing them and the topics that they will be discussing soon!. |
||||
|
||||
Registration is not required to attend! We'll just be sending you an email reminder, as well as inviting you to our calendar even |
@ -0,0 +1,9 @@ |
||||
export const metadata = { |
||||
name: "Codey", |
||||
role: "Mascot", |
||||
image: "/images/playground/codeyHi.png" |
||||
} |
||||
|
||||
The one, the only, Codey! Codey is ecstatic to be your mascot for this term. |
||||
Codey loves programming and playing on their laptop. You can often find Codey |
||||
posing for event promo graphics, or chilling in the CSC discord. |
@ -0,0 +1,5 @@ |
||||
export const metadata = { |
||||
name: "Woof Woof", |
||||
role: "Doge", |
||||
image: "/images/playground/doge.jpg" |
||||
} |
@ -0,0 +1,17 @@ |
||||
export const metadata = { |
||||
name: "Out of the Box: React", |
||||
short: "Out of the Box is a series of code-along projects that explore what's under the hood of modern web frameworks.", |
||||
date: new Date("March 23, 2021 19:00:00"), |
||||
online: true, |
||||
location: "Twitch", |
||||
poster: "/images/playground/intro-ootb.jpg", |
||||
registerLink: "http://google.com/", |
||||
}; |
||||
|
||||
Modern web frameworks are a black-box. They're easy to use, but they have numerous minute details to master in order to apply them to truly scalable websites. Over the last few years, front-end frameworks have absorbed the responsibilities of the back-end, meaning it's become ever more important to dig their details out of the box. |
||||
|
||||
Out of the Box is a series of code-along projects that explore what's under the hood of modern web frameworks. Nearly 5 million websites use React, including many of the internet's most popular websites. While its simple syntax attracts developers from all over, underneath lies a complex infrastructure of code to manage all elements from caching to hooks. Rishi will bring these ideas to light in our inaugural episode of Out of the Box. Come join him and code your own version of React! |
||||
|
||||
Only basic web experience is needed. All JavaScript code will be written within a single HTML document for simplicity. Node.js will also be required to participate in the event! |
||||
|
||||
Registration is not required to attend! We'll just be sending you an email reminder, as well as inviting you to our calendar event. |
@ -0,0 +1,14 @@ |
||||
export const metadata = { |
||||
author: "merenber", |
||||
date: new Date("2021-03-19"), |
||||
} |
||||
|
||||
Computer Science Club systems and services will be unavailable on Saturday, Mar. 20 |
||||
due to a planned power outage in the Mathematics and Computer Building (MC) from 7am to 5pm. |
||||
|
||||
The CSC will begin shutting down machines at 6am in preparation of the outage. |
||||
Please prepare for the outage by: |
||||
|
||||
- Ensuring all running processes have their state saved (configuration, data, etc.) |
||||
- Any important files are backed up off-site from the CSC |
||||
- If you have any questions/concerns, please email the Systems Committee. |
@ -1,16 +1,50 @@ |
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
|
||||
interface EventMetadata { |
||||
name: string; |
||||
short: string; |
||||
date: Date; |
||||
location: string; |
||||
} |
||||
|
||||
declare module "*.event.mdx" { |
||||
import { ComponentType } from "react"; |
||||
|
||||
interface EventMetadata { |
||||
name: string; |
||||
short: string; |
||||
date: Date; |
||||
online: boolean; |
||||
location: string; |
||||
poster?: string; |
||||
registerLink?: string; |
||||
} |
||||
|
||||
const ReactComponent: ComponentType; |
||||
|
||||
export const metadata: EventMetadata; |
||||
export default ReactComponent; |
||||
} |
||||
|
||||
declare module "*.news.mdx" { |
||||
import { ComponentType } from "react"; |
||||
|
||||
interface NewsMetadata { |
||||
author: string; |
||||
date: Date; |
||||
} |
||||
|
||||
const ReactComponent: ComponentType; |
||||
|
||||
export const metadata: NewsMetadata; |
||||
export default ReactComponent; |
||||
} |
||||
|
||||
declare module "*.team-member.mdx" { |
||||
import { ComponentType } from "react"; |
||||
|
||||
interface TeamMemberMetadata { |
||||
name: string; |
||||
role: string; |
||||
image?: string; |
||||
} |
||||
|
||||
const ReactComponent: ComponentType; |
||||
|
||||
export const metadata: TeamMemberMetadata; |
||||
export default ReactComponent; |
||||
} |
||||
|
@ -1,7 +1,9 @@ |
||||
const withMDX = require('@next/mdx')({ |
||||
extension: /\.mdx$/ |
||||
}) |
||||
const withMDX = require("@next/mdx")({ |
||||
extension: /\.mdx$/, |
||||
}); |
||||
|
||||
module.exports = withMDX({ |
||||
pageExtensions: ['ts', 'tsx', 'mdx'] |
||||
}) |
||||
pageExtensions: ["ts", "tsx", "mdx"], |
||||
trailingSlash: true, |
||||
basePath: process.env.BASE_PATH, |
||||
}); |
||||
|
File diff suppressed because it is too large
Load Diff