new featuregit status dark mode

This commit is contained in:
Joeri Exelmans 2025-11-13 19:25:43 +01:00
parent 9646d716c6
commit 6efc27453e
14 changed files with 189 additions and 149 deletions

View file

@ -1,61 +1,44 @@
/* details {
padding-left: 20;
}
summary {
margin-left: -20;
} */
details:has(+ details) { details:has(+ details) {
border-bottom: 1px lightgrey solid; border-bottom: 1px var(--separator-color) solid;
} }
.runtimeState { .runtimeState {
padding: 4px; padding: 4px;
/* padding-left: 4px;
padding-right: 4px;
padding-top: 2px;
padding-bottom: 2px; */
} }
.runtimeState:has(+.runtimeState) { .runtimeState:has(+.runtimeState) {
border-bottom: 1px lightgrey solid; border-bottom: 1px var(--separator-color) solid;
} }
.runtimeState:has(+.runtimeState.active) { .runtimeState:has(+.runtimeState.active) {
border-bottom: 0; border-bottom: 0;
} }
.runtimeState:hover { .runtimeState:hover {
/* background-color: rgba(255, 140, 0, 0.2); */ background-color: var(--light-accent-color);
background-color: rgba(0,0,255,0.2);
cursor: pointer; cursor: pointer;
} }
.runtimeState.active { .runtimeState.active {
background-color: rgba(0,0,255,0.2); background-color: var(--light-accent-color);
border: solid blue 1px; border: solid var(--accent-border-color) 1px;
} }
.runtimeState.plantStep:not(.active) { .runtimeState.plantStep:not(.active) {
background-color: #f7f7f7; background-color: var(--inactive-bg-color);
} }
.runtimeState.plantStep * { .runtimeState.plantStep * {
color: grey; color: var(--inactive-fg-color);
} }
.runtimeState.runtimeError { .runtimeState.runtimeError {
background-color: lightpink; background-color: var(--error-bg-color);
color: darkred; color: var(--error-color); /* used to be darkred, but this one's a bit lighter */
} }
.runtimeState.runtimeError.active { .runtimeState.runtimeError.active {
border-color: darkred; border-color: var(--error-color);/* used to be darkred, but this one's a bit lighter */
} }
/* details:not(:has(details)) > summary::marker {
color: white;
} */
.readonlyTextBox { .readonlyTextBox {
width: 56; width: 56;
background-color:"#eee";
text-align: "right"; text-align: "right";
} }
@ -78,20 +61,23 @@ details:has(+ details) {
} }
button { button {
background-color: #fcfcfc; background-color: var(--button-bg-color);
border: 1px lightgrey solid; border: 1px var(--separator-color) solid;
} }
button:not(:disabled):hover { button:not(:disabled):hover {
background-color: rgba(0, 0, 255, 0.2); background-color: var(--light-accent-color);
}
button:disabled {
background-color: var(--inactive-bg-color);
color: var(--inactive-fg-color);
} }
button.active { button.active {
border: solid blue 1px; border: solid var(--accent-border-color) 1px;
background-color: rgba(0,0,255,0.2); background-color: var(--light-accent-color);
/* margin-right: 1px; */ color: var(--text-color);
/* margin-left: 0; */
color: black;
} }
.modalOuter { .modalOuter {
@ -102,7 +88,7 @@ button.active {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
text-align: center; text-align: center;
background-color: rgba(200,200,200,0.7); background-color: var(--modal-backdrop-color);
z-index: 1000; z-index: 1000;
} }
@ -110,7 +96,7 @@ button.active {
position: relative; position: relative;
text-align: center; text-align: center;
display: inline-block; display: inline-block;
background-color: white; background-color: var(--background-color);
max-height: 100vh; max-height: 100vh;
overflow: auto; overflow: auto;
} }
@ -128,7 +114,7 @@ div.stackHorizontal {
div.status { div.status {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
background-color: grey; background-color: var(--status-inactive-color);
border-radius: 50%; border-radius: 50%;
height: 12px; height: 12px;
width: 12px; width: 12px;
@ -141,6 +127,6 @@ div.status.violated {
} }
div.status.satisfied { div.status.satisfied {
background-color: forestgreen; background-color: var(--status-ok-color);
} }

View file

@ -17,6 +17,7 @@ import { useUrlHashState } from "../hooks/useUrlHashState";
import { plants } from "./plants"; import { plants } from "./plants";
import { emptyState } from "@/statecharts/concrete_syntax"; import { emptyState } from "@/statecharts/concrete_syntax";
import { ModalOverlay } from "./Modals/ModalOverlay"; import { ModalOverlay } from "./Modals/ModalOverlay";
import { usePersistentState } from "@/hooks/usePersistentState";
export type EditHistory = { export type EditHistory = {
current: VisualEditorState, current: VisualEditorState,
@ -38,10 +39,14 @@ const defaultAppState: AppState = {
...defaultSideBarState, ...defaultSideBarState,
} }
export type LightMode = "light" | "auto" | "dark";
export function App() { export function App() {
const [editHistory, setEditHistory] = useState<EditHistory|null>(null); const [editHistory, setEditHistory] = useState<EditHistory|null>(null);
const [modal, setModal] = useState<ReactElement|null>(null); const [modal, setModal] = useState<ReactElement|null>(null);
const [lightMode, setLightMode] = usePersistentState<LightMode>("lightMode", "auto");
const {makeCheckPoint, onRedo, onUndo, onRotate} = useEditor(setEditHistory); const {makeCheckPoint, onRedo, onUndo, onRotate} = useEditor(setEditHistory);
const editorState = editHistory && editHistory.current; const editorState = editHistory && editHistory.current;
@ -135,7 +140,8 @@ export function App() {
const plantState = currentBigStep && currentBigStep.state.plant || plant.execution.initial()[1]; const plantState = currentBigStep && currentBigStep.state.plant || plant.execution.initial()[1];
return <ModalOverlay modal={modal} setModal={setModal}> return <div style={{height:'100%', colorScheme: lightMode!=="auto"?lightMode:undefined}}>
<ModalOverlay modal={modal} setModal={setModal}>
{/* top-to-bottom: everything -> bottom panel */} {/* top-to-bottom: everything -> bottom panel */}
<div className="stackVertical" style={{height:'100%'}}> <div className="stackVertical" style={{height:'100%'}}>
@ -150,7 +156,7 @@ export function App() {
style={{flex: '0 0 content'}} style={{flex: '0 0 content'}}
> >
{editHistory && <TopPanel {editHistory && <TopPanel
{...{onUndo, onRedo, onRotate, setModal, editHistory, ...simulator, ...setters, ...appState}} {...{onUndo, onRedo, onRotate, lightMode, setLightMode, setModal, editHistory, ...simulator, ...setters, ...appState}}
/>} />}
</div> </div>
{/* Editor */} {/* Editor */}
@ -179,7 +185,8 @@ export function App() {
{syntaxErrors && <BottomPanel {...{errors: syntaxErrors}}/>} {syntaxErrors && <BottomPanel {...{errors: syntaxErrors}}/>}
</div> </div>
</div> </div>
</ModalOverlay>; </ModalOverlay>
</div>;
} }
export default App; export default App;

View file

@ -5,6 +5,6 @@
} }
.bottom { .bottom {
border-top: 1px lightgrey solid; border-top: 1px var(--separator-color) solid;
background-color: rgb(255, 249, 235); background-color: var(--bottom-panel-bg-color);
} }

View file

@ -3,14 +3,14 @@ import { TraceableError } from "../../statecharts/parser";
import "./BottomPanel.css"; import "./BottomPanel.css";
import logo from "../../../artwork/logo-playful.svg";
import { PersistentDetailsLocalStorage } from "../PersistentDetails"; import { PersistentDetailsLocalStorage } from "../PersistentDetails";
import { Logo } from "@/Logo/Logo";
export function BottomPanel(props: {errors: TraceableError[]}) { export function BottomPanel(props: {errors: TraceableError[]}) {
const [greeting, setGreeting] = useState( const [greeting, setGreeting] = useState(
<div style={{textAlign:'center'}}> <div style={{textAlign:'center'}}>
<span style={{fontSize: 18, fontStyle: 'italic'}}> <span style={{fontSize: 18, fontStyle: 'italic'}}>
Welcome to <img src={logo} style={{maxWidth:'100%'}}/> Welcome to <Logo/>
</span> </span>
</div>); </div>);

View file

@ -1,9 +1,9 @@
import { Logo } from "@/Logo/Logo";
import { Dispatch, ReactElement, SetStateAction } from "react"; import { Dispatch, ReactElement, SetStateAction } from "react";
import logo from "../../../artwork/logo-playful.svg";
export function About(props: {setModal: Dispatch<SetStateAction<ReactElement|null>>}) { export function About(props: {setModal: Dispatch<SetStateAction<ReactElement|null>>}) {
return <div style={{maxWidth: '500px', padding: 4}}> return <div style={{maxWidth: '500px', padding: 4}}>
<p><img src={logo} style={{maxWidth:'100%'}}/></p> <p><Logo/></p>
<p>StateBuddy is an <a target="_blank" href="https://deemz.org/git/research/statebuddy">open source</a> tool for <a target="_blank" href="https://dl.acm.org/doi/10.1016/0167-6423(87)90035-9">Statechart</a> editing, simulation, (omniscient) debugging and testing.</p> <p>StateBuddy is an <a target="_blank" href="https://deemz.org/git/research/statebuddy">open source</a> tool for <a target="_blank" href="https://dl.acm.org/doi/10.1016/0167-6423(87)90035-9">Statechart</a> editing, simulation, (omniscient) debugging and testing.</p>

View file

@ -1,78 +1,51 @@
details.active {
border: rgb(192, 125, 0);
background-color:rgb(255, 251, 244);
filter: drop-shadow( 0px 0px 3px rgba(192, 125, 0, 0.856));
}
details > summary { details > summary {
padding: 2px; padding: 2px;
} }
/* these two rules add a bit of padding to an opened <details> node */
/* details:open > summary:has(+ *) {
margin-bottom: 4px;
}
details:open:has(>summary:has(+ *)) {
padding-bottom: 8px;
} */
details > summary:hover { details > summary:hover {
background-color: #eee; background-color: var(--summary-hover-bg-color);
cursor: default; cursor: default;
} }
.errorStatus details > summary:hover { .errorStatus details > summary:hover {
background-color: rgb(102, 0, 0); background-color: var(--error-hover-bg-color);
} }
.stateTree > * { .stateTree > * {
padding-left: 10px; padding-left: 10px;
/* border: 1px black solid; */
background-color: white; background-color: white;
/* margin-bottom: 4px; */
/* padding-right: 2px; */
/* padding-top: 2px; */
/* padding-bottom: 2px; */
/* color: black; */
/* width: fit-content; */
/* border-radius: 10px; */
} }
/* if <details> has no children (besides the obvious <summary> child), then hide the marker */
/* details:not(:has(:not(summary))) > summary::marker {
content: " ";
} */
.outputEvent { .outputEvent {
border: 1px black solid; cursor: default;
border: 1px var(--separator-color) solid;
border-radius: 6px; border-radius: 6px;
/* margin-left: 4px; */
padding-left: 2px; padding-left: 2px;
padding-right: 2px; padding-right: 2px;
background-color: rgb(230, 249, 255); background-color: var(--output-event-bg-color);
color: black; color: var(--text-color);
display: inline-block; display: inline-block;
} }
.internalEvent { .internalEvent {
border: 1px black solid; cursor: default;
border: 1px var(--separator-color) solid;
border-radius: 6px; border-radius: 6px;
/* margin-left: 4px; */
padding-left: 2px; padding-left: 2px;
padding-right: 2px; padding-right: 2px;
background-color: rgb(255, 218, 252); background-color: var(--internal-event-bg-color);
color: black; color: var(--text-color);
display: inline-block; display: inline-block;
} }
.inputEvent { .inputEvent {
border: 1px black solid; border: 1px var(--separator-color) solid;
border-radius: 6px; border-radius: 6px;
/* margin-left: 4px; */
padding-left: 2px; padding-left: 2px;
padding-right: 2px; padding-right: 2px;
background-color: rgb(224, 247, 209); background-color: var(--input-event-bg-color);
color: black; color: var(--text-color);
display: inline-block; display: inline-block;
} }
.inputEvent:disabled { .inputEvent:disabled {
@ -82,21 +55,24 @@ details > summary:hover {
vertical-align: middle; vertical-align: middle;
} }
button.inputEvent:hover:not(:disabled) { button.inputEvent:hover:not(:disabled) {
background-color: rgb(195, 224, 176); background-color: var(--input-event-hover-bg-color);
} }
button.inputEvent:active:not(:disabled) { button.inputEvent:active:not(:disabled) {
background-color: rgb(176, 204, 158); background-color: var(--input-event-active-bg-color);
} }
.activeState { .activeState {
border: rgb(192, 125, 0); /* border: rgb(192, 125, 0); */
background-color:rgb(255, 251, 244); /* background-color:rgb(255, 251, 244); */
filter: drop-shadow( 0px 0px 3px rgba(192, 125, 0, 0.856)); border: var(--active-state-border-color) 1px solid;
background-color: var(--active-state-bg-color);
/* filter: drop-shadow( 0px 0px 3px rgba(192, 125, 0, 0.856)); */
border-radius: 6px; border-radius: 6px;
margin-left: 4px; margin-left: 4px;
padding-left: 2px; padding-left: 2px;
padding-right: 2px; padding-right: 2px;
display: inline-block; display: inline-block;
color: var(--text-color);
} }
/* hr { /* hr {

View file

@ -2,8 +2,8 @@ import { RT_Statechart } from "@/statecharts/runtime_types";
import { Plant } from "../Plant/Plant"; import { Plant } from "../Plant/Plant";
import { TraceItem } from "../hooks/useSimulator"; import { TraceItem } from "../hooks/useSimulator";
// const endpoint = "http://localhost:15478/check_property"; const endpoint = "http://localhost:15478/check_property";
const endpoint = "https://deemz.org/apis/mtl-aas/check_property"; // const endpoint = "https://deemz.org/apis/mtl-aas/check_property";
export type PropertyTrace = { export type PropertyTrace = {
timestamp: number, timestamp: number,

View file

@ -18,12 +18,19 @@ export function PseudoStateIcon(props: {}) {
${w - 1} ${h / 2}, ${w - 1} ${h / 2},
${w / 2} ${h - 1}, ${w / 2} ${h - 1},
${1} ${h / 2}, ${1} ${h / 2},
`} fill="white" stroke="black" strokeWidth={1.2} /> `}
style={{
fill: 'var(--and-state-bg-color',
stroke: 'var(--rountangle-stroke-color',
}} strokeWidth={1.2} />
</svg>; </svg>;
} }
export function HistoryIcon(props: { kind: "shallow" | "deep"; }) { export function HistoryIcon(props: { kind: "shallow" | "deep"; }) {
const w = 20, h = 20; const w = 20, h = 20;
const text = props.kind === "shallow" ? "H" : "H*"; const text = props.kind === "shallow" ? "H" : "H*";
return <svg width={w} height={h}><circle cx={w / 2} cy={h / 2} r={Math.min(w, h) / 2 - 1} fill="white" stroke="black" /><text x={w / 2} y={h / 2 + 4} textAnchor="middle" fontSize={11} fontWeight={400}>{text}</text></svg>; return <svg width={w} height={h}><circle cx={w / 2} cy={h / 2} r={Math.min(w, h) / 2 - 1} style={{
fill: 'var(--and-state-bg-color',
stroke: 'var(--rountangle-stroke-color',
}}/><text x={w / 2} y={h / 2 + 4} style={{fill: 'var(--rountangle-stroke-color'}} textAnchor="middle" fontSize={11} fontWeight={400}>{text}</text></svg>;
} }

View file

@ -3,12 +3,16 @@ import { TimerElapseEvent, Timers } from "../../statecharts/runtime_types";
import { getSimTime, setPaused, setRealtime, TimeMode } from "../../statecharts/time"; import { getSimTime, setPaused, setRealtime, TimeMode } from "../../statecharts/time";
import { InsertMode } from "./InsertModes"; import { InsertMode } from "./InsertModes";
import { About } from "../Modals/About"; import { About } from "../Modals/About";
import { EditHistory } from "../App"; import { EditHistory, LightMode } from "../App";
import { KeyInfoHidden, KeyInfoVisible } from "./KeyInfo"; import { KeyInfoHidden, KeyInfoVisible } from "./KeyInfo";
import { UndoRedoButtons } from "./UndoRedoButtons"; import { UndoRedoButtons } from "./UndoRedoButtons";
import { ZoomButtons } from "./ZoomButtons"; import { ZoomButtons } from "./ZoomButtons";
import { formatTime } from "../../util/util"; import { formatTime } from "../../util/util";
import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode';
import BrightnessAutoIcon from '@mui/icons-material/BrightnessAuto';
import AccessAlarmIcon from '@mui/icons-material/AccessAlarm'; import AccessAlarmIcon from '@mui/icons-material/AccessAlarm';
import CachedIcon from '@mui/icons-material/Cached'; import CachedIcon from '@mui/icons-material/Cached';
import InfoOutlineIcon from '@mui/icons-material/InfoOutline'; import InfoOutlineIcon from '@mui/icons-material/InfoOutline';
@ -33,6 +37,8 @@ export type TopPanelProps = {
onInit: () => void, onInit: () => void,
onClear: () => void, onClear: () => void,
onBack: () => void, onBack: () => void,
lightMode: LightMode,
setLightMode: Dispatch<SetStateAction<LightMode>>,
insertMode: InsertMode, insertMode: InsertMode,
setInsertMode: Dispatch<SetStateAction<InsertMode>>, setInsertMode: Dispatch<SetStateAction<InsertMode>>,
setModal: Dispatch<SetStateAction<ReactElement|null>>, setModal: Dispatch<SetStateAction<ReactElement|null>>,
@ -45,7 +51,7 @@ export type TopPanelProps = {
const ShortCutShowKeys = <kbd>~</kbd>; const ShortCutShowKeys = <kbd>~</kbd>;
export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, onRedo, onRotate, onInit, onClear, onBack, insertMode, setInsertMode, setModal, zoom, setZoom, showKeys, setShowKeys, editHistory}: TopPanelProps) { export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, onRedo, onRotate, onInit, onClear, onBack, lightMode, setLightMode, insertMode, setInsertMode, setModal, zoom, setZoom, showKeys, setShowKeys, editHistory}: TopPanelProps) {
const [displayTime, setDisplayTime] = useState("0.000"); const [displayTime, setDisplayTime] = useState("0.000");
const [timescale, setTimescale] = usePersistentState("timescale", 1); const [timescale, setTimescale] = usePersistentState("timescale", 1);
@ -146,6 +152,20 @@ export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, on
}, [config, time, onInit, onChangePaused, setShowKeys, onSkip, onBack, onClear]); }, [config, time, onInit, onChangePaused, setShowKeys, onSkip, onBack, onClear]);
return <div className="toolbar"> return <div className="toolbar">
{/* light / dark mode */}
<div className="toolbarGroup">
<button title="force light mode" className={lightMode==="light"?"active":""} onClick={() => setLightMode("light")}>
<LightModeIcon fontSize="small"/>
</button>
<button title="auto light / dark mode (follows system theme)" className={lightMode==="auto"?"active":""} onClick={() => setLightMode("auto")}>
<BrightnessAutoIcon fontSize="small"/>
</button>
<button title="force dark mode" className={lightMode==="dark"?"active":""} onClick={() => setLightMode("dark")}>
<DarkModeIcon fontSize="small"/>
</button>
&emsp;
</div>
{/* shortcuts / about */} {/* shortcuts / about */}
<div className="toolbarGroup"> <div className="toolbarGroup">
<KeyInfo keyInfo={ShortCutShowKeys}> <KeyInfo keyInfo={ShortCutShowKeys}>

View file

@ -14,7 +14,8 @@ export const DiamondShape = memo(function DiamondShape(props: {size: Vec2D, extr
${minSize.x/2} ${minSize.y}, ${minSize.x/2} ${minSize.y},
${0} ${minSize.y/2} ${0} ${minSize.y/2}
`} `}
fill="white" style={{fill: 'var(--and-state-bg-color', stroke: 'var(--rountangle-stroke-color)'}}
// fill="white"
stroke="black" stroke="black"
strokeWidth={2} strokeWidth={2}
{...props.extraAttrs} {...props.extraAttrs}

View file

@ -1,6 +1,6 @@
.svgCanvas { .svgCanvas {
cursor: crosshair; cursor: crosshair;
background-color: #eee; background-color: var(--or-state-bg-color);
} }
.svgCanvas.dragging { .svgCanvas.dragging {
@ -19,16 +19,15 @@
/* rectangle drawn while a selection is being made */ /* rectangle drawn while a selection is being made */
.selecting { .selecting {
fill: blue; fill: var(--light-accent-color);
fill-opacity: 0.2;
stroke-width: 1px; stroke-width: 1px;
stroke:black; stroke: var(--accent-border-color);
stroke-dasharray: 7 6; stroke-dasharray: 7 6;
} }
.rountangle { .rountangle {
fill: white; fill: var(--and-state-bg-color);
stroke: black; stroke: var(--rountangle-stroke-color);
stroke-width: 2px; stroke-width: 2px;
} }
@ -39,9 +38,10 @@
stroke: var(--error-color); stroke: var(--error-color);
} }
.rountangle.active { .rountangle.active {
stroke: rgb(205, 133, 0); stroke: var(--active-state-border-color);
/* stroke: none; */ /* stroke: none; */
fill:rgb(255, 240, 214); /* fill:rgb(255, 240, 214); */
fill: var(--active-state-bg-color);
/* filter: drop-shadow( 2px 2px 2px rgba(124, 37, 10, 0.729)); */ /* filter: drop-shadow( 2px 2px 2px rgba(124, 37, 10, 0.729)); */
} }
@ -54,8 +54,7 @@ line.helper {
stroke-width: 16px; stroke-width: 16px;
} }
line.helper:hover:not(:active) { line.helper:hover:not(:active) {
stroke: blue; stroke: var(--light-accent-color);
stroke-opacity: 0.2;
cursor: grab; cursor: grab;
} }
@ -65,8 +64,7 @@ path.helper {
stroke-width: 16px; stroke-width: 16px;
} }
path.helper:hover:not(:active) { path.helper:hover:not(:active) {
stroke: blue; stroke: var(--light-accent-color);
stroke-opacity: 0.2;
cursor: grab; cursor: grab;
} }
@ -74,23 +72,22 @@ circle.helper {
fill: rgba(0, 0, 0, 0); fill: rgba(0, 0, 0, 0);
} }
circle.helper:hover:not(:active) { circle.helper:hover:not(:active) {
fill: blue; fill: var(--light-accent-color);
fill-opacity: 0.2;
cursor: grab; cursor: grab;
} }
.rountangle.or { .rountangle.or {
stroke-dasharray: 7 6; stroke-dasharray: 7 6;
fill: #eee; fill: var(--or-state-bg-color);
} }
.arrow { .arrow {
fill: none; fill: none;
stroke: black; stroke: var(--rountangle-stroke-color);
stroke-width: 2px; stroke-width: 2px;
} }
.arrow.selected { .arrow.selected {
stroke: blue; stroke: var(--accent-border-color);
stroke-width: 3px; stroke-width: 3px;
} }
@ -110,34 +107,29 @@ circle.helper:hover:not(:active) {
} }
line.selected, circle.selected { line.selected, circle.selected {
fill: rgba(0, 0, 255, 0.2); fill: var(--light-accent-color);
/* stroke-dasharray: 7 6; */ stroke: var(--accent-border-color);
stroke: blue;
stroke-width: 4px; stroke-width: 4px;
} }
.draggableText.selected, .draggableText.selected:hover { .draggableText.selected, .draggableText.selected:hover {
fill: blue; fill: var(--accent-border-color);
font-weight: 600; font-weight: 600;
} }
.draggableText:hover:not(:active) {
/* fill: blue; */
/* cursor: grab; */
}
text.helper { text.helper {
fill: rgba(0,0,0,0); fill: rgba(0,0,0,0);
stroke: rgba(0,0,0,0); stroke: rgba(0,0,0,0);
stroke-width: 6px; stroke-width: 6px;
} }
text.helper:hover { text.helper:hover {
stroke: blue; stroke: var(--light-accent-color);
stroke-opacity: 0.2;
cursor: grab; cursor: grab;
} }
.draggableText, .draggableText.highlight { .draggableText, .draggableText.highlight {
paint-order: stroke; paint-order: stroke;
stroke: white; fill: var(--text-color);
stroke: var(--background-color);
stroke-width: 4px; stroke-width: 4px;
stroke-linecap: butt; stroke-linecap: butt;
stroke-linejoin: miter; stroke-linejoin: miter;
@ -146,12 +138,16 @@ text.helper:hover {
} }
.draggableText.highlight:not(.selected) { .draggableText.highlight:not(.selected) {
fill: green; fill: var(--associated-color);
font-weight: 600; font-weight: 600;
} }
.draggableText.selected {
fill: var(--accent-border-color);
}
.highlight:not(.selected):not(text) { .highlight:not(.selected):not(text) {
stroke: green; stroke: var(--associated-color);
stroke-width: 3px; stroke-width: 3px;
fill: none; fill: none;
} }
@ -160,19 +156,19 @@ text.helper:hover {
stroke: var(--error-color); stroke: var(--error-color);
} }
.arrow.fired { .arrow.fired {
stroke: rgb(160 0 168); stroke: var(--fired-transition-color);
stroke-width: 3px; stroke-width: 3px;
animation: blinkTransition 1s; animation: blinkTransition 1s;
} }
@keyframes blinkTransition { @keyframes blinkTransition {
0% { 0% {
stroke: rgb(255, 128, 9); stroke: var(--firing-transition-color);
stroke-width: 6px; stroke-width: 6px;
filter: drop-shadow(0 0 5px rgba(255, 128, 9, 1)); filter: drop-shadow(0 0 5px var(--firing-transition-color));
} }
100% { 100% {
stroke: rgb(160 0 168); stroke: var(--fired-transition-color);
} }
} }
@ -191,5 +187,5 @@ g:hover > .errorHover {
} }
text.uid { text.uid {
fill: lightgrey; fill: var(--separator-color);
} }

View file

@ -11,8 +11,6 @@ export function useMouse(makeCheckPoint: () => void, insertMode: InsertMode, zoo
const [dragging, setDragging] = useState(false); const [dragging, setDragging] = useState(false);
const [shiftOrCtrlPressed, setShiftOrCtrlPressed] = useState(false); const [shiftOrCtrlPressed, setShiftOrCtrlPressed] = useState(false);
console.log(shiftOrCtrlPressed);
// not null while the user is making a selection // not null while the user is making a selection
const [selectingState, setSelectingState] = useState<SelectingState>(null); const [selectingState, setSelectingState] = useState<SelectingState>(null);
@ -347,17 +345,19 @@ export function useMouse(makeCheckPoint: () => void, insertMode: InsertMode, zoo
...state, ...state,
// @ts-ignore // @ts-ignore
selection: [ selection: [
...state.rountangles.map(r => ["left", "top", "right", "bottom"].map(part => ({uid: r.uid, part}))), ...state.rountangles.flatMap(r => ["left", "top", "right", "bottom"].map(part => ({uid: r.uid, part}))),
...state.diamonds.map(d => ["left", "top", "right", "bottom"].map(part => ({uid: d.uid, part}))), ...state.diamonds.flatMap(d => ["left", "top", "right", "bottom"].map(part => ({uid: d.uid, part}))),
...state.arrows.map(a => ["start", "end"].map(part => ({uid: a.uid, part}))), ...state.arrows.flatMap(a => ["start", "end"].map(part => ({uid: a.uid, part}))),
...state.texts.map(t => ({uid: t.uid, part: "text"})), ...state.texts.map(t => ({uid: t.uid, part: "text"})),
...state.history.map(h => ({uid: h.uid, part: "history"})), ...state.history.map(h => ({uid: h.uid, part: "history"})),
] ]
})) }))
} }
} }
}, [makeCheckPoint, deleteSelection, setState, setDragging]); }, [makeCheckPoint, deleteSelection, setState, setDragging]);
console.log(state.selection);
useEffect(() => { useEffect(() => {
// mousemove and mouseup are global event handlers so they keep working when pointer is outside of browser window // mousemove and mouseup are global event handlers so they keep working when pointer is outside of browser window
window.addEventListener("mouseup", onMouseUp); window.addEventListener("mouseup", onMouseUp);

11
src/Logo/Logo.tsx Normal file

File diff suppressed because one or more lines are too long

View file

@ -5,9 +5,44 @@ html, body {
font-size: 10pt; font-size: 10pt;
} }
body { :root {
/* --error-color: darkred; */ color-scheme: light dark;
--error-color: rgb(163, 0, 0);
--background-color: light-dark(white, rgb(26, 26, 26));
--text-color: light-dark(black, white);
--error-color: light-dark(rgb(163, 0, 0), rgb(255, 82, 82));
--error-bg-color: light-dark(lightpink, rgb(75, 0, 0));
--error-hover-bg-color: light-dark(rgb(102, 0, 0), rgb(102, 0, 0));
--light-accent-color: light-dark(rgba(0,0,255,0.2), rgba(78, 186, 248, 0.377));
--accent-border-color: light-dark(blue, rgb(64, 185, 255));
--separator-color: light-dark(lightgrey, rgb(44, 44, 44));
--inactive-bg-color: light-dark(#f7f7f7, rgb(29, 29, 29));
--inactive-fg-color: light-dark(grey, rgb(70, 70, 70));
--button-bg-color: light-dark(#fcfcfc, rgb(20, 20, 20));
--modal-backdrop-color: light-dark(rgba(200,200,200,0.7), rgba(59, 7, 7, 0.849));
--status-inactive-color: light-dark(grey, grey);
--status-ok-color: light-dark(forestgreen, forestgreen);
--or-state-bg-color: light-dark(#eee, #1a1a1a);
--and-state-bg-color: light-dark(white, rgb(0, 0, 0));
--rountangle-stroke-color: light-dark(black, #d4d4d4);
--active-state-bg-color: light-dark(rgb(255, 240, 214), rgb(53, 37, 18));
--active-state-border-color: light-dark(rgb(205, 133, 0), rgb(235, 124, 21));
--fired-transition-color: light-dark(rgb(160, 0, 168), rgb(160, 0, 168));
--firing-transition-color: light-dark(rgba(255, 128, 9, 1), rgba(255, 128, 9, 1));
--associated-color: light-dark(green, rgb(186, 245, 119));
--bottom-panel-bg-color: light-dark(rgb(255, 249, 235), rgb(41, 4, 4));
--summary-hover-bg-color: light-dark(#eee, #242424);
--internal-event-bg-color: light-dark(rgb(255, 218, 252), rgb(99, 27, 94));
--input-event-bg-color: light-dark(rgb(224, 247, 209), rgb(59, 95, 37));
--input-event-hover-bg-color: light-dark(rgb(195, 224, 176), rgb(59, 88, 40));
--input-event-active-bg-color: light-dark(rgb(176, 204, 158), rgb(77, 117, 53));
--output-event-bg-color: light-dark(rgb(230, 249, 255), rgb(28, 83, 104));
}
/* for some reason i need to add this or some elements are rendered in OS color rather than 'forced' color */
div {
color: var(--text-color);
background-color: var(--background-color);
} }
div#root { div#root {
@ -27,17 +62,18 @@ kbd {
box-shadow: inset 0 -1.5px 0 #aaa; box-shadow: inset 0 -1.5px 0 #aaa;
vertical-align: middle; vertical-align: middle;
user-select: none; user-select: none;
color: black;
} }
kbd:active { transform: translateY(1px); } kbd:active { transform: translateY(1px); }
input { input {
/* border: solid blue 2px; */ /* border: solid blue 2px; */
accent-color: rgba(0,0,255,0.2); accent-color: var(--light-accent-color);
} }
::selection { ::selection {
background-color: rgba(0,0,255,0.2); background-color: var(--light-accent-color);
} }
label { label {