Docs for how pages work #391

Merged
a3thakra merged 5 commits from adi-initial-pages-docs into main 2022-03-10 02:47:17 -05:00
2 changed files with 160 additions and 0 deletions

160
docs/pages.md Normal file
View File

@ -0,0 +1,160 @@
# Pages
All pages are a separate React component in our repository, under the [pages](../pages) folder. This is a [special directory](https://nextjs.org/docs/tag/v11.0.0/basic-features/pages) used by Next.js which maps a React component exported from this directory to a page on a url.
The React components exported by these files are wrapped by the [`App` component](../pages/_app.tsx). This lets us reuse code in between pages which makes it a good place to render the [navbar](../components/Navbar.tsx), [footer](../components/Footer.tsx), [background shapes](../components/ShapesBackground.tsx), and the general CSS layout of a page.
a3thakra marked this conversation as resolved Outdated

We could change:
component -> components (to prevent confusion in case people think it's one giant component)
css -> CSS (to be consistent with the entire readme)

Should we talk about when we used // eslint-disable-next-line @typescript-eslint/no-non-null-assertion in the dynamic pages or is that too minor?

While more details about Title component probably deserve its own docs page, should we at least mention it in pages.md since every page needs a (custom) Title?

Overall, it was very comprehensive and intuitive. LGTM!

We could change: component -> components (to prevent confusion in case people think it's one giant component) css -> CSS (to be consistent with the entire readme) Should we talk about when we used // eslint-disable-next-line @typescript-eslint/no-non-null-assertion in the dynamic pages or is that too minor? While more details about `Title` component probably deserve its own docs page, should we at least mention it in `pages.md` since every page needs a (custom) Title? Overall, it was very comprehensive and intuitive. LGTM!
## Title
We use a custom [`Title` component](../components/Title.tsx) to set the title on our pages. This is a very simple component and is just a wrapper around the Next.js [`Head` component](https://nextjs.org/docs/tag/v11.0.0/api-reference/next/head). It also automatically prefixes each title with "CSC - University of Waterloo". Look at the [code](../components/Title.tsx) for more details.
### Example 1
a3thakra marked this conversation as resolved Outdated

Maybe include a link to the Bubble component, and/or provide a description of what the bubbles look like (ie. they are horizontal hot dog shaped highlights that surround some paragraphs of the text)? For someone who hasn't seen what the About Us page looks like, it might be unclear what the bubbles are.

Maybe include a link to the `Bubble` component, and/or provide a description of what the bubbles look like (ie. they are horizontal hot dog shaped highlights that surround some paragraphs of the text)? For someone who hasn't seen what the About Us page looks like, it might be unclear what the bubbles are.
```tsx
import { Title } from "@/components/Title"
function FooPage() {
return (
<>
<Title>Title in the tab</Title>
<div>Content of the page</div>
</>
)
}
// The page's content will be "Content of the page"
// The title of the page (as shown at the top of the browser in the tab) is "CSC - University of Waterloo - Title in the tab"
```
### Example 2
You can also pass in an array of strings, and the [`Title` component](../components/Title.tsx) will automatically join them with " - ".
```tsx
import { Title } from "@/components/Title"
function FooPage() {
return (
<>
<Title>{["Foo", "Bar", "Baz"]}</Title>
<div>Content of the page</div>
</>
)
}
// The page's content will be "Content of the page"
// The title of the page (as shown at the top of the browser in the tab) is "CSC - University of Waterloo - Foo - Bar - Baz"
```
## Layout
Most pages are wrapped with the [`DefaultLayout`](../components/DefaultLayout.tsx) component which limits the page width and adds the necessary margins and paddings. However, some pages need to override these default styles to accomodate for their specific design. For example:
- The [home page](../pages/index.tsx) is wider than all the other pages.
- The [about us](../pages/about/index.tsx) needs the entire screen width to properly render the [bubbles](../components/Bubble.tsx).
<figure>
<img src="static/bubbles-example.png" alt="bubble on about page" />
<figcaption>
The bubble component on the About us page
</figcaption>
</figure>
We have an opt-in model for using a custom layout for pages. This is enabled by the static `Layout` function on a React component for a page.
### Example
```tsx
function PageXYZ() {
return <p>I am a page</p>
}
a3thakra marked this conversation as resolved Outdated

Sidenote: @a258wang do you remember why we almost never use the container's width and height in our codebase? Should this be removed?

Sidenote: @a258wang do you remember why we almost never use the container's width and height in our codebase? Should this be removed?

I'm not 100% sure why we don't use the container's width/height in our codebase... do such calculations work if JS is disabled in the browser?

I'm not 100% sure why we don't use the container's width/height in our codebase... do such calculations work if JS is disabled in the browser?

shapes are not loaded at all if JS is disabled

shapes are not loaded at all if JS is disabled

Oh I thought you were asking about why we don't use the container width/height in the other parts of the codebase... as for why the container width/height aren't used more in the shapes component, I'm not entirely sure, but I think they're used when they're needed.

Oh I thought you were asking about why we don't use the container width/height in the other parts of the codebase... as for why the container width/height aren't used more in the shapes component, I'm not entirely sure, but I think they're used when they're needed.
// If we want this page to use a custom layout, we can add a static `Layout` function to it.
PageXYZ.Layout = function PageXYZLayout(props: { children: React.ReactNode }) {
return <div className={styles.customLayoutStyles}>{props.children}</div>;
}
```
It is extremely important to return `props.children` as part of the JSX because this contains the entire page. If you fail to return it, the page will **not** show up.
Note that this functionality is **not** a part of Next.js. We take advantage of static properties in the [_app.tsx](../pages/_app.tsx#L30) file to implement this.
## Shapes Background
Just like the static `Layout` function, we use another static function on React pages called `getShapesConfig`. Most pages use the [default config](../components/ShapesBackground.tsx#L188) which positions shapes randomly on the page. Some pages require a little artistic nudge or even hardcoding the shapes to appear in certain locations.
Pages like the [home page](../pages/index.tsx) can use the `getShapesConfig` function to customize what shapes they want the page to render.
### Example 1
```tsx
import { GetShapesConfig } from "@/components/ShapesBackground";
PageXYZ.getShapesConfig = (() => {
// I ONLY LIKE DOTS AND WAVES!!!!
return {
dots: [
{
// These map to CSS properties. You don't have to use all of them. Use the ones that you want.
top: "calc(0.06 * (580rem / 0.65) / 16)",
right: "90vw",
width: "calc(168rem / 16)",
height: "calc(204rem / 16)",
filter: "var(--teal)",
opacity: "25%",
}
],
waves: [
{
top: "calc(0.5 * (580rem / 0.65) / 16)",
left: "24vw",
width: "calc(116rem / 16)",
height: "calc(58rem / 16)",
filter: "var(--teal)",
},
]
}
}) as GetShapesConfig
```
Note that background shapes are not rendered into html files during build time because it is impossible to know the window dimensions. This means that you can safely use `window.innerWidth` and `window.innerHeight` as well use the width and height of the shapes container inside the `getShapesConfig` function to change the shapes based on size of the screen.
### Example 2
```tsx
import { GetShapesConfig } from "@/components/ShapesBackground";
PageXYZ.getShapesConfig = ((containerWidth, containerHeight) => {
// I like dots on desktops
if (window.innerWidth >= 768) {
return {
dots: [
{
// These map to CSS properties. You don't have to use all of them. Use the ones that you want.
top: "calc(0.06 * (580rem / 0.65) / 16)",
right: "90vw",
width: "calc(168rem / 16)",
height: "calc(204rem / 16)",
filter: "var(--teal)",
opacity: "25%",
}
],
}
}
// but waves on phones and tables
else {
return {
waves: [
{
top: "calc(0.5 * (580rem / 0.65) / 16)",
left: "24vw",
width: "calc(116rem / 16)",
height: "calc(58rem / 16)",
filter: "var(--teal)",
},
]
}
}
}) as GetShapesConfig
```
As with the `Layout` function, this is **not** a part of Next.js. We take advantage of static properties in the [_app.tsx](../pages/_app.tsx#L51) file to implement this.

BIN
docs/static/bubbles-example.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB