Vitreum logo

Vitreum

Adaptive native and simulated glass surfaces for Flutter.

Version 0.1.2 Flutter 3.35+ Platforms iOS and Android MIT license

Vitreum uses Apple's native Liquid Glass APIs on supported iOS versions and a custom Flutter-rendered approximation on other platforms.

Vitreum's Cupertino showcase using one scoped native glass overlay on iOS 26

Actual iOS 26.5 simulator capture—not concept artwork. Glass is reserved for the control and navigation layer.

Widget preview

These are real simulator captures of Vitreum widgets over Flutter content:

Scoped native glass overlay Simulated glass navigation Diagnostics surface
VitreumNativeGlassOverlay rendering a native glass search control VitreumGlassNavigationBar rendered with the cross-platform Flutter simulation Vitreum diagnostics screen showing glass rendering controls
VitreumNativeGlassOverlay VitreumGlassNavigationBar Runtime renderer diagnostics

Why Vitreum

Vitreum gives Flutter applications one stable API for small, adaptive glass surfaces. It chooses the safest available renderer at runtime and falls back without crashing when native composition, shaders, or transparency are unavailable.

  • Adaptive rendering — native iOS, simulated Flutter, or solid fallback.
  • Honest platform behavior — Android uses a custom approximation, never Apple's native effect.
  • Accessibility first — reduced transparency and high contrast select a more opaque surface.
  • Bounded performance cost — effects are clipped to their actual surface.
  • Composable widgets — surfaces, buttons, bars, and grouped backdrops.
  • Safe failure behavior — unsupported platforms receive a readable fallback.

Important

One bounded iOS 26 platform-view overlay passed the animated, high-contrast simulator diagnostic. Multiple independent native surfaces corrupted Flutter composition, so the generic VitreumGlass API and automatic mode remain simulated. Native use is isolated in VitreumNativeGlassOverlay. See the evidence and exact scope in the native composition note.

Vitreum is not affiliated with or endorsed by Apple.

Native tab-bar preview

The native tab-bar reference is separate from Vitreum's simulated Flutter navigation. These are real iOS 26.5 simulator captures:

System UIKit content System bar with Flutter content Vitreum simulated
Native UITabBarController with UIKit content Native UITabBarController with Flutter content Vitreum simulated navigation

The first two use Apple's actual UITabBarController; the third is the cross-platform Flutter approximation. See the complete native integration guide or browse the documentation index.

Compatibility

Platform Renderer Current status
iOS 26+ Flutter default; scoped native overlay One native overlay validated; multiple views failed
iOS 13–25 Flutter simulation Supported
Android 5.0+ Flutter simulation Original approximation; never presented as Apple's glass
Other Flutter platforms Solid/translucent surface Safe fallback

Installation

Add Vitreum to pubspec.yaml:

dependencies:
  vitreum: ^0.1.2

Then fetch dependencies:

flutter pub get

Quick start

import 'package:flutter/material.dart';
import 'package:vitreum/vitreum.dart';

class GlassCard extends StatelessWidget {
  const GlassCard({super.key});

  @override
  Widget build(BuildContext context) {
    return const VitreumGlass(
      shape: VitreumShape.roundedRectangle(radius: 24),
      child: Padding(
        padding: EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Balance', style: TextStyle(fontSize: 14)),
            SizedBox(height: 8),
            Text(
              r'$2,345.67',
              style: TextStyle(fontSize: 32, fontWeight: FontWeight.w700),
            ),
          ],
        ),
      ),
    );
  }
}

The effect is painted behind child; layout, semantics, and child interaction continue to behave like normal Flutter widgets.

Scoped native iOS overlay

Use this only for one bounded native overlay on a route. It falls back to the Flutter renderer when its dedicated validation gate is unavailable:

VitreumNativeGlassOverlay(
  shape: const VitreumShape.capsule(),
  semanticLabel: 'Search',
  child: const Padding(
    padding: EdgeInsets.symmetric(horizontal: 18, vertical: 12),
    child: Text('Search spaces'),
  ),
)

Do not create several instances on one route. That topology reproduced stretched Flutter layers in the iOS 26.5 simulator and is not supported.

Core widgets

Glass surface

VitreumGlass(
  mode: VitreumMode.automatic,
  style: VitreumStyle.regular,
  quality: VitreumQuality.adaptive,
  shape: const VitreumShape.roundedRectangle(radius: 24),
  tint: const Color(0xFF8C9EFF),
  semanticLabel: 'Account summary',
  child: const Padding(
    padding: EdgeInsets.all(20),
    child: Text('Adaptive glass'),
  ),
)

Glass button

VitreumGlassButton(
  semanticLabel: 'Send payment',
  onPressed: sendPayment,
  child: const Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      Icon(Icons.arrow_outward_rounded),
      SizedBox(width: 8),
      Text('Send'),
    ],
  ),
)

Floating navigation bar

VitreumGlassNavigationBar is a cross-platform Flutter approximation. It is not a native iOS UITabBar and never presents itself as one:

VitreumGlassNavigationBar(
  selectedIndex: selectedIndex,
  onDestinationSelected: selectDestination,
  destinations: const [
    VitreumNavigationDestination(
      icon: Icons.auto_awesome,
      label: 'Showcase',
    ),
    VitreumNavigationDestination(
      icon: Icons.speed,
      label: 'Diagnostics',
    ),
  ],
)

For the real system behavior, the example iOS host provides VitreumNativeTabScaffold, an actual UITabBarController with UITabBarItems and default system appearance. It requires native host integration because a native container view controller cannot be installed by an ordinary Flutter widget. See the native tab-bar reference for the three comparison modes, FlutterEngineGroup integration, minimization settings, and limitations.

Grouped surfaces

Use a group for nearby, non-overlapping simulated surfaces that share the same backdrop:

VitreumGlassGroup(
  spacing: 12,
  child: Row(
    children: [
      VitreumGlassButton(onPressed: send, child: const Text('Send')),
      const SizedBox(width: 12),
      VitreumGlassButton(onPressed: receive, child: const Text('Receive')),
    ],
  ),
)

Grouped backdrop filters should not overlap. Use independent surfaces when each control requires different backdrop input. VitreumGlassGroup always uses the Flutter simulation, including on iOS 26. Native grouping is not claimed: Vitreum does not yet expose a single UIKit UIGlassContainerEffect hierarchy.

Interaction and material transitions

VitreumGlassButton provides touch-position illumination, restrained press scale, pointer hover, keyboard focus, cancellation, and reduced-motion behavior. For independent appearance:

VitreumGlassTransition(
  type: VitreumTransitionType.materialize,
  visible: isVisible,
  child: const VitreumGlass(
    shape: VitreumShape.capsule(),
    child: Padding(
      padding: EdgeInsets.all(16),
      child: Text('Filters'),
    ),
  ),
)

Use VitreumTransitionType.matchedGeometry with a shared matchedGeometryTag for route geometry, or identity to disable material-specific motion.

Minimize a floating bar on scroll

VitreumGlassBar(
  scrollController: controller,
  minimizeOnScroll: true,
  scrollEdgeTreatment: true,
  child: navigationItems,
)

The minimized bar remains visible and restores on upward scrolling or direct interaction.

Rendering modes

Mode Behavior
automatic Chooses the safest supported backend
native Attempts validated native rendering, then falls back safely
simulated Always uses the Flutter approximation
solid Disables backdrop blur and refraction

Force a predictable low-cost simulation:

const VitreumGlass(
  mode: VitreumMode.simulated,
  quality: VitreumQuality.low,
  child: Text('Conservative simulated glass'),
)

Runtime capabilities

final capabilities = await Vitreum.getCapabilities();

debugPrint('Platform: ${capabilities.platform.name}');
debugPrint('Backend: ${capabilities.selectedAutomaticBackend.name}');
debugPrint('Native API: ${capabilities.nativeApiExists}');
debugPrint('Native view: ${capabilities.nativeViewCanBeCreated}');
debugPrint(
  'Flutter backdrop: ${capabilities.nativeBackdropCompositionValidated}',
);
debugPrint(
  'Single overlay: '
  '${capabilities.nativeSingleOverlayCompositionValidated}',
);
debugPrint(
  'Native interaction: ${capabilities.nativeInteractiveEffectAvailable}',
);
debugPrint('Simulation: ${capabilities.simulatedRendererAvailable}');
debugPrint('Shader: ${capabilities.shaderAvailable}');
debugPrint('Reduced transparency: ${capabilities.reducedTransparency}');

Capability queries return a defensive fallback instead of throwing when native plugin registration is unavailable.

Accessibility

When reduced transparency is reported, Vitreum prefers a nearly opaque solid surface, disables expensive optical effects, and preserves contrast. Flutter high-contrast contexts also select solid rendering.

  • Give meaningful controls a semanticLabel.
  • Keep essential text contrast independent of the background.
  • Test large text and focus navigation.
  • Glass buttons preserve a minimum 48 logical-pixel touch target.
  • Press animations respect disabled-animation settings.

Performance

Glass is a rendering effect, not a free decoration. Profile the actual screen on representative hardware.

Wrap a route or application with the opt-in live overlay:

VitreumPerformanceOverlay(
  enabled: const bool.fromEnvironment('VITREUM_PERFORMANCE_OVERLAY'),
  label: 'catalog · simulated · balanced',
  child: const MyApp(),
)

Launch in profile mode:

flutter run --profile \
  --dart-define=VITREUM_PERFORMANCE_OVERLAY=true

The panel reports rolling FPS, frame time, average/maximum build and raster time, janky frames, raster-cache image data, sample count, and the configured frame budget. FPS reflects rendered frames, so evaluate it while the target animation or interaction is active. The overlay adds a small measurement cost of its own, so leave it disabled for normal production launches. Its default 16.67 ms budget targets 60 Hz; pass frameBudget: Duration(microseconds: 8333) when explicitly evaluating 120 Hz. Use DevTools for memory, CPU, GPU, energy, and timeline investigation. See the performance diagnostics guide for metric definitions, 60/90/120 Hz budgets, test procedure, interpretation, and limitations.

  • Keep glass surfaces small and bounded.
  • Keep fixed glass controls outside scrolling list rows.
  • Prefer VitreumQuality.low on dense or performance-sensitive screens.
  • Group only non-overlapping surfaces.
  • Avoid continuously animating blur radius.
  • Measure video and animated backgrounds in profile mode.

Vitreum does not publish unverified FPS claims. The example includes an adjustable stress test for count, size, quality, blur, refraction request, and interaction.

Where not to use Vitreum

  • Every row of a long ListView
  • Large full-screen blur layers
  • Video-heavy backgrounds without profiling
  • Many overlapping high-quality surfaces
  • Essential text without sufficient contrast

Troubleshooting

Native iOS glass is not selected

Native selection requires all three gates: the iOS API exists, the platform view can be created, and the requested integration path is composition-validated. Generic automatic composition is currently marked failed; only VitreumNativeGlassOverlay consults the validated single-overlay gate. Reduced Transparency, older iOS versions, grouped surfaces, or a failed gate select the Flutter or solid fallback.

The surface looks solid

Reduced transparency, high contrast, explicit solid mode, or an unsupported platform selects the readable solid fallback.

High quality looks like balanced

The optional refraction shader is not enabled in 0.1.2. High quality safely resolves to balanced when shader support is unavailable.

Scrolling becomes expensive

Reduce surface size and count, select low quality, and avoid placing glass in individual list rows.

Example and development

The example application separates a polished Cupertino showcase from a diagnostics page containing exact capability values, three composition scenes, and a configurable stress test.

See the native-versus-simulated visual validation for real captures, evaluation criteria, and known differences. Selected interaction timings and quality degradation are documented in behavior.md.

Contributions are welcome. Read CONTRIBUTING.md, then run:

flutter pub get
dart format .
flutter analyze
flutter test

License

Vitreum is available under the MIT License.

Libraries

vitreum
Adaptive native and simulated glass surfaces for Flutter.