72 lines
2.0 KiB
Markdown
72 lines
2.0 KiB
Markdown
# Haptics
|
|
|
|
## Intent
|
|
|
|
Use haptics sparingly to reinforce user actions (tab selection, refresh, success/error) and respect user preferences.
|
|
|
|
## Core patterns
|
|
|
|
- Centralize haptic triggers in a `HapticManager` or similar utility.
|
|
- Gate haptics behind user preferences and hardware support.
|
|
- Use distinct types for different UX moments (selection vs. notification vs. refresh).
|
|
|
|
## Example: simple haptic manager
|
|
|
|
```swift
|
|
@MainActor
|
|
final class HapticManager {
|
|
static let shared = HapticManager()
|
|
|
|
enum HapticType {
|
|
case buttonPress
|
|
case tabSelection
|
|
case dataRefresh(intensity: CGFloat)
|
|
case notification(UINotificationFeedbackGenerator.FeedbackType)
|
|
}
|
|
|
|
private let selectionGenerator = UISelectionFeedbackGenerator()
|
|
private let impactGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
|
private let notificationGenerator = UINotificationFeedbackGenerator()
|
|
|
|
private init() { selectionGenerator.prepare() }
|
|
|
|
func fire(_ type: HapticType, isEnabled: Bool) {
|
|
guard isEnabled else { return }
|
|
switch type {
|
|
case .buttonPress:
|
|
impactGenerator.impactOccurred()
|
|
case .tabSelection:
|
|
selectionGenerator.selectionChanged()
|
|
case let .dataRefresh(intensity):
|
|
impactGenerator.impactOccurred(intensity: intensity)
|
|
case let .notification(style):
|
|
notificationGenerator.notificationOccurred(style)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Example: usage
|
|
|
|
```swift
|
|
Button("Save") {
|
|
HapticManager.shared.fire(.notification(.success), isEnabled: preferences.hapticsEnabled)
|
|
}
|
|
|
|
TabView(selection: $selectedTab) { /* tabs */ }
|
|
.onChange(of: selectedTab) { _, _ in
|
|
HapticManager.shared.fire(.tabSelection, isEnabled: preferences.hapticTabSelectionEnabled)
|
|
}
|
|
```
|
|
|
|
## Design choices to keep
|
|
|
|
- Haptics should be subtle and not fire on every tiny interaction.
|
|
- Respect user preferences (toggle to disable).
|
|
- Keep haptic triggers close to the user action, not deep in data layers.
|
|
|
|
## Pitfalls
|
|
|
|
- Avoid firing multiple haptics in quick succession.
|
|
- Do not assume haptics are available; check support.
|