Radial menu
A floating action menu with a rotating trigger, staggered spring entrances, and an arc of reachable actions.
Real SwiftUI, captured on an iPhone 17 Pro simulator. Run the native gallery
Installation
Install the native Swift CLI, then add the component to your app.
hugsy add radial-menu
Prefer to copy it yourself? Open the complete Swift file and add it to your iOS app target in Xcode. No package dependency is required.
Usage
@State private var expanded = false
HugsyRadialMenu(actions: [
.init(id: "photo", title: "Add photo", symbol: "camera") { addPhoto() },
.init(id: "note", title: "New note", symbol: "square.and.pencil") { newNote() },
.init(id: "link", title: "Save link", symbol: "link") { saveLink() }
], isExpanded: $expanded)
Supply stable, unique action IDs and main-actor closures. Use three or four actions to keep targets separated. Reserve the component's full width and height in the layout. Actions close the menu before running their closures.
API reference
| Parameter | Type & behavior | Default |
|---|---|---|
actions | [HugsyRadialAction]Stable IDs, labels, SF Symbols, and main-actor closures. | Required |
isExpanded | Binding<Bool>Controls the action arc. Selection closes it before running an action. | Required |
radius | CGFloatArc radius in points, clamped to at least 70. Reserve sufficient layout space. | 100 |
Interaction
Open the action menu, then choose an action. The actions spring outward in sequence and collapse after selection.
Accessibility
Every action is a labeled native button. Collapsed actions are removed from hit testing and accessibility. The trigger announces expanded or collapsed state. Reduce Motion removes travel interpolation and trigger rotation.
Test with VoiceOver, Dynamic Type, and Reduce Motion on a physical device before shipping. The gallery demonstrates the interaction, not every application-specific content state.
