Anjuran dan larangan penggunaan Gaya

Halaman ini menjelaskan praktik terbaik untuk menggunakan gaya yang mencapai konsistensi di seluruh codebase Anda, serta prinsip yang kami ikuti saat mendesain API.

Anjuran

Ikuti praktik terbaik berikut:

Anjuran: Menggunakan Gaya untuk visual dan pengubah untuk perilaku

Gunakan Styles API untuk konfigurasi visual (latar belakang, padding, batas), dan sediakan pengubah untuk perilaku seperti logika klik, deteksi gestur, atau aksesibilitas.

Anjuran: Mengekspos parameter Gaya dalam sistem desain

Untuk komponen sistem desain kustom Anda sendiri, Anda harus mengekspos objek Style setelah parameter pengubah.

@Composable
fun GradientButton(
    modifier: Modifier = Modifier,
    // ✅ DO: for design system components, expose a style modifier to consumers to be able to customize the components
    style: Style = Style
) {
    // Consume the style
}

Anjuran: Mengganti parameter berbasis visual dengan Gaya

Pertimbangkan untuk mengganti parameter pada composable Anda dengan satu parameter Style. Contoh:

// Before
@Composable
fun OldButton(background: Color, fontColor: Color) {
}

// After
// ✅ DO: Replace visual-based parameters with a style that includes same properties
@Composable
fun NewButton(style: Style = Style) {
}

Anjuran: Memprioritaskan Gaya untuk animasi

Gunakan blok animate bawaan untuk gaya berbasis status dengan animasi untuk peningkatan performa dibandingkan pengubah.

Anjuran: Memanfaatkan "Last-write-wins"

Manfaatkan fakta bahwa properti style menimpa, bukan menumpuk. Gunakan ini untuk mengganti batas atau latar belakang komponen default tanpa memerlukan beberapa parameter.

Larangan

Pola berikut tidak dianjurkan:

Larangan: Menggunakan Gaya untuk logika interaksi

Jangan mencoba menangani onClick atau deteksi gestur dalam gaya. Gaya terbatas pada konfigurasi visual berdasarkan status, sehingga tidak boleh menangani logika bisnis; sebagai gantinya, gaya hanya boleh memiliki visual yang berbeda berdasarkan status.

Larangan: Menyediakan gaya default sebagai parameter default

Parameter gaya harus selalu dideklarasikan menggunakan style: Style = Style:

@Composable
fun BadButton(
    modifier: Modifier = Modifier,
    // ❌ DON'T set a default style here as a parameter
    style: Style = Style { background(Color.Red) }
) {
}

Untuk menyertakan parameter "default", gabungkan gaya parameter masuk dengan default yang ditentukan:

@Composable
fun GoodButton(
    modifier: Modifier = Modifier,
    // ✅ Do: always pass it as a Style, do not pass other defaults
    style: Style = Style
) {
    // ...
    val defaultStyle = Style { background(Color.Red) }
    // ✅ Do Combine defaults inside with incoming parameter
    Box(modifier = modifier.styleable(styleState, defaultStyle, style)) {
      // your logic
    }
}

Larangan: Menyediakan parameter gaya ke composable berbasis tata letak

Meskipun Anda dapat memberikan gaya ke composable apa pun, composable berbasis tata letak, atau composable tingkat layar, tidak diharapkan untuk menerima gaya. Dari sudut pandang konsumen, tidak jelas apa yang akan dilakukan gaya pada tingkat ini. Gaya dirancang untuk komponen, bukan tata letak.

Larangan: Membuat gaya dalam Komposisi

CompositionLocals dibaca pada titik gaya ditentukan, bukan tempat gaya digunakan. Saat gaya benar-benar digunakan, status CompositionLocal dapat berubah, sehingga menghasilkan gaya yang tidak akurat.

// DON'T - Create styles in Composition that access composition locals in this way - this will likely lead to issues when style is used / accessed, as it would not get updated when the value changes.
@Composable
fun containerStyle(): Style {
    val background = MaterialTheme.colorScheme.background
    val onBackground = MaterialTheme.colorScheme.onBackground
    return Style {
        background(background)
        contentColor(onBackground)
    }
}

// Do: Instead, Create StyleScope extension functions for your subsystems to access themed composition Locals
val StyleScope.colors: JetsnackColors
    get() = JetsnackTheme.LocalJetsnackTheme.currentValue.colors

val StyleScope.typography: androidx.compose.material3.Typography
    get() = JetsnackTheme.LocalJetsnackTheme.currentValue.typography
val StyleScope.shapes: Shapes
    get() = JetsnackTheme.LocalJetsnackTheme.currentValue.shapes
// Access CompositionLocals
val button = Style {
    background(colors.brandSecondary)
    shape(shapes.small)
}

Anjuran: Membuat satu gaya untuk perubahan nilai subsistem

Misalnya, jika beralih antara mode gelap dan terang, kueri nilai bertema yang ada (melalui CompositionLocal) untuk mengubah Style secara dinamis:

// Do: Use CompositionLocals or themed values to create a single style
val buttonStyle = Style {
    background(colors.brandSecondary)
    shape(shapes.small)
}

Anjuran: Mengganti seluruh Gaya saat komponen pada dasarnya berbeda di seluruh definisi tema

Anda dapat mengganti seluruh objek gaya di tingkat tema jika tema tersebut pada dasarnya berbeda.

Misalnya, jika Anda membuat aplikasi yang memiliki tema berbeda per produk/halaman atau penawaran, dan banyak properti untuk Gaya yang berbeda, mengganti seluruh kumpulan gaya di tingkat tema dapat diterima.

// DO Switch out whole styles when many properties differ - if Product A and Product B are two white labelled apps that provide different Themes.
val productBThemedButton = Style {
    shape(shapes.small)
    background(colors.brandSecondary)
    // other properties are fundamentally different
}

val productAThemedButton = Style {
    shape(shapes.large)
    background(colors.brand)
    // other properties are fundamentally different
}