Pantrix UI

Auto Text

Text that gets smaller to stay in view: an amount, a title or a name that is read whole in the room it has.

import com.pantrixui.components.elements.autotext.PantrixAutoText

Examples

Text that fits its room

The same name three times, each with less room than the one before, in the title style. While it has room enough, the text is as large as its style says. When it has not, it goes down, on one line, to the largest size in which all of it is in view. If it still does not fit at its smallest size, the theme's footnote size, it stops shrinking, and what does not fit is cut with an ellipsis.

The text gets its room from modifier: here a width. The grey ground shows that room.

val name = "Selim Karaosmanoğlu"
val room = PantrixTheme.colors.neutral.container
PantrixAutoText(
    text = name,
    modifier = Modifier.width(320.dp).background(room),
    style = PantrixTheme.typography.title,
    tagKey = "name_wide"
)
PantrixAutoText(
    text = name,
    modifier = Modifier.width(160.dp).background(room),
    style = PantrixTheme.typography.title,
    tagKey = "name_narrow"
)
PantrixAutoText(
    text = name,
    modifier = Modifier.width(72.dp).background(room),
    style = PantrixTheme.typography.title,
    tagKey = "name_narrowest"
)

A balance that shrinks on one line

A balance in the largest style. "Add digit" makes the amount longer: the amount is as large as its style says while it fits the line, and when it does not, it gets as small as it takes to stay on one line; "Delete digit" lets it grow back. The pale line under it is the same text without the shrinking, a PantrixText: it is cut when it does not fit.

The decimal part and the currency are half the amount's size. Their size is given in em: it is a share of the text around it, so it shrinks with the amount when the amount shrinks, and stays half of it on every platform.

var digits by rememberSaveable { mutableIntStateOf(4) }
val balance = buildAnnotatedString {
    append("1".padEnd(digits, '0').groupedInThousands())
    withStyle(SpanStyle(fontSize = 0.5.em)) { append(",00 TL") }
}
PantrixAutoText(
    text = balance,
    modifier = Modifier.fillMaxWidth(),
    style = PantrixTheme.typography.display,
    tagKey = "balance"
)
PantrixText(
    text = balance,
    style = PantrixTheme.typography.display,
    color = PantrixTheme.colors.textSecondary,
    maxLines = 1,
    tagKey = "balance_cut"
)
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
    PantrixButton(
        text = "Add digit",
        onClick = { digits++ },
        enabled = digits < 24,
        tagKey = "add_digit"
    )
    PantrixButton(
        text = "Delete digit",
        onClick = { digits-- },
        variant = ButtonVariant.Outline,
        enabled = digits > 1,
        tagKey = "remove_digit"
    )
}

private fun String.groupedInThousands(): String = reversed().chunked(3).joinToString(".").reversed()

A heading on two lines at the most

A heading fitted to two lines at the most: maxLines = 2. The text first wraps onto two lines; when two lines are not enough it is set smaller, and its lines come as much closer. minFontSize is the theme's body size: the heading is never set smaller than that, and if it still does not fit there it is cut with an ellipsis.

It is a heading even when it shrinks: with role = TextRole.Heading(level = 2) a screen reader is told so. The column is 420dp wide at the most, and the heading fills it.

Column(modifier = Modifier.widthIn(max = 420.dp)) {
    PantrixAutoText(
        text = "Your credit card statement is ready: pay by the twenty-eighth",
        modifier = Modifier.fillMaxWidth(),
        style = PantrixTheme.typography.headline,
        minFontSize = PantrixTheme.typography.body.fontSize,
        maxLines = 2,
        role = TextRole.Heading(level = 2),
        tagKey = "statement_title"
    )
}

A paragraph that fits its box

A paragraph fitted to a box of a set height. maxLines = Int.MAX_VALUE leaves the lines to the box's height: the text is set in the largest size that fits the 96dp box in width and in height at once, and never larger than its style's size. Narrow the window: the text gets smaller as the box gets narrower.

The box's ground and its padding are in the text's own modifier; the text is fitted to the room the padding leaves.

PantrixAutoText(
    text = "A design system exists so that the same decision is not made again on every screen: it is made once " +
        "and looks the same everywhere.",
    modifier = Modifier
        .fillMaxWidth()
        .height(96.dp)
        .background(PantrixTheme.colors.neutral.container)
        .padding(PantrixTheme.spacing.sm),
    style = PantrixTheme.typography.title,
    textAlign = TextAlign.Center,
    maxLines = Int.MAX_VALUE,
    tagKey = "quote"
)

The smallest size

The same text three times, in the same 200dp room; only minFontSize differs. The text stops shrinking when it gets down to that size: the smaller the smallest size, the further the text can shrink and the more of it is in view.

The first one's smallest size is 16.sp. The second is given none: it is the theme's footnote size. The third one's is 0.4.em: em is a share of the style's own size, here four tenths of the title size.

val airport = "Sabiha Gökçen International Airport"
val room = Modifier.width(200.dp).background(PantrixTheme.colors.neutral.container)
PantrixAutoText(
    text = airport,
    modifier = room,
    style = PantrixTheme.typography.title,
    minFontSize = 16.sp,
    tagKey = "min_16sp"
)
PantrixAutoText(text = airport, modifier = room, style = PantrixTheme.typography.title, tagKey = "min_default")
PantrixAutoText(
    text = airport,
    modifier = room,
    style = PantrixTheme.typography.title,
    minFontSize = 0.4.em,
    tagKey = "min_em"
)

In boxes side by side, on a fill

A number in each of two boxes side by side, in the headline style. The boxes share the width by weight, and each number is fitted to its own box: the short one stays as large as its style says, and the long one shrinks.

No colour is given. Like PantrixText, the text takes the content colour of where it sits: in the box filled with primary it is written in the colour that reads on that fill.

val colors = PantrixTheme.colors
val spacing = PantrixTheme.spacing
Row(
    modifier = Modifier.widthIn(max = 360.dp),
    horizontalArrangement = Arrangement.spacedBy(spacing.md)
) {
    PantrixSurface(modifier = Modifier.weight(1f), color = colors.primary.color) {
        Column(modifier = Modifier.padding(spacing.md)) {
            PantrixText(text = "Revenue this month", style = PantrixTheme.typography.footnote)
            PantrixAutoText(
                text = "1.284.500,75 TL",
                modifier = Modifier.fillMaxWidth(),
                style = PantrixTheme.typography.headline,
                tagKey = "revenue"
            )
        }
    }
    PantrixSurface(modifier = Modifier.weight(1f), border = colors.divider) {
        Column(modifier = Modifier.padding(spacing.md)) {
            PantrixText(text = "Orders", style = PantrixTheme.typography.footnote)
            PantrixAutoText(
                text = "32",
                modifier = Modifier.fillMaxWidth(),
                style = PantrixTheme.typography.headline,
                tagKey = "orders"
            )
        }
    }
}

API

text

Text that gets smaller to stay in view: an amount, a title or a name that is read whole in the room it has.

ParameterTypeDefaultWhat it is
textStringthe text.
modifierModifierModifierthe text's modifier: fillMaxWidth(), a weight or a size gives it the room it is fitted to.
styleTextStyleLocalPantrixTextStyle.currentthe style of the text at its largest: a role of the theme's typography, and the base text unless given, LocalPantrixTextStyle, as a PantrixText's is. A style whose size is not in sp has no smaller size to be set in, and its text is not shrunk.
minFontSizeTextUnitPantrixTheme.typography.footnote.fontSizethe smallest the text gets: a size in sp, or one in em, which is a share of the style's own. It is the theme's footnote size unless told. At the style's own size or above it the text never shrinks, and at zero there is no end to the shrinking.
colorColorColor.Unspecifiedthe text's colour. Unset, it is the style's, or the content colour of where the text sits, or the primary text colour.
textAlignTextAlign?nullhow the lines are aligned in the text's width.
maxLinesInt1the most lines the text takes: one unless told. Int.MAX_VALUE leaves the lines to the height the text is given.
minLinesInt1the least lines the text is tall, at its largest size.
overflowTextOverflowTextOverflow.Ellipsishow a text that does not fit at its smallest size is cut.
softWrapBooleantruewhether the text wraps where its width ends. A text that does not is fitted to its longest line.
roleTextRoleTextRole.Paragraphwhat the text is, for a screen reader: prose, a heading, a label or decoration.
selectableBooleanfalsewhether the user can select the text and copy it.
onTextLayout((TextLayoutResult) -> Unit)?nullcalled with the text as it is laid out, in the size it is set in.
tagKeyString?nullthe text's automation key: the text is AutoText_<tagKey>. Without one it has no tag.

text

PantrixAutoText for an AnnotatedString, with its spans and links, and inlineContent for the placeholders it names. A span's size in em follows the text's, and one in sp is kept as it is.

ParameterTypeDefaultWhat it is
textAnnotatedStringthe text, with its spans and links.
modifierModifierModifierthe text's modifier: fillMaxWidth(), a weight or a size gives it the room it is fitted to.
styleTextStyleLocalPantrixTextStyle.currentthe style of the text at its largest: a role of the theme's typography, and the base text unless given, LocalPantrixTextStyle, as a PantrixText's is. A style whose size is not in sp has no smaller size to be set in, and its text is not shrunk.
minFontSizeTextUnitPantrixTheme.typography.footnote.fontSizethe smallest the text gets: a size in sp, or one in em, which is a share of the style's own. It is the theme's footnote size unless told. At the style's own size or above it the text never shrinks, and at zero there is no end to the shrinking.
colorColorColor.Unspecifiedthe text's colour. Unset, it is the style's, or the content colour of where the text sits, or the primary text colour.
textAlignTextAlign?nullhow the lines are aligned in the text's width.
maxLinesInt1the most lines the text takes: one unless told. Int.MAX_VALUE leaves the lines to the height the text is given.
minLinesInt1the least lines the text is tall, at its largest size.
overflowTextOverflowTextOverflow.Ellipsishow a text that does not fit at its smallest size is cut.
softWrapBooleantruewhether the text wraps where its width ends. A text that does not is fitted to its longest line.
roleTextRoleTextRole.Paragraphwhat the text is, for a screen reader: prose, a heading, a label or decoration.
selectableBooleanfalsewhether the user can select the text and copy it.
inlineContentMap<String, InlineTextContent>emptyMap()
onTextLayout((TextLayoutResult) -> Unit)?nullcalled with the text as it is laid out, in the size it is set in.
tagKeyString?nullthe text's automation key: the text is AutoText_<tagKey>. Without one it has no tag.