OneScript

TabView

Switch between pages with a bottom tab bar.

TabView renders a native SwiftUI tab bar, and each Tab is one page. On iOS 26 and later, the tab bar uses the Liquid Glass style with a selection highlight.

import { app } from "onescript"
import { NavigationLink, NavigationStack, Tab, TabView, Text, useState } from "onescript/views"

function App() {
  const [tab, setTab] = useState("home")

  return (
    <TabView
      selection={tab}
      onSelectionChange={setTab}
    >
      <Tab
        value="home"
        title="Home"
        icon="house"
      >
        <NavigationStack destination={(id: string) => <Text>Item {id}</Text>}>
          <NavigationLink value="1">Open item 1</NavigationLink>
        </NavigationStack>
      </Tab>
      <Tab
        value="community"
        title="Community"
        icon={{ name: "store.default.fill", source: "pika" }}
      >
        <Text>Community</Text>
      </Tab>
      <Tab
        value="settings"
        title="Settings"
        icon="gearshape"
        badge={3}
      >
        <Text>Settings</Text>
      </Tab>
    </TabView>
  )
}

await app.show(<App />)

TabView

PropTypeDescription
selectionTOptional controlled selection. T is string | number.
onSelectionChange(value: T) => voidCalled when the user switches tabs. Required with selection.
childrenTabThe tabs.

Without selection, TabView manages the selection itself and selects the first tab by default.

Tab

PropTypeDescription
valuestring | numberUnique identifier of the tab.
titlestringTab label text.
iconstring | { name: string; source?: "sf" | "pika" }Tab icon. A string is an SF Symbol; use an object for a Pika icon.
badgenumber | stringOptional badge.
childrenViewChildThe tab content.

The tab bar automatically shows SF Symbols in their filled variant, for example house appears as house.fill. Pika icons are not converted, so use their .fill variants.

Behavior

  • TabView must be the root view passed to app.show(). It cannot be nested or placed inside a NavigationStack.
  • Write <Tab> elements directly inside TabView. Arrays, Fragments, and conditional rendering are allowed, but <Tab> cannot be wrapped in a custom component.
  • A tab can use a NavigationStack as its only direct content. Each tab keeps its own navigation stack.
  • The Close and Console buttons appear on the root page of every tab. When a tab does not set navigationTitle, its title is used as the title; use navigationTitle("") to hide it.
  • All tabs are rendered at launch and keep their state when switching. useEffect in every tab runs at launch.
  • A toolbar with placement="bottomBar" inside a tab appears above the tab bar.
  • Widgets do not support TabView.

How is this guide?

Last updated on

On this page