Pantrix UI

Select

Kontrolün açtığı bir listeden tek bir seçim: bir ülke, bir para birimi, bir plan.

import com.pantrixui.components.overlay.select.PantrixSelect

Örnekler

Tek seçim

En yalın hâli: seçenekler, selected ve onSelect. Kutu seçileni, hiçbir şey seçili değilken placeholder'ı gösterir; label kutunun üstünde, supportingText altındadır.

Kutuya bas: liste altında, kutuyla aynı genişlikte açılır ve kutu odaklı bir alan gibi çizilir. Bir seçeneğe basmak seçer ve kapatır; dışına basmak, geri tuşu ve Escape yalnızca kapatır. Kartın "Son olay" satırı onSelect'in en son ne istediğini yazar; öteki örneklerin çoğunda da aynı satır vardır.

var country by rememberSaveable { mutableStateOf<String?>(null) }
val report = LocalExampleEvents.current
PantrixSelect(
    options = COUNTRIES,
    selected = country,
    onSelect = { code ->
        country = code
        report("Ülke seçildi: ${COUNTRIES.first { it.value == code }.label}")
    },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Ülke",
    placeholder = "Bir ülke seçin",
    supportingText = "Faturanız bu ülkenin vergisiyle kesilir.",
    tagKey = "country"
)

private val COUNTRIES = listOf(
    SelectOption(value = "tr", label = "Türkiye", tagKey = "tr"),
    SelectOption(value = "de", label = "Almanya", tagKey = "de"),
    SelectOption(value = "gb", label = "Birleşik Krallık", tagKey = "gb"),
    SelectOption(value = "jp", label = "Japonya", tagKey = "jp"),
    SelectOption(value = "us", label = "Amerika Birleşik Devletleri", tagKey = "us")
)

Aranabilir

searchable = true listeye bir arama alanı koyar: yazdıkça seçenekler, etiketinde yazılanı taşıyanlara daralır ve liste kalan satırlar kadar kısalır. searchPlaceholder alanın boşken gösterdiği yazıdır.

Odak arama alanında kalır: oklar eşleşen satırlar arasında bir işareti gezdirir, klavyenin onay tuşu işaretli satırı seçer. Bir şey yazılır yazılmaz işaret ilk eşleşendedir. Masaüstünde ve masaüstündeki bir tarayıcıda alan liste açılınca odağı alır; telefonda ve tablette dokunulmasını bekler. Klavye açılınca liste kutunun altında kalır ve kısalır.

var language by rememberSaveable { mutableStateOf<String?>(null) }
val report = LocalExampleEvents.current
PantrixSelect(
    options = LANGUAGES,
    selected = language,
    onSelect = { name ->
        language = name
        report("Dil seçildi: $name")
    },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Dil seçiniz (Aranabilir)",
    placeholder = "Bir dil seçin",
    searchable = true,
    searchPlaceholder = "Dil ara…",
    tagKey = "language"
)

private val LANGUAGES = listOf(
    SelectOption(value = "Kotlin", label = "Kotlin", tagKey = "kotlin"),
    SelectOption(value = "Java", label = "Java", tagKey = "java"),
    SelectOption(value = "Swift", label = "Swift", tagKey = "swift"),
    SelectOption(value = "Dart", label = "Dart", tagKey = "dart"),
    SelectOption(value = "TypeScript", label = "TypeScript", tagKey = "typescript"),
    SelectOption(value = "JavaScript", label = "JavaScript", tagKey = "javascript"),
    SelectOption(value = "Python", label = "Python", tagKey = "python"),
    SelectOption(value = "Go", label = "Go", tagKey = "go"),
    SelectOption(value = "Rust", label = "Rust", tagKey = "rust"),
    SelectOption(value = "C#", label = "C#", tagKey = "csharp"),
    SelectOption(value = "Ruby", label = "Ruby", tagKey = "ruby")
)

Kısmi devre dışı

SelectOption(enabled = false) tek bir seçeneği kapatır. Seçenek listede kalır ve okunur, ama devre dışı renkle yazılır, basılmaz ve klavye onu atlar: seçilemeyen şey de orada olduğu bilinsin diye listeden çıkarılmaz.

var option by rememberSaveable { mutableStateOf<String?>(null) }
val report = LocalExampleEvents.current
PantrixSelect(
    options = PARTLY_DISABLED,
    selected = option,
    onSelect = { value ->
        option = value
        report("Seçildi: ${PARTLY_DISABLED.first { it.value == value }.label}")
    },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Seçenek",
    placeholder = "Bir seçenek seçin",
    tagKey = "partly_disabled"
)

private val PARTLY_DISABLED = listOf(
    SelectOption(value = "active_1", label = "Aktif Seçenek 1", tagKey = "active_1"),
    SelectOption(value = "disabled_1", label = "Devre Dışı Seçenek", enabled = false, tagKey = "disabled_1"),
    SelectOption(value = "active_2", label = "Aktif Seçenek 2", tagKey = "active_2"),
    SelectOption(value = "disabled_2", label = "Devre Dışı Seçenek 2", enabled = false, tagKey = "disabled_2")
)

Simgeli seçenekler

SelectOption(icon = …) seçeneğin başına bir ikon koyar: ikon etiketin rengindedir ve ekran okuyucu onu atlar. Seçili satır dolgusuyla ve sonundaki onay işaretiyle belli olur. Kutu yalnızca seçilenin etiketini yazar.

var folder by rememberSaveable { mutableStateOf<String?>("documents") }
val report = LocalExampleEvents.current
PantrixSelect(
    options = FOLDERS,
    selected = folder,
    onSelect = { value ->
        folder = value
        report("Klasör seçildi: ${FOLDERS.first { it.value == value }.label}")
    },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Klasör",
    tagKey = "folder"
)

private val FOLDERS = listOf(
    SelectOption(value = "documents", label = "Belgeler", icon = PantrixIcons.Folder, tagKey = "documents"),
    SelectOption(value = "favourites", label = "Sık kullanılanlar", icon = PantrixIcons.Star, tagKey = "favourites"),
    SelectOption(value = "inbox", label = "Gelen kutusu", icon = PantrixIcons.Inbox, tagKey = "inbox")
)

Çalışma alanı seçici

Bu bir PantrixSelect değil. PantrixSelect'in seçenekleri tek satırlık bir etiket ve bir ikondur; avatar, alt metin ve alttaki eylem satırı gerektiğinde seçici PantrixPopover ile kurulur ve bunlar popover'ın içeriği olarak yazılır: PantrixTextField, PantrixAvatar ve PantrixDivider ile.

Tetikleyici bir avatar, ad ve plan satırıdır. Açılan panelde bir arama alanı, bir başlık, avatarlı ve alt metinli satırlar, seçili satırın sonunda onay işareti ve en altta yeni bir çalışma alanı açan satır vardır. Bir satıra basmak onu seçer ve paneli kapatır; arama, panel her açıldığında boş başlar.

var open by rememberSaveable { mutableStateOf(false) }
var currentId by rememberSaveable { mutableStateOf(WORKSPACES.first().id) }
val report = LocalExampleEvents.current
val query = rememberTextFieldState()
val current = WORKSPACES.first { it.id == currentId }
val typed = query.text.toString().trim()
val shown = WORKSPACES.filter { it.name.contains(typed, ignoreCase = true) }
PantrixPopover(
    visible = open,
    onDismissRequest = {
        open = false
        report("Çalışma alanı paneli kapatıldı")
    },
    anchor = {
        SelectWorkspaceTrigger(
            workspace = current,
            onClick = {
                // Arama panel açılırken boşalır, kapanırken değil: panel solarken içindeki liste yerinden oynamaz.
                query.clearText()
                open = true
            }
        )
    },
    alignment = PopoverAlignment.Start,
    style = PopoverStyle(minWidth = 280.dp, maxWidth = 280.dp),
    tagKey = "workspace"
) {
    PantrixTextField(
        state = query,
        modifier = Modifier.fillMaxWidth(),
        placeholder = "Çalışma alanı ara…",
        contentDescription = "Çalışma alanı ara",
        tagKey = "workspace_search"
    )
    PantrixText(
        text = "Çalışma alanları",
        style = PantrixTheme.typography.label,
        color = PantrixTheme.colors.textSecondary
    )
    if (shown.isEmpty()) {
        PantrixText(text = "Eşleşen çalışma alanı yok", color = PantrixTheme.colors.textSecondary)
    }
    shown.forEach { workspace ->
        SelectWorkspaceRow(workspace = workspace, selected = workspace.id == currentId) {
            currentId = workspace.id
            open = false
            report("Çalışma alanı: ${workspace.name}")
        }
    }
    PantrixDivider()
    SelectWorkspaceCreateRow {
        open = false
        report("Çalışma alanı oluştur'a basıldı")
    }
}

@Composable
private fun SelectWorkspaceTrigger(
    workspace: SelectWorkspace,
    onClick: () -> Unit
) {
    val spacing = PantrixTheme.spacing
    Row(
        modifier = Modifier
            .widthIn(max = 280.dp)
            .fillMaxWidth()
            .clip(PantrixTheme.shapes.md)
            .testTag("workspace_trigger")
            .clickable(role = Role.DropdownList, onClick = onClick)
            .padding(spacing.sm),
        horizontalArrangement = Arrangement.spacedBy(spacing.sm),
        verticalAlignment = Alignment.CenterVertically
    ) {
        PantrixAvatar(contentDescription = null, initials = workspace.initials, tone = AvatarTone.Primary)
        Column(modifier = Modifier.weight(1f)) {
            PantrixText(text = workspace.name, style = PantrixTheme.typography.label, maxLines = 1)
            PantrixText(
                text = workspace.plan,
                style = PantrixTheme.typography.footnote,
                color = PantrixTheme.colors.textSecondary
            )
        }
        PantrixIcon(
            imageVector = PantrixIcons.ChevronDown,
            contentDescription = null,
            tint = PantrixTheme.colors.textSecondary
        )
    }
}

@Composable
private fun SelectWorkspaceRow(
    workspace: SelectWorkspace,
    selected: Boolean,
    onClick: () -> Unit
) {
    val spacing = PantrixTheme.spacing
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clip(PantrixTheme.shapes.md)
            .testTag("workspace_${workspace.id}")
            .selectable(selected = selected, role = Role.RadioButton, onClick = onClick)
            .padding(vertical = spacing.xs),
        horizontalArrangement = Arrangement.spacedBy(spacing.sm),
        verticalAlignment = Alignment.CenterVertically
    ) {
        PantrixAvatar(contentDescription = null, initials = workspace.initials, tone = AvatarTone.Primary)
        Column(modifier = Modifier.weight(1f)) {
            PantrixText(text = workspace.name, style = PantrixTheme.typography.label, maxLines = 1)
            PantrixText(
                text = "${workspace.projects} proje",
                style = PantrixTheme.typography.footnote,
                color = PantrixTheme.colors.textSecondary
            )
        }
        if (selected) {
            PantrixIcon(
                imageVector = PantrixIcons.Check,
                contentDescription = null,
                tint = PantrixTheme.colors.primary.color
            )
        }
    }
}

@Composable
private fun SelectWorkspaceCreateRow(onClick: () -> Unit) {
    val spacing = PantrixTheme.spacing
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clip(PantrixTheme.shapes.md)
            .testTag("workspace_create")
            .clickable(role = Role.Button, onClick = onClick)
            .padding(vertical = spacing.sm),
        horizontalArrangement = Arrangement.spacedBy(spacing.sm),
        verticalAlignment = Alignment.CenterVertically
    ) {
        PantrixIcon(imageVector = PantrixIcons.Plus, contentDescription = null)
        PantrixText(text = "Çalışma alanı oluştur", style = PantrixTheme.typography.label)
    }
}

private class SelectWorkspace(
    val id: String,
    val name: String,
    val initials: String,
    val plan: String,
    val projects: Int
)

private val WORKSPACES = listOf(
    SelectWorkspace(id = "rorty_live", name = "Rorty LIVE", initials = "RL", plan = "ücretsiz", projects = 4),
    SelectWorkspace(id = "rorty_staging", name = "Rorty Staging", initials = "RS", plan = "ücretsiz", projects = 2),
    SelectWorkspace(id = "pantrix_labs", name = "Pantrix Labs", initials = "PL", plan = "pro", projects = 7)
)

Form alanı

field alan PantrixSelect bir formun alanına bağlıdır: alanın değeri seçimdir, hatası yardım metninin yerini alır, kimliği otomasyon anahtarıdır (Select_plan). Yapılması zorunlu bir seçim, null ile başlayan bir alan ve Rules.required ile kurulur.

Bir şey seçmeden "Gönder"e bas: kuralın mesajı yardım metninin yerine geçer ve odak select'e gelir. Seçim alanı değiştirir ve "dokunuldu" sayar: bir plan seçilince mesaj kalkar. "Sıfırla" formu başa döndürür.

val form = rememberFormState()
val scope = rememberCoroutineScope()
val plan = form.field<String?>("plan", initial = null, Rules.required("Devam etmek için bir plan seçin"))
val report = LocalExampleEvents.current
PantrixSelect(
    field = plan,
    options = PLANS,
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Plan",
    placeholder = "Bir plan seçin",
    supportingText = "Sonradan değiştirebilirsiniz."
)
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
    PantrixButton(
        text = "Gönder",
        onClick = {
            scope.launch {
                form.submit { report("Form gönderildi: ${PLANS.first { it.value == plan.value }.label}") }
            }
        },
        form = form,
        tagKey = "submit_plan"
    )
    PantrixButton(
        text = "Sıfırla",
        onClick = {
            form.reset()
            report("Form sıfırlandı")
        },
        variant = ButtonVariant.Text,
        tagKey = "reset_plan"
    )
}

private val PLANS = listOf(
    SelectOption(value = "free", label = "Ücretsiz", tagKey = "free"),
    SelectOption(value = "pro", label = "Pro", tagKey = "pro"),
    SelectOption(value = "team", label = "Takım", tagKey = "team")
)

Hata ve devre dışı

error = true kutunun kenarını, etiketini ve alttaki metni temanın danger rolüne çevirir; alttaki metin ekran okuyucuya hata olarak söylenir. enabled = false kutuyu devre dışı renklerle çizer: kutu odak almaz ve liste açılmaz.

İkisi de bir metin alanının o hâllerindeki gibi çizilir. Devre dışı select neyin seçili olduğunu yine gösterir.

PantrixSelect(
    options = PLANS,
    selected = null,
    onSelect = {},
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Plan",
    placeholder = "Bir plan seçin",
    supportingText = "Devam etmek için bir plan seçin",
    error = true,
    tagKey = "plan_in_error"
)
PantrixSelect(
    options = PLANS,
    selected = "team",
    onSelect = {},
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    enabled = false,
    label = "Plan",
    supportingText = "Planı yalnızca yönetici değiştirebilir.",
    tagKey = "plan_disabled"
)

private val PLANS = listOf(
    SelectOption(value = "free", label = "Ücretsiz", tagKey = "free"),
    SelectOption(value = "pro", label = "Pro", tagKey = "pro"),
    SelectOption(value = "team", label = "Takım", tagKey = "team")
)

Uzun liste

Seçenekler listenin en çok yüksekliğini aşınca liste içinde kayar. Liste, seçili satır ortasına yakın görünecek biçimde açılır: burada altmış yılın otuz altıncısı seçilidir ve liste oraya kaymış olarak gelir.

Klavyeyle açıldığında odak seçili satırdadır. Dokunarak ya da tıklayarak açıldığında hiçbir satır odağı göstermez; ilk ok tuşu seçili satırdan devam eder.

var year by rememberSaveable { mutableStateOf<Int?>(1995) }
val report = LocalExampleEvents.current
PantrixSelect(
    options = YEARS,
    selected = year,
    onSelect = {
        year = it
        report("Yıl seçildi: $it")
    },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Doğum yılı",
    tagKey = "year"
)

private val YEARS = (1960..2019).map { year ->
    SelectOption(value = year, label = year.toString(), tagKey = year.toString())
}

Genişlik

Genişlik verilmeyen select bir metin alanının en az genişliğindedir: ilk kutu böyledir. Bir satırda Modifier.weight(1f) ile satırdaki payı kadar geniş olur: ortadaki iki kutu satırı paylaşır.

Alttaki kutuya Modifier.width(IntrinsicSize.Max) verildi: select'e ne kadar geniş olacağı sorulur ve select seçeneklerinin gerektirdiğini söyler. Kutu en uzun seçeneği kadar geniştir, daha fazla değil; hangisi seçilirse seçilsin aynı kalır. Bir araç çubuğundaki ya da bir tablonun ayağındaki select böyle kurulur: PantrixPageSize'ın select'i de budur. Başka bir para birimi seç: kutu yerinde durur.

Liste her zaman kutusu kadardır. Kutuya sığmayan etiket tek satırda kesilir; seçenekleri kadar geniş olan kutuda hiçbir seçenek kesilmez, listedeki satırında da.

var alone by rememberSaveable { mutableStateOf<String?>("usd") }
var from by rememberSaveable { mutableStateOf<String?>("try") }
var to by rememberSaveable { mutableStateOf<String?>("eur") }
var fitted by rememberSaveable { mutableStateOf<String?>("gbp") }
val report = LocalExampleEvents.current
PantrixSelect(
    options = CURRENCIES,
    selected = alone,
    onSelect = { code ->
        alone = code
        report("Para birimi: ${CURRENCIES.first { it.value == code }.label}")
    },
    label = "Para birimi",
    tagKey = "currency"
)
Row(
    modifier = Modifier.widthIn(max = 480.dp).fillMaxWidth(),
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)
) {
    PantrixSelect(
        options = CURRENCIES,
        selected = from,
        onSelect = { code ->
            from = code
            report("Kaynak para birimi: ${CURRENCIES.first { it.value == code }.label}")
        },
        modifier = Modifier.weight(1f),
        label = "Kaynak",
        tagKey = "currency_from"
    )
    PantrixSelect(
        options = CURRENCIES,
        selected = to,
        onSelect = { code ->
            to = code
            report("Hedef para birimi: ${CURRENCIES.first { it.value == code }.label}")
        },
        modifier = Modifier.weight(1f),
        label = "Hedef",
        tagKey = "currency_to"
    )
}
PantrixSelect(
    options = CURRENCIES,
    selected = fitted,
    onSelect = { code ->
        fitted = code
        report("Seçenekleri kadar geniş kutuda: ${CURRENCIES.first { it.value == code }.label}")
    },
    modifier = Modifier.width(IntrinsicSize.Max),
    contentDescription = "Para birimi",
    tagKey = "currency_fitted"
)

private val CURRENCIES = listOf(
    SelectOption(value = "try", label = "Türk lirası", tagKey = "try"),
    SelectOption(value = "eur", label = "Euro", tagKey = "eur"),
    SelectOption(value = "usd", label = "Amerikan doları", tagKey = "usd"),
    SelectOption(value = "gbp", label = "İngiliz sterlini", tagKey = "gbp")
)

Etiketsiz

Bir araç çubuğundaki ya da bir listenin başındaki select'in etiketi olmaz. Adını ekran okuyucuya contentDescription söyler; açılan liste de o adla duyurulur.

Etiket verilmediğinde kutunun üstünde yer ayrılmaz: select yalnızca kutusu kadar yer tutar.

var sort by rememberSaveable { mutableStateOf<String?>("newest") }
PantrixSelect(
    options = listOf(
        SelectOption(value = "newest", label = "En yeni", tagKey = "newest"),
        SelectOption(value = "cheapest", label = "En ucuz", tagKey = "cheapest"),
        SelectOption(value = "nearest", label = "En yakın", tagKey = "nearest")
    ),
    selected = sort,
    onSelect = { sort = it },
    contentDescription = "Sıralama",
    tagKey = "sort"
)

Kendi renkleri

colors listenin, fieldColors kutunun renkleridir; ikisi de yalnızca verilen alanları değiştirir, verilmeyen temanın kalır. Burada seçili satırın dolgusu ve yazısı (SelectColors) ile kutunun odaklı kenarı (TextFieldColors) uygulamanın kendi rengindedir.

Listeyi aç: kutunun kenarı uygulamanın morundadır, seçili satır da o morun yumuşak dolgusunda. Devre dışı bir select, renk verilse de temanın devre dışı renkleriyle çizilir.

val own = ownColors()
var plan by rememberSaveable { mutableStateOf<String?>("pro") }
val report = LocalExampleEvents.current
PantrixSelect(
    options = PLANS,
    selected = plan,
    onSelect = { value ->
        plan = value
        report("Plan seçildi: ${PLANS.first { it.value == value }.label}")
    },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Plan",
    colors = SelectColors(selectedContainer = own.container, selectedContent = own.onContainer),
    fieldColors = TextFieldColors(focusedBorder = own.color),
    tagKey = "own_plan"
)

private val PLANS = listOf(
    SelectOption(value = "free", label = "Ücretsiz", tagKey = "free"),
    SelectOption(value = "pro", label = "Pro", tagKey = "pro"),
    SelectOption(value = "team", label = "Takım", tagKey = "team")
)

Stil

style listenin, fieldStyle kutunun geometrisidir. Burada listenin satırları 56dp'dir (itemHeight), liste en çok 180dp olur ve sığmayan seçenekler içinde kayar (maxHeight), kutuyla arasında 12dp boşluk vardır (gap). Kutunun köşeleri tam yuvarlaktır: TextFieldStyle(shape = ShapeRole.Full).

Yalnızca verilen alanlar değişir; gerisi temanın ve platformun stilinden gelir. Liste, stil ne derse desin kutusu kadar geniştir ve bir satır platformun dokunma hedefinden kısa olmaz.

var currency by rememberSaveable { mutableStateOf<String?>("try") }
PantrixSelect(
    options = CURRENCIES,
    selected = currency,
    onSelect = { currency = it },
    modifier = Modifier.widthIn(max = 360.dp).fillMaxWidth(),
    label = "Para birimi",
    style = SelectStyle(maxHeight = 180.dp, gap = 12.dp, itemHeight = 56.dp),
    fieldStyle = TextFieldStyle(shape = ShapeRole.Full),
    tagKey = "styled_currency"
)

private val CURRENCIES = listOf(
    SelectOption(value = "try", label = "Türk lirası", tagKey = "try"),
    SelectOption(value = "eur", label = "Euro", tagKey = "eur"),
    SelectOption(value = "usd", label = "Amerikan doları", tagKey = "usd"),
    SelectOption(value = "gbp", label = "İngiliz sterlini", tagKey = "gbp")
)

Dialog içinde

Bir dialog'un içindeki select: liste dialog'un üstünde açılır. Escape ve geri tuşu önce listeyi kapatır, dialog açık kalır; dialog ikinci basışta kapanır.

"Adresi düzenle"ye bas, listeyi aç ve Escape'e iki kez bas: önce liste, sonra dialog kapanır. Buradaki select aranabilirdir.

var dialog by rememberSaveable { mutableStateOf(false) }
var country by rememberSaveable { mutableStateOf<String?>("tr") }
val report = LocalExampleEvents.current
PantrixButton(
    text = "Adresi düzenle",
    onClick = { dialog = true },
    variant = ButtonVariant.Outline,
    tagKey = "open_address_dialog"
)
PantrixDialog(
    visible = dialog,
    onDismissRequest = {
        dialog = false
        report("Adres penceresi kapatıldı")
    },
    title = "Teslimat adresi",
    message = "Siparişin gönderileceği ülkeyi seçin.",
    actions = {
        PantrixButton(
            text = "Tamam",
            onClick = {
                dialog = false
                report("Adres penceresi kapatıldı")
            },
            variant = ButtonVariant.Text,
            tagKey = "close_address_dialog"
        )
    },
    tagKey = "address_dialog"
) {
    PantrixSelect(
        options = COUNTRIES,
        selected = country,
        onSelect = { code ->
            country = code
            report("Teslimat ülkesi: ${COUNTRIES.first { it.value == code }.label}")
        },
        modifier = Modifier.fillMaxWidth(),
        label = "Ülke",
        searchable = true,
        searchPlaceholder = "Ülke ara…",
        tagKey = "delivery_country"
    )
}

private val COUNTRIES = listOf(
    SelectOption(value = "tr", label = "Türkiye", tagKey = "tr"),
    SelectOption(value = "de", label = "Almanya", tagKey = "de"),
    SelectOption(value = "gb", label = "Birleşik Krallık", tagKey = "gb"),
    SelectOption(value = "jp", label = "Japonya", tagKey = "jp"),
    SelectOption(value = "us", label = "Amerika Birleşik Devletleri", tagKey = "us")
)

Dar pencerede sheet

presentation = OverlayPresentation.Adaptive: dar bir pencerede liste alttan bir sheet'tir, başlığı alanın etiketi, satırları sheet kadar geniş; daha geniş pencerede kutunun altında. "Dar"ı seç ve alana bas. Varsayılan her pencerede kutunun altıdır; PantrixMultiSelect de aynı parametreyi alır.

var city by rememberSaveable { mutableStateOf<String?>(null) }
// Kartın penceresi örnek kadar uzundur: dar bir pencerede açılan sheet'e yer kalsın diye örnek uzun tutulur.
Column(Modifier.fillMaxWidth().height(400.dp)) {
    PantrixSelect(
        options = listOf("İstanbul", "Ankara", "İzmir", "Bursa", "Antalya").map {
            SelectOption(value = it, label = it)
        },
        selected = city,
        onSelect = { city = it },
        modifier = Modifier.fillMaxWidth(),
        label = "Şehir",
        tagKey = "adaptive_city",
        presentation = OverlayPresentation.Adaptive
    )
}

Başka temadaki bir bölümde

Liste, çağrıldığı temanın renklerindedir. Buradaki bölüm sayfanın tersi renkte ikinci bir temadır (PantrixTheme(darkTheme = …)): sayfa açıksa koyu, koyuysa açık. Select o temanın içinde çağrıldığı için kutusu da açılan listesi de onun renklerindedir.

Tema bir zemin çizmez: bölümün zemini, temanın içindeki PantrixSurface'tir. Bu, sayfanın son örneğidir: altında yer kalmayınca liste kutunun üstünde açılır.

var plan by rememberSaveable { mutableStateOf<String?>(null) }
val report = LocalExampleEvents.current
val pageIsDark = PantrixTheme.colors.background.luminance() < 0.5f
PantrixTheme(darkTheme = !pageIsDark) {
    PantrixSurface(modifier = Modifier.widthIn(max = 392.dp).fillMaxWidth()) {
        Column(modifier = Modifier.padding(PantrixTheme.spacing.md)) {
            PantrixSelect(
                options = PLANS,
                selected = plan,
                onSelect = { value ->
                    plan = value
                    report("Bölümde plan seçildi: ${PLANS.first { it.value == value }.label}")
                },
                modifier = Modifier.fillMaxWidth(),
                label = "Plan",
                placeholder = "Bir plan seçin",
                tagKey = "plan_in_part"
            )
        }
    }
}

private val PLANS = listOf(
    SelectOption(value = "free", label = "Ücretsiz", tagKey = "free"),
    SelectOption(value = "pro", label = "Pro", tagKey = "pro"),
    SelectOption(value = "team", label = "Takım", tagKey = "team")
)

API

options

Kontrolün açtığı bir listeden tek bir seçim: bir ülke, bir para birimi, bir plan.

ParametreTürVarsayılanNe olduğu
optionsList<SelectOption<T>>Seçenekler, gösterildikleri sırayla. Hiç seçenek yoksa liste bunu söyler.
selectedT?Şu an seçili olan: değeri buna eşit olan ilk seçenek. Hiçbir seçenekte olmayan bir değer, hiçbir şeyin seçili olmadığı anlamına gelir. Onu temsil eden bir seçenek yoksa null da öyledir.
onSelect(T) -> UnitYeni bir seçim istemek için seçeneğin değeriyle çağrılır. Seçili olan yeniden seçilince de çağrılır.
modifierModifierModifierAlanın bütününün modifier'ı: etiketinin, kutusunun ve kutunun altındakilerin. fillMaxWidth() bir formun sütununu doldurur, width(IntrinsicSize.Max) seçeneklerin gerektirdiği kadar geniştir.
enabledBooleantrueListenin açılıp açılamayacağı. Listesi açılamayan select odak almaz, devre dışı renklerle çizilir ve devre dışı olduğunu söyler.
labelString?nullSeçimin ne olduğu. Kutunun üstüne yazılır ve ekran okuyucu için alanın adıdır, listesi de bu adla duyurulur.
placeholderString?nullHiçbir şey seçili değilken kutuda gösterilir.
supportingTextString?nullKutunun altındaki yardım metni. error ile birlikte neyin düzeltileceğini söyleyen mesajdır ve ekran okuyucu onu hata olarak duyurur.
errorBooleanfalseSeçimin hatalı olup olmadığı: kenar, etiket ve yardım metni danger rolüne döner, ekran okuyucuya da söylenir.
searchableBooleanfalseListede seçenekleri aramak için bir alan olup olmadığı.
searchPlaceholderString?nullArama alanının boşken gösterdiği metin ve alanın adı. Bu null ise temanın arama için kullandığı sözcüktür.
styleSelectStyle?nullBu çağrının kendi stili, listesinin çizildiği stil: çevresindeki her stili ezer, yoğunluk ona da uygulanır. Yalnızca verdiği alanlar değişir, her platformda.
fieldStyleTextFieldStyle?nullBu çağrının kendi TextFieldStyle'ı, kutusunun çizildiği stil: çevresindeki her stili ezer, yoğunluk ona da uygulanır. Yalnızca verdiği alanlar değişir, her platformda.
colorsSelectColors?nullListesinin kendi renkleri, temanın rollerinin yerine: verdikleri kullanılır, gerisi temanın kalır.
fieldColorsTextFieldColors?nullKutusunun kendi renkleri, bir metin alanının aldığı gibi. Devre dışı bir select, ne verilirse verilsin temanın devre dışı renkleriyle çizilir.
contentDescriptionString?nullEkran okuyucunun alan için söylediği: label'ı yokken alanın adıdır, bir araç çubuğundaki select'te olduğu gibi.
tagKeyString?nullAlanın otomasyon anahtarı: alan Select_<tagKey>, listesi SelectList_<tagKey>, listenin arama alanı SelectSearch_<tagKey> diye etiketlenir, seçenekleri de onun içinde adlandırılır: Select_<tagKey>.SelectOption_<option's key>. Listesinin açıldığını ve bir seçeneğin seçildiğini bildirir: seçeneğin anahtarıyla, hiçbir zaman etiketiyle değil.
interactionSourceMutableInteractionSource?nullAlanın dışarı taşınan etkileşimleri: odağı, üstündeki fare ve basışları. Null verilirse alan kendi kaynağını tutar.
presentationOverlayPresentationOverlayPresentation.Popoverlistenin nasıl gösterildiği: varsayılan alanın altında; pencerenin altından bir sheet olarak, başlığı alanın etiketi; ya da dar bir pencerede biri, daha geniş pencerede öteki. Liste açılırken seçilir, kapanana kadar kalır.

field

Bir formun alanına bağlı select: seçimi, hatası ve adı field'dan gelir.

ParametreTürVarsayılanNe olduğu
fieldFormField<T>Select'in gösterdiği ve değiştirdiği alan.
optionsList<SelectOption<T>>Seçenekler, gösterildikleri sırayla.
modifierModifierModifierAlanın bütününün modifier'ı: etiketinin, kutusunun ve kutunun altındakilerin.
enabledBooleantrueListenin açılıp açılamayacağı.
labelString?nullSeçimin ne olduğu. Kutunun üstüne yazılır ve ekran okuyucu için alanın adıdır.
placeholderString?nullHiçbir şey seçili değilken kutuda gösterilir.
supportingTextString?nullKutunun altındaki yardım metni: alanın orada gösterecek bir hatası olmadığı sürece.
searchableBooleanfalseListede seçenekleri aramak için bir alan olup olmadığı.
searchPlaceholderString?nullArama alanının boşken gösterdiği metin ve alanın adı.
styleSelectStyle?nullBu çağrının kendi stili, listesinin çizildiği stil: çevresindeki her stili ezer, yoğunluk ona da uygulanır.
fieldStyleTextFieldStyle?nullBu çağrının kendi TextFieldStyle'ı, kutusunun çizildiği stil.
colorsSelectColors?nullListesinin kendi renkleri: verdikleri kullanılır, gerisi temanın kalır.
fieldColorsTextFieldColors?nullKutusunun kendi renkleri, bir metin alanının aldığı gibi.
contentDescriptionString?nulllabel verilmeyen alan için ekran okuyucunun söylediği.
interactionSourceMutableInteractionSource?nullAlanın dışarı taşınan etkileşimleri. Null verilirse alan kendi kaynağını tutar.
presentationOverlayPresentationOverlayPresentation.Popoverlistenin nasıl gösterildiği: alanın altında, bir sheet olarak ya da pencerenin genişliğine göre.

SelectStyle

Bir PantrixSelect'in açtığı liste: çizildiği panel, bu panelin ait olduğu kutudan ve pencerenin kenarlarından ne kadar uzakta durduğu ve satırları.

ParametreTürVarsayılanNe olduğu
shapeShapeSpecShapeSpec.UnspecifiedPanelin köşeleri: her platformda şekil ölçeğinin orta adımı, kutunun köşeleri gibi.
maxHeightDpDp.UnspecifiedPanelin en çok yüksekliği: sığmayan seçenekler kayar.
elevationDpDp.UnspecifiedPanelin uygulamanın üstünde ne kadar yüksekte durduğu, yani gölgesinin ne kadar büyük olduğu.
gapDpDp.UnspecifiedKutu ile listesinin arası.
marginDpDp.UnspecifiedPanel ile pencerenin kenarları arasında, bir de pencereyi orada örten şeylerle arasında boş bırakılan yer: bir sistem çubuğu, bir ekran çentiği, klavye.
verticalPaddingDpDp.Unspecifiedİlk satırın üstündeki ve son satırın altındaki boşluk.
itemHeightDpDp.UnspecifiedPlatformun dokunma hedefi daha yüksek değilse bir satırın en az yüksekliği.
horizontalPaddingDpDp.UnspecifiedPanelin kenarından bir satırın başındaki şeye ve satırın sonundaki şeyden öteki kenara kadar olan boşluk. Her preset metin alanının kendi değerini taşır: böylece bir seçeneğin etiketi kutudaki metnin başladığı yerde başlar.
iconSizeDpDp.UnspecifiedBir seçeneğin ikonu ve seçili olanın yanındaki onay işareti.
iconGapDpDp.UnspecifiedBir satırın parçalarının arası: onay kutusu, ikonu, etiketi ve onay işareti.

SelectColors

Temanın renklerini almayan bir çağrı için bir PantrixSelect'in listesinin boyandığı renkler: verilen renk kullanılır, verilmeyen temanın kalır. Kutunun renkleri TextFieldColors'tır.

ParametreTürVarsayılanNe olduğu
containerColorColor.UnspecifiedPanelin dolgusu. Temanın surface'ı.
contentColorColor.UnspecifiedBir seçeneğin etiketi ve ikonu. Temanın textPrimary'si.
selectedContainerColorColor.UnspecifiedTek seçimli bir select'te seçili seçeneğin satırının dolgusu. primary rolünün container'ı. Çok seçimli bir select seçimlerini onay kutularıyla gösterir ve hiçbir satırı doldurmaz.
selectedContentColorColor.UnspecifiedTek seçimli bir select'te seçili seçeneğin etiketi, ikonu ve yanındaki onay işareti. primary rolünün onContainer'ı.
borderColorColor.UnspecifiedPanelin çevresindeki ince çizgi ve satırlar ile listenin arama alanı arasındaki çizgi. Çevredeki çizgi paneli, altında duran kendi rengindeki bir yüzeyden ayırır, gölgenin az göründüğü koyu temada olduğu gibi. Temanın kendi zeminlerinde temanın divider'ıdır. Bir dolgunun üstünde, o çizginin okunmayacağı yerde, content'in bir payıdır: Subtle bir düğmenin kenarı gibi. Saydam bir renk verilirse çizgi çizilmez.

Erişilebilirlik