[FE] Add UI colors

master
Araozu 2023-09-21 17:07:18 -05:00
parent 9768daed44
commit 73205c5622
7 changed files with 407 additions and 38 deletions

View File

@ -8,9 +8,20 @@ export function OnlineClassroom() {
return (
<div class="grid grid-cols-[16rem_25rem_1fr]">
<Search setPerson={setPerson} />
<Show when={person()}>
<ClassroomUsers person={person()!} />
</Show>
<div>
<ClassroomConection />
<Show when={person()}>
<ClassroomUsers person={person()!} />
</Show>
</div>
</div>
);
}
function ClassroomConection() {
return (
<div>
Connection status
</div>
);
}

View File

@ -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);
})();

196
frontend/src/colors.css Normal file
View File

@ -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;
}
}

View File

@ -0,0 +1,31 @@
import { JSX, onCleanup, onMount} from "solid-js";
type Children = Array<JSX.Element> | 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 (
<div class={`modal transition-colors ${positionClasses()}`}>
{props.children}
</div>
);
}

View File

@ -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 (
<div class="flex flex-col justify-center items-center h-screen overflow-x-hidden">
<NavRailButton path="/" name="Inicio" icon={<HomeIcon />} />
<NavRailButton path="/certs" name="Certs" icon={<DocxIcon />} />
<NavRailButton path="/accesos" name="Accesos" icon={<KeyIcon />} />
<NavRailButton path="/escaneo" name="Escaneo" icon={<ScanIcon />} />
<NavRailButton path="/colores" name="Colores" icon={<PaletteIcon />} />
<div>
<div class="flex flex-col justify-center items-center h-screen overflow-x-hidden">
<NavRailButton path="/" name="Inicio" icon={<HomeIcon />} />
<NavRailButton path="/certs" name="Certs" icon={<DocxIcon />} />
<NavRailButton path="/accesos" name="Accesos" icon={<KeyIcon />} />
<NavRailButton path="/escaneo" name="Escaneo" icon={<ScanIcon />} />
<ColorSelector />
</div>
<div id="color-selector" />
</div>
);
}
@ -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 (
<>
<button
class="relative my-3 text-center group hover:bg-c-surface-variant rounded-xl transition-colors
max-w-[4rem] inline-block select-none"
onclick={showColorSelector}
>
<div class={"p-1 inline-block group-[.active]:bg-c-surface-variant min-w-[4rem] rounded-full transition-colors"}>
<PaletteIcon />
</div>
<span class="text-sm">
Colores
</span>
</button>
<Portal mount={document.getElementById("color-selector")!}>
<Show when={showSelector()}>
<Dialog
class="absolute left-[5rem] w-[15rem] top-[60%] z-10
border border-c-outline p-2
shadow-md rounded-md"
onClose={() => setShowSelector(false)}
>
<div class="w-full grid grid-cols-3 gap-2">
<For
each={colors}
>
{({name, color}) => <ColorButton name={name} color={color} />}
</For>
</div>
</Dialog>
</Show>
</Portal>
</>
);
}
function ColorButton(props: {name: string, color: string}) {
const select = () => {
applyColors(props.color);
};
return (
<button
class="text-center bg-c-outline rounded pt-2
border border-c-transparent hover:border-c-outline transition-colors"
style={{"background-color": `var(--c-${props.color}-surface-variant)`}}
onclick={select}
>
<span
class="inline-block w-8 h-8 rounded-full"
style={{"background-color": `var(--c-${props.color}-primary)`}}
/>
<br />
{props.name}
</button>
);
}

View File

@ -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;
--c-outline-50: rgba(143, 144, 154, 0.5);
}
@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);
}
}

View File

@ -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");