TechnologiesSwiftUIHover and Pointer Effects

PointerStyle struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A style describing the appearance of the pointer (also called a cursor) when

How it works

PointerStyle describes how the system pointer should appear while it hovers over a view, letting you communicate a region's affordance the way native apps do. On platforms with an indirect pointer, the shape of the cursor is a strong signal — a hand for something clickable, a resize arrow for a draggable edge, an open hand for something you can pick up. Rather than leaving every interactive element with the default arrow, you reach for PointerStyle to give each region a cursor that matches what it actually does. Apply one with the pointerStyle(_:) modifier on the view whose pointer behavior you want to change.

  1. Apply a pointer with the pointerStyle(_:) modifier

    PointerStyle takes effect through the pointerStyle(_:) view modifier, which sets the pointer's appearance for the region the view occupies. Attach it to any view to override the default cursor while the pointer is inside that view's bounds, as the example does on each of its Text and RoundedRectangle rows.

  2. Reach for built-in styles like .link and .grabIdle

    PointerStyle exposes static members for the system's standard cursors, so you usually name the affordance rather than construct a value. .link shows the pointing-hand cursor over tappable content, while .grabIdle shows an open hand to mark a draggable element — used here on the .foregroundStyle(.blue) link row and the "Drag handle" row respectively.

  3. Indicate resizable edges with .frameResize(position:)

    For elements that can be dragged to resize, PointerStyle provides .frameResize(position:), whose parameter says which edge or corner the pointer sits on so the system can pick the correct directional arrow. The example marks the gray bar with .pointerStyle(.frameResize(position: .leading)), signaling that its leading edge is a resize handle.

  4. Match the style to the view's real affordance

    Because PointerStyle is purely a presentation hint, it does not add behavior — it should reflect what the view already does. Place .pointerStyle(.link) on something that responds to a click and .pointerStyle(.grabIdle) on something draggable so the cursor and the interaction stay in agreement across the layout.

Try it — Change the gray bar's .pointerStyle(.frameResize(position: .leading)) to .frameResize(position: .top) and hover its edge to watch the resize arrow change direction.

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.

PointerStyle.swift
struct PointerStyleDemo: View {
    var body: some View {
        VStack(spacing: 16) {
            Text("Hover the rows")
                .font(.headline)
            Text("Link")
                .foregroundStyle(.blue)
                .pointerStyle(.link)
            Text("Drag handle")
                .pointerStyle(.grabIdle)
            RoundedRectangle(cornerRadius: 6)
                .fill(.gray.opacity(0.3))
                .frame(width: 120, height: 8)
                .pointerStyle(.frameResize(position: .leading))
        }
        .padding()
    }
}
Live preview
Hover the rows Link Drag handle
Hover the rows Link Drag handle
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →