diff --git a/frontend/src/OnlineClassroom/index.tsx b/frontend/src/OnlineClassroom/index.tsx index 6248e4b..b12cc9f 100644 --- a/frontend/src/OnlineClassroom/index.tsx +++ b/frontend/src/OnlineClassroom/index.tsx @@ -8,9 +8,20 @@ export function OnlineClassroom() { return (
- - - +
+ + + + +
+
+ ); +} + +function ClassroomConection() { + return ( +
+ Connection status
); } diff --git a/frontend/src/colorManager.ts b/frontend/src/colorManager.ts new file mode 100644 index 0000000..d2cc50b --- /dev/null +++ b/frontend/src/colorManager.ts @@ -0,0 +1,58 @@ + +export const applyColors = (colorName: string) => { + const styleStr = ` +:root { + --c-primary: var(--c-${colorName}-primary); + --c-on-primary: var(--c-${colorName}-on-primary); + --c-primary-container: var(--c-${colorName}-primary-container); + --c-on-primary-container: var(--c-${colorName}-on-primary-container); + --c-background: var(--c-${colorName}-background); + --c-on-background: var(--c-${colorName}-on-background); + --c-surface: var(--c-${colorName}-surface); + --c-on-surface: var(--c-${colorName}-on-surface); + --c-outline: var(--c-${colorName}-outline); + --c-surface-variant: var(--c-${colorName}-surface-variant); + --c-on-surface-variant: var(--c-${colorName}-on-surface-variant); + --c-success: var(--c-${colorName}-success); + --c-on-success: var(--c-${colorName}-on-success); +} +@media (prefers-color-scheme: light) { + :root { + --c-primary: var(--c-${colorName}-primary); + --c-on-primary: var(--c-${colorName}-on-primary); + --c-primary-container: var(--c-${colorName}-primary-container); + --c-on-primary-container: var(--c-${colorName}-on-primary-container); + --c-background: var(--c-${colorName}-background); + --c-on-background: var(--c-${colorName}-on-background); + --c-surface: var(--c-${colorName}-surface); + --c-on-surface: var(--c-${colorName}-on-surface); + --c-outline: var(--c-${colorName}-outline); + --c-surface-variant: var(--c-${colorName}-surface-variant); + --c-on-surface-variant: var(--c-${colorName}-on-surface-variant); + --c-success: var(--c-${colorName}-success); + --c-on-success: var(--c-${colorName}-on-success); + } +} +`; + + // Check for a previous style element in the head + let styleEl = document.getElementById("color-scheme-style"); + + if (styleEl === null) { + styleEl = document.createElement("style"); + styleEl.id = "color-scheme-style"; + document.head.appendChild(styleEl); + } + + // Apply the new color + styleEl.innerHTML = styleStr; + + // Save + localStorage.setItem("color-scheme", colorName); +}; + +// Applies colors on load +(() => { + const savedColor = localStorage.getItem("color-scheme") ?? "blue"; + applyColors(savedColor); +})(); diff --git a/frontend/src/colors.css b/frontend/src/colors.css new file mode 100644 index 0000000..7d0627f --- /dev/null +++ b/frontend/src/colors.css @@ -0,0 +1,196 @@ +/* + Material colors +*/ + +/* + * GREEN + */ + :root { + --c-green-primary: #7cdc6d; + --c-green-on-primary: #003a02; + --c-green-primary-container: #005304; + --c-green-on-primary-container: #97f986; + --c-green-background: #1a1c18; + --c-green-on-background: #e2e3dd; + --c-green-surface: #1a1c18; + --c-green-on-surface: #e2e3dd; + --c-green-outline: #8d9387; + --c-green-surface-variant: #43483f; + --c-green-on-surface-variant: #c3c8bc; +} +@media (prefers-color-scheme: light) { + :root { + --c-green-primary: #006e08; + --c-green-on-primary: #ffffff; + --c-green-primary-container: #97f986; + --c-green-on-primary-container: #002201; + --c-green-background: #fcfdf6; + --c-green-on-background: #1a1c18; + --c-green-surface: #fcfdf6; + --c-green-on-surface: #1a1c18; + --c-green-outline: #73796e; + --c-green-surface-variant: #dfe4d8; + --c-green-on-surface-variant: #43483f; + } +} + +/* + * BLUE + */ +:root { + --c-blue-primary: #adc6ff; + --c-blue-on-primary: #002e69; + --c-blue-primary-container: #0e448e; + --c-blue-on-primary-container: #d8e2ff; + --c-blue-background: #1b1b1f; + --c-blue-on-background: #e3e2e6; + --c-blue-surface: #1b1b1f; + --c-blue-on-surface: #e3e2e6; + --c-blue-outline: #8e9099; + --c-blue-surface-variant: #44474f; + --c-blue-on-surface-variant: #c4c6d0; +} +@media (prefers-color-scheme: light) { + :root { + --c-blue-primary: #315da8; + --c-blue-on-primary: #ffffff; + --c-blue-primary-container: #d8e2ff; + --c-blue-on-primary-container: #001a41; + --c-blue-background: #fefbff; + --c-blue-on-background: #1b1b1f; + --c-blue-surface: #fefbff; + --c-blue-on-surface: #1b1b1f; + --c-blue-outline: #74777f; + --c-blue-surface-variant: #e1e2ec; + --c-blue-on-surface-variant: #44474f; + } +} + +/* + * YELLOW + */ +:root { + --c-yellow-primary: #f5bf31; + --c-yellow-on-primary: #3f2e00; + --c-yellow-primary-container: #5b4300; + --c-yellow-on-primary-container: #ffdf9b; + --c-yellow-background: #1e1b16; + --c-yellow-on-background: #e9e1d9; + --c-yellow-surface: #1e1b16; + --c-yellow-on-surface: #e9e1d9; + --c-yellow-outline: #999080; + --c-yellow-surface-variant: #4d4639; + --c-yellow-on-surface-variant: #d0c5b4; +} +@media (prefers-color-scheme: light) { + :root { + --c-yellow-primary: #785a00; + --c-yellow-on-primary: #ffffff; + --c-yellow-primary-container: #ffdf9b; + --c-yellow-on-primary-container: #251a00; + --c-yellow-background: #fffbff; + --c-yellow-on-background: #1e1b16; + --c-yellow-surface: #fffbff; + --c-yellow-on-surface: #1e1b16; + --c-yellow-outline: #7f7667; + --c-yellow-surface-variant: #ede1cf; + --c-yellow-on-surface-variant: #4d4639; + } +} + + +/* + * PINK + */ +:root { + --c-pink-primary: #ffade5; + --c-pink-on-primary: #5e0051; + --c-pink-primary-container: #80156e; + --c-pink-on-primary-container: #ffd7ef; + --c-pink-background: #1f1a1d; + --c-pink-on-background: #eae0e3; + --c-pink-surface: #1f1a1d; + --c-pink-on-surface: #eae0e3; + --c-pink-outline: #9b8d94; + --c-pink-surface-variant: #4f444a; + --c-pink-on-surface-variant: #d2c2ca; +} +@media (prefers-color-scheme: light) { + :root { + --c-pink-primary: #9d3288; + --c-pink-on-primary: #ffffff; + --c-pink-primary-container: #ffd7ef; + --c-pink-on-primary-container: #3a0031; + --c-pink-background: #fffbff; + --c-pink-on-background: #1f1a1d; + --c-pink-surface: #fffbff; + --c-pink-on-surface: #1f1a1d; + --c-pink-outline: #81737a; + --c-pink-surface-variant: #efdee6; + --c-pink-on-surface-variant: #4f444a; + } +} + +/* + * ORANGE + */ +:root { + --c-orange-primary: #ffb86d; + --c-orange-on-primary: #492900; + --c-orange-primary-container: #683c00; + --c-orange-on-primary-container: #ffdcbd; + --c-orange-background: #201b16; + --c-orange-on-background: #ebe1d9; + --c-orange-surface: #201b16; + --c-orange-on-surface: #ebe1d9; + --c-orange-outline: #9d8e81; + --c-orange-surface-variant: #50453a; + --c-orange-on-surface-variant: #d5c3b5; +} +@media (prefers-color-scheme: light) { + :root { + --c-orange-primary: #9e4300; + --c-orange-on-primary: #ffffff; + --c-orange-primary-container: #ffdbcb; + --c-orange-on-primary-container: #341100; + --c-orange-background: #fffbff; + --c-orange-on-background: #201a18; + --c-orange-surface: #fffbff; + --c-orange-on-surface: #201a18; + --c-orange-outline: #85736c; + --c-orange-surface-variant: #f4ded4; + --c-orange-on-surface-variant: #52443d; + } +} + +/* + * RED + */ + :root { + --c-red-primary: #ffb4a8; + --c-red-on-primary: #690100; + --c-red-primary-container: #930100; + --c-red-on-primary-container: #ffdad4; + --c-red-background: #201a19; + --c-red-on-background: #ede0dd; + --c-red-surface: #201a19; + --c-red-on-surface: #ede0dd; + --c-red-outline: #a08c89; + --c-red-surface-variant: #534341; + --c-red-on-surface-variant: #d8c2be; +} +@media (prefers-color-scheme: light) { + :root { + --c-red-primary: #c00100; + --c-red-on-primary: #ffffff; + --c-red-primary-container: #ffdad4; + --c-red-on-primary-container: #410000; + --c-red-background: #fffbff; + --c-red-on-background: #201a19; + --c-red-surface: #fffbff; + --c-red-on-surface: #201a19; + --c-red-outline: #857370; + --c-red-surface-variant: #f5ddda; + --c-red-on-surface-variant: #534341; + } +} \ No newline at end of file diff --git a/frontend/src/components/Dialog.tsx b/frontend/src/components/Dialog.tsx new file mode 100644 index 0000000..0cc5570 --- /dev/null +++ b/frontend/src/components/Dialog.tsx @@ -0,0 +1,31 @@ +import { JSX, onCleanup, onMount} from "solid-js"; + +type Children = Array | JSX.Element; +export function Dialog(props: {onClose: () => void, children: Children, class?: string}) { + const positionClasses = () => (props.class ?? "fixed w-screen h-screen top-0 left-0"); + + const clickOutsideFn = (ev: MouseEvent) => { + const target = ev.target as HTMLElement; + if (target.closest(".modal") === null) { + props.onClose(); + } + }; + + onMount(() => { + setTimeout(() => { + // For some reason this event is fired immediately after the component is mounted, + // so we delay the event installation to the next tick. + window.addEventListener("click", clickOutsideFn); + }, 0); + }); + + onCleanup(() => { + window.removeEventListener("click", clickOutsideFn); + }); + + return ( +
+ {props.children} +
+ ); +} diff --git a/frontend/src/components/NavRail.tsx b/frontend/src/components/NavRail.tsx index b23220f..76cda3b 100644 --- a/frontend/src/components/NavRail.tsx +++ b/frontend/src/components/NavRail.tsx @@ -1,19 +1,25 @@ import { HomeIcon } from "../icons/HomeIcon"; -import type {JSX} from "solid-js"; +import {createSignal, Show, type JSX, For} from "solid-js"; import { DocxIcon } from "../icons/DocxIcon"; import { ScanIcon } from "../icons/ScanIcon"; import { KeyIcon } from "../icons/KeyIcon"; import { PaletteIcon } from "../icons/PaletteIcon"; import { A } from "@solidjs/router"; +import { Dialog } from "./Dialog"; +import { Portal } from "solid-js/web"; +import { applyColors } from "../colorManager"; export function NavRail() { return ( -
- } /> - } /> - } /> - } /> - } /> +
+
+ } /> + } /> + } /> + } /> + +
+
); } @@ -43,3 +49,94 @@ function NavRailButton(props: { return anchorEl; } + +function ColorSelector() { + const [showSelector, setShowSelector] = createSignal(false); + const colors: Array<{name: string, color: string}> = [ + { + name: "Verde", + color: "green", + }, + { + name: "Azul", + color: "blue", + }, + { + name: "Amarillo", + color: "yellow", + }, + { + name: "Rosado", + color: "pink", + }, + { + name: "Naranja", + color: "orange", + }, + { + name: "Rojo", + color: "red", + }, + ]; + + const showColorSelector = () => { + setShowSelector(true); + }; + + return ( + <> + + + + setShowSelector(false)} + > +
+ + {({name, color}) => } + +
+
+
+
+ + ); +} + +function ColorButton(props: {name: string, color: string}) { + const select = () => { + applyColors(props.color); + }; + + return ( + + ); +} diff --git a/frontend/src/index.css b/frontend/src/index.css index 3d99ddd..3ac7b8f 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,46 +1,20 @@ :root { - --c-primary: #b6c4ff; - --c-on-primary: #00287d; - --c-primary-container: #003baf; - --c-on-primary-container: #dce1ff; --c-error: #ffb4ab; --c-on-error: #690005; --c-error-container: #93000a; --c-on-error-container: #ffdad6; - --c-background: #1b1b1f; - --c-on-background: #e4e1e6; - --c-surface: #1b1b1f; - --c-on-surface: #e4e1e6; - --c-outline: #8f909a; + --c-outline-50: rgba(143, 144, 154, 0.5); - --c-surface-variant: #45464f; - --c-on-surface-variant: #c6c6d0; - - --c-success: #78da9f; - --c-on-success: #00391f; } @media (prefers-color-scheme: light) { :root { - --c-primary: #2a55cb; - --c-on-primary: #ffffff; - --c-primary-container: #dce1ff; - --c-on-primary-container: #00164f; --c-error: #ba1a1a; --c-on-error: #ffffff; --c-error-container: #ffdad6; --c-on-error-container: #410002; - --c-background: #fefbff; - --c-on-background: #1b1b1f; - --c-surface: #fefbff; - --c-on-surface: #1b1b1f; - --c-outline: #767680; - --c-outline-50: rgba(118, 118, 128, 0.5); - --c-surface-variant: #e2e1ec; - --c-on-surface-variant: #45464f; - --c-success: #006d40; - --c-on-success: #ffffff; + --c-outline-50: rgba(118, 118, 128, 0.5); } } diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 01a235b..fdd1252 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -2,8 +2,10 @@ import { render } from "solid-js/web"; import { Router } from "@solidjs/router"; +import "./colors.css"; import "./index.css"; import App from "./App"; +import "./colorManager"; const root = document.getElementById("root");