SwiftUI.js
Components

NavigationLink

NavigationLink is a component that triggers navigation to a destination within a NavigationStack. It can navigate to another component or an external URL, and supports customizable transition animations.

NavigationLink is a component that triggers navigation to a destination within a NavigationStack. It can navigate to another component or an external URL, and supports customizable transition animations.

Examples

Navigate to a Component

Preview unavailable for this example in the static docs build.

Show code
<NavigationStack>
      <VStack spacing={20}>
        <NavigationLink destination={DetailPage}>
          <Text>Go to Detail</Text>
        </NavigationLink>
      </VStack>
    </NavigationStack>

Navigate to External URL

Preview unavailable for this example in the static docs build.

Show code
<NavigationLink destination="https://example.com">External Link</NavigationLink>

Action Sheet

Preview unavailable for this example in the static docs build.

Show code
<NavigationStack>
        <VStack spacing={20}>
          <NavigationLink destination={SheetContent} pageOptions={{ type: 'actionsheet' }}>
            <Text>Show Action Sheet</Text>
          </NavigationLink>
        </VStack>
      </NavigationStack>

API

PropTypeRequiredDescription
destinationstring | ComponentTypeNoThe destination component or URL to navigate to. If a string is provided, it will navigate to that URL. If a ComponentType is provided, it will navigate to that component within the NavigationStack. Default: undefined
pageOptions{ /** * The type of page presentation. */ type?: IPageType /** * Transition configuration for page animation. * * @example * ```tsx * transition: { * type: 'view-transition', * viewTransitionName: 'shared-element' * } * ``` */ transition?: ITransitionConfig }NoOptions for configuring the page presentation.
dismissbooleanNoA Boolean value that indicates whether to dismiss the current page. When true, clicking the link will navigate back instead of forward. Default: false

Inherits additional props from IBaseComponent.

Overview

NavigationLink is a component that triggers navigation to a destination within a NavigationStack. It can navigate to another component or an external URL, and supports customizable transition animations.

SwiftUI Correspondence: Similar to SwiftUI's NavigationLink.

Page Types

Standard Page

<NavigationLink
  destination={DetailPage}
  pageOptions={{ type: 'page' }}
>
  <Text>Go to Detail</Text>
</NavigationLink>

Transition Animations

NavigationLink supports customizable transition animations through the transition option in pageOptions.

Default Slide Animation

By default, pages use a slide animation:

<NavigationLink destination={DetailPage} pageOptions={{ type: 'page' }}>
  <Button>Go to Detail</Button>
</NavigationLink>

View Transitions with Shared Elements

Use View Transitions API for smooth shared element animations. This requires setting the same viewTransitionName on both source and target elements:

// Source element (in list)
<NavigationLink
  destination={ProductDetail}
  pageOptions={{
    type: 'page',
    transition: {
      type: 'view-transition',
      viewTransitionName: 'product-image'
    }
  }}
>
  <div style={{ viewTransitionName: 'product-image' }}>
    <Image src={product.thumbnail} />
    <Text>{product.name}</Text>
  </div>
</NavigationLink>

// Target element (in ProductDetail page)
function ProductDetail({ product }) {
  return (
    <StandardPage
      id="product-detail"
      navigationTitle={product.name}
      transition={{
        type: 'view-transition',
        viewTransitionName: 'product-image'
      }}
    >
      <Image
        src={product.fullImage}
        style={{ viewTransitionName: 'product-image' }}
      />
      <Text>{product.description}</Text>
    </StandardPage>
  )
}

Fade Transition

Use fade animation for modal-like presentations:

<NavigationLink
  destination={ModalPage}
  pageOptions={{
    type: 'actionsheet',
    transition: {
      type: 'fade',
      duration: 200
    }
  }}
>
  <Button>Open Modal</Button>
</NavigationLink>

Scale Transition

Use scale animation for popover-like presentations:

<NavigationLink
  destination={PopoverPage}
  pageOptions={{
    type: 'actionsheet',
    transition: {
      type: 'scale',
      duration: 250
    }
  }}
>
  <Button>Show Popover</Button>
</NavigationLink>

Custom Duration and Easing

<NavigationLink
  destination={DetailPage}
  pageOptions={{
    type: 'page',
    transition: {
      type: 'slide',
      duration: 400,
      easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
    }
  }}
>
  <Button>Go to Detail</Button>
</NavigationLink>

No Animation

<NavigationLink
  destination={DetailPage}
  pageOptions={{
    type: 'page',
    transition: {
      type: 'none'
    }
  }}
>
  <Button>Instant Navigation</Button>
</NavigationLink>

Dismissing Pages

Use the dismiss prop to navigate back:

<NavigationLink dismiss>
  <Button>Go Back</Button>
</NavigationLink>

Or use it programmatically:

import { useNaviContext } from '@swiftuijs/ui'

function MyPage() {
  const navi = useNaviContext()

  return (
    <StandardPage id="my-page">
      <Button onClick={() => navi.dismiss()}>Go Back</Button>
    </StandardPage>
  )
}

Props Reference

PropTypeRequiredDefaultDescription
destinationstring | ComponentType-Destination component or URL to navigate to
pageOptionsobject-Options for page presentation
pageOptions.type'page' | 'actionsheet''page'Type of page presentation
pageOptions.transitionITransitionConfig{ type: 'slide' }Transition configuration
dismissbooleanfalseIf true, navigates back instead of forward
styleCSSProperties-Custom CSS styles
classNamestring-Custom CSS class name
childrenReactNode-Content to display (usually a Button or Text)

TransitionConfig

PropertyTypeDefaultDescription
type'slide' | 'fade' | 'scale' | 'view-transition' | 'none''slide'Transition animation type
direction'forwards' | 'backwards' | 'auto''auto'Transition direction (for slide type)
viewTransitionNamestring-View transition name for shared element animations
durationnumber300Animation duration in milliseconds
easingstring'cubic-bezier(0.075, 0.82, 0.165, 1)'CSS easing function

Common Patterns

Master-Detail Navigation

// Master (List)
<StandardPage id="products" navigationTitle="Products">
  <List>
    {products.map(product => (
      <NavigationLink
        key={product.id}
        destination={() => <ProductDetail product={product} />}
        pageOptions={{ type: 'page' }}
      >
        <ProductRow product={product} />
      </NavigationLink>
    ))}
  </List>
</StandardPage>

Shared Element Animation

// List item with shared element
<NavigationLink
  destination={ProductDetail}
  pageOptions={{
    type: 'page',
    transition: {
      type: 'view-transition',
      viewTransitionName: `product-${product.id}`
    }
  }}
>
  <Card style={{ viewTransitionName: `product-${product.id}` }}>
    <Image src={product.thumbnail} />
    <Text>{product.name}</Text>
  </Card>
</NavigationLink>

// Detail page with matching shared element
<StandardPage
  id="product-detail"
  transition={{
    type: 'view-transition',
    viewTransitionName: `product-${product.id}`
  }}
>
  <Card style={{ viewTransitionName: `product-${product.id}` }}>
    <Image src={product.fullImage} />
    <Text>{product.description}</Text>
  </Card>
</StandardPage>

Conditional Navigation

function ProductList({ products }) {
  const handleProductClick = (product) => {
    if (product.available) {
      // Navigate to detail
    } else {
      // Show unavailable message
    }
  }

  return (
    <List>
      {products.map(product => (
        <NavigationLink
          key={product.id}
          destination={() => <ProductDetail product={product} />}
          pageOptions={{ type: 'page' }}
        >
          <ProductRow
            product={product}
            onClick={handleProductClick}
          />
        </NavigationLink>
      ))}
    </List>
  )
}

Best Practices

  1. Use appropriate page types: Use 'page' for standard navigation, 'actionsheet' for modal-like presentations
  2. Choose the right transition: Use 'view-transition' for shared elements, 'fade' for modals, 'slide' for standard navigation
  3. Set viewTransitionName consistently: When using View Transitions, ensure source and target elements use the same name
  4. Keep transitions smooth: Use appropriate durations (200-400ms) and easing functions
  5. Provide clear destinations: Always specify a valid destination prop
  6. Use dismiss for back navigation: Use dismiss prop or navi.dismiss() for going back

View Transitions API Notes

  • View Transitions API requires browser support (Chrome 111+, Edge 111+)
  • Falls back to CSS animations if not supported
  • Shared element animations require matching viewTransitionName on both source and target
  • Works best with images, cards, and other visual elements
  • Can be combined with other transition types for different elements

On this page