Open-source project
davidmokos/expo-glass-tabs avatar
davidmokos/expo-glass-tabs

expo-glass-tabs rebuilds the tab bar for one specific scroll behaviour

Floating liquid-glass tab bar for Expo Router — minimize-on-scroll, sliding highlight, finger scrubbing with haptics, progressive edge blur

329 stars12 forksTypeScriptMIT

At a glance

What is it?
expo-glass-tabs is a floating tab bar for Expo Router that shrinks on scroll without hiding icons, supports finger scrubbing with haptics, and runs its animation on the interface thread. The glass material requires a recent iOS version, and installation pulls nine packages.
Who is it for?
This package suits an Expo Router application where the tab bar shrinking on scroll while keeping every icon visible is a deliberate design requirement, or where scrubbing between tabs with a finger is a wanted interaction. Stay with the framework's own tab navigation otherwise, since it costs no dependencies, inherits platform accessibility behaviour and keeps working without anyone maintaining it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 81 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Rebuilding a tab bar because the native one collapses wrong

This package is a floating tab bar for Expo Router, and the README's justification for its existence is unusually specific. The platform's own tab bar can minimize as the user scrolls, and when it does it collapses to a single icon. A well-known banking application's bar behaves differently: every tab stays visible, the labels drop away, and the pill shrinks in both dimensions.

That behaviour is described as unreachable from the native control, so the package rebuilds the bar on top of the framework's headless tabs while still using real platform materials for the glass effect.

That is a narrow reason to write a component and a legitimate one. The difference between collapsing to one icon and shrinking while keeping all icons visible is the difference between the user losing their navigation on scroll and merely seeing it get smaller.

The audience is anyone building an application in this framework who wants that specific interaction and has decided the native control will not give it to them.

What the interaction actually involves

The feature list is worth reading closely, because each entry describes a specific behaviour rather than a general quality.

Minimizing on scroll uses critically damped springs, and rubber-band overscroll is filtered out so the bar does not flicker when the user pulls past the end of a list. That filtering is the detail that separates a working implementation from a demonstration, since overscroll produces exactly the scroll events that make a naive implementation stutter.

The active highlight travels between tabs on an interruptible, transform-only spring. Transform-only matters because transforms can be animated without laying out again, and interruptible matters because a user who taps twice quickly should not wait for the first animation to finish.

Finger scrubbing is the most involved piece. Dragging along the bar moves the highlight with the finger, icons light as they are passed, a haptic tick fires at each boundary, and navigation happens on release rather than during the drag, so screens do not change underneath a moving finger. Deferring navigation to release is the correct choice and not the obvious one.

Everything animated runs in worklets on the interface thread with native gesture recognisers, so a busy application thread does not drop frames. For a component whose entire value is how it feels, that is the architectural decision that decides whether it succeeds.

The glass is conditional, and that is the thing to check first

The headline material is a platform glass effect available from a recent operating system version, giving squircle corners, rim refraction and content lensing. On earlier versions of that platform and on the other mobile platform, the README states there is a solid fallback.

Read that plainly: the marquee visual appears on one recent operating system version and nowhere else. Users on older releases and every user on the other platform get a solid bar. All the motion work still applies, so the minimize, the sliding highlight and the scrubbing behave the same everywhere, and the glass specifically does not.

That is disclosed rather than hidden, and it should govern the decision. If the reason you are adopting this is the glass, you are adopting it for a subset of your users, and it is worth knowing which subset before rather than after. If the reason is the interaction, the fallback costs you an appearance and keeps the behaviour.

The progressive edge blur is separate and worth noting, since content dissolves gradually behind the bar rather than meeting a hard blur line, and the same component is documented as working for top bars as well as bottom ones.

Installing it means nine packages

Installation is a single command and it brings a lot with it.

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

Nine packages for a tab bar looks heavy until you map them to the features: blur and glass for the surface treatment, haptics for the boundary ticks, symbols for the icons, gesture handling and the animation library for the scrubbing and springs, safe area and screens for the layout underneath. Most applications in this framework already carry several of them, so the marginal cost is smaller than the list suggests, and using the framework's own install command means versions are resolved to ones compatible with your runtime rather than the newest published.

One manual step is required and is easy to miss, because the router does not do it for you. The application root has to be wrapped in the gesture handler's root view.

ts
import { GestureHandlerRootView } from 'react-native-gesture-handler';

Wrap the returned tree in that component with a flexing style. Omitting it produces a bar that renders correctly and does not respond to dragging, which is a confusing failure because nothing appears broken until someone tries to scrub.

The package is pure TypeScript with no custom native code, which the README notes means it works both in the managed client and in any development build.

Version 0.1.1, and what that implies

The package version is 0.1.1 and the repository carries no tagged releases. The last push was on 2026-07-22.

For a visual component that is less alarming than it would be for a library holding data, since the failure modes are visible immediately rather than subtle, and the surface is one component with props. It still means no changelog between checkouts, no stability commitment on the interface, and a dependency you should pin.

The dependency chain is the more interesting risk. The animation library and the gesture library both make significant releases, and a component built entirely on their worklets and recognisers is exposed to both. The glass effect package is newer still, tracking a platform capability that itself only recently arrived.

The published package is lean, listing the build output, the source, the documentation and the licence, and shipping its own types alongside a source entry point, so consumers can read the implementation rather than only the compiled output. For a component whose behaviour is this specific, being able to read the spring configuration is worth more than documentation of it.

The native tab bar is the alternative, and it is free

The comparison is against the framework's own tab navigation, which is what this replaces.

The difference is entirely the interaction. The native control is platform standard, costs nothing to add, carries no additional dependencies, inherits accessibility behaviour and platform conventions automatically, and keeps working through operating system updates without anyone maintaining it. Its minimize behaviour collapses to a single icon, and finger scrubbing along the bar is not available.

This package trades that for a specific set of behaviours, at the cost of nine dependencies, a component someone must maintain, a pre-1.0 version and accessibility that is now your responsibility to verify rather than inherited. The README does not discuss screen reader behaviour, which for a custom navigation control is the question a reviewer should ask before shipping.

Take the native control unless the interaction is the point. Take this when the minimize behaviour matters enough to your design that losing the icons is unacceptable, or when scrubbing between tabs is something you actually want users to do. Those are real product decisions and this package is a credible way to implement them, provided the glass being limited to one recent platform version is understood going in.

Editorial conclusion

This package suits an Expo Router application where the tab bar shrinking on scroll while keeping every icon visible is a deliberate design requirement, or where scrubbing between tabs with a finger is a wanted interaction. Stay with the framework's own tab navigation otherwise, since it costs no dependencies, inherits platform accessibility behaviour and keeps working without anyone maintaining it. Confirm before adopting that the glass material only appears on the recent iOS version implementing it, with a solid fallback everywhere else, wrap your application root in the gesture handler root view or scrubbing will silently not work, and pin the version, because the package sits at 0.1.1 with no tagged releases.

Frequently asked questions

Does expo-glass-tabs show real glass on Android?

No. The glass material uses a platform effect available from a recent iOS version, with the README stating there is a solid fallback on older iOS and on Android. The motion behaviour, including minimize on scroll and scrubbing, works regardless.

Why does dragging along the expo-glass-tabs bar do nothing?

The application root most likely is not wrapped in the gesture handler's root view, which Expo Router does not do for you. The bar renders correctly without it, so the failure only appears when someone tries to scrub.

Why does expo-glass-tabs need so many packages?

The nine packages map to features: blur and glass for materials, haptics for boundary ticks, symbols for icons, gesture handling and the animation library for scrubbing and springs, plus safe area and screens for layout. Most Expo applications already include several of them.

Does expo-glass-tabs require a custom development build?

The README states it is pure TypeScript with no custom native code, and that it works in Expo Go as well as any development build. Installation uses the framework's own install command so dependency versions match your runtime.

Official sources

  1. davidmokos/expo-glass-tabs on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/davidmokos-expo-glass-tabs.svg)](https://hysenlabs.com/projects/davidmokos-expo-glass-tabs)