mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 01:39:46 +00:00
Yattee v2 rewrite
This commit is contained in:
150
Yattee/Extensions/View+LiquidGlassSheet.swift
Normal file
150
Yattee/Extensions/View+LiquidGlassSheet.swift
Normal file
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// View+LiquidGlassSheet.swift
|
||||
// Yattee
|
||||
//
|
||||
// View modifiers for iOS 26 Liquid Glass morphing sheet transitions.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Transition Source Modifier (for Views)
|
||||
|
||||
/// View modifier that marks a view as the source for a morphing sheet transition.
|
||||
/// Apply this to a Button inside a ToolbarItem to enable the morphing effect on iOS 26+.
|
||||
struct LiquidGlassTransitionSourceModifier: ViewModifier {
|
||||
let id: String
|
||||
let namespace: Namespace.ID
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
#if os(iOS)
|
||||
if #available(iOS 26, *) {
|
||||
content
|
||||
.matchedTransitionSource(id: id, in: namespace)
|
||||
} else {
|
||||
content
|
||||
}
|
||||
#else
|
||||
content
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Sheet Content Modifier (for sheet content)
|
||||
|
||||
/// View modifier that applies the zoom navigation transition to sheet content.
|
||||
/// Apply this to the content inside a .sheet() to complete the morphing effect on iOS 26+.
|
||||
struct LiquidGlassSheetContentModifier: ViewModifier {
|
||||
let sourceID: String
|
||||
let namespace: Namespace.ID
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
#if os(iOS)
|
||||
if #available(iOS 26, *) {
|
||||
content
|
||||
.navigationTransition(.zoom(sourceID: sourceID, in: namespace))
|
||||
} else {
|
||||
content
|
||||
}
|
||||
#else
|
||||
content
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - View Extensions
|
||||
|
||||
extension View {
|
||||
/// Marks this view as the source for a Liquid Glass morphing sheet transition.
|
||||
///
|
||||
/// Apply this modifier to a Button (or other view) that presents a sheet. On iOS 26+,
|
||||
/// the sheet will morph from this view when presented.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - id: Unique identifier for the transition (must match the sheet content's sourceID).
|
||||
/// - namespace: A namespace for the matched geometry effect.
|
||||
///
|
||||
/// Example:
|
||||
/// ```swift
|
||||
/// @Namespace private var sheetTransition
|
||||
///
|
||||
/// .toolbar {
|
||||
/// ToolbarItem(placement: .primaryAction) {
|
||||
/// Button { showSheet = true } label: {
|
||||
/// Image(systemName: "gear")
|
||||
/// }
|
||||
/// .liquidGlassTransitionSource(id: "settings", in: sheetTransition)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
func liquidGlassTransitionSource(
|
||||
id: String,
|
||||
in namespace: Namespace.ID
|
||||
) -> some View {
|
||||
modifier(LiquidGlassTransitionSourceModifier(id: id, namespace: namespace))
|
||||
}
|
||||
|
||||
/// Applies the Liquid Glass morphing transition to sheet content.
|
||||
///
|
||||
/// Apply this modifier to the content inside a `.sheet()` modifier. On iOS 26+,
|
||||
/// the sheet will morph from the matched transition source when presented.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - sourceID: Unique identifier matching the transition source's id.
|
||||
/// - namespace: A namespace for the matched geometry effect (must match the source).
|
||||
///
|
||||
/// Example:
|
||||
/// ```swift
|
||||
/// .sheet(isPresented: $showSheet) {
|
||||
/// SettingsView()
|
||||
/// .liquidGlassSheetContent(sourceID: "settings", in: sheetTransition)
|
||||
/// }
|
||||
/// ```
|
||||
func liquidGlassSheetContent(
|
||||
sourceID: String,
|
||||
in namespace: Namespace.ID
|
||||
) -> some View {
|
||||
modifier(LiquidGlassSheetContentModifier(sourceID: sourceID, namespace: namespace))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ToolbarContent Extension
|
||||
|
||||
extension ToolbarContent {
|
||||
/// Marks this toolbar content as the source for a Liquid Glass morphing sheet transition.
|
||||
///
|
||||
/// Apply this modifier to a `ToolbarItem` that presents a sheet. On iOS 26+,
|
||||
/// the sheet will morph from this toolbar item when presented.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - id: Unique identifier for the transition (must match the sheet content's sourceID).
|
||||
/// - namespace: A namespace for the matched geometry effect.
|
||||
///
|
||||
/// Example:
|
||||
/// ```swift
|
||||
/// @Namespace private var sheetTransition
|
||||
///
|
||||
/// .toolbar {
|
||||
/// ToolbarItem(placement: .primaryAction) {
|
||||
/// Button { showSheet = true } label: {
|
||||
/// Image(systemName: "gear")
|
||||
/// }
|
||||
/// }
|
||||
/// .liquidGlassTransitionSource(id: "settings", in: sheetTransition)
|
||||
/// }
|
||||
/// ```
|
||||
@ToolbarContentBuilder
|
||||
func liquidGlassTransitionSource(
|
||||
id: String,
|
||||
in namespace: Namespace.ID
|
||||
) -> some ToolbarContent {
|
||||
#if os(iOS)
|
||||
if #available(iOS 26, *) {
|
||||
self.matchedTransitionSource(id: id, in: namespace)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
#else
|
||||
self
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user