Android Coden
Android 4 min lesen

Design-System-Architektur

Ein Design System bündelt UI-Komponenten und Tokens. So bleibt deine App konsistent und barrierefrei.

Eine App, die über viele Bildschirme hinweg konsistent aussieht und sich konsistent anfühlt, lässt sich nicht durch Ad-hoc-Styling realisieren. Design-System-Architektur löst dieses Problem grundlegend: Sie schafft einen gemeinsamen Baukasten aus Tokens und Komponenten, der Markenentscheidungen und Barrierefreiheitsanforderungen einmalig kodiert und im gesamten Projekt nutzbar macht.

Was ist das?

Design-System-Architektur ist die organisatorische und technische Struktur, die UI-Entscheidungen systematisch speicherbar, versionierbar und wiederverwendbar macht. Im Kern besteht sie aus zwei Schichten.

Tokens sind atomare Designwerte – Farben wie #1A73E8, Abstände wie 16.dp oder Schriftgrößen wie 14.sp. Statt diese Werte direkt in Layouts oder Composables einzutragen, gibst du ihnen benannte Identitäten: primary, spacing.md, body.size. So lässt sich das gesamte visuelle System durch Änderung weniger Definitionen anpassen.

Komponenten bauen auf diesen Tokens auf. Ein PrimaryButton kennt seine Hintergrundfarbe nicht als Hex-Wert, sondern als MaterialTheme.colorScheme.primary. Er verweist auf das Token, nicht auf den konkreten Wert.

In der Android-Welt ist Jetpack Compose das natürliche Zuhause für diese Architektur. MaterialTheme fungiert als Theme-Provider und exponiert ein typsicheres Farbschema, Typografie und Formen, die du mit eigenen Werten befüllen kannst. Das macht Design-System-Architektur in Compose nicht nur möglich, sondern idiomatisch.

Wie funktioniert es?

Die Implementierung folgt drei Stufen, die sauber voneinander getrennt bleiben müssen.

1. Primitive Tokens definieren

Primitive Tokens sind Rohwerte ohne Kontext – sie beschreiben ein Objekt, nicht seine Rolle:

object AppColors {
    val Blue500 = Color(0xFF1A73E8)
    val Neutral100 = Color(0xFFF8F9FA)
    val Red600 = Color(0xFFD93025)
}

object AppSpacing {
    val xs = 4.dp
    val sm = 8.dp
    val md = 16.dp
    val lg = 24.dp
    val xl = 32.dp
}

2. Semantische Tokens ableiten

Semantische Tokens geben primitiven Werten eine Rolle im Kontext der App:

val LightColorScheme = lightColorScheme(
    primary = AppColors.Blue500,
    background = AppColors.Neutral100,
    error = AppColors.Red600
)

val DarkColorScheme = darkColorScheme(
    primary = AppColors.Blue500,
    background = Color(0xFF121212),
    error = AppColors.Red600
)

Eine Komponente fragt nun nicht mehr „Welcher Hex-Wert gilt hier?”, sondern „Was ist die primäre Farbe in diesem Theme?” Dark-Mode-Unterstützung entsteht dadurch nahezu automatisch.

3. Komponenten bauen und Theme konsumieren

@Composable
fun PrimaryButton(
    label: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    Button(
        onClick = onClick,
        colors = ButtonDefaults.buttonColors(
            containerColor = MaterialTheme.colorScheme.primary
        ),
        modifier = modifier
    ) {
        Text(
            text = label,
            style = MaterialTheme.typography.labelLarge,
            modifier = Modifier.semantics { contentDescription = label }
        )
    }
}

Barrierefreiheit ist hier kein Nachgedanke: Die semantics-Definition gehört direkt zur Komponentenimplementierung, nicht zu einem späteren Accessibility-Nachbesserungs-Sprint.

In der Praxis

Der häufigste Fehler beim Einstieg ist das Token-Durchstechen: Statt MaterialTheme.colorScheme.primary zu verwenden, schreibt jemand Color(0xFF1A73E8) direkt in den Composable. Das funktioniert im ersten Moment – bis das Farbschema überarbeitet werden muss. Dann sucht man alle Stellen händisch.

Eine bewährte Regel für Code-Reviews lautet: Kein hartcodierter Designwert unterhalb der Token-Schicht. Farben, Abstände und Schriftgrößen gehören ausschließlich in Token-Objekte. Wird diese Regel konsequent durchgesetzt, bleibt das Design System langfristig wartbar.

Ein zweiter Stolperstein ist das unstrukturierte Wachsen des Token-Katalogs. Sobald ein Team anfängt, für jede Variante einen neuen primitiven Token anzulegen (Blue500, Blue501, Blue502…), geht der Überblick verloren. Halte primitive Tokens auf das Minimum der tatsächlichen Markenwerte; semantische Tokens bilden die Vielfalt der Verwendungsfälle ab.

Teste dein Design System mit der Compose-Testing-Bibliothek:

@Test
fun primaryButton_hasCorrectSemantics() {
    composeTestRule.setContent {
        AppTheme {
            PrimaryButton(label = "Anmelden", onClick = {})
        }
    }
    composeTestRule
        .onNodeWithContentDescription("Anmelden")
        .assertIsDisplayed()
        .assertHasClickAction()
}

Dieser Test prüft nicht nur die visuelle Darstellung, sondern gleichzeitig das Accessibility-Verhalten – beides mit einem einzigen Testlauf.

Fazit

Ein gut strukturiertes Design System ist kein optionaler Komfort, sondern eine Investition in Wartbarkeit, Konsistenz und Barrierefreiheit. Sobald Tokens und Komponenten sauber getrennt sind, wird ein Theme-Wechsel oder die Einführung von Dark Mode zu einer gezielten Änderung an wenigen Stellen, nicht zu einer Suche-und-Ersetze-Aktion im gesamten Projekt. Schau heute in deinen eigenen Code: Gibt es hartcodierte Farbwerte oder Abstände, die durch Token-Referenzen ersetzt werden könnten? Schreib anschließend einen Compose-Test für eine deiner Kernkomponenten, der sowohl die visuelle Korrektheit als auch die Accessibility-Semantiken überprüft – das ist der schnellste Weg, um die Qualität deines Design Systems messbar zu machen.

Quellen (6)
Redaktion

Geschrieben von

Redaktion

Das Redaktionsteam recherchiert und schreibt Artikel zu aktuellen Themen rund um Tech, Lifestyle und Ratgeber.