diff --git a/.vscode/settings.json b/.vscode/settings.json index 99e58e0..eb98407 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,12 +2,13 @@ "typescript.tsdk": "node_modules/typescript/lib", "eslint.format.enable": true, "eslint.codeActionsOnSave.mode": "all", + "css.lint.validProperties": ["composes"], "css.format.spaceAroundSelectorSeparator": true, "[css]": { "editor.suggest.insertMode": "replace", "gitlens.codeLens.scopes": ["document"], "editor.formatOnSave": true, - "editor.defaultFormatter": "vscode.css-language-features" + "editor.defaultFormatter": "vscode.css-language-features", }, "[javascript]": { "editor.formatOnSave": false, diff --git a/components/ComponentWrapper.module.css b/components/ComponentWrapper.module.css new file mode 100644 index 0000000..4fad333 --- /dev/null +++ b/components/ComponentWrapper.module.css @@ -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); +} \ No newline at end of file diff --git a/components/ComponentWrapper.tsx b/components/ComponentWrapper.tsx new file mode 100644 index 0000000..8893905 --- /dev/null +++ b/components/ComponentWrapper.tsx @@ -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 ( +
+
+

{heading}

+

{bodyText}

+
+
{children}
+
+ ); +} diff --git a/components/WordCloud.tsx b/components/WordCloud.tsx index 9591dac..ca295e5 100644 --- a/components/WordCloud.tsx +++ b/components/WordCloud.tsx @@ -197,10 +197,12 @@ const shouldNotRerender = ( nextProps: WordCloudWordsProps ) => { if ( - prevProps.tooltipLeft !== nextProps.tooltipLeft || - prevProps.tooltipTop !== nextProps.tooltipTop || - nextProps.tooltipLeft === undefined || - nextProps.tooltipTop === undefined + // if width changes, rerender, else don't rerender for a tooltip change + prevProps.width === nextProps.width && + (prevProps.tooltipLeft !== nextProps.tooltipLeft || + prevProps.tooltipTop !== nextProps.tooltipTop || + nextProps.tooltipLeft === undefined || + nextProps.tooltipTop === undefined) ) { return true; // do not re-render } diff --git a/package.json b/package.json index 6358840..814c0d7 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "@visx/group": "^2.10.0", "@visx/scale": "^2.2.2", "@visx/shape": "^2.10.0", + "@visx/text": "^2.10.0", "@visx/tooltip": "^2.10.0", "@visx/wordcloud": "^2.10.0", - "@visx/text": "^2.10.0", "next": "12.1.6", "react": "18.1.0", "react-dom": "18.1.0" diff --git a/pages/_app.css b/pages/_app.css index 385e67c..eea84e8 100644 --- a/pages/_app.css +++ b/pages/_app.css @@ -75,7 +75,7 @@ body { /* Page titles (e.g. Demographics) */ h1 { font-size: calc(56rem / 16); - color: var(--primary-accent-lighter); + color: var(--primary-accent-light); margin-top: calc(32rem / 16); margin-bottom: calc(16rem / 16); } @@ -119,6 +119,10 @@ a:hover { color: var(--link-hover); } +p { + font-size: calc(28rem / 16); +} + @media only screen and (prefers-color-scheme: dark) { body { --primary-background: var(--dark--primary-background); diff --git a/pages/_app.tsx b/pages/_app.tsx index 7803bd0..52d7142 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -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 ; + return ( + <> + + + + + + ); } diff --git a/pages/index.tsx b/pages/index.tsx index 4ff1fb7..58dda94 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -5,6 +5,8 @@ export default function Home() { return (

Click here to visit the playground +
+ Click here to visit a sample page

); } diff --git a/pages/samplePage.module.css b/pages/samplePage.module.css new file mode 100644 index 0000000..b50d07b --- /dev/null +++ b/pages/samplePage.module.css @@ -0,0 +1,5 @@ +.page { + display: flex; + flex-direction: column; + justify-content: center; +} \ No newline at end of file diff --git a/pages/samplePage.tsx b/pages/samplePage.tsx new file mode 100644 index 0000000..f067888 --- /dev/null +++ b/pages/samplePage.tsx @@ -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 ( +
+ + + + + + ({ + 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} + /> + + + + + + + + + + + + + + + + ({ + text: word.key, + value: word.value, + }))} + width={isMobile ? width / 1.5 : width / 2} + height={500} + /> + +
+ ); +} diff --git a/utils/getWindowDimensions.ts b/utils/getWindowDimensions.ts new file mode 100644 index 0000000..427568b --- /dev/null +++ b/utils/getWindowDimensions.ts @@ -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({ + width: 0, + height: 0, + }); + + const handleResize = () => { + setWindowDimensions(getWindowDimensions()); + }; + + useEffect(() => { + handleResize(); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + return windowDimensions; +}; diff --git a/utils/isMobile.ts b/utils/isMobile.ts new file mode 100644 index 0000000..4022df1 --- /dev/null +++ b/utils/isMobile.ts @@ -0,0 +1,3 @@ +import { useWindowDimensions } from "./getWindowDimensions"; + +export const useIsMobile = () => useWindowDimensions().width <= 768;