Zum Hauptinhalt springen

· 3 Minuten Lesezeit
Martin Oppitz

Heute wollen wir in einem kurzen Blog-Post zeigen, wie Ihr die standardmäßig hinterlegten Icons über das Theming (Theme-Designer) ändern könnt.

1. Icon-Font integrieren

Damit Icons angezeigt werden können, muss zunächst die gewünschte Icon-Font (z.B. Font Awesome Free) in der Webseite (HTML) eingebunden werden. Dies geschieht in der Regel mittels folgendem HTML:

<head>
<link rel="stylesheet" href="assets/fontawesome-free/css/all.min.css" />
</head>

Icon-Font im Theme hinterlegen

Die Icon-Komponente von KoliBri kapselt die Icon-Font und muss daher die CSS-Definitionen von den im Design System ausgewählten Icon-Identifier kennen. Dazu muss das CSS aus der gleichen CSS-Datei, wie aus 1., in das Theme kopiert und damit hinterlegt werden.

  1. Theme-Designer öffnen
  2. Theme auswählen
  3. Icon-Komponente auswählen
  4. Schalter auf Komponent-Styling umstellen
  5. CSS aus der Icon-Font einfügen und speichern
  6. Theme in Projekt übernehmen

Standard-Icons im Theme ändern

Das Ändern eines Icons ist ganz einfach, wenn folgendes Prinzip klar ist. Alle Icons werden durch die Web Component kol-icon abgebildet. Diese Komponente exportiert immer den Part icon. Über einen Part kann man auf festgelegte CSS-Eigenschaften innerhalb einer Web Component zugreifen. Exemplarisch sieht das so aus:

kol-icon::part(icon) {
font-family: 'Font Awesome 6 Free';
font-weight: 900;
}
kol-icon::part(icon):before {
content: '😃';
}

Um ein Icon über den Designer zu ändern, sind folgende Schritte zu durchlaufen:

  1. Theme-Designer öffnen
  2. Theme auswählen
  3. Komponente auswählen, wo ein Icon geändert werden soll
  4. Schalter auf Komponent-Styling umstellen
  5. Spezifischen Selektor auf ein Icon ermitteln
  6. Spezifischen Selektor verwenden, um Schriftart und Content anzupassen
  7. Komponent-CSS speichern
  8. Theme in Projekt übernehmen

Hier mal ein komplexeres Beispiel für die Pagination:

kol-button::part(icon) {
font-family: 'Font Awesome 6 Free';
font-weight: 900;
}
kol-button.first::part(icon):before,
kol-button.previous::part(icon):before,
kol-button.next::part(icon):before,
kol-button.last::part(icon):before {
content: '😃';
}

FAQ

Warum hängt das Icon im KolIcon etwas tiefer?

Mit der CSS-Definition display: contents; am kol-icon-Tag wird das Icon passend ausgerichtet. Die Ausrichtung der Icon-Komponente innerhalb anderer Komponenten hängt immer von der jeweiligen Verwendung ab.

Warum kann ich die Schriftgröße nicht ändern?

kol-icon::part(icon) {
font-family: 'Font Awesome 6 Free';
font-size: 2rem !important;
font-weight: 900;
}

Der Grund liegt in der font CSS-Definition in der Icon-Font selbst und in der Notwendigkeit, die Schriftgröße bei Icons von Außen setzen übernehmen (erben).

.codicon[class*='codicon-'] {
font: 16px / 1 codicon;
}
:host > i,
:host > i::before {
font-size: inherit !important;
}

Möchte man ein Icon in seiner Größe anpassen, so kann man das einfach von Außen tun.

kol-icon {
font-size: 2rem;
}

· 4 Minuten Lesezeit
Martin Oppitz

Das Release 1.5 wird bald veröffentlicht und bringt zahlreiche neue Komponenten, Verbesserungen und ein vereinfachtes Theming mit.

Die wichtigsten Änderungen sind:

  • Neue Komponenten

    • Image
    • Popover
    • SplitButton
    • ToggleButton (s. InputCheckbox)
    • Quote
  • Verbesserungen

    • Performance

      • Die Performance wurde durch die überdimensionierten CSS-Definitionen in der Icon-Komponente beeinträchtigt. Hintergrund sind die vielen Icon-Selectoren in den Icon-Fonts. Für ein Design System wird jedoch nur ein Bruchteil dieser CSS-Definitionen wirklich benötigt. Für die Komponenten haben wir uns für die schlanke Icon-Font von Visual Studio Code (Codicon) entschieden und Icofont und Font-Awesome standardmäßig entfernt (kann wieder nachgerüstet werden). Somit bringt dieses Release eine erhebliche Performance-Verbesserung beim Rendern der Komponenten mit sich.
    • Assets (Fonts und Icons)

      • Versionen der Icon-Fonts wurden aktualisiert
      • Assets wurden auf die Themes aufgeteilt, wo sie relevant sind. Dadurch können die KoliBri-Artefakt (NPM-Paket) verkleinert und somit schneller heruntergeladen und installiert werden.
      • Durch das Hinterlegen eines Postinstall-Scripts können die Assets nach jeder Installation der KoliBri-Pakete automatisch in den public/assets-Ordner kopiert werden.
         // package.json
        "scripts": {

        "postinstall": "npm-run-all postinstall:*",
        "postinstall:components-assets": "cpy \"node_modules/@public-ui/components/assets/**/*\" public/assets --dot",
        "postinstall:themes-assets": "cpy \"node_modules/@public-ui/themes/assets/**/*\" public/assets --dot",
        },
        "devDependencies": {
        "cpy-cli": "^4.2.0",
        "npm-run-all": "^4.1.5",

        }
      • Weitere Icon-Fonts wurden in Themes verwendet:
        • Microsoft Codicons
        • Google Material Icons
        • Google Material Symbols
        • Tabler Icons
  • Refactorings

    • Ein paar Komponenten haben wir refactored, um die Funktionalitäten zu erweitern und die Wartbarkeit zu verbessern.
    • Accordion
      • Der Header des Accordions wird jetzt mittels KoliBri-Heading, -Button und -Span umgesetzt.
      • Accordions lassen sich jetzt auch animiert auf- und zuklappen.
    • Alert
      • Die Konstruktion der Alerts wurde überarbeitet, um die volle Flexibilität für die Gestaltung zu ermöglichen.
    • Heading
      • Die Heading-Komponente wurde mit einem Expert-Slot versehen.
    • Inputs, Select und Textarea
      • Die Konstruktion aller Eingabefelder wurde überarbeitet, um die Gestaltbarkeit und Wartbarkeit zu verbessern.
    • Nav
      • Aufklappbare Untermenüs haben jetzt einen separaten Expand-Button. So kann der eigentliche Menüpunkt unabhängig vom Auf- und Zuklappen verwendet werden.
      • Menüpunkte können jetzt Links, Buttons oder auch reiner Text sein.
    • Table Die Pagination befindet sich jetzt im DOM immer oben, um den blinden Nutzenden eine schnellere Navigation zu ermöglichen. Für sehende Nutzende kann die Pagination über das Theming entweder über oder unter der Tabelle angezeigt werden.
    • Tabs
      • Die Tabs verwenden jetzt die KoliBri-Button-Komponente.
    • Tooltip
      • Der Tooltip ist nur für die interne Verwendung in KoliBri-Komponenten gedacht. Um die Gestaltbarkeit zu verbessern, wird der Tooltip jetzt ohne Shadow-Root bereitgestellt. Sollte die Komponente außerhalb von KoliBri verwendet werden, muss das Styling in das CSS-Styling des Projekts (Webseite, App) hinzugefügt werden.
    • Alle relevante Themes wurden bzgl. der Refactorings überarbeitet
  • Adapter

    • Neuer Adapter für Angular 16 hinzugefügt
  • KoliBri-CLI

    • Templates
      • Die Templates wurden überarbeitet und aktualisiert.
      • Angular-Template auf Version 16 aktualisiert
  • Expert-Slot

    • Der Expert-Slot kann verwendet werden, um beliebiges HTML anstatt des Text-Labels auf eigene Verantwortung einfügen zu können.
    • Bei der Einführung eines Expert-Slots, wird in der Regel das Property _label Pflicht. Entweder enthält das Label einen Text, der dann ohne Slot angezeigt wird. Oder es ist leer und der Expert-Slot wird aktiviert.
      <kol-heading _label="Inhalt einer H4-Überschrift" _level="4"></kol-heading>
      <kol-heading _label="" _level="4">
      <span slot="expert"> Inhalt einer H4-Überschrift … </span>
      </kol-heading>
    • Heading: Die Heading ermöglicht jetzt das Einfügen beliebiger Inhalte im Expert-Modus. Hierzu wurde das erforderliche Property _label eingeführt. Lässt man das Property leer (_label=""), wird er Expert-Slot aktiviert.
  • Theming

    • Basis-Styling: Wir haben das CSS auf den Komponenten auf das Wesentliche reduziert. Das Styling beinhaltet primär nur noch Layout-Definitionen ohne Farben, Abstände und Tokens. Somit kann das Erstellen von eigenen Themes deutlich vereinfacht werden.
    • Alle unsere Themes wurden bezüglich der neuen Basis-Styling-Definitionen angepasst und konnten dadurch deutlich vereinfacht werden.
    • Neue Themes
      • Theme der Europäischen Kommission
      • Theme der Europäischen Union
      • Theme für die neue Version des Design System Zoll (v2)
      • Theme des Bundes Styleguides (Bundesregierung)
      • Theme des Bundeszentralamt für Steuern (WIP)
      • Theme des Freistaats Thüringen (für Demozwecke)
  • Dokumentation

    • Code-Beispiele
      • Es gibt eine Beispiel-Anwendung () mit zahlreichen Code-Beispielen.
      • Code-Beispiele wurden erweitert und aktualisiert
      • Beispiel-Anwendung kann ausgecheckt und lokal gestartet werden (ist im KoliBri-Repository).
      • Code-Bespiele werden jetzt in der Dokumentation angezeigt.
      • Code-Beispiele beinhaltet eine Handout-Sicht für Präsentationen von Themes.
    • Texte
      • Die Texte wurde überarbeitet und aktualisiert.
      • Die Texte wurde auf Englisch übersetzt.
    • Live-Editor (beta): Alle Komponenten können jetzt live umkonfiguriert werden. Die Änderungen werden daneben im Viewer direkt auf der Komponente angezeigt.
  • Funktionalitäten

    • Der Link ermöglicht jetzt die Angabe eines Dateinames für den Download-Link.
    • Der Progress kann jetzt auch den Fortschritt als lesbaren Text anzeigen und eine Bezeichnung haben.

· 2 Minuten Lesezeit
Martin Oppitz

Am Beispiel der Badge-Komponente wollen wir einmal schauen, wie das Stylen funktioniert.

Herausforderung

Die Badge-Komponente hat einen Smart-Button und der soll optisch kleiner aussehen, wie ein Button, der immer mindestens 44px hoch und breit ist.

  • Bild einfügen vorher

Wir sehen im nachfolgenden HTML-Snippet, dass der umschließende Span die Badge-Hintergrundfarbe bestimmt. Da der Button innerhalb des Span ist, wird die Hintergrundfarbe auch auf den Button gesetzt. Der Button muss mindestens 44px hoch und breit sein, also wird auch der äußere Span mindestens 44px hoch und breit. Das wollen wir nicht.

<span class="smart-button" style="background-color: rgb(204, 222, 218); color: rgb(0, 78, 55);">
<kol-span-wc class="hydrated">
<span>
<span>Badge mit Schalter</span>
</span>
</kol-span-wc>
<kol-button-wc _icon-only="" class="hydrated">
<button aria-labelledby="cf22bf" class="normal icon-only" type="button">
<kol-span-wc class="icon-only hydrated" _icon-only="">
<span>
<kol-icon class="icon left hydrated" style=""></kol-icon>
</span>
</kol-span-wc>
</button>
<kol-tooltip aria-hidden="true" class="hydrated">
<div id="floating" style="left: 1233.91px; top: 312.5px; display: none; visibility: hidden;">
<div id="arrow" style="left: 19px; bottom: -5px;"></div>
<kol-badge id="cf22bf" class="hydrated" style=""></kol-badge>
</div>
</kol-tooltip>
</kol-button-wc>
</span>

Lösung

Idee 1

Wir optimieren die Komponente, indem wir die Hintergrundfarbe vom umschließenden Span entfernen und auf die beiden inneren Span-Elemente übertragen.

<span class="smart-button" style="color: rgb(0, 78, 55);">
<kol-span-wc class="hydrated" style="background-color: rgb(204, 222, 218);">
<span>
<span>Badge mit Schalter</span>
</span>
</kol-span-wc>
<kol-button-wc _icon-only="" class="hydrated">
<button aria-labelledby="cf22bf" class="normal icon-only" type="button">
<kol-span-wc class="icon-only hydrated" _icon-only="" style="background-color: rgb(204, 222, 218);">
<span>
<kol-icon class="icon left hydrated" style=""></kol-icon>
</span>
</kol-span-wc>
</button>
<kol-tooltip aria-hidden="true" class="hydrated">
<div id="floating" style="left: 1233.91px; top: 312.5px; display: none; visibility: hidden;">
<div id="arrow" style="left: 19px; bottom: -5px;"></div>
<kol-badge id="cf22bf" class="hydrated" style=""></kol-badge>
</div>
</kol-tooltip>
</kol-button-wc>
</span>

Das geht aber nicht, weil wir an den 2. Span nicht rankommen. Wir müssen also eine andere Lösung finden.

Idee 2

Es bleibt beim der initialen Komponenten-Konstruktion. Wir versuchen es mit CSS und erzwingen eine Zeilenhöhe für den umschließenden Span.

  • Bild Heihgt 1.75rem einfügen

Wir sehen im Bild, dass der linke Rand des Button oben rausragt. Das können wir aber leicht lösen, indem wir den linken Rand des Buttons auf 0 setzen und stattdessen einen rechten Rand am Text-Span setzen.

· 4 Minuten Lesezeit
Martin Oppitz

Ein großer Vorteil von KoliBri liegt in seiner besonders guten Wiederverwendbarkeit und hohen Flexiblität. Denn auf Basis der semantisch barrierefreien Komponenten, in denen alle technische und gesetzliche Anforderungen umgesetzt sind, können eigene Themes unabhängig erstellt werden.

Rückblick

KoliBri wurde als internes Projekt des ITZBund realisiert und hat sich natürlich dabei anfangs vor allem auf die Bedürfnisse interner Projekte fokussiert. Hierbei sind in erster Linie zahlreiche Themes umgesetzt worden, die nur intern Anwendung finden.


Darüber hinaus wurden auch einige Themes zum Zwecke der Verbesserung umgesetzt, die als Proof-of-Concepts (PoC) dienten.

Migration

Wir beschreiben jetzt hier in der Migration einfach mal, wie wir das im ITZBund exemplarisch umgesetzt haben, weil dass sicher ein interessanter Aspekt für andere Behörden, Organisationen und Unternehmen ist, wie sie eigene Themes intern bereitstellen können.

Im Grunde haben wir ein neues Repository angelegt und ein Theme-Projekt erstellt (siehe nächsten Abschnitt), in dem wir alle internen Themes pflegen. Wir haben erstmal alle Themes in einem Repository, weil wir das für die Entwicklung aktuell einfacher finden. Es ist aber auch möglich, die Themes in unterschiedlichen Repositories jeweils einzeln zu pflegen.

Mittels des TypeScript-Compilers wird das Theme-Projekt in ein JavaScript-Projekt kompiliert und als NPM-Paket @itzbund/interne-kolibri-themes in unsere interne NPM-Registry versioniert gepublished.

Damit die entwickelnden Projekte jetzt das neue Theme-Paket installieren und verwenden können, muss zunächst die NPM-Konfiguration .npmrc im Projekt-Verzeichnis erweitert und die neue Abhängigkeit in die package.json hinzugefügt werden.

.npmrc (kann mit im Projekt-Verzeichnis liegen oder im Home-Verzeichnis des Benutzers)

@itzbund:registry=https://<URL-zur-internen-registry>

package.json (im Projekt-Verzeichnis)

{
"dependencies": {
"@itzbund/interne-kolibri-themes": "1.0.0"
}
}

Eigenes Theme erstellen

In diesem Abschnitt wollen wir einen kurzen Einblick geben, wie einfach es ist, ein eigenes Theme zu erstellen.

Rationale

Einer der wichtigsten Punkte, die man verstehen muss, liegt darin, dass KoliBri sich auf kleinteilige häufig wiederverwendete Komponenten konzentriert (mehr hierzu im ). Das führt dazu, dass wir uns vorallem auf standardisierbare Komponenten fokussieren. Deutlicher wird dies, wenn wir uns vorstellen, eine redundante Umsetzung einer Basis-Komponente unter Beachtung der technischen und gesetzlichen Anforderungen zu entwickeln und am Ende feststellen - die verhält sich ja genauso, wie eine KoliBri- Komponente und ist nahezu gleich semantisch aufgebaut. Insbesondere die technisch semantischen Vorgaben des W3C für die assistive Unterstützung (Barrierefreiheit) fördern das Standardisierungspotenzial.

Wir können somit von einer hohen Überdeckung von Komponenten ausgehen, die allgemein jedes Design System oder Komponenten-Bibliothek beinhalten und sich in der KoliBri-Sammlung verwendbar wiederfinden. Durch das Kompositionsprinzip kann einfach die passende Teilmenge aus KoliBri ausgewählt und wiederverwendet werden. Alle nicht vereinbarten Komponenten können unabhängig von KoliBri und unternehmensspezifisch umgesetzt werden.

Hinweis: Es ist immer möglich eine Konstellation gegen die Wiederverwendung einer KoliBri-Komponenten aufzustellen, die auf die Abweichung von der Referenzimplementierung abzielt. Es ist nicht unsere Entscheidung ob die aufgezeigte Abweichung eine vollständige Eigenentwicklung wirtschaftlich und ökonomisch rechtfertigt. Wir bieten eine Lösung an, die von alle frei und geprüft genutzt werden kann.

Umsetzung

Mit Hilfe der KoliBri-CLI (npm init kolibri my-theme) kann ein neues Theme-Projekt generiert werden. Das Theme-Projekt ist ein TypeScript-Projekt und beinhalten schon ein Dummy-Theme. Mit Hilfe des KoliBri-Designers kann dann ein Theme interaktiv auf den Basis-Komponenten erstellt, gespeichert, geladen und weiter gepflegt werden. Der vom Designer generierte Code wird einfach in das Theme-Projekt kopiert und kann dann mit dem TypeScript-Compiler kompiliert werden. Anschließend kann es mittels NPM eine interne oder in die öffentliche NPM-Registry gepublished werden.

· 3 Minuten Lesezeit
Martin Oppitz

Wir bieten heute die Varianten von Button, ButtonLink, Link und LinkButton an. Zukünftig werden wir zusätzlich den ButtonToggle (Toogle-Button) anbieten. Alle semantischen Links unterstützen dabei nur noch _href und alle Buttons nur noch _on als semantischen "Klick". Optisch gibt es Buttons die genau wie Links aussehen und Links die genauso wie Buttons aussehen.

In der folgenden Tabelle wir eine Übersicht über die Unterschiede dargestellt:

MerkmalLinkLinkButtonButtonButtonLinkToogleButton*
DesignLinkButtonButtonLinkButton
Semantikaabuttonbuttoninput
_href
_on
focus()
Wertboolean
* Der Toogle-Button wurde als Variante der Checkbox umgesetzt, weil es ein Schalter mit maximal zwei Zuständen (entweder "an" oder "aus") ist.

Motivation

KoliBri strebt neben einer hohe Standardkonformität auch eine sehr gute Wiederverwendbarkeit (Developer Experience DX) an. Diese wird durch die Einheitlichkeit zu den HTML-Attributen und dem sparsamen Umgang mit zusätlichen Properties adressiert.

Rationale: Wenn wir bei einer Link-Komponente, die zum Navigieren gedacht ist, die beiden Verhalten Navigieren und Klick ohne Navigieren anbieten würden, dann hääten wir einen Widerspruch im Verhalten. Auch bei der Verwendung in der Entwicklung müssten wir die Properties _href und _on optional machen und wir könnten nicht mehr vor der Falschverwendung warnen (Statische Codeprüfung).

Herausforderungen

Diese strenge Auslegung kann dazu führen, dass es bei der Entwicklung mit anderen Bibliotheken und Frameworks zu Problemen kommt. Vorallem dann, wenn diese bei einem Link einen Klick erwarten.

React-Router

Der React-Router bildet das Navigieren über Klicks ab. Bei der Verwendung mit der Link-Komponente gibt es unterschiedliche Möglichkeiten der Implementierung.

Wrapping:

<Link to="/">
<KolLink _href="">Home</KolLink>
</Link>
<Link to="/test">
<KolLink _href="">Test</KolLink>
</Link>

Per Klick:

<KolButtonLink
_label="Home"
_on={{
onClick: () => navigate("/")
}}
>
Home
</KolButtonLink>
<KolButtonLink
_label="Test"
_on={{
onClick: () => navigate("/test")
}}
>
Test
</KolButtonLink>

React-Link:

<KolLink
_href=""
_label="Home"
onClick={() => navigate("/")}
>
Home
</KolLink>
<KolLink
_href=""
_label="Test"
onClick={() => navigate("/test")}
>
Test
</KolLink>

Hinweis: _href="" ist eigentlich nicht erlaubt.

Hier gibt es auch ein kleines Code-Beispiel zum Navigieren mit React-Router.

Die angegebenen Beispiele zeigen, dass die Link- und ButtonLink-Komponente für die direkte Nutzung mit React-Router geeignet sind. Allerdings wird die Link-Komponente auch innerhalb anderer KoliBri-Komponenten verwendet. Wo das so nicht funktionieren würde!

Server-Side-Rendering

Das Server-Side-Rendering ist sehr ähnlich zum React-Router, weil dieser technisch sehr stark durch das Framework Remix getrieben ist. Remix ist ein Framework zum Erstellen von hybriden Client- und Server-Side-Webapplications. Das heißt die Implementierung unterscheiden sich nicht, ob ich die Anwendung später als Client- oder Server-seitige Anwendung bauen möchte. Für Server-Side-Anwendungen müssen die navigierenden Links mit einem Klick funktionieren, weil diese Anwendungen auf dem Server und nicht im Browser ausgeführt werden.

Um die Wiederverwendbarkeit von KoliBri auch für Server-Side-Webapplications zu gewährleisten, muss der Seitenwechsel auch durch Klick ohne Navigieren möglich sein.

Lösung

Um die Herausforderungen zu lösen, werden alle Komponenten, denen Link-Definitionen übergeben werden, erweitert. Wenn diesen Komponenten wahlweise auch ButtonLink-Definitionen übergeben werden können, dann können diese auch Klicks abbilden ohne zu Navigieren, sehen aber optisch weiterhin wie Links aus.

Folgende Komponenten müssen dazu noch erweitert werden:

  • Breadcrumb
  • LinkGroup
  • Nav
  • SkipNav

· Eine Minute Lesezeit
Martin Oppitz

Als Open Source-Projekt ist es für KoliBri wichtig eine Community rund um das Thema barrierefreie Basis-Komponenten aufzubauen. Damit auch hierfür eine optimiale Zugänglichkeit gegeben ist, sollten alle technischen Spezifikationen mindestens in English verfügbar sein. Wie auch in der Wissenschaft ermöglicht das Feedback und Mitwirkung aus allen potenziellen Bereichen.

Maßnahmen

Englische Spezifikation

Die technische Spezifikation wird automatisiert aus dem Quellcode generiert und synchronisiert. Alle Informationen die wir aus dem Quellcode in die Spezifikation überführen, wird in Zukunft ausschließlich in English bereitgestellt.

Das betrifft beispielsweise:

  • API-Spezifikation auf der Website
  • Details in der IDE-Autovervollständigung
  • Darstellungen die aus den Meta-Daten des Quellcodes generiert werden

Multilinguale Dokumentation

Die Dokumentation wird in Zukunft (mittelfristig) alle Inhalte jeweils primär in Deutsch und sekundär in English bereitgestellt.

Das betrifft beispielsweise:

  • Anleitungen, Konzepte, Beispiele uvm.
  • Blog-Beiträge