LiquidGlassTabs — Custom Flutter Bottom Navigation Widget

Custom Flutter bottom navigation widget bergaya Apple liquid glass yang dibangun dari nol dengan BackdropFilter, CustomPainter, dan AnimatedPositioned, tanpa package UI eksternal, dengan API reusable.

Role
Solo Flutter developer (eksplorasi UI engineering)
Ownership
Solo builder: desain empat layer visual, implementasi CustomPainter untuk highlight dan chromatic ring, drag interaction, dan dokumentasi breakdown widget.
Team
Solo project
Period
2026
Focus
Flutter, Flutter Developer, Mobile Developer

Overview

LiquidGlassTabs adalah project eksplorasi Flutter yang membuktikan bahwa efek bottom navigation premium ala Apple liquid glass bisa dibangun sendiri secara modular tanpa bergantung pada package visual khusus. Widget ini memakai empat layer visual yang ditumpuk dengan urutan tertentu: floating capsule dengan blur, glass shell dengan highlight, active liquid bubble yang bisa di-drag, dan tab button per item.

Hasilnya adalah komponen reusable dengan API bersih yang bisa dipasang di project Flutter lain.

Tech & Libraries

Teknologi dan library yang dipakai atau disentuh di project ini:

FlutterDartBackdropFilterCustomPainterAnimatedPositionedAnimatedScaleAnimatedDefaultTextStyleSweepGradientHapticFeedbackClipRRectcupertino_icons

Problem

Package bottom navigation Flutter yang ada di pub.dev umumnya tidak bisa dimodifikasi secara mendalam untuk kebutuhan visual spesifik, dan hasilnya tidak terasa seperti material kaca yang sesungguhnya. Memahami cara kerja BackdropFilter, CustomPainter, dan AnimatedPositioned secara langsung lebih berharga untuk portfolio engineering daripada memakai package yang menyembunyikan implementasinya.

My Role & Ownership

Solo builder: desain empat layer visual, implementasi CustomPainter untuk highlight dan chromatic ring, drag interaction, dan dokumentasi breakdown widget.

Technical Approach

Membangun LiquidGlassBottomTabBar sebagai widget reusable dengan empat layer visual. Layer 1 adalah floating capsule: SafeArea + ConstrainedBox + ClipRRect + BackdropFilter untuk blur konten di belakang tab (membutuhkan extendBody: true di Scaffold).

Layer 2 adalah glass shell: warna charcoal semi-transparan + border putih tipis + _GlassShellPainter yang menambahkan highlight diagonal dan sheen. Layer 3 adalah active liquid bubble: AnimatedPositioned yang bergerak antar slot, dengan BackdropFilter kedua di dalam bubble, gradient glow, dan chromatic ring dari SweepGradient via _BubbleRefractionPainter.

Layer 4 adalah tab button: _LiquidTabButton per item dengan icon, label, badge, tap target, scale animation, dan HapticFeedback.

Bubble aktif bisa di-drag horizontal antar tab; saat dilepas, widget memanggil onTap dengan tab terdekat. Lebar bubble dihitung dari lebar label aktif agar proporsinya presisi, bukan fixed width.

Architecture Notes

Arsitektur widget dipisahkan berdasarkan tanggung jawab: AppShell mengatur currentIndex, daftar TabDestination, IndexedStack, dan posisi tab bar; LiquidGlassBottomTabBar mengurus semua rendering efek kaca; helper widget dibuat private (_LiquidSelectionBubble, _LiquidTabButton, _Badge, _GlassShellPainter, _BubbleRefractionPainter) karena merupakan detail implementasi. Public API tetap kecil: hanya tiga parameter.

Tidak ada layer Data atau Domain karena project ini bukan aplikasi data-driven. Fokusnya adalah reusable visual system, sehingga arsitektur sengaja dibuat flat dan mudah dipindahkan ke project lain dengan mengambil tiga file: tab_destination.dart, liquid_glass_bottom_tab_bar.dart, dan app_theme.dart.

Trade-offs

Memilih custom widget alih-alih package karena tujuan utama adalah memahami rendering pipeline Flutter secara mendalam, bukan sekadar menghasilkan efek visual. Konsekuensinya waktu implementasi lebih lama dan ada beberapa edge case (seperti lebar bubble di tablet) yang perlu ditangani manual.

Efek ini mendekati Apple liquid glass secara visual tetapi belum melakukan refractive distortion fisik yang membelokkan pixel background; untuk level itu dibutuhkan fragment shader atau custom render pipeline yang di luar scope project ini.

Implementation Highlights

  • BackdropFilter + ClipRRect untuk blur konten di belakang capsule; extendBody: true di Scaffold wajib agar konten benar-benar berada di belakang tab.
  • CustomPainter dipakai dua kali: _GlassShellPainter untuk highlight diagonal dan sheen di shell luar, _BubbleRefractionPainter untuk gradient glow dan chromatic ring (SweepGradient) di bubble aktif.
  • AnimatedPositioned untuk movement bubble dengan Curves.easeOutCubic; lebar bubble dihitung dari lebar label aktif agar proporsi presisi.
  • Drag interaction: GestureDetector di bubble menangkap horizontal drag, posisi bubble mengikuti jari, onTap dipanggil dengan tab terdekat saat drag selesai.
  • API reusable: LiquidGlassBottomTabBar menerima items (List<TabDestination>), currentIndex, dan onTap; TabDestination mendefinisikan label, icon, gradient, badge, dan avatar.

Results

  • Menunjukkan pemahaman rendering pipeline Flutter: cara BackdropFilter bekerja dengan extendBody, cara CustomPainter dipakai untuk efek visual yang tidak bisa dicapai dengan widget standar, dan cara AnimatedPositioned dipakai untuk movement yang terasa liquid.
  • Custom LiquidGlassBottomTabBar dengan API reusable: items, currentIndex, onTap.
  • Empat layer visual yang ditumpuk: floating capsule blur, glass shell highlight, active liquid bubble, dan tab button per item.
  • Draggable liquid bubble: active bubble bisa ditarik horizontal antar tab dan commit ke tab terdekat saat dilepas.
  • Zero package dependency untuk efek visual: hanya Flutter SDK dan cupertino_icons.
  • Dokumentasi breakdown per layer (LIQUID_GLASS_BREAKDOWN.md) dan cara integrasi ke project lain.
  • Zero external package untuk efek visual; hanya Flutter SDK.
  • Public proof: repo publik di GitHub dengan dokumentasi LIQUID_GLASS_BREAKDOWN.md.

Links