Expo UI and Router for iOSExpo SDK 57 and later, iOS only
Components

Text

A SwiftUI Text component for displaying styled text with support for nested texts.

Expo UI Text matches the official SwiftUI Text API.

Usage

Basic text

import { Host, Text } from '@expo/ui/swift-ui';

export default function BasicTextExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Text>Hello world</Text>
    </Host>
  );
}
The words Hello world in the default system font
The words Hello world in the default system font

Text with modifiers

Use modifiers to style the entire text.

import { Host, Text } from '@expo/ui/swift-ui';
import { font, foregroundStyle } from '@expo/ui/swift-ui/modifiers';

export default function StyledTextExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Text
        modifiers={[
          font({ size: 24, weight: 'bold' }),
          foregroundStyle('blue'),
        ]}>
        Large Bold Blue Text
      </Text>
    </Host>
  );
}
The words Large Bold Blue Text rendered in a large bold blue font
The words Large Bold Blue Text rendered in a large bold blue font

Nested text (per-segment styling)

Nest Text components to style individual segments differently. This is useful for inline formatting, such as bold or colored words within a sentence.

Note: Nested text uses SwiftUI's Text concatenation, so only modifiers that return Text (such as bold, italic, font, foregroundColor, and foregroundStyle with color) will apply to nested segments.

import { Host, Text } from '@expo/ui/swift-ui';
import {
  bold,
  italic,
  foregroundStyle,
} from '@expo/ui/swift-ui/modifiers';

export default function NestedTextExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Text>
        Hello{' '}
        <Text modifiers={[bold(), foregroundStyle('red')]}>
          world
        </Text>
        !
      </Text>
    </Host>
  );
}
The sentence Hello world! where the word world is bold and red
The sentence Hello world! where the word world is bold and red

Mixed inline styles

Combine multiple styled segments for rich text formatting.

import { Host, Text } from '@expo/ui/swift-ui';
import {
  bold,
  italic,
  foregroundStyle,
  font,
} from '@expo/ui/swift-ui/modifiers';

export default function MixedStylesExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Text>
        This is <Text modifiers={[bold()]}>bold</Text>,{' '}
        <Text modifiers={[italic()]}>italic</Text>, and{' '}
        <Text modifiers={[foregroundStyle('orange')]}>colored</Text>{' '}
        text.
      </Text>
    </Host>
  );
}
A sentence where the word bold is bold, italic is italic, and colored is orange
A sentence where the word bold is bold, italic is italic, and colored is orange

Font weights

Use the font modifier to apply different font weights.

import { Host, Text, VStack } from '@expo/ui/swift-ui';
import { font } from '@expo/ui/swift-ui/modifiers';

export default function FontWeightsExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={4}>
        <Text modifiers={[font({ weight: 'ultraLight' })]}>
          Ultra Light
        </Text>
        <Text modifiers={[font({ weight: 'light' })]}>Light</Text>
        <Text modifiers={[font({ weight: 'regular' })]}>
          Regular
        </Text>
        <Text modifiers={[font({ weight: 'medium' })]}>Medium</Text>
        <Text modifiers={[font({ weight: 'semibold' })]}>
          Semibold
        </Text>
        <Text modifiers={[font({ weight: 'bold' })]}>Bold</Text>
        <Text modifiers={[font({ weight: 'heavy' })]}>Heavy</Text>
        <Text modifiers={[font({ weight: 'black' })]}>Black</Text>
      </VStack>
    </Host>
  );
}
Eight stacked lines showing the weights from Ultra Light through Black
Eight stacked lines showing the weights from Ultra Light through Black

Font designs

Use the font modifier to apply different font designs.

import { Host, Text, VStack } from '@expo/ui/swift-ui';
import { font } from '@expo/ui/swift-ui/modifiers';

export default function FontDesignsExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={4}>
        <Text modifiers={[font({ design: 'default', size: 18 })]}>
          Default Design
        </Text>
        <Text modifiers={[font({ design: 'rounded', size: 18 })]}>
          Rounded Design
        </Text>
        <Text modifiers={[font({ design: 'serif', size: 18 })]}>
          Serif Design
        </Text>
        <Text
          modifiers={[font({ design: 'monospaced', size: 18 })]}>
          Monospaced Design
        </Text>
      </VStack>
    </Host>
  );
}
Four stacked lines showing the default, rounded, serif, and monospaced designs
Four stacked lines showing the default, rounded, serif, and monospaced designs

Custom fonts

Use the font modifier with a family parameter to use custom fonts. You can load custom fonts using expo-font library.

import { Host, Text, VStack } from '@expo/ui/swift-ui';
import { font } from '@expo/ui/swift-ui/modifiers';

export default function CustomFontExample() {
  return (
    <Host matchContents style={{ alignSelf: 'center' }}>
      <VStack spacing={4}>
        <Text
          modifiers={[font({ family: 'Inter-Bold', size: 18 })]}>
          Inter Bold
        </Text>
        <Text
          modifiers={[font({ family: 'Inter-Regular', size: 18 })]}>
          Inter Regular
        </Text>
      </VStack>
    </Host>
  );
}
Two lines of text, Inter Bold above Inter Regular.
Two lines of text, Inter Bold above Inter Regular.

Text with line limit

Use the lineLimit modifier to truncate text after a certain number of lines.

import { Host, Text } from '@expo/ui/swift-ui';
import { lineLimit } from '@expo/ui/swift-ui/modifiers';

export default function LineLimitExample() {
  const longText =
    'This is a very long text that will be truncated after two lines. '.repeat(
      5
    );

  return (
    <Host style={{ flex: 1 }}>
      <Text modifiers={[lineLimit(2)]}>{longText}</Text>
    </Host>
  );
}
A long paragraph cut off after two lines with a trailing ellipsis
A long paragraph cut off after two lines with a trailing ellipsis

Markdown

Use the markdownEnabled property to enable Markdown formatting for the text content.

import { Host, Text, VStack } from '@expo/ui/swift-ui';

export default function MarkdownTextExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={4}>
        <Text markdownEnabled>Regular text.</Text>
        <Text markdownEnabled>
          This is **bold text**, *italic text* and ***text in both
          bold and italic***.
        </Text>
        <Text markdownEnabled>~~Strikethrough text~~</Text>
        <Text markdownEnabled>`This is monospaced text`</Text>
        <Text markdownEnabled>
          Visit the [Expo
          Docs](https://docs.expo.dev/versions/latest/sdk/ui/) to
          learn more about Expo UI
        </Text>
      </VStack>
    </Host>
  );
}
Five lines showing bold, italic, strikethrough, and monospaced text, and a blue link
Five lines showing bold, italic, strikethrough, and monospaced text, and a blue link

Auto-updating date

Use the date and dateStyle props to display a date that automatically updates as time passes. This is especially useful in widgets and Live Activities.

import { Host, Text } from '@expo/ui/swift-ui';

export default function DateTextExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Text
        date={new Date(Date.now() + 300000)}
        dateStyle="timer"
      />
    </Host>
  );
}
A countdown reading 4 minutes and 53 seconds
A countdown reading 4 minutes and 53 seconds

Timer interval

Use timerInterval to display a live countdown or count-up timer. This requires iOS/tvOS 16+.

import { Host, Text } from '@expo/ui/swift-ui';

export default function TimerIntervalExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Text
        timerInterval={{
          lower: new Date(),
          upper: new Date(Date.now() + 600000),
        }}
        countsDown
      />
    </Host>
  );
}
A countdown reading 9 minutes and 54 seconds
A countdown reading 9 minutes and 54 seconds

Note: timerInterval, countsDown, and pauseTime require iOS 16.0+ / tvOS 16.0+. On older versions, the timer interval will not render.

API

import { Text } from '@expo/ui/swift-ui';

Component

Text

Type: React.Element<TextProps>

TextProps

children

Optional • Type: ReactNode

Text content or nested Text components.

countsDown

iOS 16+

Optional • Type: boolean • Default: true

Whether the timer counts down (true) or up (false).

date

Optional • Type: Date

A date to display using the specified dateStyle. The text auto-updates as time passes.

dateStyle

Optional • Type: TextDateStyle • Default: 'date'

The style used to format the date prop.

markdownEnabled

Optional • Type: boolean

Enables Markdown formatting for the text content using SwiftUI LocalizedStringKey.

pauseTime

iOS 16+

Optional • Type: Date

A date at which the timer should appear paused.

timerInterval

iOS 16+

Optional • Type: ClosedRangeDate

A time interval to display as a live-updating timer.

Inherited props

Types

TextDateStyle

Literal type: string

The style used to format a date in a SwiftUI Text view.

Acceptable values are: 'timer' | 'relative' | 'offset' | 'date' | 'time'

Modifiers

Use these modifiers in the modifiers prop of the SwiftUI and Universal version.

Expo UI lets you put any of the 89 modifiers for any view on Text, but not all of them do something here.

  • 68 change what you see on Text.
  • 4 work, but not in the way that you may expect.
  • 8 have no visible effect on Text.
  • 13 work only in one place, such as a widget or a Grid.

Where the modifiers go

modifiers on the outer Text apply to all of the text. A nested Text uses only bold, italic, monospacedDigit, font, foregroundColor and foregroundStyle. It ignores other modifiers, and in debug builds it shows a red warning.

Best modifiers for Text

These modifiers are made for Text, or they are the ones that you use most with it.

Also works on Text

Text takes these modifiers too, and each one works in the usual way.

Needs care on Text

These modifiers work on Text, but not in the way that you may expect.

ModifierWhat to know
kerningA nested Text ignores this modifier. In debug builds, the nested text shows a red warning.
strikethroughA nested Text ignores this modifier. In debug builds, the nested text shows a red warning.
textCaseA nested Text ignores this modifier. In debug builds, the nested text shows a red warning.
underlineA nested Text ignores this modifier. In debug builds, the nested text shows a red warning.

No visible effect on Text

Text accepts these modifiers, but you see no change. They do not give an error.

ModifierWhy nothing happens
accessibilityElementIt joins the child views into one accessibility element, and Text takes no child views.
containerShapeIt sets the shape that the child views use for containerRelativeShape, and Text takes no child views.
disabledIt turns off the controls in the view, and Text has none.
geometryGroup iOS 17+It works on the child views that you give the component, and Text takes none.
imageScaleIt changes only SF Symbols, and Text shows none.
layoutPriorityIt has an effect only when the view shares an axis with other views in a stack.
tintIt changes the accent colour of controls and SF Symbols, and Text shows neither.
zIndexIt changes the order of views that cover each other in the same parent, and Text does not stack its children.

Only in some places

These modifiers work only in a widget, in a Grid, in a Namespace or in a parent that asks for them.

ModifierWhere it works
activityBackgroundTintWorks only in a Live Activity. It has no effect in the app.
alignmentGuideHas an effect only when the parent, such as a VStack or ZStack, aligns its children by the same guide.
containerBackgroundWorks only in a widget, or in a navigation container when you use a navigation placement.
glassEffectIdWorks only on a view that also has glassEffect, in a GlassEffectContainer and a Namespace.
gridCellAnchor iOS 16+Works only on a cell of a Grid. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
gridCellColumnsWorks only on a view in a Grid.Row. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
gridCellUnsizedAxesWorks only on a view in a Grid. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
gridColumnAlignment iOS 16+Works only on a view in a Grid.Row. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
invalidatableContent iOS 17+Has an effect only when a parent view uses redacted with the invalidated reason.
matchedGeometryEffectWorks only in a Namespace. Give two views the same id and change between them with an animation.
privacySensitiveHas an effect only when a parent view uses redacted with the privacy reason.
unredactedHas an effect only in a parent view that uses redacted.
widgetURLWorks only in a widget. It has no effect in the app.

Sources

The original Expo docs for this page:

  • Text (SwiftUI) (source-of-truth/versions/v57.0.0/sdk/ui/swift-ui/text.md)
  • Text (Universal) (source-of-truth/versions/v57.0.0/sdk/ui/universal/text.md)

On this page