mobile team member card
continuous-integration/drone/push Build is passing Details

This commit is contained in:
b38peng 2021-07-24 15:33:02 -03:00
parent 801a200664
commit d296fe2d7b
12 changed files with 213 additions and 168 deletions

View File

@ -26,3 +26,14 @@
font-weight: 600; font-weight: 600;
color: var(--purple-2); color: var(--purple-2);
} }
@media only screen and (max-width: calc(768rem / 16)) {
.img {
width: calc(85rem / 16);
}
.caption {
font-size: calc(10rem / 16);
margin-top: 1rem;
}
}

View File

@ -17,7 +17,7 @@ export const TeamMember: React.FC<TeamMemberProps> = ({
<div className={styles.container}> <div className={styles.container}>
<Image <Image
className={styles.img} className={styles.img}
src={image ?? "/images/team/team-member-placeholder.svg"} src={image ?? "/images/team/team-member-placeholder.png"}
alt={`Picture of ${name}`} alt={`Picture of ${name}`}
/> />
<div className={styles.caption}> <div className={styles.caption}>

View File

@ -38,6 +38,7 @@
grid-area: role; grid-area: role;
margin: 0; margin: 0;
color: var(--purple-2);
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
line-height: calc(40 / 24); line-height: calc(40 / 24);
font-weight: 600; font-weight: 600;
@ -51,38 +52,90 @@
margin-top: 0; margin-top: 0;
} }
/* @media only screen and (max-width: calc(375rem / 16)) { /* Popup */
.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); .popup_background {
position: fixed;
background-color: var(--navbar-gray);
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1;
}
.popup_container {
position: fixed;
display: flex;
flex-direction: column;
background-color: var(--off-white);
padding: calc(20rem / 16) calc(40rem / 16);
left: 0;
top: 50%;
transform: translate(0, -50%);
z-index: 2;
}
.close_btn {
align-self: flex-end;
/* reset default button styling */
width: min-content;
background: transparent;
border: 0px solid transparent;
padding: 0;
font-family: inherit;
line-height: inherit;
}
.popup_content {
display: flex;
flex-direction: column;
align-items: center;
}
.popup_image {
width: 100%;
}
.popup_name {
color: var(--blue-2);
margin: calc(24rem / 16) 0 0 0;
font-size: calc(18rem / 16);
font-weight: 600;
}
.popup_role {
color: var(--purple-2);
margin: 0 0 1rem 0;
font-size: calc(18rem / 16);
font-weight: 600;
}
.popup_description {
font-size: calc(14rem / 16);
}
@media only screen and (max-width: calc(768rem / 16)) {
.card {
display: flex;
flex-direction: column;
align-items: center;
max-width: calc(135rem / 16);
margin: 0;
} }
.picture { .name {
max-width: calc(70rem / 16); margin-top: calc(24rem / 16);
max-height: calc(70rem / 16); font-weight: 700;
} }
.name, .name,
.role,
.description {
line-height: 1.5;
}
.role { .role {
margin-bottom: calc(12rem / 16); text-align: center;
font-size: calc(14rem / 16);
} }
.description { .description {
justify-self: top; display: none;
margin-top: calc(12rem / 16);
margin-left: calc(12rem / 16);
} }
} */ }

View File

@ -1,27 +1,81 @@
import React from "react"; import React, { useState } from "react";
import { Image } from "./Image"; import { Image } from "./Image";
import useWindowDimensions from "../hooks/useWindowDimension";
import styles from "./TeamMemberCard.module.css"; import styles from "./TeamMemberCard.module.css";
interface TeamMemberCardProps { export interface TeamMemberCardProps {
name: string; name: string;
role: string; role: string;
image?: string; // path to image of person, relative to public directory image?: string; // path to image of person, relative to public directory
children: React.ReactNode; children: React.ReactNode;
} }
export function TeamMemberCard(props: TeamMemberCardProps) { export function TeamMemberCard({
name,
image,
role,
children,
}: TeamMemberCardProps) {
const { width } = useWindowDimensions();
const [isOpen, setIsOpen] = useState(false);
const handleClick = () => {
if (width <= 768) {
setIsOpen(!isOpen);
}
};
return ( return (
<article className={styles.card}> <>
<div className={styles.picture}> <article className={styles.card} onClick={handleClick}>
<Image <div className={styles.picture}>
className={styles.image} <Image
src={props.image ?? "/images/team-member-placeholder.svg"} className={styles.image}
alt={`Picture of ${props.name}`} src={image ?? "/images/team/team-member-placeholder.png"}
/> alt={`Picture of ${name}`}
</div> />
<h1 className={styles.name}>{props.name}</h1> </div>
<h2 className={styles.role}>{props.role}</h2> <h1 className={styles.name}>{name}</h1>
<div className={styles.description}>{props.children}</div> <h2 className={styles.role}>{role}</h2>
</article> <div className={styles.description}>{children}</div>
</article>
{isOpen && (
<ExecPopup
name={name}
role={role}
image={image}
handleClick={handleClick}
>
{children}
</ExecPopup>
)}
</>
);
}
interface Propup extends TeamMemberCardProps {
handleClick: () => void;
}
function ExecPopup({ name, image, role, children, handleClick }: Propup) {
return (
<>
<div className={styles.popup_background} onClick={handleClick} />
<div className={styles.popup_container}>
<button className={styles.close_btn} onClick={handleClick}>
<Image src="images/team/popup-close.svg" />
</button>
<div className={styles.popup_content}>
<div className={styles.picture}>
<Image
className={styles.popup_image}
src={image ?? "/images/team/team-member-placeholder.png"}
alt={`Picture of ${name}`}
/>
</div>
<h1 className={styles.popup_name}>{name}</h1>
<h2 className={styles.popup_role}>{role}</h2>
<div className={styles.popup_description}>{children}</div>
</div>
</div>
</>
); );
} }

View File

@ -1,7 +1,7 @@
--- ---
name: Nakul Vijhani name: Nakul Vijhani
role: Assistant Vice President role: Assistant Vice President
image: /images/team/team-member-placeholder.svg image:
--- ---
words words words codey words words words words codey words words words words codey words words words words codey words words words words codey words words words words words codey words words words words codey words words words words codey words words words words codey words words words words words words codey words words words words codey words words words words codey words words words words codey words words words words codey words words words words words codey words words words words codey words words words words codey words words words words codey words words words

View File

@ -11,8 +11,7 @@
}, },
{ {
"name": "Bill Xiang", "name": "Bill Xiang",
"role": "Member", "role": "Member"
"image": "/images/team/team-member-placeholder.png"
}, },
{ {
"name": "Raymond Li", "name": "Raymond Li",

View File

@ -11,8 +11,7 @@
}, },
{ {
"name": "Amy Wang", "name": "Amy Wang",
"role": "Developer", "role": "Developer"
"image": "/images/team/team-member-placeholder.png"
}, },
{ {
"name": "Bonnie Peng", "name": "Bonnie Peng",

View File

@ -0,0 +1,39 @@
import { useEffect, useState } from "react";
interface WindowDimension {
width: number;
height: number;
}
function getWindowDimension() {
const { innerWidth: width, innerHeight: height } = window;
return {
width,
height,
};
}
function useWindowDimension(): WindowDimension {
const [windowSize, setWindowDimension] = useState<WindowDimension>({
width: 0,
height: 0,
});
useEffect(() => {
const handleResize = () => {
setWindowDimension(getWindowDimension());
};
// Set size at the first client-side load
handleResize();
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
return windowSize;
}
export default useWindowDimension;

View File

@ -1,4 +1,4 @@
.headerContainer { .header_container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
padding-bottom: calc(24rem / 16); padding-bottom: calc(24rem / 16);
@ -10,7 +10,7 @@
display: none; display: none;
} }
.headerTextContainer { .header_text_container {
margin: auto 0 0 0; margin: auto 0 0 0;
} }
@ -33,60 +33,7 @@
width: calc(360rem / 16); width: calc(360rem / 16);
} }
.execsMobile { .execs {
display: none;
}
.reset_button {
/* reset default button styling */
background: transparent;
border: 0px solid transparent;
font-family: inherit;
line-height: inherit;
}
.execButton {
display: flex;
justify-content: center;
}
.popup_background {
position: fixed;
background-color: var(--navbar-gray);
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.popup_container {
position: fixed;
background-color: var(--off-white);
padding: calc(20rem / 16) calc(40rem / 16);
top: 0;
left: 0;
}
.popup_content {
display: flex;
flex-direction: column;
}
.close {
float: right;
}
.exec {
display: flex;
flex-direction: column;
align-items: center;
}
.exec > p {
font-size: calc(14rem / 16);
}
.execsDesktop {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: calc(26rem / 16); gap: calc(26rem / 16);
@ -109,7 +56,7 @@
margin-top: 6rem; margin-top: 6rem;
} }
.electionSubheading { .election_subheading {
color: var(--blue-2); color: var(--blue-2);
font-size: calc(36rem / 16); font-size: calc(36rem / 16);
font-weight: 600; font-weight: 600;
@ -121,7 +68,7 @@
} }
@media only screen and (max-width: calc(768rem / 16)) { @media only screen and (max-width: calc(768rem / 16)) {
.headerContainer { .header_container {
flex-direction: column-reverse; flex-direction: column-reverse;
padding-bottom: 1rem; padding-bottom: 1rem;
} }
@ -151,15 +98,10 @@
padding-bottom: calc(15rem / 16); padding-bottom: calc(15rem / 16);
} }
.execsMobile { .execs {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(calc(130rem / 16), 1fr)); grid-template-columns: repeat(auto-fill, minmax(calc(132rem / 16), 1fr));
row-gap: calc(24rem / 16); justify-items: center;
column-gap: calc(24rem / 16);
}
.execsDesktop {
display: none;
} }
.members { .members {
@ -171,7 +113,7 @@
padding: 2rem; padding: 2rem;
} }
.electionSubheading { .election_subheading {
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
} }
} }

View File

@ -29,8 +29,8 @@ export default function MeetTheTeam({ execs }: Props) {
return ( return (
<MDXProvider components={{}}> <MDXProvider components={{}}>
<> <>
<div className={styles.headerContainer}> <div className={styles.header_container}>
<div className={styles.headerTextContainer}> <div className={styles.header_text_container}>
<h1 className={styles.header}>Meet the Team!</h1> <h1 className={styles.header}>Meet the Team!</h1>
<div className={styles.nav}> <div className={styles.nav}>
<Link href="#execs">The Executives</Link> <Link href="#execs">The Executives</Link>
@ -47,7 +47,7 @@ export default function MeetTheTeam({ execs }: Props) {
</div> </div>
<Image src="images/team/team-codey.svg" className={styles.codey} /> <Image src="images/team/team-codey.svg" className={styles.codey} />
</div> </div>
<div className={styles.execsDesktop} id="execs"> <div className={styles.execs} id="execs">
{execs.map((exec) => { {execs.map((exec) => {
return ( return (
<div key={exec.metadata.name}> <div key={exec.metadata.name}>
@ -72,7 +72,7 @@ export default function MeetTheTeam({ execs }: Props) {
</div> </div>
<Bubble> <Bubble>
<div className={styles.elections}> <div className={styles.elections}>
<h2 className={styles.electionSubheading}>Elections</h2> <h2 className={styles.election_subheading}>Elections</h2>
<ElectionContent /> <ElectionContent />
</div> </div>
</Bubble> </Bubble>
@ -95,58 +95,6 @@ function MembersList(props: MembersProps) {
); );
} }
// interface MobileExecProps {
// metadata: Metadata;
// content: ComponentType;
// }
// interface Propup extends MobileExecProps {
// handleClose: () => void;
// }
// function MobileExec(props: MobileExecProps) {
// const [isOpen, setIsOpen] = useState(false);
// const togglePopup = () => {
// setIsOpen(!isOpen);
// };
// return (
// <>
// <button
// className={styles.reset_button + " " + styles.execButton}
// onClick={togglePopup}
// >
// <TeamMember {...props.metadata} size="medium" />
// </button>
// {isOpen && (
// <>
// <div className={styles.popup_background} onClick={togglePopup}></div>
// <ExecPopup
// metadata={props.metadata}
// content={props.content}
// handleClose={togglePopup}
// />
// </>
// )}
// </>
// );
// }
// function ExecPopup(props: Propup) {
// return (
// <div className={styles.popup_container}>
// <div className={styles.popup_content}>
// <button className={styles.reset_button} onClick={props.handleClose}>
// <Image src="images/team/popup-close.svg" className={styles.close} />
// </button>
// <div className={styles.exec}>
// <TeamMember {...props.metadata} size="medium" />
// <props.content />
// </div>
// </div>
// </div>
// );
// }
export const getStaticProps: GetStaticProps<Props> = async () => { export const getStaticProps: GetStaticProps<Props> = async () => {
const execNames = await getExecNames(); const execNames = await getExecNames();
const execs = (await Promise.all( const execs = (await Promise.all(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 173 KiB