Phase 4: Vite-React-Geruest und Workspace-Anbindung
npm-Workspace im Repo-Root verbindet companion-app mit @audi-dash/ui, so dass die App die Komponentenbibliothek als echte Abhaengigkeit nutzt statt nur in der Doku. Dazu Vite, React 18, Einstiegsdateien und eine schlanke Grundlage-CSS, die nur enthaelt was eine App braucht und eine Bibliothek nicht mitbringt: Vollbild, sichere Bereiche, Scrollverhalten. Zwei Audit-Befunde des alten Panels sind hier von Anfang an beruecksichtigt: Formularfelder mit 16px (sonst zoomt iOS Safari beim Fokus) und ein globaler :focus-visible-Ring. Nebenbei im design-system den Kontrastwert --fg3 nachgezogen: dort stand noch #657081 mit 3,0:1 auf --tile, das Panel hatte den Wert laengst auf #8a94a3 korrigiert. Ohne das haette die neue App den bereits behobenen WCAG-Verstoss geerbt.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, viewport-fit=cover"
|
||||
/>
|
||||
<meta name="color-scheme" content="dark light" />
|
||||
<meta name="theme-color" content="#161b23" />
|
||||
<title>DataMetric360</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wurzel"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,14 +2,31 @@
|
||||
"name": "datametric360",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "DataMetric360 — private Fahrzeug-App (iOS/Android via Capacitor, zusätzlich als Iframe im Home-Assistant-Dashboard). Dieses Paket enthält vorerst nur die Datenschicht; die Oberfläche folgt aus dem Claude-Design-Entwurf.",
|
||||
"description": "DataMetric360 — private Fahrzeug-App (iOS/Android via Capacitor, zusätzlich als Iframe im Home-Assistant-Dashboard). Datenschicht plus Oberfläche auf Basis von @audi-dash/ui.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"smoke": "node --experimental-strip-types scripts/smoke.ts"
|
||||
"smoke": "node --experimental-strip-types scripts/smoke.ts",
|
||||
"smoke:auth": "node --experimental-strip-types scripts/smoke-auth.ts",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@audi-dash/ui": "*",
|
||||
"leaflet": "^1.9.4",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/leaflet": "^1.9.12",
|
||||
"@types/node": "^24.13.3",
|
||||
"typescript": "^5.7.2"
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"typescript": "^5.7.2",
|
||||
"vite": "^6.0.7",
|
||||
"vitest": "^2.1.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Tile } from "@audi-dash/ui"
|
||||
|
||||
/**
|
||||
* Vorläufiger Einstieg — wird in Phase 5 durch die App-Shell ersetzt.
|
||||
* Das äußerste Element trägt immer `ads-root` und `data-theme`, sonst greifen
|
||||
* die Design-Tokens nicht (siehe design-system/.design-sync/conventions.md).
|
||||
*/
|
||||
export function App() {
|
||||
return (
|
||||
<div className="ads-root dm-wurzel" data-theme="nacht">
|
||||
<div className="dm-scroll" style={{ flex: 1, padding: 22 }}>
|
||||
<span className="ads-eyebrow">DataMetric360</span>
|
||||
<Tile>
|
||||
<div style={{ fontWeight: 300, fontSize: 20 }}>Gerüst steht</div>
|
||||
</Tile>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { StrictMode } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
|
||||
import "@audi-dash/ui/styles.css"
|
||||
import "./stile/grundlage.css"
|
||||
import { App } from "./App"
|
||||
|
||||
const wurzel = document.getElementById("wurzel")
|
||||
if (!wurzel) throw new Error("Wurzelelement #wurzel fehlt in index.html")
|
||||
|
||||
createRoot(wurzel).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Grundlayout der App. Alles Gestalterische kommt aus @audi-dash/ui
|
||||
* (Tokens + Komponenten) — hier steht nur, was eine App braucht und eine
|
||||
* Komponentenbibliothek nicht mitbringen kann: Vollbild, sichere Bereiche,
|
||||
* Scrollverhalten, Fokusring.
|
||||
*/
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overscroll-behavior-y: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--canvas);
|
||||
}
|
||||
|
||||
#wurzel {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Wurzel der App: setzt Schrift, Farben und Zahlendarstellung (.ads-root aus
|
||||
der Bibliothek) und spannt sich über die volle Höhe. */
|
||||
.dm-wurzel {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Tastaturbedienung: im alten Panel als Audit-Befund nachgerüstet, hier von
|
||||
Anfang an. :focus-visible statt :focus lässt Maus und Touch unberührt. */
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--red);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.dm-scroll {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.dm-scroll::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.dm-scroll::-webkit-scrollbar-thumb {
|
||||
background: var(--line-strong);
|
||||
border-radius: var(--r-pill);
|
||||
}
|
||||
|
||||
/* Formularfelder: mindestens 16px, sonst zoomt iOS Safari beim Fokus die
|
||||
ganze Seite (Audit-Befund aus dem alten Panel). */
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
button {
|
||||
font-family: inherit;
|
||||
font-size: 16px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"types": ["vite/client"],
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
@@ -16,5 +18,5 @@
|
||||
"skipLibCheck": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "scripts/**/*.ts"]
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "scripts/**/*.ts", "vite.config.ts"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { defineConfig } from "vite"
|
||||
import react from "@vitejs/plugin-react"
|
||||
|
||||
// Basispfad relativ: die App wird sowohl unter einer eigenen Domain als auch
|
||||
// aus einem Unterordner heraus ausgeliefert (Home Assistant: /local/dm360/),
|
||||
// und in der Capacitor-Hülle direkt vom Dateisystem.
|
||||
export default defineConfig({
|
||||
base: "./",
|
||||
plugins: [react()],
|
||||
server: { port: 5173 },
|
||||
build: {
|
||||
outDir: "dist",
|
||||
target: "es2022",
|
||||
sourcemap: true,
|
||||
},
|
||||
})
|
||||
@@ -29,7 +29,10 @@
|
||||
--line-strong: rgba(255, 255, 255, .20);
|
||||
--fg: #FFFFFF;
|
||||
--fg2: #9aa1ad;
|
||||
--fg3: #657081;
|
||||
/* Design-Audit A2: von #657081 (nur 3,0:1 auf --tile, WCAG AA verfehlt) auf
|
||||
4,9:1 angehoben. Das Panel hat diesen Wert bereits, hier war er noch der
|
||||
alte — nachgezogen, damit beide dasselbe zeigen. */
|
||||
--fg3: #8a94a3;
|
||||
--ok: #15da15;
|
||||
--warn: #ffaa00;
|
||||
--bad: #fd2c4e;
|
||||
|
||||
Generated
+4237
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "audi-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Werkstatt für DataMetric360: Design-System, Companion-App und das Home-Assistant-Panel.",
|
||||
"workspaces": [
|
||||
"design-system",
|
||||
"companion-app"
|
||||
],
|
||||
"scripts": {
|
||||
"build:ds": "npm run build --workspace @audi-dash/ui",
|
||||
"dev": "npm run dev --workspace datametric360",
|
||||
"build": "npm run build:ds && npm run build --workspace datametric360",
|
||||
"typecheck": "npm run typecheck --workspaces --if-present",
|
||||
"test": "npm run test --workspace datametric360"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user