Fixes for dirents
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Jared He 2021-08-16 16:02:46 -05:00
commit 590b2554c0
64 changed files with 2820 additions and 355 deletions

View File

@ -1,30 +1,30 @@
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: node14 name: node16
steps: steps:
- name: install-deps - name: install-deps
image: node:14 image: node:16
commands: commands:
- npm install - npm install
- name: lint - name: lint
image: node:14 image: node:16
depends_on: depends_on:
- install-deps - install-deps
commands: commands:
- npm run lint - npm run lint
- name: build - name: build
image: node:14 image: node:16
depends_on: depends_on:
- install-deps - install-deps
commands: commands:
- npm run build - npm run build
- name: export - name: export
image: node:14 image: node:16
depends_on: depends_on:
- build - build
commands: commands:

View File

@ -9,6 +9,9 @@ module.exports = {
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking", "plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"plugin:react/recommended", "plugin:react/recommended",
"plugin:prettier/recommended", "plugin:prettier/recommended",
], ],
@ -16,12 +19,37 @@ module.exports = {
rules: { rules: {
"prettier/prettier": "error", "prettier/prettier": "error",
"import/first": "error",
"import/order": [
"error",
{
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true,
},
"pathGroups": [
{
"pattern": "@/**",
"group": "external",
"position": "after",
},
{
"pattern": "./*.css",
"group": "index",
"position": "after",
}
],
},
],
"react/prop-types": "off", "react/prop-types": "off",
"react-hooks/rules-of-hooks": "error", "react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "error", "react-hooks/exhaustive-deps": "error",
// Turn off these rules // Turn off these rules
"@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/explicit-module-boundary-types": "off",
"import/no-unresolved": "off",
}, },
settings: { settings: {
react: { react: {

View File

@ -3,5 +3,5 @@
} }
.bubble:nth-child(odd) { .bubble:nth-child(odd) {
background-color: var(--blue-1-20); background-color: var(--primary-accent-light);
} }

View File

@ -1,5 +1,7 @@
import React from "react"; import React from "react";
import { DefaultLayout } from "./DefaultLayout"; import { DefaultLayout } from "./DefaultLayout";
import styles from "./Bubble.module.css"; import styles from "./Bubble.module.css";
export default function Bubble(props: { children: React.ReactNode }) { export default function Bubble(props: { children: React.ReactNode }) {

View File

@ -2,8 +2,8 @@
.link { .link {
font-family: "Poppins", "sans-serif"; font-family: "Poppins", "sans-serif";
border-radius: calc(20rem / 16); border-radius: calc(20rem / 16);
background-color: var(--blue-2); background-color: var(--primary-accent);
color: white; color: var(--primary-background);
border: none; border: none;
outline: none; outline: none;
transition-duration: 0.3s; transition-duration: 0.3s;
@ -13,7 +13,7 @@
.button:hover, .button:hover,
.link:hover { .link:hover {
background-color: var(--teal-2); background-color: var(--secondary-accent);
cursor: pointer; cursor: pointer;
} }

View File

@ -1,4 +1,5 @@
import React, { AnchorHTMLAttributes, ButtonHTMLAttributes } from "react"; import React, { AnchorHTMLAttributes, ButtonHTMLAttributes } from "react";
import styles from "./Button.module.css"; import styles from "./Button.module.css";
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {

View File

@ -1,5 +1,5 @@
.header { .header {
color: var(--blue-2); color: var(--primary-accent);
font-weight: 600; font-weight: 600;
font-size: calc(36rem / 16); font-size: calc(36rem / 16);
} }

View File

@ -1,7 +1,9 @@
import React from "react"; import React from "react";
import styles from "./ConnectWithUs.module.css";
import { SocialLinks } from "./SocialLinks";
import { Link } from "./Link"; import { Link } from "./Link";
import { SocialLinks } from "./SocialLinks";
import styles from "./ConnectWithUs.module.css";
export function ConnectWithUs() { export function ConnectWithUs() {
return ( return (

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import styles from "./DefaultLayout.module.css"; import styles from "./DefaultLayout.module.css";
export function DefaultLayout(props: { children: React.ReactNode }) { export function DefaultLayout(props: { children: React.ReactNode }) {

View File

@ -3,7 +3,7 @@
} }
.header { .header {
color: var(--blue-2); color: var(--primary-accent);
font-weight: 600; font-weight: 600;
font-size: calc(36rem / 16); font-size: calc(36rem / 16);
} }

View File

@ -1,8 +1,10 @@
import React from "react"; import React from "react";
import styles from "./EmailSignup.module.css";
import { Button } from "./Button"; import { Button } from "./Button";
import { Input } from "./Input"; import { Input } from "./Input";
import styles from "./EmailSignup.module.css";
export function EmailSignup() { export function EmailSignup() {
return ( return (
<section className={styles.container}> <section className={styles.container}>

View File

@ -41,7 +41,7 @@
} }
.content > h2 { .content > h2 {
color: var(--purple-2); color: var(--primary-heading);
font-size: 1rem; font-size: 1rem;
margin-bottom: calc(14rem / 16); margin-bottom: calc(14rem / 16);
} }

View File

@ -1,10 +1,11 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { Button } from "./Button";
import styles from "./EventCard.module.css";
import { Button } from "./Button";
import { EventSetting } from "./EventSetting"; import { EventSetting } from "./EventSetting";
import { Image } from "./Image"; import { Image } from "./Image";
import styles from "./EventCard.module.css";
interface EventCardProps { interface EventCardProps {
name: string; name: string;
short: string; short: string;

View File

@ -4,7 +4,7 @@
max-width: calc(540rem / 16); max-width: calc(540rem / 16);
padding: calc(24rem / 16); padding: calc(24rem / 16);
border-radius: calc(20rem / 16); border-radius: calc(20rem / 16);
background-color: white; background-color: var(--primary-background);
} }
.poster { .poster {
@ -35,7 +35,7 @@
.setting { .setting {
margin: 0; margin: 0;
color: var(--blue-2); color: var(--primary-accent);
font-size: calc(14rem / 16); font-size: calc(14rem / 16);
font-weight: 600; font-weight: 600;
} }
@ -67,7 +67,7 @@
.poster { .poster {
width: calc(95rem / 16); width: calc(95rem / 16);
height: calc(95rem / 16); height: calc(95rem / 16);
border: 1px solid var(--purple-2); border: 1px solid var(--primary-heading);
box-sizing: border-box; box-sizing: border-box;
margin-right: calc(14rem / 16); margin-right: calc(14rem / 16);
} }

View File

@ -1,10 +1,12 @@
import React from "react"; import React from "react";
import { Button } from "./Button"; import { Button } from "./Button";
import { Image } from "./Image";
import { EventSetting } from "./EventSetting"; import { EventSetting } from "./EventSetting";
import styles from "./EventDescriptionCard.module.css"; import { Image } from "./Image";
import { Discord, Twitch, Instagram, Facebook } from "./SocialLinks"; import { Discord, Twitch, Instagram, Facebook } from "./SocialLinks";
import styles from "./EventDescriptionCard.module.css";
interface Props { interface Props {
name: string; name: string;
short: string; short: string;

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import styles from "./EventSetting.module.css"; import styles from "./EventSetting.module.css";
interface Props { interface Props {

View File

@ -1,6 +1,6 @@
.footer { .footer {
box-sizing: border-box; box-sizing: border-box;
background: var(--purple-2); background: var(--primary-heading);
height: calc(66rem / 16); height: calc(66rem / 16);
padding: calc(14rem / 16) 0; padding: calc(14rem / 16) 0;
width: 100%; width: 100%;
@ -18,7 +18,7 @@
} }
.text { .text {
color: var(--white); color: var(--primary-background);
font-style: normal; font-style: normal;
text-align: center; text-align: center;
} }

View File

@ -1,7 +1,9 @@
import React from "react"; import React from "react";
import styles from "./Footer.module.css";
import { SocialLinks } from "./SocialLinks"; import { SocialLinks } from "./SocialLinks";
import styles from "./Footer.module.css";
export function Footer() { export function Footer() {
return ( return (
<footer className={styles.footer}> <footer className={styles.footer}>

View File

@ -8,20 +8,20 @@
border: 0; border: 0;
border-radius: calc(20rem / 16); border-radius: calc(20rem / 16);
background-color: var(--grey-1-24); background-color: var(--input-background);
font-size: calc(18rem / 16); font-size: calc(18rem / 16);
line-height: calc(30rem / 16); line-height: calc(30rem / 16);
color: var(--grey-3); color: var(--input-text);
} }
.input::placeholder { .input::placeholder {
color: var(--grey-2); color: var(--input-placeholder-text);
font-weight: 700; font-weight: 700;
} }
.input:is(:active, :hover, :focus) { .input:is(:active, :hover, :focus) {
box-sizing: border-box; box-sizing: border-box;
border: calc(3rem / 16) solid var(--blue-1); border: calc(3rem / 16) solid var(--primary-accent-soft);
border-radius: calc(20rem / 16); border-radius: calc(20rem / 16);
outline: none; outline: none;
padding: calc(7rem / 16) calc(28rem / 16); padding: calc(7rem / 16) calc(28rem / 16);

View File

@ -1,4 +1,5 @@
import React, { InputHTMLAttributes } from "react"; import React, { InputHTMLAttributes } from "react";
import styles from "./Input.module.css"; import styles from "./Input.module.css";
export function Input(props: InputHTMLAttributes<HTMLInputElement>) { export function Input(props: InputHTMLAttributes<HTMLInputElement>) {

View File

@ -1,10 +1,10 @@
.link { .link {
color: var(--blue-2); color: var(--primary-accent);
transition-duration: 0.3s; transition-duration: 0.3s;
text-decoration: none; text-decoration: none;
white-space: normal; white-space: normal;
} }
.link:hover { .link:hover {
color: var(--teal-2); color: var(--secondary-accent);
} }

View File

@ -1,7 +1,7 @@
import NextLink, { LinkProps as NextLinkProps } from "next/link";
import React from "react"; import React from "react";
import styles from "./Link.module.css"; import styles from "./Link.module.css";
import NextLink from "next/link";
import { LinkProps as NextLinkProps } from "next/link";
type Props = Omit<NextLinkProps, "href"> & { href: string }; type Props = Omit<NextLinkProps, "href"> & { href: string };

View File

@ -5,7 +5,7 @@
} }
.card:nth-child(odd) { .card:nth-child(odd) {
background-color: var(--teal-2-20); background-color: var(--secondary-accent-light);
} }
.name { .name {
@ -19,7 +19,7 @@
} }
.info { .info {
color: var(--purple-2); color: var(--primary-heading);
margin-bottom: calc(12rem / 16); margin-bottom: calc(12rem / 16);
} }
@ -29,7 +29,7 @@
right: 0; right: 0;
cursor: pointer; cursor: pointer;
margin: calc(20rem / 16); margin: calc(20rem / 16);
color: var(--blue-2); color: var(--primary-accent);
font-size: calc(14rem / 16); font-size: calc(14rem / 16);
} }
@ -46,5 +46,5 @@
} }
.dropDownIcon { .dropDownIcon {
fill: var(--blue-2); fill: var(--primary-accent);
} }

View File

@ -1,5 +1,7 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { EventSetting } from "./EventSetting"; import { EventSetting } from "./EventSetting";
import styles from "./MiniEventCard.module.css"; import styles from "./MiniEventCard.module.css";
interface Props { interface Props {

View File

@ -1,6 +1,7 @@
import { DEFAULT_MIN_VERSION } from "node:tls";
import React from "react"; import React from "react";
import { Image } from "./Image"; import { Image } from "./Image";
import styles from "./MiniTechTalkCard.module.css"; import styles from "./MiniTechTalkCard.module.css";
interface MiniTechTalkProps { interface MiniTechTalkProps {

View File

@ -4,7 +4,7 @@
align-items: center; align-items: center;
z-index: 10; z-index: 10;
background-color: var(--white); background-color: var(--primary-background);
} }
.navContent { .navContent {
@ -63,16 +63,16 @@
} }
.navMenu a { .navMenu a {
color: var(--purple-2); color: var(--primary-heading);
text-decoration: none; text-decoration: none;
} }
.navMenu a.currentPage { .navMenu a.currentPage {
color: var(--blue-2); color: var(--primary-accent);
} }
.navMenu > li > a:hover { .navMenu > li > a:hover {
color: var(--blue-2); color: var(--primary-accent);
font-weight: 600; font-weight: 600;
} }
@ -116,8 +116,8 @@
padding: 0; padding: 0;
border-radius: calc(8rem / 16); border-radius: calc(8rem / 16);
background-color: var(--white); background-color: var(--primary-background);
box-shadow: 0 calc(8rem / 16) 1rem var(--blue-1-20); box-shadow: 0 calc(8rem / 16) 1rem var(--primary-accent-light);
font-size: calc(14rem / 16); font-size: calc(14rem / 16);
} }
@ -134,7 +134,7 @@
.dropdown li:hover a, .dropdown li:hover a,
.dropdown li a:focus { .dropdown li a:focus {
background-color: var(--blue-1-20); background-color: var(--primary-accent-light);
} }
.dropdown li:first-child a { .dropdown li:first-child a {
@ -224,7 +224,7 @@
left: 0; left: 0;
z-index: 20; z-index: 20;
background-color: var(--navbar-gray); background-color: var(--navbar-page-overlay);
opacity: 0; opacity: 0;
transition: 0.5s; transition: 0.5s;
@ -244,7 +244,7 @@
padding: calc(calc(64rem / 16) - 1rem); padding: calc(calc(64rem / 16) - 1rem);
padding-left: calc(calc(78rem / 16) - 1rem); padding-left: calc(calc(78rem / 16) - 1rem);
background-color: var(--off-white); background-color: var(--secondary-background);
transform: translateX(100vw); transform: translateX(100vw);
transition: 0.5s; transition: 0.5s;

View File

@ -1,7 +1,9 @@
import React, { useReducer } from "react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useReducer } from "react";
import { Image } from "./Image"; import { Image } from "./Image";
import styles from "./Navbar.module.css"; import styles from "./Navbar.module.css";
type Menu = { type Menu = {

View File

@ -1,7 +1,7 @@
.card { .card {
padding: calc(30rem / 16) calc(40rem / 16); padding: calc(30rem / 16) calc(40rem / 16);
max-width: calc(524rem / 16); max-width: calc(524rem / 16);
background-color: var(--white); background-color: var(--primary-background);
border-radius: calc(20rem / 16); border-radius: calc(20rem / 16);
} }
@ -11,7 +11,7 @@
} }
.author { .author {
color: var(--purple-1); color: var(--secondary-heading);
font-style: normal; font-style: normal;
} }

View File

@ -1,4 +1,5 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import styles from "./NewsCard.module.css"; import styles from "./NewsCard.module.css";
interface NewsCardProps { interface NewsCardProps {

View File

@ -6,7 +6,7 @@
margin: 1rem 0; margin: 1rem 0;
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
font-weight: 600; font-weight: 600;
color: var(--blue-2); color: var(--primary-accent);
} }
.content { .content {
@ -17,7 +17,7 @@
.nav { .nav {
margin: calc(8rem / 16) calc(32rem / 16) 0 0; margin: calc(8rem / 16) calc(32rem / 16) 0 0;
color: var(--purple-2); color: var(--primary-heading);
font-weight: 500; font-weight: 500;
} }
@ -26,7 +26,7 @@
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
font-size: calc(14rem / 16); font-size: calc(14rem / 16);
border-bottom: calc(1rem / 16) solid var(--blue-2-25); border-bottom: calc(1rem / 16) solid var(--primary-accent-light);
align-items: center; align-items: center;
height: calc(40rem / 16); height: calc(40rem / 16);
width: calc(284rem / 16); width: calc(284rem / 16);
@ -41,8 +41,8 @@
} }
.selected { .selected {
background-color: var(--blue-1-05); background-color: var(--primary-accent-dim);
color: var(--blue-2); color: var(--primary-accent);
font-weight: 700; font-weight: 700;
} }
@ -56,7 +56,7 @@
.selected .marker { .selected .marker {
display: inline; display: inline;
background-color: var(--blue-2); background-color: var(--primary-accent);
height: calc(24rem / 16); height: calc(24rem / 16);
width: calc(4rem / 16); width: calc(4rem / 16);
margin-right: 1rem; margin-right: 1rem;
@ -73,7 +73,7 @@
flex: 1; flex: 1;
display: flex; display: flex;
cursor: pointer; cursor: pointer;
color: var(--purple-2); color: var(--primary-heading);
font-size: calc(12rem / 16); font-size: calc(12rem / 16);
} }
@ -88,15 +88,15 @@
} }
.arrowHeading { .arrowHeading {
color: var(--blue-2); color: var(--primary-accent);
font-size: calc(14rem / 16); font-size: calc(14rem / 16);
font-weight: 700; font-weight: 700;
border-bottom: calc(2rem / 16) solid var(--blue-2); border-bottom: calc(2rem / 16) solid var(--primary-accent);
padding-bottom: calc(4rem / 16); padding-bottom: calc(4rem / 16);
} }
.arrow { .arrow {
fill: var(--blue-2); fill: var(--primary-accent);
margin-top: calc(27rem / 16); margin-top: calc(27rem / 16);
} }

View File

@ -1,4 +1,5 @@
import React, { ReactNode, ComponentType } from "react"; import React, { ReactNode, ComponentType } from "react";
import styles from "./OrganizedContent.module.css"; import styles from "./OrganizedContent.module.css";
export interface LinkProps { export interface LinkProps {

View File

@ -18,9 +18,9 @@
} }
.blue { .blue {
fill: var(--blue-1); fill: var(--primary-accent-soft);
} }
.white { .white {
fill: var(--white); fill: var(--primary-background);
} }

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import styles from "./SocialLinks.module.css"; import styles from "./SocialLinks.module.css";
interface Props { interface Props {

View File

@ -18,10 +18,10 @@
.name { .name {
font-weight: 700; font-weight: 700;
color: var(--blue-2); color: var(--primary-accent);
} }
.role { .role {
font-weight: 600; font-weight: 600;
color: var(--purple-2); color: var(--primary-heading);
} }

View File

@ -1,7 +1,9 @@
import React from "react"; import React from "react";
import styles from "./TeamMember.module.css";
import { Image } from "./Image"; import { Image } from "./Image";
import styles from "./TeamMember.module.css";
interface TeamMemberProps { interface TeamMemberProps {
name: string; name: string;
role: string; role: string;

View File

@ -29,7 +29,7 @@
grid-area: name; grid-area: name;
margin: 0; margin: 0;
color: var(--blue-2); color: var(--primary-accent);
font-size: calc(36rem / 16); font-size: calc(36rem / 16);
font-weight: 600; font-weight: 600;
} }

View File

@ -1,5 +1,7 @@
import React from "react"; import React from "react";
import { Image } from "./Image"; import { Image } from "./Image";
import styles from "./TeamMemberCard.module.css"; import styles from "./TeamMemberCard.module.css";
interface TeamMemberCardProps { interface TeamMemberCardProps {

View File

@ -1,5 +1,7 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { Image } from "./Image"; import { Image } from "./Image";
import styles from "./TechTalkCard.module.css"; import styles from "./TechTalkCard.module.css";
interface TechTalkProps { interface TechTalkProps {

178
components/Theme.tsx Normal file
View File

@ -0,0 +1,178 @@
import React, {
createContext,
ReactElement,
useContext,
useEffect,
useState,
} from "react";
type BuiltInThemes = "light" | "dark";
export interface Theme {
name: BuiltInThemes | "custom";
palette: Palette;
}
export type SetThemeInput = BuiltInThemes | Partial<Palette>;
export const PALETTE_NAMES = [
"--primary-background",
"--secondary-background",
"--primary-accent",
"--primary-accent-soft",
"--primary-accent-light",
"--primary-accent-dim",
"--secondary-accent",
"--secondary-accent-light",
"--primary-heading",
"--secondary-heading",
"--text",
"--form-invalid",
"--input-background",
"--input-placeholder-text",
"--input-text",
"--navbar-page-overlay",
] as const;
export const emptyPalette = PALETTE_NAMES.reduce(
(partial, varName) => ({
...partial,
[varName]: "#c4e0f8",
}),
{} as Palette
);
const ThemeContext =
createContext<
| {
theme: Theme;
setTheme(input: SetThemeInput): void;
save(): void;
clearSaved(): void;
}
| undefined
>(undefined);
export interface Props {
children?: ReactElement;
}
export function ThemeProvider(props: Props) {
const update = useForcedUpdate();
const [themeName, setThemeName] =
useState<Theme["name"] | undefined>(undefined);
const setTheme = (input: SetThemeInput) => {
if (typeof input === "string") {
PALETTE_NAMES.forEach((name) =>
document.body.style.setProperty(name, "")
);
if (input === "light") {
document.body.classList.remove("dark");
} else if (input === "dark") {
document.body.classList.add("dark");
}
setThemeName(input);
} else {
const properties = Object.keys(input) as PaletteNames[];
properties.forEach((property) =>
document.body.style.setProperty(
property,
input[property]?.trim() ?? null
)
);
setThemeName("custom");
}
update();
};
useEffect(() => {
const customPalette = getSavedPalette();
if (customPalette == null) {
setThemeName("light");
} else {
setTheme(customPalette);
setThemeName("custom");
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<ThemeContext.Provider
value={
themeName == null
? undefined
: {
theme: {
name: themeName,
get palette() {
return getCurrentPalette();
},
},
setTheme,
save: () => savePalette(getCurrentPalette()),
clearSaved: clearSavedPalette,
}
}
>
{props.children}
</ThemeContext.Provider>
);
}
export function useThemeContext() {
return useContext(ThemeContext);
}
export type PaletteNames = typeof PALETTE_NAMES[number];
export type Palette = {
[key in PaletteNames]: string;
};
function getCurrentPalette() {
const styles = getComputedStyle(document.body);
return PALETTE_NAMES.reduce(
(partial, varName) => ({
...partial,
[varName]: styles.getPropertyValue(varName).trim(),
}),
{} as Palette
);
}
function useForcedUpdate() {
const [fakeState, setFakeState] = useState(true);
return () => setFakeState(!fakeState);
}
const STORAGE_KEY = "csc-theme-palette";
function getSavedPalette() {
const raw = localStorage.getItem(STORAGE_KEY);
return raw == null ? undefined : (JSON.parse(raw) as Palette);
}
function savePalette(palette: Palette) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(palette));
}
function clearSavedPalette() {
localStorage.removeItem(STORAGE_KEY);
}

View File

@ -1,13 +1,13 @@
.newsDemo { .newsDemo {
padding: calc(50rem / 16); padding: calc(50rem / 16);
background-color: var(--off-white); background-color: var(--secondary-background);
display: inline-block; display: inline-block;
} }
.newsTitle { .newsTitle {
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
color: var(--purple-2); color: var(--primary-heading);
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
line-height: calc(36 / 24); line-height: calc(36 / 24);
margin-bottom: calc(14rem / 16); margin-bottom: calc(14rem / 16);
@ -19,20 +19,20 @@
font-size: calc(14rem / 16); font-size: calc(14rem / 16);
line-height: calc(21 / 14); line-height: calc(21 / 14);
white-space: pre-line; white-space: pre-line;
color: var(--purple-2); color: var(--primary-heading);
vertical-align: baseline; vertical-align: baseline;
} }
.news > hr { .news > hr {
border: none; border: none;
height: calc(1rem / 16); height: calc(1rem / 16);
background-color: var(--purple-2); background-color: var(--primary-heading);
margin: 0 0 calc(13rem / 16) 0; margin: 0 0 calc(13rem / 16) 0;
} }
.eventDescriptionCardDemo { .eventDescriptionCardDemo {
padding: calc(50rem / 16) 0; padding: calc(50rem / 16) 0;
background-color: var(--off-white); background-color: var(--secondary-background);
display: inline-block; display: inline-block;
} }
@ -54,7 +54,7 @@
.committee { .committee {
margin: 0; margin: 0;
color: var(--purple-2); color: var(--primary-heading);
font-weight: 600; font-weight: 600;
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
line-height: calc(36 / 24); line-height: calc(36 / 24);
@ -63,7 +63,7 @@
.teamMemberDemo > hr { .teamMemberDemo > hr {
border: none; border: none;
height: calc(1rem / 16); height: calc(1rem / 16);
background-color: var(--blue-2); background-color: var(--primary-accent);
width: 100%; width: 100%;
margin-top: calc(24rem / 16); margin-top: calc(24rem / 16);
margin-bottom: calc(46rem / 16); margin-bottom: calc(46rem / 16);
@ -78,24 +78,24 @@
.linkDemo { .linkDemo {
padding: calc(50rem / 16); padding: calc(50rem / 16);
background-color: var(--off-white); background-color: var(--secondary-background);
} }
.linkTitle { .linkTitle {
font-weight: bold; font-weight: bold;
color: var(--purple-2); color: var(--primary-heading);
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
} }
.miniTechTalkDemo > *:nth-child(odd) { .miniTechTalkDemo > *:nth-child(odd) {
background: var(--background-teal-2); background: var(--secondary-accent-light);
} }
@media only screen and (max-width: calc(768rem / 16)) { @media only screen and (max-width: calc(768rem / 16)) {
.newsDemo, .newsDemo,
.eventDescriptionCardDemo { .eventDescriptionCardDemo {
padding: calc(20rem / 16); padding: calc(20rem / 16);
background-color: var(--off-white); background-color: var(--secondary-background);
} }
.eventDescriptionCardDemo > * { .eventDescriptionCardDemo > * {

View File

@ -1,59 +1,56 @@
import React, { useState } from "react"; import React, { useState } from "react";
import styles from "./playground.module.css";
import AfterHoursContent, { import AfterHoursContent, {
metadata as afterHoursMetadata, metadata as afterHoursMetadata,
} from "../content/playground/after-hours.event.mdx"; } from "../content/playground/after-hours.event.mdx";
import OOTBReact, {
metadata as OOTBReactEventMetadata,
} from "../content/playground/ootb-react.event.mdx";
import AltTab, { import AltTab, {
metadata as altTabEventMetadata, metadata as altTabEventMetadata,
} from "../content/playground/alt-tab.event.mdx"; } from "../content/playground/alt-tab.event.mdx";
import CodeyInfo, {
import Name, { metadata as codeyMetadata,
metadata as nameOrganizedContentMetadata, } from "../content/playground/codey.team-member.mdx";
} from "../content/playground/constitution/name.section.mdx";
import Purpose, {
metadata as purposeOrganizedContentMetadata,
} from "../content/playground/constitution/purpose.section.mdx";
import Membership, {
metadata as membershipOrganizedContentMetadata,
} from "../content/playground/constitution/membership.section.mdx";
import Officers, {
metadata as officersOrganizedContentMetadata,
} from "../content/playground/constitution/officers.section.mdx";
import Duties, { import Duties, {
metadata as dutiesOrganizedContentMetadata, metadata as dutiesOrganizedContentMetadata,
} from "../content/playground/constitution/duties-of-officers.section.mdx"; } from "../content/playground/constitution/duties-of-officers.section.mdx";
import ExecutiveCouncil, { import ExecutiveCouncil, {
metadata as executiveCouncilOrganizedContentMetadata, metadata as executiveCouncilOrganizedContentMetadata,
} from "../content/playground/constitution/executive-council.section.mdx"; } from "../content/playground/constitution/executive-council.section.mdx";
import Membership, {
import UnavailableContent, { metadata as membershipOrganizedContentMetadata,
metadata as unavailableMetadata, } from "../content/playground/constitution/membership.section.mdx";
} from "../content/playground/unavailable.news.mdx"; import Name, {
metadata as nameOrganizedContentMetadata,
} from "../content/playground/constitution/name.section.mdx";
import Officers, {
metadata as officersOrganizedContentMetadata,
} from "../content/playground/constitution/officers.section.mdx";
import Purpose, {
metadata as purposeOrganizedContentMetadata,
} from "../content/playground/constitution/purpose.section.mdx";
import { metadata as dogeMetadata } from "../content/playground/doge.team-member.mdx"; import { metadata as dogeMetadata } from "../content/playground/doge.team-member.mdx";
import CodeyInfo, { import OOTBReact, {
metadata as codeyMetadata, metadata as OOTBReactEventMetadata,
} from "../content/playground/codey.team-member.mdx"; } from "../content/playground/ootb-react.event.mdx";
import TempTechTalk, { import TempTechTalk, {
metadata as tempTechTalkMetadata, metadata as tempTechTalkMetadata,
} from "../content/playground/temp.talk.mdx"; } from "../content/playground/temp.talk.mdx";
import UnavailableContent, {
metadata as unavailableMetadata,
} from "../content/playground/unavailable.news.mdx";
import { MiniEventCard } from "./MiniEventCard"; import { Button } from "./Button";
import { NewsCard } from "./NewsCard";
import { Link } from "./Link";
import { EventCard } from "./EventCard"; import { EventCard } from "./EventCard";
import { EventDescriptionCard } from "./EventDescriptionCard"; import { EventDescriptionCard } from "./EventDescriptionCard";
import { Link } from "./Link";
import { MiniEventCard } from "./MiniEventCard";
import { MiniTechTalkCard } from "./MiniTechTalkCard";
import { NewsCard } from "./NewsCard";
import { OrganizedContent, LinkProps } from "./OrganizedContent";
import { TeamMember } from "./TeamMember"; import { TeamMember } from "./TeamMember";
import { TeamMemberCard } from "./TeamMemberCard"; import { TeamMemberCard } from "./TeamMemberCard";
import { OrganizedContent, LinkProps } from "./OrganizedContent";
import { Button } from "./Button";
import { Footer } from "./Footer";
import { TechTalkCard } from "./TechTalkCard"; import { TechTalkCard } from "./TechTalkCard";
import { MiniTechTalkCard } from "./MiniTechTalkCard";
import styles from "./playground.module.css";
const events = [ const events = [
{ Content: OOTBReact, metadata: OOTBReactEventMetadata }, { Content: OOTBReact, metadata: OOTBReactEventMetadata },

View File

@ -1,36 +0,0 @@
import React, { createContext, ReactElement, useEffect, useState } from "react";
type Theme = "light" | "dark";
const ThemeContext = createContext<{
theme: Theme;
setTheme(newTheme: Theme): void;
}>({
theme: "light",
setTheme: () => {
throw new Error("Use ThemeProvider instead.");
},
});
interface Props {
theme: Theme;
children?: ReactElement;
}
export function ThemeProvider({ children, theme }: Props) {
const [currentTheme, setTheme] = useState(theme);
useEffect(() => {
if (currentTheme === "light") {
document.body.classList.remove("dark");
} else if (currentTheme === "dark") {
document.body.classList.add("dark");
}
}, [currentTheme]);
return (
<ThemeContext.Provider value={{ theme: currentTheme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}

View File

@ -1,4 +1,4 @@
import Bubble from "./../../components/Bubble"; import Bubble from "@/components/Bubble";
<Bubble> <Bubble>

View File

@ -18,7 +18,7 @@ The Computer Science club graciously thanks the Mathematics Endowment Fund for t
## MathSoc Capital Improvements Fund ## MathSoc Capital Improvements Fund
The [MathSoc Capital Improvements Fund](http://mathsoc.uwaterloo.ca/council/policies/Capital+Improvements+Fund) has provided funding of new office hardware: The [MathSoc Capital Improvements Fund](https://mathsoc.uwaterloo.ca/wp-content/uploads/Mathsoc_Policies.pdf#page=54) has provided funding of new office hardware:
- Strombola and Bit-Shifter hardware upgrade (new motherboard, CPU and RAM) - Strombola and Bit-Shifter hardware upgrade (new motherboard, CPU and RAM)
- 2x 8-port 10Gbps SFP+ network cards for the Math Student Orgs routers/switches - 2x 8-port 10Gbps SFP+ network cards for the Math Student Orgs routers/switches

7
deploy-demo.bash Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
export NEXT_PUBLIC_BASE_PATH="/~$USER/website-demo"
rm -rf ~/www/website-demo
npm install
npm run build
npm run export
mv out ~/www/website-demo

View File

@ -7,17 +7,13 @@ import { MDXRemoteSerializeResult } from "next-mdx-remote";
const EVENTS_PATH = path.join("content", "events"); const EVENTS_PATH = path.join("content", "events");
export async function getYears(): Promise<string[]> { export async function getYears(): Promise<string[]> {
return (await fs.readdir(EVENTS_PATH, { withFileTypes: true })).map( return (await fs.readdir(EVENTS_PATH, { withFileTypes: true }))
(dirent) => dirent.name .filter((dirent) => dirent.isDirectory())
); .map((dirent) => dirent.name);
} }
export async function getTermsByYear(year: string): Promise<string[]> { export async function getTermsByYear(year: string): Promise<string[]> {
return ( return await fs.readdir(path.join(EVENTS_PATH, year));
await fs.readdir(path.join(EVENTS_PATH, year), {
withFileTypes: true,
})
).map((dirent) => dirent.name);
} }
interface Metadata { interface Metadata {

2348
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,10 @@
{ {
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"engines": {
"node": "^16",
"npm": "^7"
},
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
@ -30,6 +34,7 @@
"@typescript-eslint/parser": "4.28.4", "@typescript-eslint/parser": "4.28.4",
"eslint": "7.32.0", "eslint": "7.32.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.24.0",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "7.24.0", "eslint-plugin-react": "7.24.0",
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",

View File

@ -1,35 +1,31 @@
body { body {
/* Default is light theme */ /* Default is light theme */
--white: #ffffff; --primary-background: #ffffff;
--off-white: #fdf8f5; --secondary-background: #fdf8f5;
--teal-1: #76ffdc;
--teal-2: #4ed4b2;
--teal-2-20: #4ed4b234;
--blue-1: #5caff9;
--blue-1-05: #5caff90d;
--blue-1-20: #5caff934;
--blue-2: #1482e3;
--blue-2-25: #1482e340;
--purple-1: #525284;
--purple-2: #2a2a62;
--black: #000000;
--grey-1: #c4c4c4;
--grey-1-24: #c4c4c440;
--grey-2: #bbbbbb;
--grey-3: #6b6b6b;
--red: #9f616a;
--gradient-blue-green: linear-gradient(
99.94deg,
#1481e3 -17.95%,
#4ed4b2 172.82%
);
--background-teal-2: rgb(78, 212, 178, 0.2);
/* used in mobile navbar background */
--navbar-gray: #787878b2;
/* used in home page */
--home-title-purple: #27153e;
color: var(--black); --primary-accent: #1482e3;
--primary-accent-soft: #5caff9;
--primary-accent-light: #c4e0f8;
--primary-accent-dim: #f7fbff;
--secondary-accent: #4ed4b2;
--secondary-accent-light: #dcf6f0;
--primary-heading: #2a2a62;
--secondary-heading: #525284;
--text: #000000;
--form-invalid: #9f616a;
--input-background: #f0f0f0;
--input-placeholder-text: #bbbbbb;
--input-text: #6b6b6b;
--navbar-page-overlay: #787878b2;
background-color: var(--primary-background);
color: var(--text);
font-family: "Poppins", "sans-serif"; font-family: "Poppins", "sans-serif";
font-size: 1rem; font-size: 1rem;
font-weight: 400; font-weight: 400;
@ -42,25 +38,8 @@ input {
font-family: "Poppins", "sans-serif"; font-family: "Poppins", "sans-serif";
} }
/* FIXME: Dark theme is the same as light theme right now */
.dark { .dark {
--white: #ffffff; /* FIXME: Implement dark theme */
--off-white: #fdf8f5;
--teal-1: #76ffdc;
--teal-2: #4ed4b2;
--blue-1: #5caff9;
--blue-1-05: #5caff90d;
--blue-1-20: #5caff934;
--blue-2: #1482e3;
--purple-1: #525284;
--purple-2: #2a2a62;
--gradient-blue-green: linear-gradient(
99.94deg,
#1481e3 -17.95%,
#4ed4b2 172.82%
);
/* used in mobile navbar background */
--navbar-gray: #787878b2;
} }
h1, h1,
@ -71,7 +50,7 @@ h5,
h6 { h6 {
font-style: normal; font-style: normal;
line-height: 1.5; line-height: 1.5;
color: var(--purple-2); color: var(--primary-heading);
} }
h1, h1,

View File

@ -1,12 +1,14 @@
import React, { ComponentType, ReactNode } from "react"; import { MDXProvider } from "@mdx-js/react";
import { NextComponentType, NextPageContext } from "next"; import { NextComponentType, NextPageContext } from "next";
import { AppProps as DefaultAppProps } from "next/app"; import { AppProps as DefaultAppProps } from "next/app";
import { MDXProvider } from "@mdx-js/react"; import React, { ComponentType, ReactNode } from "react";
import { ThemeProvider } from "../components/theme";
import { Navbar } from "../components/Navbar"; import { DefaultLayout } from "@/components/DefaultLayout";
import { Footer } from "../components/Footer"; import { Footer } from "@/components/Footer";
import { Link } from "../components/Link"; import { Link } from "@/components/Link";
import { DefaultLayout } from "../components/DefaultLayout"; import { Navbar } from "@/components/Navbar";
import { ThemeProvider } from "@/components/Theme";
import styles from "./_app.module.css"; import styles from "./_app.module.css";
import "./_app.css"; import "./_app.css";
@ -16,7 +18,7 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
const Layout = Component.Layout ?? DefaultLayout; const Layout = Component.Layout ?? DefaultLayout;
return ( return (
<ThemeProvider theme="light"> <ThemeProvider>
<MDXProvider components={{ a: Link }}> <MDXProvider components={{ a: Link }}>
<div className={styles.appContainer}> <div className={styles.appContainer}>
<Navbar /> <Navbar />

View File

@ -9,12 +9,12 @@
} }
.content { .content {
color: black; color: var(--text);
background-color: white; background-color: var(--primary-background);
} }
.content span { .content span {
color: var(--blue-2); color: var(--primary-accent);
} }
.titleContainer { .titleContainer {

View File

@ -1,10 +1,13 @@
import React from "react"; import React from "react";
import { Image } from "../../components/Image";
import { ConnectWithUs } from "@/components/ConnectWithUs";
import { DefaultLayout } from "@/components/DefaultLayout";
import { EmailSignup } from "@/components/EmailSignup";
import { Image } from "@/components/Image";
import Content from "../../content/about/index.mdx"; import Content from "../../content/about/index.mdx";
import styles from "./index.module.css"; import styles from "./index.module.css";
import { ConnectWithUs } from "components/ConnectWithUs";
import { EmailSignup } from "components/EmailSignup";
import { DefaultLayout } from "components/DefaultLayout";
export default function AboutUs() { export default function AboutUs() {
return ( return (

View File

@ -3,18 +3,18 @@
flex-direction: row; flex-direction: row;
align-items: flex-end; align-items: flex-end;
padding-bottom: 1rem; padding-bottom: 1rem;
border-bottom: calc(1rem / 16) solid var(--purple-2); border-bottom: calc(1rem / 16) solid var(--primary-heading);
} }
.header { .header {
color: var(--purple-2); color: var(--primary-heading);
margin: 0 1rem 0 0; margin: 0 1rem 0 0;
text-align: center; text-align: center;
} }
.content h2 { .content h2 {
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
color: var(--blue-2); color: var(--primary-accent);
} }
@media only screen and (max-width: calc(768rem / 16)) { @media only screen and (max-width: calc(768rem / 16)) {

View File

@ -1,6 +1,9 @@
import React from "react"; import React from "react";
import { Image } from "../../components/Image";
import { Image } from "@/components/Image";
import Content from "../../content/about/our-supporters.mdx"; import Content from "../../content/about/our-supporters.mdx";
import styles from "./our-supporters.module.css"; import styles from "./our-supporters.module.css";
export default function OurSupporters() { export default function OurSupporters() {

View File

@ -5,16 +5,16 @@
.page > header { .page > header {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
border-bottom: calc(1rem / 16) solid var(--purple-2); border-bottom: calc(1rem / 16) solid var(--primary-heading);
} }
.headerText > h1 { .headerText > h1 {
color: var(--purple-2); color: var(--primary-heading);
margin: 0 0 calc(8rem / 16) 0; margin: 0 0 calc(8rem / 16) 0;
} }
.headerText > p { .headerText > p {
color: var(--black); color: var(--text);
margin: 0 0 calc(22rem / 16) 0; margin: 0 0 calc(22rem / 16) 0;
} }
@ -27,7 +27,7 @@
} }
.content h2 { .content h2 {
color: var(--blue-2); color: var(--primary-accent);
} }
.content strong { .content strong {
@ -60,7 +60,7 @@
} }
.headerText > h1 { .headerText > h1 {
color: var(--purple-2); color: var(--primary-heading);
font-size: calc(24rem / 16); font-size: calc(24rem / 16);
margin-bottom: (12rem / 16); margin-bottom: (12rem / 16);
} }

View File

@ -1,8 +1,11 @@
import React from "react"; import React from "react";
import { Image } from "../components/Image";
import { ConnectWithUs } from "../components/ConnectWithUs"; import { ConnectWithUs } from "@/components/ConnectWithUs";
import { EmailSignup } from "../components/EmailSignup"; import { EmailSignup } from "@/components/EmailSignup";
import { Image } from "@/components/Image";
import Content from "../content/get-involved.mdx"; import Content from "../content/get-involved.mdx";
import styles from "./get-involved.module.css"; import styles from "./get-involved.module.css";
export default function GetInvolved() { export default function GetInvolved() {

View File

@ -47,13 +47,13 @@
font-family: "Futura", "sans-serif"; font-family: "Futura", "sans-serif";
font-size: calc(33rem / 16); font-size: calc(33rem / 16);
text-align: center; text-align: center;
color: var(--home-title-purple); color: var(--primary-heading);
} }
.clubDescription { .clubDescription {
margin-bottom: calc(50rem / 16); margin-bottom: calc(50rem / 16);
text-align: center; text-align: center;
color: var(--purple-2); color: var(--primary-heading);
} }
.clubDescription br { .clubDescription br {
@ -71,7 +71,7 @@
margin: 0; margin: 0;
width: 100%; width: 100%;
background-color: var(--off-white); background-color: var(--secondary-background);
} }
.cards { .cards {
@ -154,7 +154,7 @@
.clubDescription { .clubDescription {
margin: calc(8rem / 16) 0 calc(26rem / 16); margin: calc(8rem / 16) 0 calc(26rem / 16);
color: var(--purple-2); color: var(--primary-heading);
} }
.clubDescription br { .clubDescription br {
@ -196,6 +196,6 @@
margin: 1rem 0 calc(34rem / 16); margin: 1rem 0 calc(34rem / 16);
height: calc(1rem / 16); height: calc(1rem / 16);
border: none; border: none;
background-color: var(--purple-2); background-color: var(--primary-heading);
} }
} }

View File

@ -1,24 +1,27 @@
import React from "react"; import React from "react";
import { Image } from "../components/Image";
import { SocialLinks } from "../components/SocialLinks";
import { EventDescriptionCard } from "../components/EventDescriptionCard";
import { NewsCard } from "../components/NewsCard";
import { ConnectWithUs } from "../components/ConnectWithUs";
import { EmailSignup } from "../components/EmailSignup";
import { DefaultLayout } from "../components/DefaultLayout";
import styles from "./index.module.css";
// temporary event and news imports import { ConnectWithUs } from "@/components/ConnectWithUs";
import OOTBReact, { import { DefaultLayout } from "@/components/DefaultLayout";
metadata as OOTBReactEventMetadata, import { EmailSignup } from "@/components/EmailSignup";
} from "../content/playground/ootb-react.event.mdx"; import { EventDescriptionCard } from "@/components/EventDescriptionCard";
import { Image } from "@/components/Image";
import { NewsCard } from "@/components/NewsCard";
import { SocialLinks } from "@/components/SocialLinks";
import AltTab, { import AltTab, {
metadata as altTabEventMetadata, metadata as altTabEventMetadata,
} from "../content/playground/alt-tab.event.mdx"; } from "../content/playground/alt-tab.event.mdx";
import OOTBReact, {
metadata as OOTBReactEventMetadata,
} from "../content/playground/ootb-react.event.mdx";
import UnavailableContent, { import UnavailableContent, {
metadata as unavailableMetadata, metadata as unavailableMetadata,
} from "../content/playground/unavailable.news.mdx"; } from "../content/playground/unavailable.news.mdx";
import styles from "./index.module.css";
// temporary event and news imports
export default function Home() { export default function Home() {
const events = [ const events = [
{ Content: OOTBReact, metadata: OOTBReactEventMetadata }, { Content: OOTBReact, metadata: OOTBReactEventMetadata },

View File

@ -10,11 +10,11 @@ import {
ButtonDemo, ButtonDemo,
TechTalkDemo, TechTalkDemo,
MiniTechTalkDemo, MiniTechTalkDemo,
} from "../components/playground"; } from "@/components/playground";
import { ConnectWithUs } from "../components/ConnectWithUs"; import { ConnectWithUs } from "@/components/ConnectWithUs";
import { EmailSignup } from "../components/EmailSignup"; import { EmailSignup } from "@/components/EmailSignup";
import { TeamMemberCard } from "../components/TeamMemberCard"; import { TeamMemberCard } from "@/components/TeamMemberCard";
# Playground # Playground

View File

@ -1,5 +1,5 @@
import React from "react";
import Head from "next/head"; import Head from "next/head";
import React from "react";
export default function Resources() { export default function Resources() {
return ( return (

38
pages/themer.module.css Normal file
View File

@ -0,0 +1,38 @@
.page {
margin-bottom: calc(60rem / 16);
}
.controls {
display: flex;
justify-content: space-between;
}
.controls > *:first-child {
margin-right: calc(20rem / 16);
}
.palette {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(calc(150rem / 16), 1fr));
row-gap: calc(20rem / 16);
column-gap: calc(40rem / 16);
}
.palette > * {
display: flex;
flex-direction: column;
align-items: center;
}
.colorSelector {
height: calc(75rem / 16);
}
.colorReset {
margin-bottom: calc(10rem / 16);
transition-duration: unset;
}
.colorName {
text-align: center;
}

79
pages/themer.tsx Normal file
View File

@ -0,0 +1,79 @@
import React from "react";
import { Button } from "@/components/Button";
import { Input } from "@/components/Input";
import { useThemeContext, emptyPalette } from "@/components/Theme";
import styles from "./themer.module.css";
export default function Themer() {
const context = useThemeContext();
const palette = context?.theme.palette ?? emptyPalette;
return (
<main className={styles.page}>
<h1>Themer</h1>
<form onSubmit={(event) => event.preventDefault()}>
<div className={styles.controls}>
<Button
type="reset"
onClick={() => {
context?.clearSaved();
context?.setTheme("light");
}}
>
Reset to light mode
</Button>
<Button type="submit" onClick={() => context?.save()}>
Save
</Button>
</div>
<div className={styles.palette}>
{Object.entries(palette).map(([key, value]) => {
const color =
value.length === 4 && value.startsWith("#")
? `#${value[1].repeat(2)}${value[2].repeat(2)}${value[3].repeat(
2
)}`
: value;
const isValidColor = color.startsWith("#") && color.length === 7;
return (
<div key={key}>
<Input
id={`color-${key}`}
type="color"
className={styles.colorSelector}
value={color}
onChange={(event) =>
context?.setTheme({ [key]: event.target.value })
}
/>
<Button
type="button"
className={styles.colorReset}
size="small"
onClick={() => context?.setTheme({ [key]: "" })}
>
Reset
</Button>
<code className={styles.colorName}>
<label htmlFor={`color-${key}`}>
{!isValidColor && "🚧 "}
{key
.slice(2)
.split("-")
.map((word) => word[0].toUpperCase() + word.slice(1))
.join(" ")}
{!isValidColor && " 🚧"}
</label>
</code>
</div>
);
})}
</div>{" "}
</form>
</main>
);
}

View File

@ -1,3 +1,5 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json" "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"dependencyDashboard": true,
"labels": ["Dependencies"]
} }

View File

@ -24,6 +24,9 @@
"strictBindCallApply": true, "strictBindCallApply": true,
"strictPropertyInitialization": true, "strictPropertyInitialization": true,
"strictFunctionTypes": true, "strictFunctionTypes": true,
"paths": {
"@/components/*": ["components/*"]
}
}, },
"include": [ "include": [
"next-env.d.ts", "next-env.d.ts",