TechnologiesSwiftUIHover and Pointer Effects

HoverEffectPhaseOverride struct

iOSmacOStvOSwatchOSvisionOS✓ renders

Options for overriding a hover effect's current phase.

How it works

HoverEffectPhaseOverride lets you drive a hover effect to a specific phase yourself, rather than leaving its active state entirely to the system's pointer tracking. A hover effect normally transitions between its resting and active phases as a pointer enters and leaves a view, and the closure form of hoverEffect(_:) hands you the current phase so you can shape that transition. Reach for the override when you need a view to read as hovered (or not) independently of where the pointer actually is — for example to mirror a selection, reflect focus, or force the effect during a programmatic interaction.

  1. Apply the customizable hover effect with hoverEffect(_:)

    The closure-based hoverEffect(_:) modifier is where the override surfaces. It attaches a hover effect to a view and calls back as the phase changes, letting you compose the effect's appearance for each phase. In the example the modifier wraps the Text("Hover me") card built from .padding() and .background(.blue.opacity(0.15), in: .rect(cornerRadius: 12)).

  2. Receive the effect, active state, and phase override in the closure

    The closure is handed the base effect to build on, an isActive flag for whether the effect is currently engaged, and a third parameter — the phase override — that reports any forced phase. In the demo these arrive as { effect, isActive, _ in ... }, with the override position bound to _ because the view simply tracks real pointer state.

  3. Branch your styling on the resolved phase

    Inside the closure you read the active/inactive distinction and configure the effect accordingly, so the same view describes both its resting and hovered looks in one place. Here effect.scaleEffect(isActive ? 1.1 : 1.0) grows the card to 110% only while the effect is active and returns it to 1.0 otherwise.

  4. Animate the phase change with animation(_:value:)

    Because the phase is a value that flips between states, you animate the override the way you would any state change — by attaching .animation(_:value:) keyed to the same flag. The example uses .animation(.easeInOut, value: isActive) so the scale interpolates smoothly each time the effect's phase changes instead of snapping.

Try it — Replace the _ in { effect, isActive, _ in ... } with a named phase-override binding and drive scaleEffect from it instead of isActive to see the effect honor a forced phase rather than the live pointer.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

HoverEffectPhaseOverride.swift
struct HoverEffectPhaseOverrideDemo: View {
    var body: some View {
        VStack(spacing: 16) {
            Text("Hover Effect")
                .font(.headline)
            Text("Hover me")
                .padding()
                .background(.blue.opacity(0.15), in: .rect(cornerRadius: 12))
                .hoverEffect { effect, isActive, _ in
                    effect
                        .scaleEffect(isActive ? 1.1 : 1.0)
                        .animation(.easeInOut, value: isActive)
                }
        }
        .padding()
    }
}
Live preview
Hover Effect Hover me
Hover Effect Hover me
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →