Expo UI and Router for iOS
Components

Button

A SwiftUI Button component for displaying native buttons.

Expo UI Button matches the official SwiftUI Button API and supports styling via the buttonStyle, controlSize, and other modifiers.

Usage

Basic button

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

export default function BasicButtonExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button label="Press me" onPress={() => alert('Pressed!')} />
    </Host>
  );
}

Button with system image

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

export default function ButtonWithImageExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button
        label="Download"
        systemImage="arrow.down.circle"
        onPress={() => alert('Downloading...')}
      />
    </Host>
  );
}

Icon-only button

Use the labelStyle modifier to show only the icon while keeping the label for accessibility.

import { Host, Button } from '@expo/ui/swift-ui';
import { labelStyle } from '@expo/ui/swift-ui/modifiers';

export default function IconOnlyButtonExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button
        label="Settings"
        systemImage="gear"
        modifiers={[labelStyle('iconOnly')]}
        onPress={() => alert('Settings')}
      />
    </Host>
  );
}

Button styles

Use the buttonStyle modifier to change the button's appearance. Available styles are: bordered, borderedProminent, borderless, plain, glass, and glassProminent.

Note: The glass and glassProminent styles are only available on iOS 26+ when built with Xcode 26.

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

export default function ButtonStylesExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={8}>
        <Button
          label="Bordered"
          modifiers={[buttonStyle('bordered')]}
        />
        <Button
          label="Bordered Prominent"
          modifiers={[buttonStyle('borderedProminent')]}
        />
        <Button
          label="Borderless"
          modifiers={[buttonStyle('borderless')]}
        />
        <Button label="Plain" modifiers={[buttonStyle('plain')]} />
      </VStack>
    </Host>
  );
}

Button border shape

Use the buttonBorderShape modifier to change the shape of a styled button. Available shapes are: automatic, capsule, roundedRectangle, and circle (iOS 17+).

import { Host, Button } from '@expo/ui/swift-ui';
import {
  buttonStyle,
  controlSize,
  buttonBorderShape,
  labelStyle,
} from '@expo/ui/swift-ui/modifiers';

export default function ButtonBorderShapeExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button
        label="Favorite"
        systemImage="heart.fill"
        modifiers={[
          buttonStyle('glass'),
          controlSize('extraLarge'),
          labelStyle('iconOnly'),
          buttonBorderShape('circle'),
        ]}
        onPress={() => alert('Favorited')}
      />
    </Host>
  );
}

Control sizes

Use the controlSize modifier to adjust the button size. Available sizes are: mini, small, regular, large, and extraLarge.

Note: The extraLarge size is only available on iOS 17+.

import { Host, Button, VStack } from '@expo/ui/swift-ui';
import {
  buttonStyle,
  controlSize,
} from '@expo/ui/swift-ui/modifiers';

export default function ControlSizeExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={8}>
        <Button
          label="Mini"
          modifiers={[controlSize('mini'), buttonStyle('bordered')]}
        />
        <Button
          label="Small"
          modifiers={[
            controlSize('small'),
            buttonStyle('bordered'),
          ]}
        />
        <Button
          label="Regular"
          modifiers={[
            controlSize('regular'),
            buttonStyle('bordered'),
          ]}
        />
        <Button
          label="Large"
          modifiers={[
            controlSize('large'),
            buttonStyle('bordered'),
          ]}
        />
      </VStack>
    </Host>
  );
}

Button roles

Use the role prop to indicate the semantic role of the button. Available roles are: default, cancel, and destructive.

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

export default function ButtonRolesExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={8}>
        <Button label="Default" role="default" />
        <Button label="Cancel" role="cancel" />
        <Button label="Delete" role="destructive" />
      </VStack>
    </Host>
  );
}

Tinted button

Use the tint modifier to change the button's color.

import { Host, Button } from '@expo/ui/swift-ui';
import { tint } from '@expo/ui/swift-ui/modifiers';

export default function TintedButtonExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button label="Custom Color" modifiers={[tint('#FF6347')]} />
    </Host>
  );
}

Disabled button

Use the disabled modifier to disable the button.

import { Host, Button } from '@expo/ui/swift-ui';
import { disabled } from '@expo/ui/swift-ui/modifiers';

export default function DisabledButtonExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button label="Disabled" modifiers={[disabled()]} />
    </Host>
  );
}

Custom label content

You can pass custom components as children for more complex button label content.

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

export default function CustomContentExample() {
  return (
    <Host style={{ flex: 1 }}>
      <Button onPress={() => console.log('Pressed!')}>
        <VStack spacing={4}>
          <Image systemName="folder" />
          <Text>Folder</Text>
        </VStack>
      </Button>
    </Host>
  );
}

API

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

Component

Button

Type: React.Element<ButtonProps>

Displays a native button component.

Example

import { Button } from '@expo/ui/swift-ui';
import { buttonStyle, controlSize, tint, disabled } from '@expo/ui/swift-ui/modifiers';

<Button
  role="destructive"
  onPress={handlePress}
  label="Delete"
  modifiers={[
    buttonStyle('bordered'),
    controlSize('large'),
    tint('#FF0000'),
    disabled(true)
  ]}
/>

ButtonProps

children

Optional • Literal type: union

Custom content for the button label. Use this for custom label views. Only nested elements are supported, not plain strings.

Acceptable values are: ReactElement<unknown, string | JSXElementConstructor<any>> | ReactElement[]

label

Optional • Type: string

The text label for the button. Use this for simple text buttons.

onPress

Optional • Type: () => void

A callback that is called when the button is pressed.

role

Optional • Type: ButtonRole

Indicates the role of the button.

systemImage

Optional • Type: SFSymbols7_0

A string describing the system image to display in the button. Only used when label is provided.

target

Optional • Type: string

Target identifier for the button, used for identifying which button was pressed in widgets and live activities.

Inherited props

Types

ButtonRole

Literal type: string

The role of the button.

  • default - The default button role.
  • cancel - A button that cancels the current operation.
  • destructive - A button that deletes data or performs a destructive action.

Acceptable values are: 'default' | 'cancel' | 'destructive'

Modifiers

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

Modifiers for Button

Modifiers for any view

Sources

The original Expo docs for this page:

On this page