# AI_GUIDE — Liquid Glass Tab Bars (App 4)

> **Audience: AI coding agents** (Claude, Cursor, Copilot, GPT…) and developers.
> **Goal (A):** choose one of 6 open-source Liquid Glass tab-bar projects and add it **correctly** to a real app.
> **Goal (B):** rebuild **anything shown in App 4** (7 sections, every phone, every control) exactly, and customise it. See **§11 Rebuild map** and **§12 Customisation cookbook**.
> Exact numbers for everything: **`tokens.json`**.
> **Goal (C): design anything for Apple platforms** (not just tab bars). Use **`workbench/`**, the Apple Design Workbench: `workbench/AGENT_SKILL.md` (contract, platform rules, scales, component map, charts, RTL), `workbench/src/data-platforms.js` (type scales, colours, spacing, hit targets, motion, devices, states, each with a confidence), `workbench/src/data-library.js` (55 component/pattern cards + 9 chart types), `workbench/src/data-sources.js` (124 cited sources). Open `workbench/Apple Design Workbench.html` to generate a cited plan and code for a brief.
> Read this file top to bottom. Follow the steps literally. Do **not** invent APIs: if something is not written here, open the linked README before coding.
> Visual tokens (colours, sizes, motion) live in `DESIGN_SYSTEM.md` in the same folder. The interactive reference is `App 4 - Liquid Glass Tab Bars.html`.

Last reviewed: 2026-09. Upstream projects change. **Always check the upstream README before you pin versions or API names.**

---

## 0. Machine-readable index

```yaml
projects:
  - id: liquidglasstabbars
    name: LiquidGlassTabBars
    product: LiquidUI
    repo: https://github.com/mikonyaa/LiquidGlassTabBars
    install: { spm: "https://github.com/mikonyaa/LiquidGlassTabBars.git", product: LiquidUI }
    platform: [iOS 17+, native glass on iOS 26+, Swift 6, Xcode 26+]
    stack: SwiftUI
    license: MIT
    kind: library
    variants: [system, floating, morphing]
    max_tabs_custom: 5
  - id: uniontabview
    name: UnionTabView
    repo: https://github.com/unionst/union-tab-view
    docs: https://www.swiftipedia.org/documentation/uniontabview
    install: { spm: "https://github.com/unionst/union-tab-view.git", product: UnionTabView }
    platform: [iOS 17+, Swift 6, Xcode 16+]
    stack: SwiftUI
    license: MIT
    kind: library
    strength: custom item views (avatar, badge, animated symbols) inside the iOS 26 glass bar
  - id: fabbar
    name: FabBar
    repo: https://github.com/ryanashcraft/FabBar
    install: { spm: "https://github.com/ryanashcraft/FabBar.git", from: "1.0.0", product: FabBar }
    platform: [iOS 26]
    stack: SwiftUI API + UIKit internals
    license: MIT
    kind: library
    strength: tinted floating action button next to the tab bar
    risk: relies on internal UIKit view hierarchy; may break on iOS updates
  - id: square
    name: Square
    repo: https://github.com/Lelonio/Square
    platform: [Android 8.0+]
    stack: Kotlin + Jetpack Compose
    license: GPL-3.0-or-later
    kind: app            # NOT a library — use as design reference only
    glass_library: backdrop   # see id: backdrop
    icons: Phosphor Icons (MIT)
  - id: expo-glass-tabs
    name: expo-glass-tabs
    repo: https://github.com/davidmokos/expo-glass-tabs
    install: { npm: expo-glass-tabs }
    platform: [Expo Router, iOS 26 real glass, solid fallback on older iOS and Android]
    stack: React Native + TypeScript (Reanimated, Gesture Handler)
    license: MIT
    kind: library
    strength: Revolut-style bar that minimizes on scroll (all icons stay), finger scrubbing
  - id: figma-liquid-glass
    name: iOS 26 Liquid Glass Effect (Figma kit)
    author: Jan Decker
    source: https://www.figma.com/community/file/1514186232748375562/ios-26-liquid-glass-effect
    kind: design kit (material + components) — web port in src/figma-glass.{css,jsx}
    platform: [Figma, Web (CSS backdrop-filter), maps to SwiftUI .glassEffect / Compose Backdrop]
    license: Figma Community (free); web port original
    tokens: tokens.json#07_figma_liquid_glass
  - id: backdrop
    name: AndroidLiquidGlass (Backdrop)
    repo: https://github.com/Kyant0/AndroidLiquidGlass    # default branch: kmp
    docs: https://kyant.gitbook.io/backdrop
    docs_for_ai: https://kyant.gitbook.io/backdrop/llms.txt   # append .md to any docs page URL
    install: { gradle: "io.github.kyant0:backdrop:<version>", version_source: "https://central.sonatype.com/artifact/io.github.kyant0/backdrop" }
    platform: [Compose Multiplatform, Android 12+ (effects), Android 13+ (lens), iOS via CMP]
    stack: Kotlin + Compose
    license: Apache-2.0
    kind: library (low-level; NO high-level components shipped)
    copy_components_from: app/src/commonMain/kotlin/com/kyant/backdrop/catalog/components/{LiquidBottomTabs,LiquidButton,LiquidToggle,LiquidSlider}.kt
```

---

## 1. Decision tree (pick exactly one)

```
What is the app built with?
├─ SwiftUI (iOS)
│   ├─ Standard tabs, least maintenance ............ LiquidGlassTabBars → SystemGlassTabView
│   ├─ Branded single capsule / expanding tabs ...... LiquidGlassTabBars → LiquidTabBar(.floating | .morphing)
│   ├─ Avatar / badge / animated icon inside bar .... UnionTabView
│   └─ Primary "create" action beside tabs .......... FabBar   (iOS 26 only, UIKit-internals risk)
├─ Jetpack Compose / Compose Multiplatform ......... Backdrop (AndroidLiquidGlass) (code, §5b) + Square (visual reference, §5)
├─ React Native / Expo Router ....................... expo-glass-tabs
├─ Web ............................................. copy the web port from this folder (§7)
└─ Need the glass MATERIAL or non-tab controls
   (buttons, cards, search, toggles, sliders, menus) … 07 Figma glass kit (§6b) — web port or native mapping
```

Hard rules:
- Custom bars (Floating, Morphing, UnionTabView, FabBar, expo-glass-tabs) should hold **2–5 tabs**. With more than 5, use the native/System bar.
- **Never copy Square source code into a non-GPL app.** Copy its look; use AndroidLiquidGlass for the code.
- Do not use a `role: .search` tab as a fake action button. Use FabBar instead.
- Keep glass on **navigation and controls only**, never on long-form content.
- Minimum touch target **44 pt**.

---

## 2. LiquidGlassTabBars (SwiftUI) — recipe

**Install:** Xcode → File → Add Package Dependencies → `https://github.com/mikonyaa/LiquidGlassTabBars.git` → product **LiquidUI**.

**Step 1: tab enum**
```swift
enum AppTab: Hashable, Sendable { case home, activity, library, profile }
```
**Step 2a: native (preferred)**
```swift
import LiquidUI
SystemGlassTabView(selection: $selectedTab, tint: .blue) {
    HomeView().tabItem { Label("Home", systemImage: "house.fill") }.tag(AppTab.home)
    ActivityView().tabItem { Label("Activity", systemImage: "waveform.path.ecg") }.tag(AppTab.activity)
}
```
**Step 2b: custom Floating / Morphing**
```swift
let items = [
  LiquidTabItem(id: AppTab.home, title: "Home", systemImage: "house.fill"),
  LiquidTabItem(id: AppTab.activity, title: "Activity", systemImage: "waveform.path.ecg"),
  LiquidTabItem(id: AppTab.library, title: "Library", systemImage: "square.grid.2x2.fill"),
  LiquidTabItem(id: AppTab.profile, title: "Profile", systemImage: "person.crop.circle.fill")
]
RootContent(tab: selectedTab)
  .safeAreaInset(edge: .bottom, spacing: 0) {
    LiquidTabBar(selection: $selectedTab, items: items, variant: .floating, theme: .classic,
                 onReselect: { _ in /* scroll to top */ })
      .padding(.horizontal, 16).padding(.vertical, 8)
  }
```
Themes: `.classic` (tint #3394FF) · `.violet` (#C287FF) · `.ocean` (#47D1FF) · `.neutral`, or `LiquidTabBarTheme(tint:inactiveForeground:fallbackFill:fallbackBorder:selectedFillOpacity:selectedBorderOpacity:shadowColor:shadowRadius:itemSpacing:)`.
Motion: `.spring(response: 0.32, dampingFraction: 0.82)`, removed automatically under Reduce Motion.

---

## 3. UnionTabView (SwiftUI) — recipe

**Install:** SPM `https://github.com/unionst/union-tab-view.git` → product **UnionTabView**. iOS 17+.

```swift
import UnionTabView

enum RootTab: CaseIterable { case home, explore, activity, profile }

UnionTabView(selection: $tab, tabs: RootTab.allCases) {
    NavigationStack { HomeView() }.unionTab(RootTab.home)          // REQUIRED on every tab root
    NavigationStack { ExploreView() }.unionTab(RootTab.explore)
    NavigationStack { ActivityView() }.unionTab(RootTab.activity)
    NavigationStack { ProfileView() }.unionTab(RootTab.profile)
} item: { tab, isSelected in
    // ANY SwiftUI view: avatar, badge, animated symbol
    Image(systemName: icon(for: tab))
        .symbolEffect(.bounce, value: isSelected)
        .foregroundStyle(isSelected ? .blue : .secondary)
}
```
- `.unionTab(_:)` hides the system bar on iOS 26 and adds safe-area spacing; on iOS 17–25 it acts as `.tag()`.
- Profile picture guide: https://www.swiftipedia.org/documentation/uniontabview/customviewsinliquidglasstabbars
- Internals: an invisible `UISegmentedControl` provides the sliding indicator, haptics and VoiceOver. Item views use `allowsHitTesting(false)`.

---

## 4. FabBar (SwiftUI, iOS 26) — recipe

**Install:** `.package(url: "https://github.com/ryanashcraft/FabBar.git", from: "1.0.0")` → product **FabBar**.

```swift
import FabBar
TabView(selection: $selectedTab) {
  Tab("Home", systemImage: "house.fill", value: .home) {
    HomeView().fabBarSafeAreaPadding().toolbarVisibility(tabBarVisibility, for: .tabBar)
  }
  // …same for every tab
}
.fabBar(
  selection: $selectedTab,
  tabs: [
    FabBarTab(value: .home, title: "Home", systemImage: "house.fill", onReselect: { scrollToTop() }),
    FabBarTab(value: .explore, title: "Explore", systemImage: "map.fill"),
    FabBarTab(value: .profile, title: "Profile", systemImage: "person.fill"),
  ],
  action: FabBarAction(systemImage: "plus", accessibilityLabel: "Add Item") { addItem() },
  isVisible: !isSelecting
)
```
where `tabBarVisibility = horizontalSizeClass == .compact ? .hidden : .visible` (on iPad FabBar hides itself and the native bar shows).
- Manual placement: use the `FabBar` view inside `.safeAreaBar(edge: .bottom)` with **21 pt** padding, plus `.ignoresSafeArea(.container, edges: .bottom)`.
- Custom asset icon: `FabBarTab(value:, title:, image: "name", imageBundle: .main)`.
- Limitations to tell the user about: no Large Content Viewer, VoiceOver focus may jump, no automatic scroll-to-top (use `onReselect`), dimensions hard-coded to iOS 26.

---

## 5. Square → Android (Compose) — recipe

Square is an **app** under **GPL-3.0**. Treat it as a *visual spec*. Implement with **AndroidLiquidGlass** (Apache-2.0).

1. Add Backdrop (§5b): `io.github.kyant0:backdrop:<version>`, with the version taken from Maven Central.
2. Build one reusable `GlassSurface` composable. Every control uses it: tab bar, mini player, player buttons, chips, sheets and menus.
3. Expose Square's five glass settings with its presets (DESIGN_SYSTEM §15.1): **Colour 100% · Frost 2 dp · Edge depth 24 dp · Bend 38 dp · Edge light 55%** (Quality). Balanced = 100/2/16/22/45 and Fastest = 100/0/0/0/30. Map them to Backdrop as Colour→`colorControls(saturation)`, Frost→`blur`, Edge depth→`lens(refractionHeight)`, Bend→`lens(refractionAmount)`, Edge light→`highlight` alpha.
4. Layout to reproduce (DESIGN_SYSTEM §15.1): a 5-tab light glass capsule **Home · New · Radio · Library · Search** (58 dp) and a 55 dp glass mini player above it; a player tinted from the cover with a 61 dp now-playing pill plus outlined ring buttons, 58/73/58 dp glass transport, and a 4-pane glass switcher (cover · lyrics · effects · credits).
5. Icons: Phosphor Icons (MIT), `phosphor-icons` for Compose or the SVGs.
6. Do **not** copy Square's Spotify/YouTube code. It is outside tab-bar scope and legally restricted.

---

## 5b. Backdrop / AndroidLiquidGlass (Compose) — recipe

**Install:**
```kotlin
// build.gradle.kts (module) — resolve <version> from Maven Central; never guess
dependencies { implementation("io.github.kyant0:backdrop:<version>") }
```
**Step 1:** record the background and draw a glass bottom bar (official tutorial pattern):
```kotlin
Box(Modifier.fillMaxSize()) {
    val backgroundColor = MaterialTheme.colorScheme.background
    val backdrop = rememberLayerBackdrop {          // paint bg too, or glass shows transparent pixels
        drawRect(backgroundColor)
        drawContent()
    }
    MainNavHost(modifier = Modifier.layerBackdrop(backdrop))

    Box(
        Modifier
            .safeContentPadding()
            .drawBackdrop(
                backdrop = backdrop,
                shape = { CircleShape },               // lens REQUIRES a CornerBasedShape
                effects = {
                    vibrancy()                         // 1. color filter
                    blur(4f.dp.toPx())                 // 2. blur
                    lens(16f.dp.toPx(), 32f.dp.toPx()) // 3. lens (Android 13+)
                },
                onDrawSurface = { drawRect(Color.White.copy(alpha = 0.5f)) }   // readability
            )
            .height(64f.dp)
            .fillMaxWidth()
            .align(Alignment.BottomCenter)
    )
}
```
**Step 2: interactive tabs.** Copy `LiquidBottomTabs.kt` plus its utils (`catalog/utils/DampedDragAnimation`, `InteractiveHighlight`) and `com.kyant.shapes.Capsule` usage from the catalog (keep the Apache-2.0 notice). Signature:
```kotlin
LiquidBottomTabs(
    selectedTabIndex = { selected },
    onTabSelected = { selected = it },
    backdrop = backdrop,
    tabsCount = 4,
    modifier = Modifier.padding(horizontal = 16.dp).navigationBarsPadding()
) { /* RowScope: one item per tab (icon + label), weight(1f) */ }
```
Tokens: 64 dp capsule, padding 4, `vibrancy(); blur(8.dp); lens(24.dp, 24.dp)`, container `#FAFAFA@40%` (dark `#121212@40%`), accent `#0088FF` (dark `#0091FF`).
**Tinted glass button:** `onDrawSurface = { drawRect(tint, blendMode = BlendMode.Hue); drawRect(tint.copy(alpha = 0.75f)) }`.
**Rules:** effect order = color filter ⇒ blur ⇒ lens · `refractionHeight ≤ minCornerRadius` · `refractionAmount ≤ minDimension` · below Android 12 no effects render, so provide a solid surface colour fallback.
**When unsure:** GET `https://kyant.gitbook.io/backdrop/<page>.md?ask=<question>` (the docs support AI queries).

## 6. expo-glass-tabs (Expo Router) — recipe

**Install (exact):**
```bash
npx expo install expo-glass-tabs expo-blur expo-glass-effect expo-haptics expo-symbols react-native-gesture-handler react-native-reanimated react-native-safe-area-context react-native-screens
```
**Step 1:** wrap the root in `GestureHandlerRootView` (Expo Router does **not** do this for you):
```tsx
// app/_layout.tsx
import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function RootLayout() { return <GestureHandlerRootView style={{ flex: 1 }}>{/* Stack / Slot */}</GestureHandlerRootView>; }
```
**Step 2:** the tabs layout (`app/(tabs)/_layout.tsx`):
```tsx
import { useRouter } from 'expo-router';
import { Tabs, TabList, TabSlot, TabTrigger } from 'expo-router/ui';
import { GlassTabBar, GlassTabButton, TabBarMinimizeProvider, renderFadingTabScreen, type GlassTabItem } from 'expo-glass-tabs';

const ITEMS: (GlassTabItem & { href: string })[] = [
  { name: 'index', href: '/', label: 'Home', icon: 'house.fill' },
  { name: 'invest', href: '/invest', label: 'Invest', icon: 'chart.line.uptrend.xyaxis' },
  { name: 'payments', href: '/payments', label: 'Payments', icon: 'arrow.left.arrow.right' },
  { name: 'crypto', href: '/crypto', label: 'Crypto', icon: 'bitcoinsign' },
];

export default function AppTabs() {
  const router = useRouter();
  return (
    <TabBarMinimizeProvider>
      <Tabs>
        <TabSlot style={{ height: '100%' }} renderFn={renderFadingTabScreen} />
        <TabList asChild>
          <GlassTabBar onIndexSelected={(i) => router.navigate(ITEMS[i].href as never)}>
            {ITEMS.map(({ href, ...item }, index) => (
              <TabTrigger key={item.name} name={item.name} href={href as never} asChild>
                <GlassTabButton item={item} index={index} />
              </TabTrigger>
            ))}
          </GlassTabBar>
        </TabList>
      </Tabs>
    </TabBarMinimizeProvider>
  );
}
```
**Step 3:** in **every** scrollable screen that should minimize the bar:
```tsx
import Animated from 'react-native-reanimated';
import { useMinimizeOnScroll } from 'expo-glass-tabs';
const onScroll = useMinimizeOnScroll();
<Animated.ScrollView onScroll={onScroll} scrollEventThrottle={16}>{/* … */}</Animated.ScrollView>
```
- Theme prop: `theme={{ activeTint, inactiveTint, highlight, glassTint, solidFallback }}`, `haptics` (default true).
- Custom icon: `renderIcon: ({ tint }) => <Image source={…} tintColor={tint} style={{ width: 18, height: 17 }} />`.
- Extra exports: `useTabBarMinimized()` (0..1 progress), `ProgressiveBlur` (`direction="top"` for headers), `MINIMIZE_SPRING`.

---

## 6b. iOS 26 Liquid Glass Effect (Figma kit) — recipe

**Web (copy these files):** `src/icons.jsx` (for `SF`), `src/figma-glass.css`, `src/figma-glass.jsx`. `<Device>` and `<SecHead>` live in `src/union.jsx`; only the demo phones need them.

```jsx
// 1. put the kit root around your screen (class + CSS vars = the whole theme)
const kit = { ...LG_DEFAULT, variant: 'regular', tone: 'dark', accent: '#0A84FF' };
<div className={lgClass(kit)} style={lgVars(kit)}>
  <LGButton icon="location.fill">Button primary</LGButton>
  <LGIconButton icon="ellipsis" label="More" />
  <LGSearch placeholder="Search" value={q} onChange={setQ} />
  <LGSegmented options={['Day','Week','Month']} value={seg} onChange={setSeg} />
  <LGlass radius={28} className="lg-card">
    <div className="lg-row"><span className="lg-row-t">Wi-Fi</span><LGToggle on={wifi} onChange={setWifi} label="Wi-Fi" /></div>
    <div className="lg-row col"><LGSlider value={v} onChange={setV} left="sun.max.fill" right="sun.max.fill" /></div>
  </LGlass>
  <LGTabBar tabs={[{id:'home',title:'Home',icon:'house.fill'}]} sel={tab} onSel={setTab} />
</div>
// 2. any custom glass shape:
<LGlass as="button" interactive radius={18} style={{ width: 120, height: 48 }}>…</LGlass>
// 3. refraction (Chromium): render <LGFilters/> once and add "lg-can-refract rf-soft" to the kit root
```
**Rules:** glass must sit over **varied content** (a photo or gradient); on a flat colour it looks like a grey pill · keep text ≥ 4.5:1 (use Frosted or raise the tint on busy images) · never put glass on glass without a gap: group touching shapes (SwiftUI `GlassEffectContainer`) · with `.rt` everything becomes opaque `--lg-solid`.
**SwiftUI:** `.glassEffect(.regular | .clear | .regular.tint(c), in: .capsule | .rect(cornerRadius: 28))`, `.interactive()` for controls, `.buttonStyle(.glass | .glassProminent)`. Do **not** add custom blur on iOS 26.
**Compose:** see §5b and use the playground's "Compose" export.
**Playground export:** the 07 playground prints ready-to-paste CSS, React, SwiftUI and Compose code for the current slider values. Copy it instead of guessing.

## 7. Web — reuse the port in this folder

Files: `src/icons.jsx` (SF-Symbol look-alikes, `<Sym name/>`), `src/figma-glass.jsx` + `src/figma-glass.css` (07), `src/tabbars.jsx` (01), `src/union.jsx` (02 + shared `Device`, `SecHead`, `Code`), `src/fabbar.jsx` (03), `src/square.jsx` (04), `src/expo.jsx` (05), `src/backdrop.jsx` (06), `src/demo.jsx` (page shell).
CSS lives in `App 4 - Liquid Glass Tab Bars.html` under the headings `/* 1 · SYSTEM */`, `/* 2 · FLOATING */`, `/* 3 · MORPHING */`, `/* 02 · UnionTabView */`, `/* 03 · FabBar */`, `/* 04 · Square */`, `/* 05 · expo-glass-tabs */` and `/* 06 · Backdrop */`.
Each JSX file starts with `Object.assign(window, { useState… })` and ends with `Object.assign(window, {…exports})`. Load order: icons → tabbars → union → fabbar → square → expo → backdrop → **figma-glass** → demo. `figma-glass.css` is linked in `<head>` after the inline `<style>`.

---

## 8. Verification checklist (run before saying "done")

- [ ] The bar sits in a bottom safe-area inset; content scrolls fully clear of it.
- [ ] 2–5 tabs; each hit target is ≥ 44 pt.
- [ ] Selection animates; with **Reduce Motion** on, it switches instantly.
- [ ] With **Reduce Transparency** on (or on unsupported OS versions), an opaque fallback is shown and contrast still passes.
- [ ] VoiceOver/TalkBack reads each item as a tab with its title and selected state.
- [ ] Reselecting a tab scrolls to the top where expected (`onReselect`).
- [ ] iPad / large screens: the native bar or sidebar is used where the library says so (FabBar hides itself).
- [ ] The licence notice is added to the app's Acknowledgements (MIT authors; Apache-2.0 for AndroidLiquidGlass).
- [ ] No Square (GPL) source copied into a non-GPL codebase.

## 9. Common mistakes (avoid)

| Mistake | Fix |
|---|---|
| Custom blur added on top of `SystemGlassTabView` | Don't: the system owns the glass on iOS 26 |
| Missing `.unionTab()` on a tab root | The system bar reappears or overlaps; add it to every root |
| Missing `.fabBarSafeAreaPadding()` | Content hides under FabBar |
| No `GestureHandlerRootView` in Expo | Scrubbing and taps fail; wrap the root layout |
| `useMinimizeOnScroll` on a plain `ScrollView` | Must be `Animated.ScrollView` with `scrollEventThrottle={16}` |
| More than 5 tabs in a custom bar | Use the native bar, or restructure navigation |
| Backdrop effects in the wrong order (lens before blur) | Always use color filter ⇒ blur ⇒ lens |
| Backdrop `lens` on a non-CornerBasedShape | Use CircleShape / RoundedCornerShape / Capsule |
| Transparent pixels in Backdrop glass | Paint the background inside `rememberLayerBackdrop { drawRect(bg); drawContent() }` |
| Shape mismatch after customising corners (LiquidUI) | Change glass, contentShape, border and pill together |

## 11. Rebuild map — every element in App 4 → where it lives

Use this to reproduce any part **exactly**: open the file, copy the component and its CSS block, then take the numbers from `tokens.json`.

| Section | What you see | Component (file) | CSS block (in the HTML `<style>` unless noted) | Tokens |
|---|---|---|---|---|
| Page | Hero, TOC, section cards, footer | `App4` (demo.jsx) | top of `<style>` (`.hero .toc .sec .sh`) | — |
| shared | iPhone frame 393×852, status bar, island, home bar | `Device` (union.jsx) | `/* devices */` | `device` |
| shared | Section header with repo + copy buttons | `SecHead`, `Code` (union.jsx) | `.sh .btn-l .code` | — |
| shared | SF-Symbol look-alikes | `Sym` / `SF` (icons.jsx), `LgI` / `LGI` (figma-glass.jsx) | `.sym` | — |
| 01 | System / Floating / Morphing bars, themes, top menu, demo screen | `LiquidTabBar`, `themeVars` (tabbars.jsx) · `PhoneDemo`, `Menu`, `DemoScreen`, `Ring` (demo.jsx) | `/* 1 · SYSTEM */` `/* 2 · FLOATING */` `/* 3 · MORPHING */` `.glass` `.topmenu` `.ds` | `01_liquidglasstabbars` |
| 02 | Custom items, bounce, pill | `UnionBar`, `UNION_ITEMS` (union.jsx) | `/* 02 · UnionTabView */` | `02_uniontabview` |
| 03 | Light bar + FAB, tints, selection mode | `FabBar`, `FabPhone` (fabbar.jsx) | `/* 03 · FabBar */` | `03_fabbar` |
| 04 | Player, lyrics, effects, album, artist, glass settings | `SquareSection` and children (square.jsx) | `/* 04 · Square */` (`.sq2*`) | `04_square` |
| 05 | Minimising Revolut-style bar, scrubbing | `ExpoPhone` (expo.jsx) | `/* 05 · expo-glass-tabs */` (`.ex-*`) | `05_expo_glass_tabs` |
| 06 | LiquidBottomTabs, playground, toggle/slider/button | `LiquidBottomTabs`, `BdPlayground`, `BdControls` (backdrop.jsx) | `/* 06 · Backdrop */` (`.bd-*`) | `06_backdrop` |
| 07 | Glass primitive, 14 components, Home / Controls / Now Playing phones, playground + code export | `LGlass` + `LG*` components, `LGHomePhone`, `LGControlsPhone`, `LGPlayerPhone`, `LGPlayground` (figma-glass.jsx) | **`src/figma-glass.css`** (sections 1–4 inside) | `07_figma_liquid_glass` |

**Rebuild procedure (for any row):**
1. Copy the component, and everything it references, from the listed file. Each file's last line `Object.assign(window,{…})` lists its exports.
2. Copy the CSS block. Keep the class names; the JSX depends on them.
3. Wrap it in the same scope it uses on the page: `themeVars()` for 01, `lgClass/lgVars` for 07, `.sq2` vars for 04, a `theme.vars` object for 05.
4. Check against `tokens.json` (sizes, colours, radii) and the screenshot of the live page. Then run the §8 checklist.

## 12. Customisation cookbook

| I want to… | Do this |
|---|---|
| Change the brand colour everywhere in 07 | `accent` in the kit state → `--lg-accent` (tab selection, prominent buttons, tinted glass) |
| Make 07 glass more or less see-through | Raise or lower `tint` (0–0.9) and `blur` (0–40). Presets: Clear < Regular < Frosted |
| Put glass on a light UI | `tone: 'light'` (`fg #111`, white tint 42%) |
| Change the corner radius of one glass element | `<LGlass radius={20}>` or `--lg-radius:20px` in CSS |
| Brighter or softer edges | `shine` (inner light) and `rim` (1px gradient stroke). `--lg-angle` moves the light direction |
| Add a new glass component | Wrap the markup in `<LGlass>`. Put children after the 4 layers (the component does this). Add `interactive` if it's pressable. Size it with a class |
| Different tab items (01) | Edit `TABS` (demo.jsx) or pass your own `items=[{id,title,systemImage}]`, 2–5 items |
| New 01 theme | Add a key to `THEMES` in tabbars.jsx with `tint` (r,g,b), `inactive`, `fallbackFill`, `fallbackBorder`, `shadow` |
| Custom tab item view (02) | Add a function to `UNION_ITEMS`: `(tab, isSelected) => JSX` |
| FAB tint or icon (03) | `FAB_TINTS` array / the `plus` Sym inside `FabBar` |
| Square glass strength (04) | Glass-settings sliders → vars `--frost --depth --bend --elight --colour`; presets in DESIGN_SYSTEM §15.1 |
| Expo bar colours (05) | Add an entry to `EX_THEMES` with `--ex-active --ex-inactive --ex-hl --ex-glass --ex-solid` |
| Backdrop accent (06) | `BD_ACCENT` + `.bd-tab.on` colour |
| Replace a wallpaper | Put the image in `assets/`, edit `LG_WALLS` (07) or the `bg` prop of `Device` |
| Replace an icon | Add an SVG (24×24 viewBox, `currentColor`) to `LGI` or `SF` under an SF-Symbol-style name |
| Turn off motion or transparency | `.rm` / `.rt` class on any ancestor (the section toggles in 01 do this for the whole page) |
| Port to native | 07 → DESIGN_SYSTEM §18.5 table, or use the playground export tabs |

**Do not:** rename CSS classes without updating the JSX · stack two `.lg` elements edge-to-edge (the rims double up) · put glass on long text content · change the effect order (Effect → Tint → Shine → Rim).

## 10. Credits

LiquidGlassTabBars © mikonyaa (MIT) · UnionTabView © Ben Sage / Union St (MIT) · FabBar © Ryan Ashcraft (MIT; idea credit Kavsoft) · Square © Lelonio (GPL-3.0-or-later) · AndroidLiquidGlass © Kyant0 (Apache-2.0) · expo-glass-tabs © David Mokos (MIT) · Phosphor Icons (MIT) · iOS 26 Liquid Glass Effect Figma kit © Jan Decker (Figma Community). Wallpapers in `assets/` are public-domain photos.
Apple, iOS, SwiftUI and SF Symbols are trademarks of Apple Inc. Spotify and YouTube are trademarks of their owners. Not affiliated with or endorsed by any of them.
