glassy_ui_ios 0.1.0
glassy_ui_ios: ^0.1.0 copied to clipboard
90 native iOS components (SwiftUI + UIKit) for Flutter with Liquid Glass on iOS 26+, classic styling on iOS 17-18, fully configurable from Dart.
glassy_ui_ios #
90 real native iOS components for Flutter, written in SwiftUI and UIKit and embedded as platform views. On iOS 26+ they use Apple's Liquid Glass. On iOS 17–18 they fall back to classic materials automatically. Everything is configurable from Dart, with no Cupertino widgets involved.
Features #
- 90 components: navigation bars, toolbars, glass buttons, tab bars, sidebars, split views, sheets, alerts, menus, pickers, progress, media and camera controls, and Liquid Glass effects. See the gallery below.
- Truly native: SwiftUI and UIKit render each component, so system sheets, menus, popovers and haptics behave exactly like iOS.
- Adaptive design:
glassEffect,.glass/.glassProminent,GlassEffectContainerand glass morphing on iOS 26+, with material fallbacks on iOS 17–18. - Configurable from Dart: title, images (SF Symbols, assets, bytes), items, values, colors, background, corner radius, glass variant, fonts and light/dark. Changes apply live.
- Two-way communication: every interaction comes back to Dart as a
NativeEvent, and Dart drives components withtrigger(),reset()and custom commands. - Extensible: register your own SwiftUI views and use them from Dart.
- Swift Package Manager and a privacy manifest are included.
Requirements #
| Minimum | |
|---|---|
| iOS | 17.0 (Liquid Glass needs iOS 26) |
| Flutter | 3.27 |
| Xcode | 26 (to compile the Liquid Glass APIs) |
| Integration | Swift Package Manager |
Installation #
dependencies:
glassy_ui_ios: ^0.1.0
This plugin is distributed with Swift Package Manager, so turn it on for your app in pubspec.yaml:
flutter:
config:
enable-swift-package-manager: true
You can also turn it on globally with flutter config --enable-swift-package-manager.
Then set the iOS deployment target to 17.0: in Xcode, select Runner → General → Minimum Deployments. If your app still has a Podfile, set platform :ios, '17.0' there as well.
Quick start #
import 'package:glassy_ui_ios/glassy_ui_ios.dart';
SizedBox(
height: 400,
child: NativeComponent(
type: NativeComponentType.prominentGlassButton,
config: const NativeComponentConfig(
title: 'Continue',
image: NativeImage.symbol('arrow.right'),
style: NativeStyle(
tintColor: Colors.teal,
cornerRadius: 20,
backgroundGradient: [Colors.indigo, Colors.pink],
),
),
onEvent: (event) => debugPrint('${event.name}: ${event.value}'),
),
);
NativeComponent sizes itself to its parent, like any platform view. Give it bounded constraints: an Expanded, a SizedBox, or a full page.
Controlling a component from Dart #
late NativeComponentController controller;
NativeComponent(
type: NativeComponentType.halfSheet,
onCreated: (c) => controller = c,
);
await controller.trigger(); // primary action: present, toggle, next…
await controller.reset(); // back to the initial state
await controller.send('custom', 42); // custom commands for your own components
controller.events.listen(print); // stream of NativeEvent
NativeComponentType.triggerLabel describes what trigger() does for each component.
Live updates #
Put the config in state and change it. The native view updates in place without being recreated:
setState(() {
config = config.copyWith(
title: 'Updated',
style: config.style.copyWith(tintColor: Colors.orange, glass: NativeGlass.clear),
);
});
Configuration #
Every component reads the same NativeComponentConfig. Each one documents the fields it uses in its Swift source (ios/glassy_ui_ios/Sources/glassy_ui_ios/Components/).
| Field | Purpose |
|---|---|
title, subtitle, message, placeholder |
Text content |
image |
Main icon or artwork: NativeImage.symbol('star.fill'), NativeImage.asset('assets/cover.jpg'), NativeImage.bytes(data) |
items |
Tabs, menu actions, segments, options, rows (List<NativeItem>; nest with children for submenus and columns) |
value, min, max, step |
Initial value and range. DateTime and Color values are encoded automatically |
enabled |
Disables the whole component |
extra |
Component-specific options, e.g. {'detents': ['0.25', 'medium', 'large']} |
style |
A NativeStyle (see below) |
NativeStyle #
| Property | Description |
|---|---|
tintColor |
Accent color for buttons, switches, sliders and selection |
foregroundColor |
Primary text and icon color |
backgroundColor / backgroundGradient |
Background behind the component |
showBackdrop |
Colorful default backdrop that makes glass refraction visible |
surfaceColor |
Card color when glass is disabled |
cornerRadius |
Corner radius of cards, sheets and rounded glass |
glass |
NativeGlass.regular, .clear or .none |
glassTint, interactive |
Glass tint and touch reaction |
padding, spacing |
Layout |
fontSize, fontWeight, fontDesign |
Title typography |
colorScheme |
Force light or dark |
controlSize |
mini … extraLarge |
NativeItem #
const NativeItem.symbol('Inbox', 'tray', badge: '3');
const NativeItem(id: 'delete', title: 'Delete', symbol: 'trash', role: NativeItemRole.destructive);
const NativeItem(title: 'Export', children: [NativeItem(title: 'PDF'), NativeItem(title: 'PNG')]);
Images from assets #
Declare the asset in your app's pubspec.yaml and pass its path:
NativeComponentConfig(image: const NativeImage.asset('assets/album.jpg'));
Events #
NativeEvent has a name, a value and a time. The names are consistent across components:
| Event | Sent when |
|---|---|
change |
A value changed (slider, toggle, picker, tab…) |
select |
An item, row or menu entry was chosen (value = item id) |
tap / action |
A button or action was pressed |
presented / dismissed |
A sheet or overlay appeared or disappeared |
complete |
A progress indicator finished |
Custom native components #
Any SwiftUI view in your app can become a component. Make it conform to NativeComponent and register it:
import glassy_ui_ios
import SwiftUI
struct RatingView: NativeComponent {
static let componentId = "rating"
@EnvironmentObject private var context: ComponentContext
@Environment(\.nativeConfig) private var config
@State private var rating = 0
var body: some View {
ComponentScaffold {
GlassCard(config.title ?? "Rate") {
HStack {
ForEach(1...5, id: \.self) { star in
Button {
rating = star
context.emit("change", star)
} label: {
Image(systemName: star <= rating ? "star.fill" : "star")
}
}
}
}
}
.seed($rating, from: config.int(or: 0))
.onNativeCommand { if $0.name == "reset" { rating = 0 } }
}
}
// AppDelegate, after GeneratedPluginRegistrant.register(...)
NativeComponentRegistry.register(RatingView.self)
NativeComponent.custom(id: 'rating', config: const NativeComponentConfig(title: 'Rate us'));
These building blocks are available to your views: adaptiveGlass, nativeGlass, nativeButtonStyle, AdaptiveGlassContainer, adaptiveGlassID, adaptiveGlassUnion, ComponentScaffold, ComponentBackground, GlassCard, NativeIcon, NativeArtwork, NativeItemLabel, NativeItemButton, CloseButton, GlassIconButton and GlassSupport.isAvailable.
System helpers #
final info = await NativeSystem.info(); // iOS version, liquidGlass, registered ids
await NativeSystem.haptic(NativeHaptic.success);
Component gallery #
Screenshots were taken on an iPhone simulator running iOS 27 (Liquid Glass), using each component's default configuration. The example app contains all 90 components and a live Customize panel.
Navigation & Toolbars (9) #
![]() Navigation Bar / App Bar NativeComponentType.navBarNavigationStack + .toolbar — glass bar on iOS 26 | ![]() Back Button NativeComponentType.backButtonNavigationStack(path:) system back button | ![]() Close Button NativeComponentType.closeButtonButton(role: .close) / xmark.circle.fill |
![]() Navigation Title NativeComponentType.navTitle.navigationTitle + .toolbarTitleMenu | ![]() Large Navigation Title NativeComponentType.largeNavTitle.navigationBarTitleDisplayMode(.large) | ![]() Toolbar NativeComponentType.toolbarToolbarItemGroup + ToolbarSpacer (iOS 26) |
![]() Floating Toolbar NativeComponentType.floatingToolbarGlassEffectContainer + .glassEffect / material capsule | ![]() Bottom Toolbar NativeComponentType.bottomToolbarToolbarItem(placement: .bottomBar) | ![]() Toolbar Action Button NativeComponentType.toolbarActionButton.confirmationAction + .glassProminent |
Buttons (9) #
![]() Glass Button NativeComponentType.glassButton.buttonStyle(.glass) / .bordered | ![]() Prominent Glass Button NativeComponentType.prominentGlassButton.buttonStyle(.glassProminent) / .borderedProminent | ![]() Image Button NativeComponentType.imageButtonButton with image label + custom ButtonStyle |
Circular Icon Button NativeComponentType.circularIconButton.buttonBorderShape(.circle) + glass | ![]() SF Symbols Button NativeComponentType.sfSymbolsButton.symbolEffect, rendering modes, variableValue | ![]() Plus Button NativeComponentType.plusButtonGlass circle + .numericText transition |
![]() Minus Button NativeComponentType.minusButtonGlass circle + .numericText transition | ![]() Floating Action Button NativeComponentType.floatingActionButtonGlass morphing with glassEffectID | Avatar Action Button NativeComponentType.avatarActionButtonToolbar Menu with avatar label |
Controls (7) #
![]() Segmented Control NativeComponentType.segmentedControlPicker(.segmented) | ![]() Toggle / Switch NativeComponentType.toggleToggle(.switch) | ![]() Stepper NativeComponentType.stepperStepper(value:in:step:) |
![]() Slider NativeComponentType.sliderSlider with min/max value labels | ![]() Slider with Tick Marks NativeComponentType.sliderTicksSlider(tick:) iOS 26 / drawn ticks | ![]() Page Indicator NativeComponentType.pageIndicatorTabView(.page) + .indexViewStyle |
![]() Checkbox-Style Control NativeComponentType.checkboxCustom ToggleStyle with SF Symbols |
Tabs & Structure (10) #
![]() Tab Bar NativeComponentType.tabBarTabView + .tabItem | ![]() Floating Tab Bar NativeComponentType.floatingTabBar.tabBarMinimizeBehavior(.onScrollDown) / custom capsule | ![]() Tab Bar Item NativeComponentType.tabBarItem.tabItem + .badge |
![]() Expandable Tab Bar NativeComponentType.expandableTabBarGlass capsules that expand with glassEffectID | ![]() Search Tab NativeComponentType.searchTabTab(role: .search) iOS 18+ / tabItem | ![]() Sidebar NativeComponentType.sidebarNavigationSplitView + .listStyle(.sidebar) |
![]() Navigation Stack NativeComponentType.navigationStackNavigationStack(path:) + navigationDestination | ![]() Split View NativeComponentType.splitViewThree-column NavigationSplitView | ![]() Floating Accessory View NativeComponentType.floatingAccessory.tabViewBottomAccessory (iOS 26) / safeAreaInset |
![]() Inspector Panel NativeComponentType.inspector.inspector(isPresented:) |
Sheets, Dialogs & Overlays (11) #
![]() Bottom Sheet NativeComponentType.bottomSheetSheet with .height detent + background interaction | ![]() Half-Screen Sheet NativeComponentType.halfSheet.presentationDetents([.medium]) | ![]() Full-Screen Sheet NativeComponentType.fullSheet.fullScreenCover |
![]() Detented Sheet NativeComponentType.detentedSheetDetents with selection binding | ![]() Sheet Drag Indicator NativeComponentType.dragIndicator.presentationDragIndicator | ![]() Alert Dialog NativeComponentType.alert.alert with roles + text field |
![]() Confirmation Dialog NativeComponentType.confirmationDialog.confirmationDialog — popover on iOS 26 | ![]() Action Sheet NativeComponentType.actionSheetUIKit UIAlertController(.actionSheet) | ![]() Popover NativeComponentType.popover.popover + .presentationCompactAdaptation |
![]() Toast / Notification Overlay NativeComponentType.toastGlass capsule overlay with transition | ![]() Confirmation Popup NativeComponentType.confirmationPopupCustom glass card modal |
Menus (7) #
![]() Popup Menu NativeComponentType.popupMenuMenu + Picker (pop-up button) | ![]() Dropdown Menu NativeComponentType.dropdownMenuMenu with sections, Picker and Toggle | ![]() Context Menu NativeComponentType.contextMenu.contextMenu with preview |
![]() Overflow Menu NativeComponentType.overflowMenuToolbar Menu with ellipsis | ![]() Nested Submenu NativeComponentType.nestedSubmenuMenu inside Menu | ![]() Share Menu NativeComponentType.shareMenuShareLink + UIActivityViewController |
![]() Text Selection Menu NativeComponentType.textSelectionMenuUITextView editMenuForTextIn |
Input & Pickers (10) #
![]() Text Field NativeComponentType.textFieldTextField styles + glass field | ![]() Secure Password Field NativeComponentType.secureFieldSecureField with reveal + strength | ![]() Search Field NativeComponentType.searchField.searchable + .searchSuggestions |
![]() Multiline Text Editor NativeComponentType.textEditorTextEditor + FocusState | ![]() Date Picker NativeComponentType.datePickerDatePicker(.graphical / .compact) | ![]() Time Picker NativeComponentType.timePickerDatePicker(.hourAndMinute, .wheel) |
![]() Wheel Picker NativeComponentType.wheelPickerPicker(.wheel) multi-column | ![]() Menu Picker NativeComponentType.menuPickerPicker(.menu) | ![]() Color Picker NativeComponentType.colorPickerColorPicker (returns hex to Dart) |
![]() Floating Search Bar NativeComponentType.floatingSearchBarGlass search capsule over content |
Progress (7) #
![]() Circular Progress Indicator NativeComponentType.circularProgressGauge(.accessoryCircularCapacity) + ring | ![]() Linear Progress Bar NativeComponentType.linearProgressProgressView(value:) | ![]() Determinate Progress Bar NativeComponentType.determinateProgressProgressView(value:total:) + Gauge |
![]() Indeterminate Loading Indicator NativeComponentType.indeterminateLoadingProgressView() + animated bar | ![]() Download Progress Indicator NativeComponentType.downloadProgressApp Store-style ring button | ![]() Upload Progress Indicator NativeComponentType.uploadProgressPer-file ProgressView |
![]() Activity Indicator NativeComponentType.activityIndicatorUIKit UIActivityIndicatorView |
Media & Camera (11) #
![]() Gallery Toolbar NativeComponentType.galleryToolbarGrid + bottomBar selection toolbar | ![]() Photo Viewer Toolbar NativeComponentType.photoViewerToolbarGlass top/bottom chrome | ![]() Media Playback Controls NativeComponentType.mediaControlsNow Playing glass card |
![]() Play / Pause Button NativeComponentType.playPause.contentTransition(.symbolEffect(.replace)) | ![]() Skip Forward / Backward Button NativeComponentType.skipButtonsgobackward.15 / goforward.30 + bounce | ![]() Volume Slider NativeComponentType.volumeSliderSlider + MPVolumeView |
![]() Full-Screen Media Close Button NativeComponentType.mediaCloseGlass xmark over media | ![]() Picture-in-Picture Controls NativeComponentType.pipControlsDraggable mini player + AVKit support check | ![]() Camera Controls NativeComponentType.cameraControlsShutter, modes, flash, flip |
![]() Zoom Controls NativeComponentType.zoomControlsZoom pills + MagnifyGesture | ![]() Crop Controls NativeComponentType.cropControlsAspect ratios, straighten dial, rotate |
Liquid Glass (9) #
![]() Scroll-Edge Glass Effect NativeComponentType.scrollEdge.scrollEdgeEffectStyle(.soft / .hard) | ![]() Glass Background NativeComponentType.glassBackgroundGlass.regular / .clear / .tint | ![]() Custom Glass Shape NativeComponentType.customGlassShape.glassEffect(in: customShape) |
![]() Glass Button Group NativeComponentType.glassButtonGroup.glassEffectUnion | ![]() Glass Effect Container NativeComponentType.glassContainerGlassEffectContainer(spacing:) blending | ![]() Glass Morphing Animation NativeComponentType.glassMorphing.glassEffectID morphing |
![]() Glass Transition NativeComponentType.glassTransition.glassEffectTransition(.materialize) | App Icon with Layered Glass Styling NativeComponentType.appIconLayered icon: default / dark / clear / tinted | ![]() Widget with Clear or Tinted Appearance NativeComponentType.widgetAppearanceFull colour / clear / tinted rendering |
Limitations #
- Glass refracts only native content inside the platform view, not the Flutter widgets behind it. That's why components draw their own backdrop (
NativeStyle.showBackdrop). - iOS only. On other platforms
NativeComponentshows itsfallbackwidget. - Picture-in-picture and camera controls are UI only: no video asset and no camera session are used.
MPVolumeViewrenders only on physical devices. - Every component is a platform view, so prefer a few large components per screen over many small ones.
License #
MIT. See LICENSE.






















































































