From f30bec6f06314f74e64da36cb6d1df5bafa2666a Mon Sep 17 00:00:00 2001 From: PepperLola Date: Tue, 22 Aug 2023 11:59:44 -0700 Subject: [PATCH] added toast colors and util file --- react/src/App.tsx | 1 + react/src/ThemeContext.tsx | 16 ++++- react/src/ToastContext.tsx | 3 + react/src/components/Slider.tsx | 2 +- react/src/components/Toast.tsx | 7 ++- react/src/main.tsx | 3 + .../theme-editor/ThemeEditorModal.tsx | 24 ++++--- react/src/util/CEFAPI.ts | 11 ++++ react/tailwind.config.js | 63 +++++++++++-------- 9 files changed, 83 insertions(+), 47 deletions(-) create mode 100644 react/src/util/CEFAPI.ts diff --git a/react/src/App.tsx b/react/src/App.tsx index 6157f21d62..65ad917467 100644 --- a/react/src/App.tsx +++ b/react/src/App.tsx @@ -46,6 +46,7 @@ import ScoringZonesPanel from "./panels/configuring/scoring/ScoringZonesPanel" import ZoneConfigPanel from "./panels/configuring/scoring/ZoneConfigPanel" import ScoreboardPanel from "./panels/information/ScoreboardPanel" import DriverStationPanel from "./panels/simulation/DriverStationPanel" +import Toast from "./components/Toast" const initialModals = [ , diff --git a/react/src/ThemeContext.tsx b/react/src/ThemeContext.tsx index e9a5313338..f2e997c627 100644 --- a/react/src/ThemeContext.tsx +++ b/react/src/ThemeContext.tsx @@ -28,13 +28,23 @@ export type ColorName = | "AcceptCancelButtonText" | "MatchRedAlliance" | "MatchBlueAlliance" + | "ToastInfo" + | "ToastWarning" + | "ToastError" -const colorNameToProp = (colorName: ColorName) => { +export const colorNameToTailwind = (colorName: ColorName) => { + return "bg" + + colorName + .replace(/([A-Z]+)/g, "-$1") + .replace(/(?<=[A-Z])([A-Z])(?![A-Z]|$)/g, "-$1") + .toLowerCase() +} +export const colorNameToProp = (colorName: ColorName) => { return ( "-" + colorName .replace(/([A-Z]+)/g, "-$1") - .replace(/(?<=[A-Z])([A-Z])(?![A-Z])/g, "-$1") + .replace(/(?<=[A-Z])([A-Z])(?![A-Z]|$)/g, "-$1") .toLowerCase() ) } @@ -113,7 +123,7 @@ export const ThemeProvider: React.FC = ({ const propName = colorNameToProp(n as ColorName) root.style.setProperty( propName, - `rgba(${c.r}, ${c.g}, ${c.b}, ${c.a}` + `rgba(${c.r}, ${c.g}, ${c.b}, ${c.a})` ) }) } diff --git a/react/src/ToastContext.tsx b/react/src/ToastContext.tsx index b8ca6f8039..38411dff63 100644 --- a/react/src/ToastContext.tsx +++ b/react/src/ToastContext.tsx @@ -71,6 +71,9 @@ export const ToastContainer: React.FC = () => { return (
+ + + {toasts.length > 0 && toasts.map(t => ( diff --git a/react/src/components/Slider.tsx b/react/src/components/Slider.tsx index b03087d485..c207fb623c 100644 --- a/react/src/components/Slider.tsx +++ b/react/src/components/Slider.tsx @@ -64,7 +64,7 @@ const Slider: React.FC = ({ else percent += step - diff } const v = percent * (max - min) + min - onChange(v) + if (onChange) onChange(v) setValue(v) } } diff --git a/react/src/components/Toast.tsx b/react/src/components/Toast.tsx index 1cff5a8f43..71308ed561 100644 --- a/react/src/components/Toast.tsx +++ b/react/src/components/Toast.tsx @@ -9,6 +9,7 @@ const TOAST_TIMEOUT: number = 5_000 const Toast: React.FC = ({ id, type, title, description }) => { const { removeToast } = useToastContext() + useEffect(() => { const timer = setTimeout(() => { removeToast(id) @@ -30,7 +31,7 @@ const Toast: React.FC = ({ id, type, title, description }) => { className="h-full w-full text-main-text" /> ) - className = "bg-purple-700" + className = "bg-toast-info" break case "warning": icon = ( @@ -39,7 +40,7 @@ const Toast: React.FC = ({ id, type, title, description }) => { className="h-full w-full text-main-text" /> ) - className = "bg-yellow-500" + className = "bg-toast-warning" break case "error": icon = ( @@ -48,7 +49,7 @@ const Toast: React.FC = ({ id, type, title, description }) => { className="h-full w-full text-main-text" /> ) - className = "bg-red-500" + className = "bg-toast-error" break } diff --git a/react/src/main.tsx b/react/src/main.tsx index d2c2bd93db..1bbcb3b6ce 100644 --- a/react/src/main.tsx +++ b/react/src/main.tsx @@ -31,6 +31,9 @@ const defaultColors: Theme = { FloorGrid: { r: 93, g: 93, b: 93, a: 255 }, MatchRedAlliance: { r: 255, g: 0, b: 0, a: 255 }, MatchBlueAlliance: { r: 0, g: 0, b: 255, a: 255 }, + ToastInfo: { r: 126, g: 34, b: 206, a: 255 }, + ToastWarning: { r: 234, g: 179, b: 8, a: 255 }, + ToastError: { r: 239, g: 68, b: 68, a: 255 }, } const themes = { Default: defaultColors, diff --git a/react/src/modals/configuring/theme-editor/ThemeEditorModal.tsx b/react/src/modals/configuring/theme-editor/ThemeEditorModal.tsx index 57c2e261c9..65dcf53c29 100644 --- a/react/src/modals/configuring/theme-editor/ThemeEditorModal.tsx +++ b/react/src/modals/configuring/theme-editor/ThemeEditorModal.tsx @@ -1,17 +1,19 @@ import React, { useState } from "react" import { FaChessBoard } from "react-icons/fa6" -import Modal, { ModalPropsImpl } from "../../../components/Modal" +import Modal, { ModalPropsImpl } from "@/components/Modal" import { RgbaColor, RgbaColorPicker } from "react-colorful" -import Stack, { StackDirection } from "../../../components/Stack" -import Dropdown from "../../../components/Dropdown" -import Button from "../../../components/Button" +import Stack, { StackDirection } from "@/components/Stack" +import Dropdown from "@/components/Dropdown" +import Button from "@/components/Button" import { ColorName, Theme, + colorNameToProp, + colorNameToTailwind, defaultThemeName, useTheme, -} from "../../../ThemeContext" -import { useModalControlContext } from "../../../ModalContext" +} from "@/ThemeContext" +import { useModalControlContext } from "@/ModalContext" const ThemeEditorModal: React.FC = ({ modalId }) => { const { themes, currentTheme, setTheme, updateColor, applyTheme } = @@ -97,18 +99,14 @@ const ThemeEditorModal: React.FC = ({ modalId }) => { {Object.entries(themes[selectedTheme]).map(([n, c]) => (
{ setSelectedColor(n as ColorName) }} >
{n}
diff --git a/react/src/util/CEFAPI.ts b/react/src/util/CEFAPI.ts new file mode 100644 index 0000000000..d53409861e --- /dev/null +++ b/react/src/util/CEFAPI.ts @@ -0,0 +1,11 @@ +export const click = (btn: number, x: number, y: number) => { + const el = document.elementFromPoint(x, y); + + const event = new MouseEvent("click", { + clientX: x, + clientY: y, + bubbles: true, + button: btn + }) + el?.dispatchEvent(event) +} diff --git a/react/tailwind.config.js b/react/tailwind.config.js index 014753baea..eec892cedc 100644 --- a/react/tailwind.config.js +++ b/react/tailwind.config.js @@ -1,4 +1,38 @@ /** @type {import('tailwindcss').Config} */ + +let colors = { + 'interactive-element-solid': 'var(--interactive-element-solid)', + 'interactive-element-left': 'var(--interactive-element-left)', + 'interactive-element-right': 'var(--interactive-element-right)', + 'background': 'var(--background)', + 'background-secondary': 'var(--background-secondary)', + 'interactive-background': 'var(--interactive-background)', + 'background-hud': 'var(--background-hud)', + 'interactive-hover': 'var(--interactive-hover)', + 'interactive-select': 'var(--interactive-select)', + 'main-text': 'var(--main-text)', + 'scrollbar': 'var(--scrollbar)', + 'accept-button': 'var(--accept-button)', + 'cancel-button': 'var(--cancel-button)', + 'interactive-element-text': 'var(--interactive-element-text)', + 'icon': 'var(--icon)', + 'main-hud-icon': 'var(--main-hud-icon)', + 'main-hud-close-icon': 'var(--main-hud-close-icon)', + 'highlight-hover': 'var(--highlight-hover)', + 'highlight-select': 'var(--highlight-select)', + 'skybox-top': 'var(--skybox-top)', + 'skybox-bottom': 'var(--skybox-bottom)', + 'floor-grid': 'var(--floor-grid)', + 'accept-cancel-button-text': 'var(--accept-cancel-button-text)', + 'match-red-alliance': 'var(--match-red-alliance)', + 'match-blue-alliance': 'var(--match-blue-alliance)', + 'toast-info': 'var(--toast-info)', + 'toast-warning': 'var(--toast-warning)', + 'toast-error': 'var(--toast-error)', +} + +let safelist = Object.keys(colors).map(c => "bg-" + c); + export default { content: [ "./index.html", @@ -6,35 +40,10 @@ export default { ], theme: { extend: { - colors: { - 'interactive-element-solid': 'var(--interactive-element-solid)', - 'interactive-element-left': 'var(--interactive-element-left)', - 'interactive-element-right': 'var(--interactive-element-right)', - 'background': 'var(--background)', - 'background-secondary': 'var(--background-secondary)', - 'interactive-background': 'var(--interactive-background)', - 'background-hud': 'var(--background-hud)', - 'interactive-hover': 'var(--interactive-hover)', - 'interactive-select': 'var(--interactive-select)', - 'main-text': 'var(--main-text)', - 'scrollbar': 'var(--scrollbar)', - 'accept-button': 'var(--accept-button)', - 'cancel-button': 'var(--cancel-button)', - 'interactive-element-text': 'var(--interactive-element-text)', - 'icon': 'var(--icon)', - 'main-hud-icon': 'var(--main-hud-icon)', - 'main-hud-close-icon': 'var(--main-hud-close-icon)', - 'highlight-hover': 'var(--highlight-hover)', - 'highlight-select': 'var(--highlight-select)', - 'skybox-top': 'var(--skybox-top)', - 'skybox-bottom': 'var(--skybox-bottom)', - 'floor-grid': 'var(--floor-grid)', - 'accept-cancel-button-text': 'var(--accept-cancel-button-text)', - 'match-red-alliance': 'var(--match-red-alliance)', - 'match-blue-alliance': 'var(--match-blue-alliance)', - } + colors: colors, }, }, + safelist: safelist, plugins: [], }