Pantrix UI

Card

Tek bir konuyu toplayan kapsayıcı: kendi yüzeyinde bir başlık, bir gövde ve eylemler, üstlerinde kenardan kenara duran bir görsel.

import com.pantrixui.components.container.card.PantrixCard

Örnekler

En yalın hâli

En az yazılan hâli: bir PantrixCard ve gövdesi. Varyant verilmedi, Elevated'dır. Gövdedeki satırlar alt alta durur, aralarında temanın küçük boşluğu vardır.

İlk karta genişlik verilmedi: en geniş satırı kadar geniştir. İkincisine fillMaxWidth() verildi ve bulunduğu yeri doldurur.

PantrixCard {
    PantrixText(text = "Haftalık özet", style = PantrixTheme.typography.title)
    PantrixText(text = "Üç yeni sipariş, bir iade")
}
PantrixCard(modifier = Modifier.fillMaxWidth()) {
    PantrixText(text = "Aylık özet", style = PantrixTheme.typography.title)
    PantrixText(text = "Genişlik verildi: kart bulunduğu yeri doldurur")
}

Üç varyant

variant kartın durduğu yerden nasıl ayrıldığını seçer. Elevated temanın surface rengindedir ve bir gölgeyle yükselir; iOS'ta gölgesi yoktur, kartı yalnızca yüzey rengi ayırır. Filled yükselmez, nötr rolün dolgusuyla ayrılır: zaten yükselmiş bir yüzeyin üstündeki kart içindir. Outlined temanın divider renginde ince bir kenarla çevrilir: çok gölgenin gürültüye dönüştüğü sık kart listeleri içindir.

PantrixCard(modifier = Modifier.fillMaxWidth(), variant = CardVariant.Elevated) {
    PantrixText(text = "Yükseltilmiş kart", style = PantrixTheme.typography.title)
    PantrixText(text = "Varsayılan varyant: gölgeyle ayrılır")
}
PantrixCard(modifier = Modifier.fillMaxWidth(), variant = CardVariant.Filled) {
    PantrixText(text = "Dolgulu kart", style = PantrixTheme.typography.title)
    PantrixText(text = "Gölge yerine renkle ayrılır")
}
PantrixCard(modifier = Modifier.fillMaxWidth(), variant = CardVariant.Outlined) {
    PantrixText(text = "Kenarlı kart", style = PantrixTheme.typography.title)
    PantrixText(text = "İnce bir kenarla ayrılır")
}

Görsel, başlık ve eylemler

Kartın üç yuvası. media en üstte, başlığın da üstünde durur ve kartın iç boşluğunu almaz: kartın kenarlarına kadar uzanır, köşelerini kart keser. header gövdenin üstündedir, çoğunlukla kartın başlığıdır. footer eylemleri bir satırda, kartın bitiş kenarında toplar; ana eylem sonda durur.

Karta genişlik verildiği için görsel o genişliğe yayılır ve eylemler bitiş kenarına yaslanır.

PantrixCard(
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    header = {
        PantrixText(
            text = "Compose Multiplatform",
            style = PantrixTheme.typography.title,
            role = TextRole.Heading(level = 3)
        )
    },
    media = {
        PantrixImage(
            painter = painterResource(Res.drawable.compose_multiplatform),
            modifier = Modifier.height(140.dp).background(PantrixTheme.colors.info.container),
            contentDescription = null
        )
    },
    footer = {
        PantrixButton(text = "Sonra", onClick = {}, variant = ButtonVariant.Text, tagKey = "article_later")
        PantrixButton(text = "Oku", onClick = {}, tagKey = "article_read")
    },
    tagKey = "article"
) {
    PantrixText(text = "Tek bir kod tabanıyla Android, iOS, masaüstü ve web.")
}

Bir satırda aynı boyda

Bir satırdaki kartlar en uzununun boyunda: satıra height(IntrinsicSize.Min), her karta weight(1f) ve fillMaxHeight() verildi. Yükseklik verilen kartın gövdesi onu doldurur: footer kartın dibinde durur, kısa açıklamalı planın düğmesi de. Gövdede Modifier.weight(1f) alan bir çocuk aradaki yeri alır ve fiyatı düğmenin üstüne iter.

Yükseklik verilmeyen bir kart içindekiler kadar uzundur ve footer gövdenin hemen altında durur.

Row(
    modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Min),
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.md)
) {
    PLANS.forEach { plan ->
        PantrixCard(
            modifier = Modifier.weight(1f).fillMaxHeight(),
            variant = CardVariant.Outlined,
            footer = { PantrixButton(text = "Seç", onClick = {}, tagKey = "plan_${plan.key}") },
            tagKey = "plan_${plan.key}"
        ) {
            PantrixText(text = plan.name, style = PantrixTheme.typography.title)
            PantrixText(text = plan.summary, color = PantrixTheme.colors.textSecondary)
            Spacer(Modifier.weight(1f))
            PantrixText(text = plan.price, style = PantrixTheme.typography.callout)
        }
    }
}

private val PLANS = listOf(
    Plan("solo", "Tek kişi", "Bir uygulama için.", "Ücretsiz"),
    Plan("team", "Ekip", "Beş kişiye kadar bir ekip, ortak bir tema ve paylaşılan bileşenler için.", "Aylık 400 ₺")
)

private class Plan(val key: String, val name: String, val summary: String, val price: String)

Tamamı tek bir düğme

onClick verilen kartın tamamı tek bir düğmedir. Bir şey açan kartı kurmanın erişilebilir yolu budur: ekran okuyucu tek bir hedef duyar, kartın yazısıyla ya da verildiyse contentDescription ile. İlk karta bas: uygulamanın snackbar'ı haber verir.

İkinci kartın enabled'ı false: basılamaz ve içindekilere temanın devre dışı rengini verir; basılamadığını yazısının bu rengi söyler. onClick'i olmayan bir kart enabled'a bakmaz.

val snackbars = LocalPantrixSnackbars.current
val scope = rememberCoroutineScope()
PantrixCard(
    modifier = Modifier.fillMaxWidth(),
    variant = CardVariant.Outlined,
    onClick = { scope.launch { snackbars?.show(message = "Sipariş #1043 açıldı", tagKey = "order_opened") } },
    contentDescription = "Sipariş 1043'ü aç",
    tagKey = "order_1043"
) {
    PantrixText(text = "Sipariş #1043", style = PantrixTheme.typography.title)
    PantrixText(text = "Kartın tamamı tek bir düğme", color = PantrixTheme.colors.textSecondary)
}
PantrixCard(modifier = Modifier.fillMaxWidth(), variant = CardVariant.Outlined, onClick = {}, enabled = false) {
    PantrixText(text = "Sipariş #1039", style = PantrixTheme.typography.title)
    PantrixText(text = "İptal edildi, açılamaz")
}

Kendi renkleriyle

colors karta varyantının değil, verilen renkleri verir; verilmeyen alan varyantınki kalır.

İlk karta yalnızca dolgu verildi ve o dolgu temanın bir rolünün rengi: tema, üstünde okunan rengi kendisi eşleştirir. İkincinin dolgusu temanın hiçbir rolünde yok, uygulamanın kendi moru: üstünde ne okunacağını tema bilemez, content de verilir. Üçüncü Outlined kartın yalnızca kenarı değişti.

val own = ownColors()
PantrixCard(
    modifier = Modifier.fillMaxWidth(),
    variant = CardVariant.Filled,
    colors = CardColors(container = PantrixTheme.colors.info.container)
) {
    PantrixText(text = "Yeni özellik", style = PantrixTheme.typography.title)
    PantrixText(text = "Yalnızca dolgu verildi, yazının rengini tema eşleştirdi")
}
PantrixCard(
    modifier = Modifier.fillMaxWidth(),
    variant = CardVariant.Filled,
    colors = CardColors(container = own.container, content = own.onContainer),
    tagKey = "own_colors"
) {
    PantrixText(text = "Üyelik", style = PantrixTheme.typography.title)
    PantrixText(text = "Dolgu da içeriğin rengi de verildi")
}
PantrixCard(
    modifier = Modifier.fillMaxWidth(),
    variant = CardVariant.Outlined,
    colors = CardColors(border = own.color)
) {
    PantrixText(text = "Seçili plan", style = PantrixTheme.typography.title)
    PantrixText(text = "Yalnızca kenarın rengi verildi")
}

Şekil, iç boşluk ve stil

shape tek bir kartın köşelerini değiştirir ve stilin köşesinin önüne geçer. contentPadding başlığın, gövdenin ve eylemlerin çevresindeki boşluktur; varsayılanı spacing.lg'dir, ikinci kartta spacing.sm verildi.

style kartın geometrisini değiştirir: son kartta CardStyle(elevation = 8.dp) ile daha derin bir gölge. Yalnızca verilen alan değişir ve her platformda değişir: bu kartın iOS'ta da gölgesi vardır.

PantrixCard(modifier = Modifier.fillMaxWidth(), shape = PantrixTheme.shapes.none) {
    PantrixText(text = "Köşeli", style = PantrixTheme.typography.title)
    PantrixText(text = "shape = PantrixTheme.shapes.none")
}
PantrixCard(
    modifier = Modifier.fillMaxWidth(),
    variant = CardVariant.Outlined,
    contentPadding = PaddingValues(PantrixTheme.spacing.sm)
) {
    PantrixText(text = "Dar iç boşluk", style = PantrixTheme.typography.title)
    PantrixText(text = "contentPadding = PaddingValues(PantrixTheme.spacing.sm)")
}
PantrixCard(modifier = Modifier.fillMaxWidth(), style = CardStyle(elevation = 8.dp)) {
    PantrixText(text = "Daha derin gölge", style = PantrixTheme.typography.title)
    PantrixText(text = "style = CardStyle(elevation = 8.dp)")
}

Veri gelene kadar: iskelet

"Yenile"ye bas: iki kart iki saniyeliğine iskeletleriyle yer değiştirir. PantrixCardSkeleton bir karta benzetilerek çizilmez, kartın kendi şekli, dolgusu, gölgesi, iç boşluğu ve aralıklarıyla kurulur. Çubukları, yerini tuttukları şeyin kapladığı yeri kaplar: veri gelince kartın yüksekliği değişmez ve altındaki hiçbir şey yerinden oynamaz.

İskelet kartın içinde ne olduğunu bilemez: showHeader, lines, footerButtons ve mediaHeight yerine geçtiği karta göre verilir. İlk kartın bir başlığı, bir satırı ve iki düğmesi var: lines = 1, footerButtons = 2.

"Kampanya" kartının dolgusu ve içeriğinin rengi dışarıdan verildi. İskeleti de kartın renklerini colors ile alır; çubukları skeletonColors ile verilen renkte çizilir.

val own = ownColors()
val campaign = CardColors(container = own.container, content = own.onContainer)
var loading by remember { mutableStateOf(false) }
LaunchedEffect(loading) {
    if (loading) {
        delay(2_000)
        loading = false
    }
}
if (loading) {
    PantrixCardSkeleton(modifier = Modifier.fillMaxWidth(), lines = 1, footerButtons = 2)
} else {
    PantrixCard(
        modifier = Modifier.fillMaxWidth(),
        header = {
            PantrixText(
                text = "Sipariş #1042",
                style = PantrixTheme.typography.title,
                role = TextRole.Heading(level = 3)
            )
        },
        footer = {
            PantrixButton(
                text = "Yenile",
                onClick = { loading = true },
                variant = ButtonVariant.Text,
                tagKey = "reload"
            )
            PantrixButton(text = "Takip et", onClick = {}, tagKey = "track")
        }
    ) {
        PantrixText(text = "İki ürün, perşembe günü teslim")
    }
}
if (loading) {
    PantrixCardSkeleton(
        modifier = Modifier.fillMaxWidth(),
        variant = CardVariant.Filled,
        colors = campaign,
        skeletonColors = SkeletonColors(base = own.onContainer.copy(alpha = 0.3f), highlight = own.container),
        lines = 1
    )
} else {
    PantrixCard(
        modifier = Modifier.fillMaxWidth(),
        variant = CardVariant.Filled,
        colors = campaign,
        tagKey = "campaign"
    ) {
        PantrixText(text = "Kampanya", style = PantrixTheme.typography.title)
        PantrixText(text = "Dolgusu ve içeriğinin rengi dışarıdan verildi")
    }
}

API

modifier

Tek bir konuyu toplayan kapsayıcı: kendi yüzeyinde bir başlık, bir gövde ve eylemler, üstlerinde kenardan kenara duran bir görsel.

ParametreTürVarsayılanNe olduğu
modifierModifierModifierKartın modifier'ı.
variantCardVariantCardVariant.ElevatedKartın durduğu yerden nasıl ayrıldığı: dolgusu, gölgesi ve kenarı.
onClick(() -> Unit)?nullVerildiğinde kartın tamamı tek bir düğme olur ve bir basış, varyantı taşıyan bir Card olayı olarak bildirilir.
enabledBooleantrueonClick'i olan bir karta basılıp basılamayacağı. onClick'i olmayan kart buna bakmaz.
styleCardStyle?nullBu çağrının kendi stili: çevresindeki her stili ezer, yoğunluk ona da uygulanır. Yalnızca verdiği alanlar değişir ve her platformda değişir.
shapeShapePantrixTheme.style(CardStyle, style).shape.toShape()Kartın köşeleri: varsayılanı, geçerli stilin köşeleridir. Burada verilen şekil, style'ın köşelerinin önüne geçer.
colorsCardColors?nullBu kartın kendi renkleri: verdiği renkler kullanılır, gerisi varyantınki kalır.
contentPaddingPaddingValuesPaddingValues(PantrixTheme.spacing.lg)Başlığın, gövdenin ve eylemlerin çevresindeki boşluk. Görsel bu boşluğu almaz.
header(@Composable () -> Unit)?nullGövdenin üstüne çizilir: çoğunlukla kartın başlığıdır.
media(@Composable () -> Unit)?nullİç boşluğu olan içeriğin üstüne, kenardan kenara çizilir; çünkü kartın iç boşluğu kadar içeri çekilmiş bir resim hata gibi görünür.
footer(@Composable RowScope.() -> Unit)?nullKartın eylemleri; bitiş kenarında bir satırda durur, ana eylem sondadır: orası telefonda başparmağa en yakın yer, geniş bir kartta da gözün okumayı bitirdiği yerdir. İçindekilerden uzun bir kartta kartın dibinde dururlar.
contentDescriptionString?nullEkran okuyucunun kart için söylediği. onClick'i olan bir kartta, kartın neyi açtığı yazılır.
tagKeyString?nullKartın otomasyon anahtarı: kart Card_<tagKey> olarak etiketlenir.
interactionSourceMutableInteractionSource?nullKartın dışarı taşınan etkileşimleri. Null olduğunda kart kendi kaynağını tutar.
content@Composable ColumnScope.() -> UnitKartın gövdesi: çocuklarının arasında spacing.sm olan bir sütunda durur. Ağırlık verilen bir çocuk, kartın yüksekliğinin bıraktığı yeri alır.

CardStyle

PantrixCard'ın geometrisi: köşeleri ve yükseltilmiş varyantının gölgesi.

ParametreTürVarsayılanNe olduğu
shapeShapeSpecShapeSpec.UnspecifiedKartın köşeleri: Android'de orta, iOS'ta büyük, masaüstünde ve web'de küçük.
elevationDpDp.UnspecifiedCardVariant.Elevated'ın altındaki gölge: Android'de 2dp, iOS'ta yok, masaüstünde ve web'de 1dp. Öteki varyantlar gölge çizmez.

CardColors

Varyantının renklerini almayan bir PantrixCard'ın boyandığı renkler: verilen renk kullanılır, verilmeyen varyantınki kalır.

ParametreTürVarsayılanNe olduğu
containerColorColor.UnspecifiedKartın dolgusu. Temanın surface'ıdır; bir CardVariant.Filled kartta nötr rolün container'ıdır.
contentColorColor.UnspecifiedKartın içindekilerin, bir çocuk kendi rengini vermedikçe, çizildiği renk: container üstünde okunan renk. Temanın surface'ı üstünde yoktur: orada her çocuk kendi varsayılanıyla çizilir, bir metin textPrimary ile. Dolgulu bir kartta nötr rolün onContainer'ıdır.
borderColorColor.UnspecifiedKartın çevresindeki ince kenar. Bir CardVariant.Outlined kartta temanın divider'ıdır; o karta temanın zeminlerinden olmayan, o çizginin okunmayacağı bir dolgu verildiğinde ise orada yazılan rengin bir payıdır: Subtle düğmenin kenarı gibi. Öteki varyantların, burada verilmedikçe, ince kenarı yoktur.