Skip to main content

Formatting and layout

Formatting happens on the native side, so the layout is known before the first frame.

PropExample
fractionDigits={2}1234.5 → 1234.50
minimumIntegerDigits={3}7 → 007
groupingSeparator=","1234567 → 1,234,567
decimalSeparator=","1234.5 → 1234,5
prefix="$" / suffix="%"$42 / 42%

A negative value gets a leading - that slides in and out like a digit column. At most 18 digits are shown.

From a NumberFormat​

Pass a NumberFormat as format and the number takes its prefix and suffix (the currency where the locale puts it), separators, fraction digits and minimum integer digits from it:

const eur = new NumberFormat('de-DE', { style: 'currency', currency: 'EUR' })

<NitroNumber value={1234.5} format={eur} /> // 1.234,50 €

The props you set yourself win, so format={eur} suffixFontSize={20} keeps the euro and sizes it. The number keeps its own model: digits grouped in threes, a leading minus and Latin digits, so a format outside it (Indian grouping, Arabic-Indic digits, accounting parentheses) is followed as far as that goes.

Currency​

Money is usually set with the currency mark at a different size from the amount. prefixFontSize / suffixFontSize size the affixes, and affixAlign (or prefixAlign / suffixAlign) says how they line up with the digits. NitroInput takes the same props.

affixAlignWhat lines up
baseline (default)The affix shares the digits' baseline.
topThe affix's cap height meets the digits' cap height.
bottomThe bottom of the glyphs' ink, so an all-caps code sits on the digits' baseline.
centerThe affix's line box is centred on the digits'.

The affixes are part of the animated layout: when a leading digit appears, the prefix slides left with it.

Switching currency​

Change prefix, suffix, the separators and fractionDigits together with value, and the switch plays as one change, the way SwiftUI's numeric text plays a new string: the old mark blurs out while the new one comes into focus, the digits keep their place value and swap or roll to the new amount, decimal columns that go close and new ones open, and the decimal separator fades with them. A switch that arrives before the last one has finished plays from wherever the figure is.

Try Switch currency above: every transition plays it, the roll included.

Spacing and offsets​

letterSpacing adds points after every glyph, like Text's; a negative value tightens a heavy display face. A smaller prefix or suffix gets it in proportion to its size, since tracking is relative to the size of the type.

prefixSpacing and suffixSpacing set the gap between an affix and the digits exactly, in points, instead of relying on the font's space. prefixOffset and suffixOffset move an affix down (or up, negative) after affixAlign has placed it, for a symbol a design puts a couple of points off every preset. An offset moves only what is drawn: the number's size stays the same.

<NitroNumber
value={balance}
prefix="$"
prefixFontSize={24}
affixAlign="bottom"
fontSize={44}
letterSpacing={-2.2} // -5% of 44
prefixSpacing={2}
prefixOffset={-2}
/>

NitroInput takes the same five props.

Proportional digits​

Digits are tabular by default: every one as wide as the widest, so a column never moves as the value changes, which is what a ticker or a price list wants. tabularNums={false} sets each digit at its own width instead, the font's proportional figures. Use it for a face whose "1" is much narrower than its "0", or that has no tabular figures at all, where tabular digits leave gaps around every 1. While a column rolls or swaps, its width eases once from the old digit's to the new one's, on the roll's own easing, whatever digits it passes on the way; a reveal keeps its target's widths from the first frame, so the count does not shuffle.

<NitroNumber value={1111.11} fontFamily="OpenRunde-Bold" tabularNums={false} />

Fonts​

fontSize, fontWeight, fontFamily and color work like Text's, and custom fonts resolve the same way (UIAppFonts on iOS, React Native's font manager on Android, including expo-font). Digits use tabular figures, so every column has the same width. allowFontScaling follows the system text size, capped by maxFontSizeMultiplier; it is off by default, so an amount keeps its design size.

Sizing​

The view sizes itself to its content. When a column appears the box grows at once; when the number gets narrower the box shrinks only after the animation has finished, so digits on their way out are never squeezed. While it grows or shrinks, the digits keep to whichever edge the parent holds the box by (textAlign="auto"): a figure at the end of a row grows to the left, a centred one from its middle, with no prop to set. Give it a width if the layout around it should not move at all as digits appear; that also removes the one JS round trip, the size report.

adjustsFontSizeToFit scales the whole number down when the view is narrower than its content, down to minimumFontScale (default 0.5), and back up when it fits again. The box keeps its height; only the amount scales. The scale follows the content as it is drawn, half-appeared columns included, so it changes continuously with the animation, and it is a layer or canvas transform, so no font is rebuilt while fitting.

Right-to-left​

In a right-to-left app (I18nManager.isRTL, or style={{ direction: 'rtl' }} on one figure), textAlign="auto" means the right edge, the prefix sits at the right and the suffix at the left, and the digits still read left to right.