Add branding splash and simulator cycle timing

This commit is contained in:
masterdev
2026-06-17 13:51:12 +01:00
parent d2ddcb2b20
commit 6d5e11e433
8 changed files with 203 additions and 15 deletions

BIN
simulator-ui/public/KSS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -120,6 +120,7 @@ function parseInputValue(value: string): boolean | number | string {
}
function App() {
const [showSplash, setShowSplash] = useState(true);
const [language, setLanguage] = useState<Language>(() => {
const savedLanguage = localStorage.getItem(LANGUAGE_STORAGE_KEY);
return savedLanguage === "en" || savedLanguage === "fr" ? savedLanguage : "fr";
@@ -141,6 +142,11 @@ function App() {
return value[language];
}
useEffect(() => {
const timer = window.setTimeout(() => setShowSplash(false), 900);
return () => window.clearTimeout(timer);
}, []);
useEffect(() => {
apiRequest<Machine[]>("/api/machines")
.then((items) => {
@@ -220,18 +226,29 @@ function App() {
const selectedMachineInfo = machines.find((machine) => machine.code === selectedMachine);
const machinePowerLabel = selectedMachineInfo?.powered_on ? t("Powered ON", "Sous tension") : t("Powered OFF", "Hors tension");
if (showSplash) {
return (
<main className="splash-screen" aria-label="Plast Track Simulator">
<img src="/KSS.png" alt="KSS" />
</main>
);
}
return (
<main className="shell">
<section className="hero">
<div>
<p className="eyebrow">{t("Separate test console", "Console de test separee")}</p>
<h1>{t("Passive Signal Simulator", "Simulateur signaux passifs")}</h1>
<p className="hero__copy">
{t(
"Simulate cycles, power states, stops, alarms, signal edges, debounce noise, and raw digital inputs without adding test controls to the production dashboard.",
"Simuler cycles, etats alimentation, arrets, alarmes, fronts signal, bruit anti-rebond et entrees digitales brutes sans ajouter de controles de test au tableau de production.",
)}
</p>
<div className="brand-lockup">
<img className="brand-lockup__logo" src="/KSS.png" alt="KSS" />
<div>
<p className="eyebrow">{t("Separate test console", "Console de test separee")}</p>
<h1>{t("Passive Signal Simulator", "Simulateur signaux passifs")}</h1>
<p className="hero__copy">
{t(
"Simulate cycles, power states, stops, alarms, signal edges, debounce noise, and raw digital inputs without adding test controls to the production dashboard.",
"Simuler cycles, etats alimentation, arrets, alarmes, fronts signal, bruit anti-rebond et entrees digitales brutes sans ajouter de controles de test au tableau de production.",
)}
</p>
</div>
</div>
<div className="hero__side">
<label className="language-select">
@@ -285,7 +302,7 @@ function App() {
<div className="numeric-grid">
<label className="field">
<span>{t("Cycle time sec", "Temps cycle sec")}</span>
<span>{t("Real cycle time sec", "Temps de cycle reel sec")}</span>
<input
min="1"
step="0.1"

View File

@@ -22,6 +22,19 @@ body {
min-width: 320px;
}
.splash-screen {
display: grid;
min-height: 100vh;
place-items: center;
background: #ffffff;
}
.splash-screen img {
width: min(220px, 58vw);
height: auto;
animation: splash-enter 420ms ease both;
}
button,
input,
select {
@@ -54,6 +67,21 @@ button:disabled {
max-width: 1280px;
}
.brand-lockup {
display: flex;
min-width: 0;
align-items: flex-start;
gap: 18px;
}
.brand-lockup__logo {
width: 82px;
max-height: 68px;
flex: 0 0 auto;
object-fit: contain;
margin-top: 4px;
}
.eyebrow {
margin: 0 0 8px;
color: var(--accent);
@@ -371,10 +399,20 @@ pre {
}
.hero,
.brand-lockup,
.control-grid {
grid-template-columns: 1fr;
}
.brand-lockup {
display: grid;
}
.brand-lockup__logo {
width: 72px;
margin-top: 0;
}
.connection-card {
min-width: 0;
}
@@ -384,6 +422,18 @@ pre {
}
}
@keyframes splash-enter {
from {
opacity: 0;
transform: translateY(8px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@media (max-width: 620px) {
.scenario-grid,
.numeric-grid {