Das WebKit im Schaufenster
Zuletzt geändert: 06.06.2026 20:09

Übersicht

Das WebKit im Schaufenster #

Eine Oberfläche für ein EULANDA-Plugin zu bauen fühlt sich an wie HTML schreiben - nur dass am Ende kein nacktes Formular steht, sondern ein fertiger, themenfähiger, mehrsprachiger Dialog. Das WebKit aus EulandaXtools liefert dafür einen ganzen Satz eul-*-Bausteine: Sie kennen Hell- und Dunkelmodus, sie sind lokalisiert, sie sehen über alle Plugins gleich aus - und man bindet sie ein, indem man ein Tag schreibt. Kein Framework-Projekt, kein Build-Schritt, keine Node-Toolchain.

Dieses Kapitel ist die Einladung: ein Rundgang durch die Bausteine, jeweils mit einem Blick in ein echtes Fenster und der einen Zeile, die ihn erzeugt. Am schnellsten erlebt man das live - Show-EulWebUiStyleguide öffnet genau diese Galerie als Dialog samt Theme-Umschalter; alle Abbildungen hier stammen daraus.

Schnellstart: installieren und ausprobieren #

Man braucht nur Windows mit Windows PowerShell - kein Visual Studio, kein Node. Ein PowerShell-Fenster öffnen und das folgende Skript einfügen. Es holt EulandaXtools (nur falls online eine neuere Version liegt) und öffnet anschließend genau diesen Style Guide. Das Skript ist eingeklappt - direkt kopieren oder zum Lesen aufklappen:

Skript anzeigen
# EulandaXtools bei Bedarf aktualisieren und den Style Guide öffnen.
$ProgressPreference = 'SilentlyContinue'
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$module = 'EulandaXtools'
$base   = "https://files.eulanda.eu/$($module.ToLower())"

# Modulpfad im (ggf. nach OneDrive umgelenkten) Benutzerprofil - Windows PowerShell 5.1
$modulesRoot = Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'WindowsPowerShell\Modules'
$installRoot = Join-Path $modulesRoot $module

# Online-Version von files.eulanda.eu (IIS) lesen
$online = (Invoke-RestMethod "$base/version.txt") -replace '[^\d.]', ''
Write-Host "Online (files.eulanda.eu): $module $online" -ForegroundColor Cyan

# Höchste lokal installierte Version ermitteln
$installed = $null
if (Test-Path $installRoot) {
  $installed = Get-ChildItem $installRoot -Directory |
    Where-Object { $_.Name -as [version] } |
    Sort-Object { [version]$_.Name } -Descending |
    Select-Object -First 1 -ExpandProperty Name
}
if ($installed) { Write-Host "Lokal installiert:         $module $installed" -ForegroundColor Cyan } else { Write-Host "Lokal installiert:         (noch nicht vorhanden)" -ForegroundColor Cyan }

if (-not $installed -or [version]$online -gt [version]$installed) {
  Write-Host "Aktualisiere auf $online ..." -ForegroundColor Yellow
  $tmp = Join-Path $modulesRoot ".$module-download"
  $ext = Join-Path $tmp 'extracted'
  if (Test-Path $tmp) { Remove-Item $tmp -Recurse -Force }
  New-Item -ItemType Directory -Path $ext -Force | Out-Null
  $zip = Join-Path $tmp "$module.zip"
  Invoke-WebRequest "$base/$($module.ToLower()).zip" -OutFile $zip
  Expand-Archive $zip -DestinationPath $ext -Force

  # Das Manifest (.psd1) ist die verbindliche Quelle für die Versionsnummer
  $psd1 = Get-ChildItem $ext -Recurse -Filter "$module.psd1" | Select-Object -First 1
  if (-not $psd1) { throw "$module.psd1 im Download nicht gefunden." }
  $version = (Import-PowerShellDataFile $psd1.FullName).ModuleVersion

  $target = Join-Path $installRoot $version
  if (Test-Path $target) { Remove-Item $target -Recurse -Force }
  New-Item -ItemType Directory -Path $target -Force | Out-Null
  Copy-Item (Join-Path $psd1.Directory.FullName '*') $target -Recurse -Force
  Get-ChildItem $target -Recurse -File | Unblock-File -ErrorAction SilentlyContinue   # Mark of the Web entfernen
  Remove-Item $tmp -Recurse -Force
  Write-Host "Installiert: $module $version" -ForegroundColor Green
} else {
  Write-Host "Bereits aktuell - kein Download." -ForegroundColor Green
}

Write-Host "Starte den Style Guide ..." -ForegroundColor Cyan
Import-Module $module -Force
Show-EulWebUiStyleguide

Was das Skript tut:

  • Versionsabgleich: Es liest die Online-Version aus version.txt und vergleicht sie mit der höchsten lokal installierten - heruntergeladen wird nur, wenn das Web wirklich neuer ist.
  • Sichere Versionsbestimmung: Der Download landet zuerst in einem Temp-Ordner; die maßgebliche Versionsnummer kommt aus dem Manifest (.psd1), nicht aus dem Dateinamen. Erst damit entsteht der endgültige Zielordner ...\Modules\EulandaXtools\<Version>\. Genau so macht es auch ErpXe beim Nachladen.
  • OneDrive-fest: Der Modulpfad wird über den Windows-Known-Folder „Eigene Dokumente" aufgelöst - also auch bei nach OneDrive umgeleitetem Dokumente-Ordner.
  • Sofort lauffähig: Set-ExecutionPolicy -Scope Process RemoteSigned erlaubt das Laden des EV-signierten Moduls in dieser Sitzung; Unblock-File nimmt den frisch entpackten Dateien das „Mark of the Web". Danach Import-Module -Force - und der Beispieldialog geht auf.

Ein manuelles Freischalten vorab ist nicht nötig. Das Skript wird in ein PowerShell-Fenster eingefügt (interaktiv ausgeführt, nicht als .ps1-Datei gestartet) - die Execution Policy blockt nur Skript-/Moduldateien, nicht eingefügte Befehle. Deshalb läuft die erste Zeile auch unter der Standardrichtlinie „Restricted", ohne Adminrechte, und Scope Process betrifft nur diese eine Sitzung. Wer das Skript stattdessen als .ps1 speichert und startet, ruft es mit powershell -ExecutionPolicy Bypass -File <datei>.ps1 auf. (Einzige echte Ausnahme: eine per Gruppenrichtlinie zentral erzwungene Policy.)

Ab jetzt steht Show-EulWebUiStyleguide jederzeit bereit und alle eul-*-Bausteine sind einsatzbereit. Und damit der Rundgang:

Buttons #

Der Anfang ist unspektakulär und genau deshalb angenehm: Ein eul-button ist ein Button, der schon richtig aussieht. Fünf Varianten transportieren die Bedeutung (primary, secondary, ghost, success, danger), drei Größen die Gewichtung - mehr muss man nicht entscheiden.

Buttons in allen Varianten und Größen

Varianten und Größen - jede Farbe trägt eine Bedeutung.

<eul-button variant="success">Speichern</eul-button>
<eul-button variant="ghost"><eul-icon name="settings"></eul-icon></eul-button>

Formularfelder #

Text, E-Mail, Zahl, Auswahl, Checkbox, Radio, Schalter - die üblichen Verdächtigen, aber aus einem Guss. Das Sahnehäubchen ist eul-tag-input: ein Feld mit Autocomplete, das Vorschläge filtert und als Chips übernimmt - ideal, wenn der Anwender Spalten oder Schlagworte zusammenstellt.

Eingabefelder, Schalter und Tag-Input

Von Text bis Schalter, plus das Tag-Input mit Vorschlagsliste.

<eul-input type="email" placeholder="name@firma.de"></eul-input>
<eul-switch checked>Aktiv</eul-switch>

Form-Layout #

Formulare sollen ohne Handarbeit ordentlich aussehen. eul-form mit eul-form-row legt Label und Eingabe ab 560 px Breite nebeneinander und stapelt sie darunter - per Container-Query, nicht per Fensterbreite. Der graue Hilfetext unter einem Feld ist eine einzige Zeile.

Responsives Label-Eingabe-Layout

Label und Eingabe sortieren sich je nach Platz selbst.

<eul-form>
  <div class="eul-form-row">
    <label>E-Mail</label>
    <div>
      <eul-input type="email"></eul-input>
      <div class="eul-form-help">Wird für Benachrichtigungen genutzt.</div>
    </div>
  </div>
</eul-form>

Datepicker #

Datum, Datum mit Uhrzeit, Zeitraum - eul-datepicker deckt alle drei ab, mit deutschem Format und Kalender-Popup. Ein Attribut entscheidet, welcher Typ.

Datum, Datum mit Zeit und Zeitraum

Drei Picker-Typen aus einer Komponente.

<eul-datepicker type="range" placeholder="von - bis"></eul-datepicker>

HTML-Editor #

Wo der Anwender formatierten Text braucht - ein Anschreiben, eine Mail-Vorlage - liefert eul-htmleditor einen WYSIWYG-Editor mit drei Toolbar-Stufen. Wichtig fürs Backend: el.mailHtml gibt sauberes, auf das EULANDA-Subset reduziertes HTML zurück, kein Editor-Wirrwarr.

WYSIWYG-Editor mit Mail-Toolbar

Formatierter Text, der als sauberes HTML zurückkommt.

<eul-htmleditor toolbar="mail" height="160"></eul-htmleditor>
const html = document.querySelector('eul-htmleditor').mailHtml;

Cards / Tönungen #

eul-card ist der Rahmen für alles. Über tone bekommt eine Karte eine Bedeutung (info, success, warning, danger), über elevation Tiefe, über level eine saubere Verschachtelung - aus drei Attributen entsteht eine ganze Gestaltungssprache.

Tönungen, Schattenstufen und Ebenen

Variant, Tone, Elevation und verschachtelte Level.

<eul-card tone="warning">Bitte prüfen</eul-card>

Tabs / Accordion #

Zwei klassische Gliederungen, beide rein über CSS-Klassen, ohne eine Zeile JavaScript: eul-tabs für Reiter nebeneinander, eul-accordion für aufklappbare Abschnitte untereinander. Je das erste Element trägt selected beziehungsweise open.

Reiter und Aufklapp-Bereiche

Tabs oben, Accordion darunter - rein deklarativ.

<eul-tabs>
  <div class="eul-tabs-list">
    <button class="eul-tab" selected>Allgemein</button>
    <button class="eul-tab">Optionen</button>
  </div>
  <div class="eul-tab-panel" selected>...</div>
  <div class="eul-tab-panel">...</div>
</eul-tabs>

Feedback #

Rückmeldung an den Anwender ist Einzeiler-Sache. EulUI.toast wirft eine kurze Meldung ein (vier Varianten), EulUI.alert und EulUI.confirm liefern Hinweis und Rückfrage als Promise. Dazu eul-spinner und eul-progress für alles, was dauert.

Toasts, Alert, Confirm, Spinner und Fortschritt

Kurzmeldungen, Dialoge und Ladeanzeigen.

EulUI.toast('Gespeichert', { variant: 'success' });
if (await EulUI.confirm('Wirklich löschen?')) { /* ... */ }

Wizard #

Mehrstufige Abläufe - Import, Einrichtung, Migration - führt eul-wizard Schritt für Schritt. Jede Seite trägt ihren Titel im data-title, die Schritt-Navigation entsteht von selbst.

Schritt-für-Schritt-Assistent

Geführter Ablauf mit Fortschrittsleiste.

<eul-wizard>
  <div class="eul-wizard-content">
    <div class="eul-wizard-page" data-title="Start" active>...</div>
    <div class="eul-wizard-page" data-title="Prüfen">...</div>
  </div>
</eul-wizard>

Tree / Listview #

Hierarchien zeigt eul-tree - mit Checkboxen, Einfachauswahl und einer Echtzeitsuche, die den Baum beim Tippen filtert. Für flache Listen gibt es eul-listview. Daten kommen als Property, die Auswahl liest man über .checkedIds oder .selectedId zurück.

Baum mit Echtzeitsuche, daneben eine Liste

Baum mit Sofortfilter und Mehrfachauswahl, plus Liste.

<eul-tree id="t" checkboxes searchable></eul-tree>
document.getElementById('t').data = [
  { id: 'a', label: 'Eigenschaften', children: [{ id: 'farbe', label: 'Farbe' }] }
];

Grid #

Die Tabelle, die im echten Plugin am häufigsten gebraucht wird. eul-grid bringt Suche, Sortierung und Pagination schon als Attribute mit; Spalten und Zeilen setzt man über .columns und .data. Sind keine Daten da, erscheint automatisch ein Empty-Overlay.

Tabelle mit Suche, Sortierung und Seitenzahlen

Volltextsuche, Spaltensortierung und Pagination ohne Zutun.

<eul-grid search sort pagination></eul-grid>
const g = document.querySelector('eul-grid');
g.columns = ['ArtNr', 'Bezeichnung', 'Bestand', 'Preis'];
g.data = rows;

Charts #

Zahlen werden Bild: eul-chart umhüllt Chart.js für Balken, Torte, Linie und Doughnut. Ein Attribut wählt den Typ, .data nimmt das vertraute Chart.js-Format.

Balken- und Tortendiagramm

Aus einem Datenobjekt wird ein fertiges Diagramm.

<eul-chart type="bar" height="220"></eul-chart>
document.querySelector('eul-chart').data = {
  labels: ['Jan', 'Feb', 'Mär'],
  datasets: [{ label: 'Umsatz', data: [42, 48, 55] }]
};

Icons #

40 randscharfe Lucide-Icons als Inline-SVG, skalierbar und einfärbbar. size bestimmt die Größe, color die Bedeutung - und im Button wird daraus mit einem Tag ein Icon-Button.

Das Lucide-Set in Größen und Farben

Ein konsistentes Icon-Set, das überall passt.

<eul-icon name="trash-2" color="danger"></eul-icon>
<eul-button><eul-icon name="save"></eul-icon> Speichern</eul-button>

EULANDA-Icons #

Eigene Bilddateien - Logos, Symbole - liegen im Modul-Ordner lib/img/ und sind im Dialog als eulimg/... erreichbar; den Virtual-Host dafür richtet Show-EulWebView2Dialog automatisch ein. eul-image zeigt sie scharf in jeder Größe.

Bilder aus dem Modul über den eulimg-Virtual-Host

Modul-eigene Bilder, ohne Pfad-Gefummel.

<eul-image src="eulimg/eulanda-logo.png" width="48"></eul-image>

App-Layout #

Und schließlich der Rahmen, der alles zusammenhält: eul-app mit Kopfleiste und Body, darin eul-sidebar (Navigationsleiste links, Seiten rechts) oder eul-ribbon (Reiter oben). Der Seitenwechsel läuft über ein data-page-Attribut - genau dieses Muster trägt auch der Style Guide selbst.

Sidebar- und Ribbon-Layout

Der Plugin-Rahmen als Sidebar oder Ribbon.

<eul-sidebar>
  <nav slot="nav">
    <a data-page="start" active>Start</a>
    <a data-page="export">Export</a>
  </nav>
  <eul-page id="start" active>...</eul-page>
  <eul-page id="export">...</eul-page>
</eul-sidebar>

All das kommt aus einem einzigen Bundle, das Show-EulWebView2Dialog automatisch einsetzt - Design-Tokens, Komponenten, Sprache. Man schreibt die eul-*-Tags, der Rest ist erledigt. Wer loslegen will: WebView2 in PowerShell zeigt das Gerüst, Dialog-Aufbau und Bausteine die Struktur dahinter.