Underline tabs with gliding indicator and press ink.
$ npx lumioui add tabs
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs/tabs";
Parts: TabsList · TabsTrigger · TabsContent
Files installed into your repo
components/ui/tabs/tabs.tsx
Registry dependencies (installed automatically)
Native packages required
@lumioui/core@latestreact-native-reanimated@*
Props6
| value? | string | Controlled selected value. Omit with defaultValue for uncontrolled use. |
| defaultValue? | string | Initial value for uncontrolled use. |
| onValueChange? | (value: string) => void | |
| variant? | TabsVariant | Visual variant: "pill" (default, gliding pill) or "line" (underlined list). |
| glass? | boolean | iOS 26 liquid treatment — pill tabs ride inside a glass capsule and the gliding indicator is a raised glass pill. |
| className? | string | |
Tabs — Liquid capsuleglass.tsx
Live preview offline the relay is unreachable — check back shortly
tabs/variants/glass.tsx open Underline tabs with gliding indicator and press ink.
import { TabsGlass } from "@/components/ui/tabs/variants/glass";
export function Example() {
return (
<TabsGlass />
);
}
import * as React from "react";
import { View } from "react-native";
import { Tabs, TabsList, TabsTrigger } from "../tabs";
import { Ambient } from "../../glass/ambient";
/** TabsGlass — the tab bar floats as a liquid capsule over media. */
export function TabsGlass() {
return (
<View className="relative h-[420px] w-full overflow-hidden rounded-3xl">
<Ambient seed="tabs" />
<View className="absolute bottom-5 left-4 right-4">
<Tabs glass defaultValue="all">
<TabsList>
<TabsTrigger value="all">All</TabsTrigger>
<TabsTrigger value="saved">Saved</TabsTrigger>
<TabsTrigger value="shared">Shared</TabsTrigger>
</TabsList>
</Tabs>
</View>
</View>
);
}
Tabs — Spendspend.tsx
Live preview offline the relay is unreachable — check back shortly
tabs/variants/spend.tsx open Underline tabs with gliding indicator and press ink.
import { TabsSpend } from "@/components/ui/tabs/variants/spend";
export function Example() {
return (
<TabsSpend />
);
}
import * as React from "react";
import { View } from "react-native";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../tabs";
import { Icon } from "../../icon/icon";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
function StatRow({ label, value }: { label: string; value: string }) {
return (
<Glass interactive curvature="edge" className="flex-row items-center justify-between rounded-lg px-3 py-2">
<Text variant="muted">{label}</Text>
<Text variant="small" className="tabular-nums">{value}</Text>
</Glass>
);
}
/** TabsSpend — period switcher over a spend summary with stat rows. */
export function TabsSpend() {
const [value, setValue] = React.useState("today");
return (
<View className="w-full gap-3">
<Glass interactive curvature="edge" className="w-full gap-3 rounded-2xl p-4">
<View className="flex-row items-center gap-2">
<Icon name="credit-card" size="sm" color="mutedForeground" />
<Text variant="small" className="font-semibold">Lumo Wallet · Spend</Text>
</View>
<Tabs glass value={value} onValueChange={setValue} className="w-full">
<TabsList>
<TabsTrigger value="today">Today</TabsTrigger>
<TabsTrigger value="week">Week</TabsTrigger>
<TabsTrigger value="month">Month</TabsTrigger>
</TabsList>
<TabsContent value="today">
<View className="gap-1.5 py-2">
<Text variant="large">$1,240.00</Text>
<StatRow label="Transfers" value="3" />
<StatRow label="Largest" value="$860 to Savings" />
</View>
</TabsContent>
<TabsContent value="week">
<View className="gap-1.5 py-2">
<Text variant="large">$4,280.50</Text>
<StatRow label="Transfers" value="18" />
<StatRow label="vs last week" value="+4.2%" />
</View>
</TabsContent>
<TabsContent value="month">
<View className="gap-1.5 py-2">
<Text variant="large">$16,940.00</Text>
<StatRow label="Transfers" value="74" />
<StatRow label="Includes" value="rent · payroll" />
</View>
</TabsContent>
</Tabs>
</Glass>
</View>
);
}