native_liquid_glass 0.2.7
native_liquid_glass: ^0.2.7 copied to clipboard
Liquid Glass iOS platform views for Flutter using native UIKit components.
Changelog #
0.2.7 #
Performance overhaul (all interactive widgets) #
- TextPainter / size-estimate caching.
LiquidGlassButton._estimateWrapContentSizeandLiquidGlassToolbar._estimateToolbarWidthno longer allocate a freshTextPainterand run.layout()on every rebuild. Results are cached on a key derived from the inputs that actually affect measurement (label, text-style signature, icon presence, item spacing, resolved padding, text direction) and returned on cache hit. Biggest win on toolbars with many labeled items and buttons inside frequently-rebuilt trees (lists, animated containers). creationParamsMap caching. Every interactive native widget (button, toolbar, button_group, tab_bar, search_scaffold, search_bar, menu, navigation_bar) now reuses the sameMap<String, Object?>across rebuilds when the inputs haven't changed.UiKitView.creationParamsis consumed once at native-view creation, so the previous per-build Map + nested-list allocations were pure waste — measurable pressure on the Dart GC for toolbars / button groups with many items.- Redundant post-creation native sync eliminated.
_onPlatformViewCreatedpreviously reset_lastConfigHash = nulland fired an immediateupdateConfig/updateButtons/updateToolbarround-trip that re-sent exactly whatcreationParamshad just delivered. Now seeds the hash from the creationParams cache key so the follow-up sync is a no-op in the common case; only fires the delta if props genuinely drifted between build and the native-view callback (e.g. a late icon payload resolved). - Button channel traffic halved on every prop change.
LiquidGlassButton._syncPropsToNativeIfNeedednow consumes the{width, height}already returned by the nativeupdateConfigcall instead of making a separategetIntrinsicSizeround-trip after every update. Each prop change (enabled toggle, icon swap, tint change, etc.) goes from 2 channel round-trips → 1. - Tab bar label-style hashing no longer allocates a Map.
_labelStyleSignatureused to call_buildLabelStylePayload(style)— building an intermediateMapon each call — just to iterate its entries forObject.hashAllUnordered. Now hashes the fourTextStylefields directly viaObject.hash, no Map allocation. - Payload-generation counter replaces manual hash-null in
LiquidGlassToolbarandLiquidGlassButtonGroup. Async icon-payload resolution no longer needs_lastConfigHash = nullbookkeeping; bumping a generation counter that's folded into the config hash invalidates both the native-sync check and the cached creationParams map in one step. - Cache invalidation on
reassemble(hot-reload). Every widget that holds cached estimates / params now clears them inreassembleso code changes to measurement constants take effect without a full restart.
Native touch forwarding — "stuck press" fix #
- Root cause. Several widgets'
UiKitViewdeclared nogestureRecognizersfactory. Flutter's default lazy-forwarding pipeline for platform views then buffered touches, and on taps where the arena resolved late the release event could arrive as a cancel (or not at all) — the most visible symptom beingLiquidGlassButtonscaling up on the interactive glass press and never returning because the press/release pair wasn't clean. - Fix. Every interactive native view now declares the gesture recognizers its native side actually needs:
LiquidGlassButton/LiquidGlassButtonGroup/LiquidGlassToolbar/LiquidGlassTabBar/LiquidGlassSearchScaffold/LiquidGlassNavigationBar/LiquidGlassColorPicker—TapGestureRecognizer.LiquidGlassMenu—TapGestureRecognizer+LongPressGestureRecognizer(nativeUIMenuopens on either).LiquidGlassSearchBar—TapGestureRecognizer+HorizontalDragGestureRecognizer(text-field focus taps + selection-handle drag).LiquidGlassDatePicker—TapGestureRecognizer+ vertical & horizontal drag (wheel-style spinners specifically needed this; without it the wheel could jam mid-spin).
- With the native view claiming the gesture arena up-front, the full down → up sequence reaches the SwiftUI button every press, so the interactive glass scale always has a clean release to animate against.
LiquidGlassContainer — native press animation #
- Press feedback moved from Flutter to native. The interactive spring scale previously ran Flutter-side via
SpringBuilder+Transform.scale, which rebuilt the widget tree on every frame of the animation. That path has been removed. - New native path:
GestureDetectorforwards two edge events per tap (setPressed(true)on down,setPressed(false)on up/cancel) via the method channel. The SwiftUI view model flips@Published var isPressedinsidewithAnimation(.bouncy(duration: 0.35, extraBounce: 0.0)), and the body applies.scaleEffect(isPressed ? 1.04 : 1.0). CoreAnimation drives the spring; Flutter does zero per-frame work, and the platform view never gets a per-frame transform applied to it. - Visual result matches Apple's
Glass.interactive()press feel onLiquidGlassButton/LiquidGlassToolbar— visible overshoot on release, snappy press-down — so a container sitting next to a native button reads as a single system. .interactive()on non-interactive containers is a no-op (identity transform at rest), so the change costs nothing for non-pressable containers.
0.2.6 #
Glass overlay suppression (automatic) #
- New: all glass platform views automatically hide when a Flutter overlay (bottom sheet, dialog, page push) covers them, preventing the native glass from bleeding through Flutter-drawn content. Glass items inside the overlay stay visible.
- Uses
ModalRoute.of(context).isCurrent— fully automatic, zero setup required. Each widget manages its own visibility via the newLiquidGlassRouteSuppressionmixin. - Two suppression layers that can coexist:
- Route-based (automatic): per-widget, driven by Flutter's
InheritedWidgetmechanism. Works with any navigator, handles nested popups via the route's ownisCurrentstate. - Global (manual):
NativeLiquidGlassLifecycle.suppressGlassEffects()/.unsuppressGlassEffects()for custom overlays that don't use the Navigator. Reference-counted for safe nesting.
- Route-based (automatic): per-widget, driven by Flutter's
- Optional
LiquidGlassNavigatorObserverstill available for apps that prefer the observer pattern. - Example app: container preview page now includes "Bottom Sheet" and "Push Screen" test buttons.
0.2.5 #
LiquidGlassContainer #
- Add
LiquidGlassConfig.backgroundColor— a solid color drawn inside the same shape but behind the glass material. Two complementary effects:- Density: the alpha channel controls how dense the glass reads.
Color(...).withValues(alpha: 0.4)gives a denser pill than the bare-glass default;alpha: 1.0produces an effectively solid colored surface with the glass material's highlight + shadow on top. Apple's iOS 26GlassAPI doesn't expose a density/intensity knob, so this controlled backdrop is the supported way to thicken the visible material. - Stable color: fixes the "colors below the glass appear inverted as I scroll" issue on iOS 26. The Liquid Glass material runs an adaptive-contrast pass that samples the brightness of whatever's behind it and inverts the material's tone for legibility — over varying Flutter content this can read as flickering. With
backgroundColorset, the glass refracts your fixed backdrop instead and stays stable.
- Density: the alpha channel controls how dense the glass reads.
- iOS implementation: rendered as
shape.fill(color)inside a.background { ... }modifier applied after.glassEffect(...), so the z-order isbackdrop → glass material → border overlay → Flutter child. The backdrop uses the sameBuiltInGlassShape/AnimatableCustomPathShapereference as the glass fill, so it animates with shape changes (corner radius, custom-path morph) underanimateChanges: true.
0.2.4 #
Custom border #
- Add new
LiquidGlassBorderclass (shared) — a stroked outline that follows the widget's underlying shape (capsule, rounded rect, circle, or custom path). Exposescolorandwidth. Exported frompackage:native_liquid_glass/native_liquid_glass.dart. LiquidGlassContainer: newLiquidGlassConfig.borderfield. Border traces every supported shape including animatable custom paths (the stroke animates with the shape via the sameanimatableDataused by the glass fill).LiquidGlassButton: newborderwidget property on both constructors (text + icon-only). Stroke followsborderRadius(capsule when null, rounded rect otherwise).LiquidGlassToolbar: newborderwidget property. Applied per capsule so every pill in a split toolbar gets the same outline.- iOS side: border renders as
shape.stroke(color, lineWidth:)inside an.overlay { ... }after.glassEffect(...), so the stroke sits on top of the glass material and matches the fill geometry exactly.
LiquidGlassContainer #
- Fix: re-added the
GlassEffectContainer(spacing: 0)wrapper around the container's SwiftUI body. This was claimed in the 0.2.0 CHANGELOG but the actual wrapping was missing from the shipped code, with three visible consequences: (a)Glass.clearrendered as a frosted white panel in light mode instead of the proper translucent material, (b)glassEffectUnion(id:)/glassEffectID(_:)— applied viaapplyLiquidGlassContainerModifiers— silently did nothing because they require aGlassEffectContainerancestor, and (c) interactive glass under-rendered. All three now work as documented. - Defensive:
hostingController.view.clipsToBounds = false(andlayer.masksToBounds = false) so the glass material's subtle drop-shadow doesn't clip at the host-view boundary (matches the toolbar's existing treatment). - Doc: clarified that
glass.interactive()on the native side is effectively dead because theUiKitViewis wrapped inIgnorePointerto let Flutter child widgets inside the container still receive taps. Touches never reach the native glass view, so the visual press feedback is produced Flutter-side viaSpringBuilder+Transform.scale. The.interactive()call is kept anyway because it subtly adjusts the baseline material, keeping the rendered look consistent withLiquidGlassButton/LiquidGlassToolbar.
0.2.3 #
LiquidGlassButton #
- Fix: the Dart-side wrap-content estimator (
_estimateWrapContentSize) was measuring text with a hardcodedTextStyle(fontSize: 17, fontWeight: .w600)and ignoringwidget.labelTextStyle. That mismatched what the nativeUIButtonactually renders when the caller passes a scaledlabelTextStyle(e.g. a ScreenUtil-scaled style on iPad) — the button would sit at a stale estimated width until the asyncgetIntrinsicSizeround-trip caught up, which in timing-sensitive layouts looked like the button was "frozen" at the wrong width. Estimator now resolveslabelTextStyle.fontSize/.fontWeight/.fontFamily/.letterSpacingbefore measuring, falling back to the 17pt / semibold iOS default only when the caller omits them. - Deprecated:
LiquidGlassButton.shrinkWrap. The field was never wired into layout — it's a no-op — but was documented as functional, which was misleading. Actual wrap-content behavior comes from leavingwidth: null(triggers anUnconstrainedBoxinternally). Now@Deprecatedwith the correct guidance; retained for source compatibility.
SVG asset icons #
- Fix:
NativeLiquidGlassIcon.asset(...)no longer crashes the app when the SVG has a wide viewBox (e.g.0 0 1000 1000) being rendered into a small icon target (e.g. 20pt). The button and toolbar decoders previously calledsvgImage.size = CGSize(width: iconSize, height: iconSize)before reading.uiImage, which triggers an SVGKit rendering crash at very small scale factors with certain SVG content (transforms, gradients, path numerics). Both decoders now let SVGKit render at the SVG's natural viewBox size and scale down with UIKit (matching what the tab bar decoder already does), plus gate on the rendered image having a non-zero size.
LiquidGlassToolbar #
heightnow maps 1:1 to the visible glass bar height. Reverted the 12pt vertical overflow padding added in 0.2.0 — the outer widget footprint now equalswidget.heightwith no implicit margin. Setting a smallheight(e.g. 32) actually shrinks the bar instead of just shrinking the surrounding padding.- Dropped the implicit 44pt minimum height on toolbar items (only the horizontal 44pt floor is kept for a comfortable tap target), so heights below 44 truly shrink the bar.
- Each capsule now snaps to an explicit
height(from the Flutter-suppliedwidget.height) instead of relying on.frame(maxHeight: .infinity), which didn't always force the full height through every SwiftUI layout path. - Add
itemSpacingparameter (default8, in points) — the horizontal gap between adjacent items. Implemented asitemSpacing / 2of horizontal padding per item, soitemSpacingis both the gap between adjacent items and the inset from each end of the capsule. - Add
paddingparameter (EdgeInsetsGeometry, defaultEdgeInsets.zero) applied inside each glass capsule (CSS-style padding of the capsule container), so the pill grows around its items rather than inserting an outer margin around the widget. In wrap-content mode the widget still wraps the capsule(s) tightly. Horizontal padding is the typical use; vertical padding shrinks the item content area while the capsule keepsheight. SupportsEdgeInsetsDirectionalfor RTL. - Fix: wrap-content (
width: null) no longer silently swells to the parent's width when the toolbar sits inside a tight-horizontal parent (e.g.Column(crossAxisAlignment: .stretch)or aPaddinginside one). Flutter clamps a child's preferred size up to the parent's tight constraint; that left theUiKitViewwider than the capsule(s) and rendered the leftover space as ifpadding/itemSpacinghad leaked outside the glass pill. The widget now wraps itself inUnconstrainedBox(constrainedAxis: Axis.vertical, alignment: Alignment.center)in wrap-content mode, so the bar shrinks to the estimated content width and centers within its parent slot (matching Apple's iOS 26 floating-toolbar visual). Passwidth: double.infinityfor explicit fill-parent. width: nullnow auto-promotes to fill-parent when [items] contains a flexibleLiquidGlassToolbarSpacer. Without this, a flex spacer in wrap-content mode silently collapsed to0and left the split capsules stuck together at one edge — almost never what a caller using a flex spacer wants. With a flex spacer in items, the toolbar now fills the parent's width so the spacer can distribute the capsule groups (the iOS 26 split-toolbar pattern). Without a flex spacer, wrap-content behavior is unchanged.- Behavior change:
LiquidGlassToolbarSpacer(flexible: false, width: X)now also splits the toolbar into separate capsules (with anX-point fixed gap between them), matching the behavior of flexible spacers. Previously fixed spacers stayed inside one capsule as an in-pill gap; now both spacer kinds produce the iOS 26 split-toolbar pattern. Theflexibleflag controls only whether the gap between capsules is variable (Spacer()) or a fixed width. - Fix: the leading capsule in a split toolbar (items separated by a flexible
LiquidGlassToolbarSpacer) is no longer clipped/invisible. EachToolbarGroupCapsulenow wraps its own.glassEffect(.regular.interactive(), in: Capsule())in a dedicatedGlassEffectContainer(spacing: 0). A single shared outer container was merging sibling pills into one fused surface and clipping the leading one; omitting the container entirely leftGlass.interactive()without the compositing context it needs to render fully (which is why other interactive-glass widgets likeLiquidGlassButtonalways pair.interactive()with aGlassEffectContainer). Per-capsule containment gives each pill an independent, fully-rendered glass surface.
LiquidGlassButton #
- Fix: icon-only buttons with
size: nulland text buttons withwidth: nullno longer swell to the parent's width when placed inside a tight-horizontal parent. SameUnconstrainedBox(constrainedAxis: Axis.vertical)treatment as the toolbar — this was observable on iPad where layout contexts more often pass tight horizontal constraints. Pass an explicitsize/width(ordouble.infinity) to opt out.
0.2.0 #
SVG Path Utility #
- Add
SvgPathExtensiononStringfor converting SVG path data into FlutterPathorLiquidGlassConfig.customPathops. toPath()/toPathScaled({viewBox, target})— parse SVG path data into a FlutterPath, with optional scaling.toLiquidGlassPath()— parse directly intoList<LiquidGlassPathOp>forLiquidGlassConfig.customPath.toLiquidGlassPathScaled({viewBox, target})— handles non-zero-origin viewBoxes (e.g."1 0 24 226") by translating then scaling every coordinate.- Accepts paths with leading whitespace, newlines, comments, or stray characters (everything before the first
M/mis stripped). - Quadratic Béziers are normalized to cubic Béziers to match the native iOS path rendering.
- Add
path_parsing: ^1.1.0as a direct dependency.
LiquidGlassContainer #
- Wrap SwiftUI glass content in
GlassEffectContainersoGlass.clearrenders with its proper translucent appearance in light mode instead of falling back to a frosted white panel, and soglassEffectUnionId/glassEffectIdmodifiers work as documented. - Press feedback on
interactive: truenow scales up to 1.04 (was: down to 0.96) so it visually mirrors the "spring out" aesthetic of Apple's nativeGlass.interactive()used byLiquidGlassButtonandLiquidGlassToolbar. The container can't use native.interactive()directly (itsUiKitViewisIgnorePointer-wrapped so Flutter child widgets inside can still receive taps), so this keeps the press-response visually consistent across the plugin. SameLiquidGlassSpring.interactive()preset as before.
LiquidGlassButton #
LiquidGlassButton.iconnow wraps its content whensizeis not provided, matching Flutter button semantics. The default forsizechanged from50tonull; when null, the button is sized fromiconSizeplus a minimum 44pt touch target, then refined to the native intrinsic size reported by the platform view. Breaking for callers that relied on the implicitsize: 50default — passsize: 50explicitly to preserve the old behavior.- The native
getIntrinsicSizeround-trip now runs for icon-only buttons too (previously only text buttons requested it), so icon buttons with nullsizesettle to the exact size Apple's Liquid Glass rendering prefers.
LiquidGlassTabBar #
- Fix: per-tab
selectedItemColor(fromLiquidGlassTabItem.selectedItemColor) no longer reverts to the globalselectedItemColorafter a Flutter navigation push/pop. The tab bar'sUITabBarAppearance.selectedcolors are now kept in sync with the currently-applied per-tab tint, and the tint is re-applied when the view re-attaches to a window.
LiquidGlassToolbar #
- On iOS 26+ the toolbar is now rendered as a SwiftUI
HStackwith.glassEffect(.regular, in: Capsule())(hosted viaUIHostingController).heightnow actually resizes the visible Liquid Glass bar — previously the underlyingUIToolbarlocked its glass rendering to the system-intrinsic 44pt and any extra height became transparent padding. - Each run of items between flexible
LiquidGlassToolbarSpacers is now rendered as its own independent glass capsule, matching the iOS 26 split-toolbar pattern (multiple floating pill bars side-by-side). Fixed spacers stay inside their group as internal gaps. - Press feedback now uses Apple's native
Glass.regular.interactive()on each capsule — the same mechanismLiquidGlassButtonuses. iOS 26's system handles the spring-out + tint response internally, so behavior (timing, scale, damping) is identical acrossLiquidGlassButton,LiquidGlassButtonGroup, andLiquidGlassToolbar. Sibling capsules in a split toolbar are unaffected when one is pressed. - Fix:
LiquidGlassToolbarItem.tintColornow actually colors the item's icon/text. Previously.tint(...)was applied to the item'sButton, but our customButtonStyleonly re-emitsconfiguration.label, so the tint never reached theImage/Text. Tint is now applied directly via.foregroundStyle(color)on the visible element. - Breaking: removed
LiquidGlassToolbarItem.styleand theLiquidGlassToolbarItemStyleenum. Text items now render withLiquidGlassToolbar.labelTextStyle's weight (or.regularif none supplied) — there's no longer a.donebold variant. If you need bold text for a specific item, pass alabelTextStyleon the whole toolbar. - The widget now reserves vertical overflow padding so the capsule's drop shadow and spring scale-down are not clipped. The visible bar still honors the supplied
height; only the outer widget footprint grows to accommodate the overflow. - Item spacing tightened to match UIToolbar's visual rhythm (minimum 44pt hit targets with 4pt inter-item padding instead of the previous 12pt HStack gap).
- Add optional
widthparameter. When null (default), the toolbar wraps its content — width is estimated from item sizes (TextPainterfor labels,iconSizefor icons, fixed spacer widths, plus glass overflow padding). Passdouble.infinityor wrap inExpandedfor full-parent-width behavior. Flexible spacers only expand when an explicit ordouble.infinitywidth is provided; in wrap-content mode they collapse to 0. - On iOS 15–25 the existing
UIToolbarpath is kept as a fallback (still constrained to 44pt, which matches the non-Liquid-Glass system behavior).
0.1.0 #
Spring Animation System #
- Add
LiquidGlassSpringwith four presets:bouncy,snappy,smooth,interactive. - Add
SingleSpringControllerandOffsetSpringControllerfor imperative spring-driven values. - Add
SpringBuilder,VelocitySpringBuilder, andOffsetSpringBuilderdeclarative widgets. - All builders respect
MediaQuery.disableAnimationsOffor accessibility (reduce motion).
Custom Shape Support for LiquidGlassContainer #
- Add
LiquidGlassEffectShape.customfor arbitrary glass container shapes. - Add
LiquidGlassPathOpsealed class (moveTo,lineTo,cubicTo,quadTo,close) for defining custom paths. - Add
customPathandcustomPathSizetoLiquidGlassConfig— coordinates are in your SVG/design space, the native side scales automatically. - Native
CustomPathShape(SwiftUIShape) renders the custom path on iOS 26+.
Animated Config Transitions #
- Add
animateChangesproperty toLiquidGlassContainer. - When enabled, shape/effect/tint/cornerRadius changes animate with a native SwiftUI spring transition.
- Refactored native side from view recreation to
ObservableObjectViewModel — the SwiftUI view stays alive across config updates. - Built-in shape transitions (rect/capsule/circle) use
Animatablecorner radius interpolation. - Custom shape transitions use
AnimatableCustomPathShapewith control point morphing viaVectorArithmetic. - Built-in to/from custom transitions use opacity crossfade.
Interactive Container #
LiquidGlassContainernow shows a spring press animation (scale down/bounce back) whenconfig.interactiveis true, matchingLiquidGlassButtonbehavior.- Add
onTapcallback toLiquidGlassContainer— uses Flutter's gesture system so child widgets receive touches normally. - Native
UiKitViewis wrapped inIgnorePointer; all gesture handling is Flutter-side.
Container Sizing #
LiquidGlassContainernow wraps its child size whenwidth/heightare omitted, matching FlutterContainerbehavior.- Native glass view uses
Positioned.fillto match the child-determined size.
0.0.3 #
- Add Swift Package Manager (SPM) support for iOS.
0.0.2 #
- Switch iOS tab bar implementation from custom SwiftUI rendering to system
UITabBarController. - Rely on iOS system Liquid Glass appearance on iOS 26+ instead of custom
.glassEffect()drawing. - Remove unsupported action-button and custom-shape parameters from
LiquidGlassTabBarAPI. - Add supported native customization: selected color and item positioning/spacing/width.
- Remove
backgroundColorandshadowColor; tab bar background and shadow visuals are now system-driven. - Remove
unselectedItemColorparameter so unselected item appearance is system-driven by iOS Liquid Glass behavior. - Add iOS tab badge support per item (
iosBadgeValue). - Remove
iosBadgeColorandiosBadgeTextColor; badge styling is now system-driven. - Add three icon source options for
LiquidGlassTabItem:sfSymbolName,iconData, andassetIconPath(plus selected variants). - Rename icon parameters to meaningful source-based names while keeping deprecated aliases (
icon,activeIcon,iosSystemImage,iosActiveSystemImage). - Add reusable static synchronous utility
NativeLiquidGlassUtils.isDeviceQualifiedForLiquidGlassWidget()for iOS 26+ qualification checks before rendering native widgets (noawaitrequired). - Add native customization for tab icon size via
LiquidGlassTabBar.iconSize. - Add per-item icon size override via
LiquidGlassTabItem.iconSize. - Add native label typography customization via
LiquidGlassTabBar.labelTextStyle(font size/weight/family/letter spacing). - Add per-item selected color override via
LiquidGlassTabItem.selectedItemColor. - Add SVG decoding support for
assetIconPathandselectedAssetIconPathon iOS. - Add optional iOS action button support via
iosActionButtonandonActionButtonPressed. - Remove iOS search feature and related callbacks (
iosShowSearchButton,onSearchButtonPressed,onSearchQueryChanged,onSearchSubmitted,onSearchDismissed). - Add
LiquidGlassButtonwith iOS native platform-view rendering and Flutter fallback. - Add
LiquidGlassIconButtonwith iOS native platform-view rendering and Flutter fallback. - Add three icon source options for buttons (
sfSymbolName,iconData,assetIconPath) with iOS native source-priority resolution. - Add native button visual parameters:
iconColor,foregroundColor,glassTintColor,imagePadding, andglassInteractive. - Use default UIKit button configuration APIs for button rendering; on iOS/iPadOS 26+ use
UIButton.Configuration.prominentGlass()with interactiveUIGlassEffect. - Performance:
LiquidGlassButtonGroupicon payload resolution is now gated by an icon signature — payloads are not re-resolved unless icons actually change between widget rebuilds. - Performance:
LiquidGlassButtonGroupresolves icon payloads for all buttons concurrently withFuture.waitinstead of sequentially. - Performance:
LiquidGlassButtonskipsTextPainterlayout cost duringbuildwhen both explicitwidthandheightare provided. - Fix:
LiquidGlassNavigationBarnow correctly syncs changes toleadingItems,trailingItems, andtitleTextStyleto the native bar after initial creation; a matchingsetItemschannel method was added on the Swift side.
0.0.1 #
- Convert package template to Flutter iOS plugin scaffolding.
- Add native Liquid Glass-style tab bar behavior for iOS.
- Add runtime fallback rendering for non-iOS platforms.
- Expose
LiquidGlassTabBarFlutter widget API. - Add interactive example app showcasing the tab bar.
- Remove standalone
LiquidGlassViewitem from the package API.