mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
add docs
This commit is contained in:
parent
6eef4e7df7
commit
3407cf4f11
5 changed files with 779 additions and 0 deletions
128
apple/docs/liquid-glass/appkit.md
Normal file
128
apple/docs/liquid-glass/appkit.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# Liquid Glass in AppKit
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Class | Purpose | Key Properties |
|
||||
|-------|---------|---------------|
|
||||
| `NSGlassEffectView` | Single glass effect | `contentView`, `cornerRadius`, `tintColor` |
|
||||
| `NSGlassEffectContainerView` | Multiple glass effects | `contentView`, `spacing` |
|
||||
|
||||
## NSGlassEffectView
|
||||
|
||||
### Basic Usage
|
||||
```swift
|
||||
let glassView = NSGlassEffectView(frame: NSRect(x: 0, y: 0, width: 200, height: 100))
|
||||
glassView.cornerRadius = 16.0
|
||||
glassView.tintColor = NSColor.systemBlue.withAlphaComponent(0.3)
|
||||
glassView.contentView = myContentView
|
||||
```
|
||||
|
||||
### Interactive Glass
|
||||
```swift
|
||||
class InteractiveGlass: NSGlassEffectView {
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
NSAnimationContext.runAnimationGroup { context in
|
||||
context.duration = 0.2
|
||||
animator().tintColor = NSColor.accent.withAlphaComponent(0.2)
|
||||
}
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
NSAnimationContext.runAnimationGroup { _ in
|
||||
animator().tintColor = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## NSGlassEffectContainerView
|
||||
|
||||
### Container Setup
|
||||
```swift
|
||||
let container = NSGlassEffectContainerView()
|
||||
container.spacing = 40.0 // Merge distance
|
||||
|
||||
let contentView = NSView()
|
||||
container.contentView = contentView
|
||||
|
||||
// Add multiple glass views to contentView
|
||||
[glass1, glass2, glass3].forEach { contentView.addSubview($0) }
|
||||
```
|
||||
|
||||
### Animated Merging
|
||||
```swift
|
||||
NSAnimationContext.runAnimationGroup { context in
|
||||
context.duration = 0.5
|
||||
// Move glass views closer to trigger merge
|
||||
glass2.animator().frame.origin.x -= 50
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Glass Button
|
||||
```swift
|
||||
class GlassButton: NSButton {
|
||||
private let glass = NSGlassEffectView()
|
||||
|
||||
override init(frame: NSRect) {
|
||||
super.init(frame: frame)
|
||||
setup()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
setup()
|
||||
}
|
||||
|
||||
private func setup() {
|
||||
bezelStyle = .rounded
|
||||
isBordered = false
|
||||
glass.autoresizingMask = [.width, .height]
|
||||
glass.cornerRadius = 8.0
|
||||
addSubview(glass, positioned: .below, relativeTo: nil)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Glass Toolbar
|
||||
```swift
|
||||
// Add glass to toolbar area
|
||||
let toolbar = NSToolbar(identifier: "main")
|
||||
let glassView = NSGlassEffectView()
|
||||
glassView.frame = NSRect(x: 0, y: view.bounds.height - 50,
|
||||
width: view.bounds.width, height: 50)
|
||||
glassView.autoresizingMask = [.width, .minYMargin]
|
||||
view.addSubview(glassView)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Z-Order
|
||||
- Only `contentView` guaranteed inside effect
|
||||
- Arbitrary subviews may render incorrectly
|
||||
|
||||
### Performance
|
||||
- Batch in containers when possible
|
||||
- Limit total glass views (5-10 max)
|
||||
- Disable when scrolling for performance
|
||||
|
||||
### Animation
|
||||
- Use `NSAnimationContext` for smooth transitions
|
||||
- Standard duration: 0.2-0.5 seconds
|
||||
- Animate `tintColor` for state changes
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Glass not visible | Check view hierarchy, ensure added to window |
|
||||
| Performance lag | Use containers, reduce glass count |
|
||||
| Merge not working | Check container spacing value |
|
||||
| Content outside glass | Use contentView property exclusively |
|
||||
|
||||
## See Also
|
||||
- [Overview](overview.md)
|
||||
- [SwiftUI Implementation](swiftui.md)
|
||||
- [Common Patterns](patterns.md)
|
||||
- [Apple Docs: NSGlassEffectView](https://developer.apple.com/documentation/AppKit/NSGlassEffectView)
|
||||
60
apple/docs/liquid-glass/overview.md
Normal file
60
apple/docs/liquid-glass/overview.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Liquid Glass Design Overview
|
||||
|
||||
## What is Liquid Glass?
|
||||
|
||||
Dynamic material design combining optical glass properties with fluidity:
|
||||
- **Blurs** content behind it
|
||||
- **Reflects** color and light from surroundings
|
||||
- **Reacts** to touch and pointer interactions
|
||||
- **Morphs** between shapes during transitions
|
||||
|
||||
## Platform Availability
|
||||
|
||||
| Platform | Framework | Primary Class/Modifier | Min Version |
|
||||
|----------|-----------|----------------------|-------------|
|
||||
| macOS | AppKit | `NSGlassEffectView` | macOS 14.0+ |
|
||||
| macOS | SwiftUI | `.glassEffect()` | macOS 14.0+ |
|
||||
| iOS/iPadOS | SwiftUI | `.glassEffect()` | iOS 17.0+ |
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Glass Variants
|
||||
- **Regular**: Standard glass effect
|
||||
- **Prominent**: Enhanced visibility with tint
|
||||
- **Interactive**: Responds to user input
|
||||
|
||||
### Container Optimization
|
||||
Containers improve performance and enable effect merging:
|
||||
- **AppKit**: `NSGlassEffectContainerView`
|
||||
- **SwiftUI**: `GlassEffectContainer`
|
||||
|
||||
### Key Properties
|
||||
- `cornerRadius` / `shape`: Visual appearance
|
||||
- `tintColor` / `.tint()`: Color overlay
|
||||
- `spacing`: Merge distance threshold
|
||||
|
||||
## Quick Start
|
||||
|
||||
### SwiftUI
|
||||
```swift
|
||||
Text("Hello").glassEffect()
|
||||
Button("Click").buttonStyle(.glass)
|
||||
```
|
||||
|
||||
### AppKit
|
||||
```swift
|
||||
let glass = NSGlassEffectView()
|
||||
glass.cornerRadius = 12.0
|
||||
glass.contentView = myView
|
||||
```
|
||||
|
||||
## Performance Guidelines
|
||||
1. Use containers for multiple glass views
|
||||
2. Limit total glass effects on screen
|
||||
3. Consider GPU impact on older devices
|
||||
4. Batch similar effects together
|
||||
|
||||
## Next Steps
|
||||
- [AppKit Implementation](appkit.md)
|
||||
- [SwiftUI Implementation](swiftui.md)
|
||||
- [Common Patterns](patterns.md)
|
||||
188
apple/docs/liquid-glass/patterns.md
Normal file
188
apple/docs/liquid-glass/patterns.md
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
# Liquid Glass Common Patterns
|
||||
|
||||
## Cross-Platform Patterns
|
||||
|
||||
### State-Based Glass
|
||||
**SwiftUI**
|
||||
```swift
|
||||
.glassEffect(.regular.tint(isActive ? .blue : .clear))
|
||||
```
|
||||
|
||||
**AppKit**
|
||||
```swift
|
||||
glassView.tintColor = isActive ? NSColor.systemBlue.withAlphaComponent(0.3) : nil
|
||||
```
|
||||
|
||||
### Hover Effects
|
||||
**SwiftUI**
|
||||
```swift
|
||||
@State private var isHovered = false
|
||||
Text("Hover")
|
||||
.glassEffect(.regular.tint(isHovered ? .blue : .clear))
|
||||
.onHover { isHovered = $0 }
|
||||
```
|
||||
|
||||
**AppKit**
|
||||
```swift
|
||||
override func mouseEntered(with: NSEvent) {
|
||||
animator().tintColor = NSColor.systemBlue.withAlphaComponent(0.2)
|
||||
}
|
||||
```
|
||||
|
||||
### Animated Transitions
|
||||
**SwiftUI**
|
||||
```swift
|
||||
.animation(.spring(duration: 0.3), value: glassState)
|
||||
```
|
||||
|
||||
**AppKit**
|
||||
```swift
|
||||
NSAnimationContext.runAnimationGroup { context in
|
||||
context.duration = 0.3
|
||||
// animations
|
||||
}
|
||||
```
|
||||
|
||||
## UI Component Patterns
|
||||
|
||||
### Glass Card
|
||||
```swift
|
||||
// SwiftUI
|
||||
struct GlassCard<Content: View>: View {
|
||||
let content: Content
|
||||
var body: some View {
|
||||
content
|
||||
.padding()
|
||||
.glassEffect(in: .rect(cornerRadius: 16))
|
||||
}
|
||||
}
|
||||
|
||||
// AppKit
|
||||
class GlassCard: NSView {
|
||||
let glass = NSGlassEffectView()
|
||||
init(content: NSView) {
|
||||
super.init(frame: .zero)
|
||||
glass.cornerRadius = 16
|
||||
glass.contentView = content
|
||||
addSubview(glass)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Glass Badge
|
||||
```swift
|
||||
// SwiftUI
|
||||
struct GlassBadge: View {
|
||||
let count: Int
|
||||
var body: some View {
|
||||
Text("\(count)")
|
||||
.padding(.horizontal, 8)
|
||||
.glassEffect(.regular.tint(.red))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Glass Toolbar
|
||||
```swift
|
||||
// SwiftUI
|
||||
.toolbar {
|
||||
ToolbarItemGroup {
|
||||
Button("One") { }.buttonStyle(.glass)
|
||||
Button("Two") { }.buttonStyle(.glass)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Layout Patterns
|
||||
|
||||
### Grid of Glass Items
|
||||
```swift
|
||||
// SwiftUI
|
||||
GlassEffectContainer(spacing: 20) {
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))]) {
|
||||
ForEach(items) { item in
|
||||
ItemView(item).glassEffect()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Merging Glass Groups
|
||||
```swift
|
||||
// SwiftUI with union
|
||||
@Namespace private var ns
|
||||
ForEach(items.indices) { i in
|
||||
ItemView(items[i])
|
||||
.glassEffect()
|
||||
.glassEffectUnion(id: groupID(for: i), namespace: ns)
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Patterns
|
||||
|
||||
### Pulse Effect
|
||||
```swift
|
||||
// SwiftUI
|
||||
@State private var isPulsing = false
|
||||
Circle()
|
||||
.glassEffect(.regular.tint(isPulsing ? .blue : .clear))
|
||||
.animation(.easeInOut(duration: 1).repeatForever(), value: isPulsing)
|
||||
.onAppear { isPulsing = true }
|
||||
```
|
||||
|
||||
### Morphing Between States
|
||||
```swift
|
||||
// SwiftUI
|
||||
@Namespace private var namespace
|
||||
if expanded {
|
||||
LargeView().glassEffect().glassEffectID("morph", in: namespace)
|
||||
} else {
|
||||
SmallView().glassEffect().glassEffectID("morph", in: namespace)
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Patterns
|
||||
|
||||
### Lazy Loading Glass
|
||||
```swift
|
||||
// SwiftUI
|
||||
ScrollView {
|
||||
LazyVStack {
|
||||
ForEach(items) { item in
|
||||
ItemView(item)
|
||||
.glassEffect(isEnabled: item.isVisible)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Batch Processing
|
||||
```swift
|
||||
// AppKit
|
||||
let container = NSGlassEffectContainerView()
|
||||
container.spacing = 20
|
||||
// Add all glass views to container's contentView
|
||||
```
|
||||
|
||||
## Decision Matrix
|
||||
|
||||
| Use Case | SwiftUI | AppKit |
|
||||
|----------|---------|--------|
|
||||
| Simple glass | `.glassEffect()` | `NSGlassEffectView` |
|
||||
| Multiple glass | `GlassEffectContainer` | `NSGlassEffectContainerView` |
|
||||
| Button styling | `.buttonStyle(.glass)` | Custom `GlassButton` class |
|
||||
| Morphing | `.glassEffectID()` | Manual animation |
|
||||
| Performance | Container + lazy | Container + batch |
|
||||
|
||||
## Tips & Tricks
|
||||
|
||||
1. **Merge Control**: Adjust container spacing to control merge distance
|
||||
2. **State Changes**: Use tint color for visual feedback
|
||||
3. **Touch Feedback**: Enable `.interactive()` for user interaction
|
||||
4. **Performance**: Disable glass when off-screen
|
||||
5. **Consistency**: Match corner radius across app
|
||||
|
||||
## See Also
|
||||
- [Overview](overview.md)
|
||||
- [AppKit Implementation](appkit.md)
|
||||
- [SwiftUI Implementation](swiftui.md)
|
||||
190
apple/docs/liquid-glass/swiftui.md
Normal file
190
apple/docs/liquid-glass/swiftui.md
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# Liquid Glass in SwiftUI
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Modifier/View | Purpose | Parameters |
|
||||
|---------------|---------|------------|
|
||||
| `.glassEffect()` | Apply glass to view | `Glass`, `Shape`, `isEnabled` |
|
||||
| `GlassEffectContainer` | Optimize multiple glass | `spacing`, `content` |
|
||||
| `.buttonStyle(.glass)` | Glass button style | N/A |
|
||||
| `.glassEffectID()` | Morphing transitions | `id`, `namespace` |
|
||||
|
||||
## Basic Implementation
|
||||
|
||||
### Simple Glass Effect
|
||||
```swift
|
||||
Text("Hello")
|
||||
.padding()
|
||||
.glassEffect() // Default: regular glass, capsule shape
|
||||
```
|
||||
|
||||
### Custom Shape & Tint
|
||||
```swift
|
||||
Image(systemName: "star")
|
||||
.glassEffect(
|
||||
.regular.tint(.blue).interactive(),
|
||||
in: .rect(cornerRadius: 12)
|
||||
)
|
||||
```
|
||||
|
||||
## Glass Variants
|
||||
|
||||
### Configuration Options
|
||||
```swift
|
||||
// Regular glass
|
||||
.glassEffect(.regular)
|
||||
|
||||
// With tint
|
||||
.glassEffect(.regular.tint(.orange))
|
||||
|
||||
// Interactive (responds to touch)
|
||||
.glassEffect(.regular.interactive())
|
||||
|
||||
// Combined
|
||||
.glassEffect(.regular.tint(.blue).interactive())
|
||||
```
|
||||
|
||||
## Container Usage
|
||||
|
||||
### Multiple Glass Views
|
||||
```swift
|
||||
GlassEffectContainer(spacing: 40) {
|
||||
HStack(spacing: 40) {
|
||||
ForEach(items) { item in
|
||||
ItemView(item)
|
||||
.glassEffect()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Union Effect
|
||||
```swift
|
||||
@Namespace private var namespace
|
||||
|
||||
GlassEffectContainer {
|
||||
HStack {
|
||||
ForEach(items.indices, id: \.self) { index in
|
||||
ItemView(items[index])
|
||||
.glassEffect()
|
||||
.glassEffectUnion(
|
||||
id: index < 2 ? "group1" : "group2",
|
||||
namespace: namespace
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Morphing Transitions
|
||||
|
||||
### Animated Morphing
|
||||
```swift
|
||||
@State private var expanded = false
|
||||
@Namespace private var namespace
|
||||
|
||||
GlassEffectContainer {
|
||||
if expanded {
|
||||
LargeView()
|
||||
.glassEffect()
|
||||
.glassEffectID("item", in: namespace)
|
||||
} else {
|
||||
SmallView()
|
||||
.glassEffect()
|
||||
.glassEffectID("item", in: namespace)
|
||||
}
|
||||
}
|
||||
.animation(.spring(), value: expanded)
|
||||
```
|
||||
|
||||
## Button Styles
|
||||
|
||||
### Glass Buttons
|
||||
```swift
|
||||
// Standard glass button
|
||||
Button("Action") { }
|
||||
.buttonStyle(.glass)
|
||||
|
||||
// Prominent glass button
|
||||
Button("Important") { }
|
||||
.buttonStyle(.glassProminent)
|
||||
```
|
||||
|
||||
## Toolbar Integration
|
||||
|
||||
### Glass in Toolbar
|
||||
```swift
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button("Save") { }
|
||||
.buttonStyle(.glass)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Toolbar Background
|
||||
```swift
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .principal) {
|
||||
Text("Title")
|
||||
.sharedBackgroundVisibility(.hidden)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Techniques
|
||||
|
||||
### Conditional Glass
|
||||
```swift
|
||||
@State private var glassEnabled = true
|
||||
|
||||
Text("Dynamic")
|
||||
.glassEffect(isEnabled: glassEnabled)
|
||||
```
|
||||
|
||||
### Navigation Transitions
|
||||
```swift
|
||||
@Namespace private var namespace
|
||||
|
||||
NavigationStack {
|
||||
Content()
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button("Open") { }
|
||||
.matchedTransitionSource(id: "btn", in: namespace)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $show) {
|
||||
DetailView()
|
||||
.navigationTransition(.zoom(sourceID: "btn", in: namespace))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Container Usage**: Always wrap multiple glass views
|
||||
2. **Spacing**: Smaller = merge closer, larger = merge farther
|
||||
3. **Limit Count**: 5-10 glass effects maximum
|
||||
4. **Disable When Hidden**: Use `isEnabled` parameter
|
||||
|
||||
## Common Patterns
|
||||
|
||||
| Pattern | Implementation |
|
||||
|---------|---------------|
|
||||
| Toggle glass | `.glassEffect(isEnabled: condition)` |
|
||||
| Group merge | `.glassEffectUnion(id:namespace:)` |
|
||||
| Custom shape | `.glassEffect(in: .rect(cornerRadius: 20))` |
|
||||
| State indication | `.tint(isActive ? .blue : .clear)` |
|
||||
|
||||
## Platform Notes
|
||||
|
||||
- **iOS**: Bottom bar placement works well
|
||||
- **iPadOS**: Consider larger touch targets
|
||||
- **macOS**: Toolbar customization expected
|
||||
|
||||
## See Also
|
||||
- [Overview](overview.md)
|
||||
- [AppKit Implementation](appkit.md)
|
||||
- [Common Patterns](patterns.md)
|
||||
- [Apple Docs: glassEffect](https://developer.apple.com/documentation/SwiftUI/View/glassEffect)
|
||||
213
apple/docs/toolbar/swiftui-features.md
Normal file
213
apple/docs/toolbar/swiftui-features.md
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# SwiftUI Toolbar Features
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Feature | Modifier/Type | Purpose |
|
||||
|---------|--------------|---------|
|
||||
| `.toolbar(id:)` | Customizable toolbar | User can add/remove/reorder |
|
||||
| `ToolbarSpacer` | Spacing control | Fixed or flexible spacing |
|
||||
| `.searchToolbarBehavior()` | Search field display | Minimize/expand behavior |
|
||||
| `DefaultToolbarItem` | System items | Reposition system controls |
|
||||
| `.matchedTransitionSource()` | Transitions | Zoom from toolbar items |
|
||||
|
||||
## Customizable Toolbars
|
||||
|
||||
### Basic Setup
|
||||
```swift
|
||||
.toolbar(id: "main") {
|
||||
ToolbarItem(id: "save") { SaveButton() }
|
||||
ToolbarItem(id: "share") { ShareButton() }
|
||||
ToolbarSpacer(.flexible)
|
||||
ToolbarItem(id: "more") { MoreButton() }
|
||||
}
|
||||
```
|
||||
|
||||
### Spacer Types
|
||||
```swift
|
||||
ToolbarSpacer(.fixed) // Fixed width
|
||||
ToolbarSpacer(.flexible) // Pushes items apart
|
||||
```
|
||||
|
||||
## Search Integration
|
||||
|
||||
### Minimize Behavior
|
||||
```swift
|
||||
@State private var searchText = ""
|
||||
|
||||
NavigationStack {
|
||||
ContentView()
|
||||
.searchable($searchText)
|
||||
.searchToolbarBehavior(.minimize) // Compact search button
|
||||
}
|
||||
```
|
||||
|
||||
### Repositioning Search
|
||||
```swift
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .bottomBar) { Button1() }
|
||||
DefaultToolbarItem(kind: .search, placement: .bottomBar)
|
||||
ToolbarItem(placement: .bottomBar) { Button2() }
|
||||
}
|
||||
```
|
||||
|
||||
## Placement Options
|
||||
|
||||
### Common Placements
|
||||
```swift
|
||||
.toolbar {
|
||||
// Navigation bar
|
||||
ToolbarItem(placement: .navigationBarLeading) { }
|
||||
ToolbarItem(placement: .navigationBarTrailing) { }
|
||||
ToolbarItem(placement: .principal) { }
|
||||
|
||||
// Bottom bar (iOS)
|
||||
ToolbarItem(placement: .bottomBar) { }
|
||||
|
||||
// Large title area
|
||||
ToolbarItem(placement: .largeSubtitle) { CustomSubtitle() }
|
||||
}
|
||||
```
|
||||
|
||||
### Large Subtitle
|
||||
```swift
|
||||
NavigationStack {
|
||||
Content()
|
||||
.navigationTitle("Title")
|
||||
.navigationSubtitle("Subtitle")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .largeSubtitle) {
|
||||
// Overrides navigationSubtitle
|
||||
CustomSubtitleView()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Visual Effects
|
||||
|
||||
### Matched Transitions
|
||||
```swift
|
||||
@State private var showDetail = false
|
||||
@Namespace private var namespace
|
||||
|
||||
NavigationStack {
|
||||
Content()
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button("Open") { showDetail = true }
|
||||
.matchedTransitionSource(id: "btn", in: namespace)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showDetail) {
|
||||
DetailView()
|
||||
.navigationTransition(.zoom(sourceID: "btn", in: namespace))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Background Visibility
|
||||
```swift
|
||||
.toolbar(id: "main") {
|
||||
ToolbarItem(id: "status", placement: .principal) {
|
||||
StatusView()
|
||||
.sharedBackgroundVisibility(.hidden) // No glass background
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## System Items
|
||||
|
||||
### Default Items
|
||||
```swift
|
||||
.toolbar {
|
||||
// Reposition system search
|
||||
DefaultToolbarItem(kind: .search, placement: .bottomBar)
|
||||
|
||||
// Sidebar toggle
|
||||
DefaultToolbarItem(kind: .sidebar, placement: .navigationBarLeading)
|
||||
}
|
||||
```
|
||||
|
||||
## Platform Considerations
|
||||
|
||||
### iOS/iPadOS
|
||||
```swift
|
||||
#if os(iOS)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .bottomBar) {
|
||||
// Bottom bar items for iPhone
|
||||
}
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### macOS
|
||||
```swift
|
||||
#if os(macOS)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .automatic) {
|
||||
// macOS toolbar items
|
||||
}
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Dynamic Toolbar
|
||||
```swift
|
||||
@State private var isEditing = false
|
||||
|
||||
.toolbar {
|
||||
if isEditing {
|
||||
ToolbarItem(id: "done") { DoneButton() }
|
||||
} else {
|
||||
ToolbarItem(id: "edit") { EditButton() }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Grouped Actions
|
||||
```swift
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .bottomBar) {
|
||||
Button("One") { }
|
||||
Button("Two") { }
|
||||
Button("Three") { }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Contextual Items
|
||||
```swift
|
||||
@State private var selection: Item?
|
||||
|
||||
.toolbar {
|
||||
if selection != nil {
|
||||
ToolbarItem { DeleteButton() }
|
||||
ToolbarItem { ShareButton() }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Unique IDs**: Use meaningful identifiers for customizable items
|
||||
2. **Logical Groups**: Use spacers to group related actions
|
||||
3. **Platform Awareness**: Test on all target platforms
|
||||
4. **Consistent Placement**: Follow platform conventions
|
||||
5. **Minimal Items**: Avoid overcrowding toolbars
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Items not customizable | Add `id` to toolbar and items |
|
||||
| Search not minimizing | Apply `.searchToolbarBehavior(.minimize)` |
|
||||
| Transition not working | Check namespace and ID match |
|
||||
| Items hidden | Check placement compatibility |
|
||||
|
||||
## References
|
||||
- [Apple Docs: ToolbarContent](https://developer.apple.com/documentation/SwiftUI/ToolbarContent)
|
||||
- [Apple Docs: CustomizableToolbarContent](https://developer.apple.com/documentation/SwiftUI/CustomizableToolbarContent)
|
||||
- [Liquid Glass Integration](../liquid-glass/swiftui.md)
|
||||
Loading…
Reference in a new issue