import { type ReactNode } from "react"; import { type ColorTokens, type StyleProp, type ViewStyle, type TextStyle } from "../../style/index.js"; export interface TabBarItem { /** Stable identity for the destination; passed to onSelect and compared to `active`. */ key: string; label: string; /** Renders the tab's glyph; `active` lets the caller tint it (e.g. primary vs muted). */ icon: (active: boolean) => ReactNode; /** Something new waits behind the destination: a small destructive dot over the cell's * glyph, and ", unread" after the tab's accessible name. */ unread?: boolean; } export interface TabBarProps { items: TabBarItem[]; /** The active item's key; omit for uncontrolled use. */ active?: string; /** Initial active key for uncontrolled use (defaults to the first item's key). */ defaultActive?: string; /** Called with the pressed destination's key (both modes). */ onSelect?: (key: string) => void; /** E2E hook forwarded to the tablist row. */ testID?: string; /** * Safe-area bottom inset, e.g. `insets.bottom`. It is added BELOW the bar's own symmetric * vertical padding (not in place of it), so the bar clears the home indicator without making * the bottom margin heavier than the top. Defaults to 0 (web desktop / no inset). */ bottomInset?: number; /** Outer layout composition only. Use bottomInset for the safe area. */ style?: StyleProp; } export interface TabBarSkin { /** Bar shape: hairline, radius, min height and padding (the fill/border colors come from `fill`). */ bar: (tokens: ColorTokens) => ViewStyle; /** * Bar fill and border colors from the active tokens. Solid mode paints them; under * glass the material replaces the fill and the border is the rim. Defaults to the * card fill with the border hairline. */ fill?: (tokens: ColorTokens) => { backgroundColor: string; borderColor?: string; }; /** * A floating capsule instead of a docked, full-bleed bar: `horizontal` is the inset * from the container's sides, `bottom` the least space kept under the capsule, and * `clearance` how far into the safe-area inset the capsule may reach (the bar sits * `max(bottom, bottomInset - clearance)` above the container's bottom edge, so it * floats over the home-indicator zone without touching the indicator itself, the * way the iOS 26 tab bar does). Undefined for a docked bar. */ floating?: { horizontal: number; bottom: number; clearance: number; }; /** One destination cell: flex 1, centered, icon/label gap + vertical padding. */ item: ViewStyle; /** Label type per active state (size/line-height/weight/tracking; the color is applied by shared). */ label: (active: boolean) => TextStyle; /** The label's ink per active state; the accent's text ink active and `muted-foreground` at rest when left out. */ labelColor?: (tokens: ColorTokens, active: boolean) => string; /** The space between the destination cells (none when left out). */ cellGap?: number; /** Android press ripple (null on iOS/web, which dim instead). */ ripple: ((tokens: ColorTokens) => { color: string; borderless: boolean; radius?: number; }) | null; /** iOS/web press dim (null on Android, where the ripple carries it). */ pressedOpacity: number | null; /** * The active indicator. With `pillCovers: "icon"` (the default) it is a fixed-size * pill centred behind the glyph, so the style carries a `width` and `height` * (Android's M3 dimensions). With `pillCovers: "cell"` it is a capsule filling the * whole destination cell, so the style carries only the fill and radius. `dark` * lets the fill follow the scheme. Returns the indicator's style; null for a bar * whose selection is the tint alone. */ pill: ((tokens: ColorTokens, dark: boolean) => ViewStyle) | null; pillCovers?: "icon" | "cell"; /** The `unread` dot, positioned in the destination cell over its glyph. */ unread: (tokens: ColorTokens) => ViewStyle; } export declare function createTabBar(skin: TabBarSkin): ({ items, active, defaultActive, onSelect, bottomInset, style, testID }: TabBarProps) => import("react").JSX.Element; //# sourceMappingURL=tab-bar.shared.d.ts.map