commit
924b6c4a57
@ -0,0 +1,59 @@ |
||||
.sideWrapperCommon { |
||||
background-color: var(--secondary-background); |
||||
display: flex; |
||||
padding: calc(40rem / 16) calc(50rem / 16); |
||||
margin: calc(65rem / 16) 0; |
||||
width: 90%; |
||||
} |
||||
|
||||
.wrapperRight { |
||||
composes: sideWrapperCommon; |
||||
align-self: end; |
||||
margin-right: 0; |
||||
padding-right: 0; |
||||
border-radius: calc(200rem / 16) 0 0 calc(200rem / 16); |
||||
flex-direction: row-reverse; |
||||
padding-right: calc(50rem / 16); |
||||
} |
||||
|
||||
.wrapperLeft { |
||||
composes: sideWrapperCommon; |
||||
align-self: start; |
||||
margin-left: 0; |
||||
padding-left: 0; |
||||
border-radius: 0 calc(200rem / 16) calc(200rem / 16) 0; |
||||
flex-direction: row; |
||||
padding-left: calc(50rem / 16); |
||||
} |
||||
|
||||
.noBackground { |
||||
background: none; |
||||
align-self: center; |
||||
} |
||||
|
||||
.wrapperCenter { |
||||
flex-direction: column; |
||||
text-align: center; |
||||
gap: calc(25rem / 16); |
||||
/* to match the 65px margin with the left/right variant: |
||||
add 45px bottom margin, since internal wrapper contributes 20px for the center component |
||||
0px top margin, since h3 contributes 45px and internal wrapper contributes 20px for the center component |
||||
*/ |
||||
margin: 0 0 calc(45rem / 16) 0; |
||||
padding: 0 15%; |
||||
} |
||||
|
||||
@media screen and (max-width: 768px) { |
||||
.sideWrapperCommon { |
||||
margin: auto; |
||||
flex-direction: column; |
||||
text-align: center; |
||||
padding: 0; |
||||
border-radius: 0; |
||||
width: 100%; |
||||
} |
||||
} |
||||
|
||||
.internalWrapper { |
||||
padding: calc(20rem / 16); |
||||
} |
@ -0,0 +1,42 @@ |
||||
import React from "react"; |
||||
|
||||
import styles from "./ComponentWrapper.module.css"; |
||||
|
||||
type AlignOption = "left" | "center" | "right"; |
||||
|
||||
type ComponentWrapperProps = { |
||||
children: React.ReactNode; |
||||
heading: string; |
||||
bodyText: string; |
||||
align?: AlignOption; |
||||
noBackground?: boolean; |
||||
}; |
||||
|
||||
export function ComponentWrapper({ |
||||
heading, |
||||
bodyText, |
||||
children, |
||||
align = "left", |
||||
noBackground = false, |
||||
}: ComponentWrapperProps) { |
||||
const alignClasses: { [key in AlignOption]: string } = { |
||||
left: styles.wrapperLeft, |
||||
center: styles.wrapperCenter, |
||||
right: styles.wrapperRight, |
||||
}; |
||||
|
||||
return ( |
||||
<div |
||||
className={` |
||||
${alignClasses[align]}
|
||||
${noBackground ? styles.noBackground : ""} |
||||
`}
|
||||
> |
||||
<div className={styles.internalWrapper}> |
||||
<h3>{heading}</h3> |
||||
<p>{bodyText}</p> |
||||
</div> |
||||
<div className={styles.internalWrapper}>{children}</div> |
||||
</div> |
||||
); |
||||
} |
@ -1,9 +1,20 @@ |
||||
import type { AppProps } from "next/app"; |
||||
import Head from "next/head"; |
||||
import React from "react"; |
||||
|
||||
import "./_app.css"; |
||||
import "./font.css"; |
||||
|
||||
export default function App({ Component, pageProps }: AppProps): JSX.Element { |
||||
return <Component {...pageProps} />; |
||||
return ( |
||||
<> |
||||
<Head> |
||||
<meta |
||||
name="viewport" |
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=0" |
||||
/> |
||||
</Head> |
||||
<Component {...pageProps} /> |
||||
</> |
||||
); |
||||
} |
||||
|
@ -0,0 +1,5 @@ |
||||
.page { |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
} |
@ -0,0 +1,127 @@ |
||||
import { BarGraphHorizontal, BarGraphVertical } from "components/BarGraph"; |
||||
import { mockCategoricalData, moreMockCategoricalData } from "data/mocks"; |
||||
import React from "react"; |
||||
import { useWindowDimensions } from "utils/getWindowDimensions"; |
||||
import { useIsMobile } from "utils/isMobile"; |
||||
|
||||
import { ComponentWrapper } from "@/components/ComponentWrapper"; |
||||
|
||||
import { WordCloud } from "../components/WordCloud"; |
||||
|
||||
import styles from "./samplePage.module.css"; |
||||
|
||||
export default function SamplePage() { |
||||
const { width } = useWindowDimensions(); |
||||
const isMobile = useIsMobile(); |
||||
|
||||
return ( |
||||
<div className={styles.page}> |
||||
<ComponentWrapper |
||||
heading="What program are you in?" |
||||
bodyText="There are a total of 106 respondents of the CS Class Profile. Interestingly, there are a huge number of students that are just in CS, partially due to the overwhelming number of people in CS as seen in the total demographics." |
||||
> |
||||
<BarGraphVertical |
||||
data={mockCategoricalData} |
||||
// For components that are in the side wrappers, it looks better if they fill a certain amount of width, so we can make the width dynamic like this
|
||||
width={isMobile ? width / 1.25 : width / 2} |
||||
height={500} |
||||
margin={{ |
||||
top: 20, |
||||
bottom: 80, |
||||
left: 60, |
||||
right: 20, |
||||
}} |
||||
/> |
||||
</ComponentWrapper> |
||||
|
||||
<ComponentWrapper |
||||
heading="What program are you in?" |
||||
bodyText="There are a total of 106 respondents of the CS Class Profile. Interestingly, there are a huge number of students that are just in CS, partially due to the overwhelming number of people in CS as seen in the total demographics." |
||||
align="center" |
||||
> |
||||
<WordCloud |
||||
data={moreMockCategoricalData.map((word) => ({ |
||||
text: word.key, |
||||
value: word.value, |
||||
}))} |
||||
// For components that we don't want to match the width necessarily we can provide direct values
|
||||
width={isMobile ? width / 1.5 : 800} |
||||
height={500} |
||||
/> |
||||
</ComponentWrapper> |
||||
|
||||
<ComponentWrapper |
||||
heading="What program are you in?" |
||||
bodyText="There are a total of 106 respondents of the CS Class Profile. Interestingly, there are a huge number of students that are just in CS, partially due to the overwhelming number of people in CS as seen in the total demographics." |
||||
align="right" |
||||
> |
||||
<BarGraphHorizontal |
||||
className={styles.barGraphDemo} |
||||
data={mockCategoricalData} |
||||
width={isMobile ? width / 1.45 : width / 2} |
||||
height={500} |
||||
margin={{ |
||||
top: 20, |
||||
bottom: 40, |
||||
left: 150, |
||||
right: 20, |
||||
}} |
||||
/> |
||||
</ComponentWrapper> |
||||
|
||||
<ComponentWrapper |
||||
heading="What program are you in?" |
||||
bodyText="There are a total of 106 respondents of the CS Class Profile. Interestingly, there are a huge number of students that are just in CS, partially due to the overwhelming number of people in CS as seen in the total demographics." |
||||
align="left" |
||||
noBackground |
||||
> |
||||
<BarGraphHorizontal |
||||
className={styles.barGrapDemo} |
||||
data={mockCategoricalData} |
||||
width={isMobile ? width / 1.45 : width / 2} |
||||
height={500} |
||||
margin={{ |
||||
top: 20, |
||||
bottom: 40, |
||||
left: 150, |
||||
right: 20, |
||||
}} |
||||
/> |
||||
</ComponentWrapper> |
||||
|
||||
<ComponentWrapper |
||||
heading="What program are you in?" |
||||
bodyText="There are a total of 106 respondents of the CS Class Profile. Interestingly, there are a huge number of students that are just in CS, partially due to the overwhelming number of people in CS as seen in the total demographics." |
||||
> |
||||
<BarGraphHorizontal |
||||
className={styles.barGraphDemo} |
||||
data={mockCategoricalData} |
||||
width={isMobile ? width / 1.45 : width / 2} |
||||
height={500} |
||||
margin={{ |
||||
top: 20, |
||||
bottom: 40, |
||||
left: 150, |
||||
right: 20, |
||||
}} |
||||
/> |
||||
</ComponentWrapper> |
||||
|
||||
<ComponentWrapper |
||||
heading="What program are you in?" |
||||
bodyText="There are a total of 106 respondents of the CS Class Profile. Interestingly, there are a huge number of students that are just in CS, partially due to the overwhelming number of people in CS as seen in the total demographics." |
||||
align="left" |
||||
noBackground |
||||
> |
||||
<WordCloud |
||||
data={moreMockCategoricalData.map((word) => ({ |
||||
text: word.key, |
||||
value: word.value, |
||||
}))} |
||||
width={isMobile ? width / 1.5 : width / 2} |
||||
height={500} |
||||
/> |
||||
</ComponentWrapper> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,35 @@ |
||||
// Attribution: https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs
|
||||
import { useState, useEffect } from "react"; |
||||
|
||||
type WindowDimensions = { |
||||
width: number; |
||||
height: number; |
||||
}; |
||||
|
||||
const getWindowDimensions = (): WindowDimensions => { |
||||
const { innerWidth, innerHeight } = window; |
||||
|
||||
return { |
||||
width: innerWidth, |
||||
height: innerHeight, |
||||
}; |
||||
}; |
||||
|
||||
export const useWindowDimensions = (): WindowDimensions => { |
||||
const [windowDimensions, setWindowDimensions] = useState<WindowDimensions>({ |
||||
width: 0, |
||||
height: 0, |
||||
}); |
||||
|
||||
const handleResize = () => { |
||||
setWindowDimensions(getWindowDimensions()); |
||||
}; |
||||
|
||||
useEffect(() => { |
||||
handleResize(); |
||||
window.addEventListener("resize", handleResize); |
||||
return () => window.removeEventListener("resize", handleResize); |
||||
}, []); |
||||
|
||||
return windowDimensions; |
||||
}; |
@ -0,0 +1,3 @@ |
||||
import { useWindowDimensions } from "./getWindowDimensions"; |
||||
|
||||
export const useIsMobile = () => useWindowDimensions().width <= 768; |
Loading…
Reference in new issue