Pantrix UI

Page Size

Chooses how many rows a page of a list shows: the words "Per page" and, beside them, a select of sizes.

import com.pantrixui.components.data.pagination.PantrixPageSize

Examples

In a table's foot: page size and go to page

A table's foot: PantrixPageSize chooses how many orders a page shows, PantrixPagination moves between the pages, and PantrixPageJump goes to the page whose number is typed. The three are in a FlowRow: where there is room they stand side by side, and in a narrow place the one that does not fit goes down to the next line; on a phone held upright the three stand one under another. A Row does not take what does not fit down a line: it squeezes the last one into the room that is left. The three may not be the same height: itemVerticalAlignment lines them up by their middles.

All three read the screen's state, and none knows of the others. Change the page size: forty-eight orders make sixteen pages three at a time, and five pages ten at a time; the row's numbers and the number of digits the field takes follow the new number of pages. As the size changes the first order shown stays on screen: the page that is opened is the one that order falls on at the new size. On the fourth page, with orders 16–20 shown, choose 10: the second page comes, orders 11–20. For forty-eight orders the sizes are small: 3 and 5, before the first of the ready sizes (DefaultPageSizes), 10.

Type a number in the field and press Enter: that page is opened, the field is emptied and the focus stays in the field. A number larger than the last page opens the last page; the field takes nothing but digits. The page that was asked for, whatever asked for it, is written on the card's "Last event" line.

val report = LocalExampleEvents.current
var pageSize by rememberSaveable { mutableIntStateOf(ORDERS_PER_PAGE) }
var page by rememberSaveable { mutableIntStateOf(1) }
val pageCount = (ORDER_COUNT + pageSize - 1) / pageSize
val first = (page - 1) * pageSize + 1
val last = minOf(page * pageSize, ORDER_COUNT)
val open: (Int) -> Unit = { asked ->
    page = asked
    report("Page $asked was asked for")
}
OrderRows(first = first, last = last, rows = pageSize, tagKey = "row")
PantrixText(
    text = "$first–$last of $ORDER_COUNT orders",
    color = PantrixTheme.colors.textSecondary,
    tagKey = "foot_shown"
)
FlowRow(
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg),
    verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm),
    itemVerticalAlignment = Alignment.CenterVertically
) {
    PantrixPageSize(
        pageSize = pageSize,
        onPageSizeChange = { size ->
            // The page that is opened is the one the first order shown falls on at the new size: the order stays on screen.
            val kept = (first - 1) / size + 1
            pageSize = size
            page = kept
            report("$size orders to a page: page $kept was opened")
        },
        pageSizes = listOf(3, 5) + DefaultPageSizes.first(),
        tagKey = "foot"
    )
    PantrixPagination(page = page, pageCount = pageCount, onPageChange = open, tagKey = "foot")
    PantrixPageJump(pageCount = pageCount, onPageChange = open, tagKey = "foot")
}

@Composable
private fun OrderRows(
    first: Int,
    last: Int,
    rows: Int,
    tagKey: String
) {
    PantrixSurface(modifier = Modifier.fillMaxWidth(), border = PantrixTheme.colors.divider) {
        Column {
            for (order in first until first + rows) {
                val listed = order <= last
                // The line of an empty row keeps its place too, but is not drawn.
                val line = if (listed) Color.Unspecified else Color.Transparent
                if (order > first) PantrixHorizontalDivider(color = line)
                Row(
                    modifier = Modifier.fillMaxWidth().padding(PantrixTheme.spacing.md),
                    horizontalArrangement = Arrangement.SpaceBetween
                ) {
                    if (listed) {
                        PantrixText(text = "Order #${FIRST_ORDER + order}", tagKey = "${tagKey}_$order")
                        PantrixText(text = "Items: ${1 + order % 4}", color = PantrixTheme.colors.textSecondary)
                    } else {
                        // An empty text is a line tall too; it has nothing to say to a screen reader.
                        PantrixText(text = "", role = TextRole.Decorative)
                    }
                }
            }
        }
    }
}

private const val ORDER_COUNT = 48

private const val ORDERS_PER_PAGE = 5

private const val FIRST_ORDER = 4800

API

pageSize

Chooses how many rows a page of a list shows: the words "Per page" and, beside them, a select of sizes.

ParameterTypeDefaultWhat it is
pageSizeInthow many rows a page shows now.
onPageSizeChange(pageSize: Int) -> Unittold the size that was chosen, where it is another than pageSize. The select shows it once pageSize says so.
modifierModifierModifierapplied to the row.
pageSizesList<Int>DefaultPageSizesthe sizes to choose from, in the order they are listed: DefaultPageSizes unless given. A size given twice is listed once. There is one at the least, and each is a row or more: a list that is empty or holds a number under one is refused.
labelStringPantrixTheme.strings.perPagethe words before the select, and the select's name for a screen reader: the theme's "Per page" unless given.
enabledBooleantruewhether a size can be chosen: a row that cannot be used has its words in the disabled text colour and a select that is disabled, which takes no focus and says so.
tagKeyString?nulla locale-independent key for automation: the row's tag is PageSize_<tagKey> and its words are PageSize_<tagKey>.Text_label. The select in it has the key <tagKey>_page_size, and is tagged as a select is: Select_<tagKey>_page_size, its list SelectList_<tagKey>_page_size, and a size in the list Select_<tagKey>_page_size.SelectOption_<size>. A key too long for a tag is cut, and _page_size is kept whole. A choice is reported as PageSize, with the size. That the list of sizes opened is reported as PageSize too, with the row's tag: the row is one component, and reports under one name.

Accessibility