[FE] Add UI colors
This commit is contained in:
parent
9768daed44
commit
73205c5622
@ -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>
|
||||
);
|
||||
}
|
||||
|
58
frontend/src/colorManager.ts
Normal file
58
frontend/src/colorManager.ts
Normal 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
196
frontend/src/colors.css
Normal 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;
|
||||
}
|
||||
}
|
31
frontend/src/components/Dialog.tsx
Normal file
31
frontend/src/components/Dialog.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user