# Interactive Side Menu, a Swift slide-out menu with a known safe area bug

> InteractiveSideMenu is an iOS side menu library written in Swift, installed with CocoaPods or Carthage, where the host container holds the menu and the content controllers. Its customization surface covers animation duration, visible content width, content scale, spring animations and per-orientation settings, and its documentation still carries an unresolved safe area layout issue.

**raw-materials/InteractiveSideMenu** — iOS Interactive Side Menu written in Swift.

- Repository: https://github.com/raw-materials/InteractiveSideMenu
- Stars: 694 · Forks: 162
- Language: Swift
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/raw-materials-interactivesidemenu

## Two view controllers and a protocol do the whole job

Interactive Side Menu is described as a customizable, interactive, auto expanding and collapsing side menu for iOS written in Swift. The integration model is small enough to hold in your head.

You subclass two view controllers. MenuContainerViewController is the main container that hosts the side menu and the content controller, and MenuViewController is the container controller for the side menu itself. Any screen that should be reachable from the menu conforms to the SideMenuItemContent protocol, and the host keeps an array of those controllers in its contentViewControllers property.

Setting it up takes three steps. You assign the menu controller to the menuViewController property of the host, you set the host's contentViewControllers array with an array of SideMenuItemContent controllers, and you call selectContentViewController(_ selectedContentVC: MenuItemContentViewController) from the host to pick the first one.

The protocol is what makes the menu work from anywhere. Because a content controller conforms to SideMenuItemContent, it can call showSideMenu() directly, as the README's example does from an @IBAction, without a reference to the container. Switching content from a menu item is equally direct, since the container exposes both the array of controllers and the select and hide calls.

## Installing with CocoaPods or Carthage

Two package managers are supported. With CocoaPods you add one line to your Podfile:

```ruby
pod 'InteractiveSideMenu'
```

With Carthage you add one line to your Cartfile naming the repository:

```text
github "raw-materials/InteractiveSideMenu"
```

There is a migration note attached to the CocoaPods route. The README asks you not to forget to run the pod update command to update your local specs repository during migration from one version to another. That is easy to miss and produces a confusing failure, because a Podfile that has not been refreshed will keep resolving the old version of the library regardless of what you write in it.

The badges give the environment the project was built against: Swift 5.0, CocoaPods 2.3.1, Carthage compatible, and the licence is Apache 2.0. The repository is laid out the way a CocoaPods library normally is, with an InteractiveSideMenu.podspec, an Xcode project, a Sources directory, a Sample project, a CHANGELOG.md, a CONTRIBUTING.md and a CODE_OF_CONDUCT.md.

## Transition options control the open and close animation

The customization list in the README names animation duration, visible content width, content scale, UIView spring animations, animation curves, and customized animation settings for different orientations. All of that is reached through one property, transitionOptions, on your MenuContainerViewController subclass.

The basic setup, which the sample project performs in viewDidLoad(), looks like this:

```swift
override func viewDidLoad() {
    super.viewDidLoad()
    let screenSize: CGRect = UIScreen.main.bounds
    self.transitionOptions = TransitionOptions(duration: 0.4, visibleContentWidth: screenSize.width / 6)
    ...
}
```

The visible content width is the fraction of the screen the content view keeps when the menu is open, so screenSize.width / 6 leaves most of the screen for the menu and slides the content mostly off screen.

Orientation-specific behaviour is a matter of overriding the standard transition callback and rebuilding the options. The README says this can also be done with trait collections using traitCollectionDidChange(_:), which is the route to take on iPad where the size class changes without a rotation:

```swift
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    var options = TransitionOptions()
    options.duration = size.width < size.height ? 0.4 : 0.6
    options.visibleContentWidth = size.width / 6
    self.transitionOptions = options
}
```

The pattern of constructing a fresh TransitionOptions, mutating it and assigning it back is what lets one call express a different animation per orientation, with a shorter duration in portrait and a longer one in horizontal.

## Using the menu with tab bar and navigation controllers

There is one rule that trips people up, and the README states it directly: to use the menu with a TabBar or a NavigationController, you indicate the UITabBarController or the UINavigationController as item content directly, not any of the corresponding view controllers.

So the conforming type is the container, not the screen inside it:

```swift
class NavigationViewController: UINavigationController, SideMenuItemContent {
}

class InnerViewController: UIViewController {

    @IBAction func openMenu(_ sender: Any) {
        if let navigationViewController = self.navigationController as? SideMenuItemContent {
            navigationViewController.showSideMenu()
        }
    }
}
```

The reason for the cast in the action method is that a view controller inside a navigation stack does not itself conform to SideMenuItemContent, so it has to reach through self.navigationController and downcast to find the protocol implementation. That is a small cost for a menu that keeps the navigation stack intact as its content rather than flattening it.

The README also points to the Sample directory for the UITabBarController implementation, which the main text does not include, so the tab bar case is one you will need to read in the sample project rather than in the documentation.

## The content scale value that breaks the safe area

The known issues section documents a real layout bug. There is an issue associated with the content controller's view not properly having its safeAreaInsets set, which causes the view's layout to shift when the side menu is closed. The issue appears to be tied to the transition options contentScale setting, and a value in the range 0.87 to 0.91 causes safeAreaInsets.top to be set to 0.0.

The README notes that the default value of the library is no longer within this range, but warns you to be mindful if you change that value for your own application. That is the whole story in one sentence: the default is safe, the range 0.87 to 0.91 is not, and contentScale is one of the knobs you are invited to customize.

The failure mode is a layout that shifts, which is the kind of bug that gets reported as a jittery transition rather than as a crash, and it only shows up on devices with a notch or a status bar. If you need a specific content scale for a design, check the value against that range before shipping, and if the layout shifts, that setting is the first thing to look at rather than your own layout code.

## The release history is old, the repository is not

The published versions stop a while back. The listed releases are 2.2 and 2.2.1 on the same day in February 2018, and 2.3 on 2018-02-20, with the CocoaPods badge showing 2.3.1. The last push to the master branch was on 2026-08-15, so the source tree has moved well past the last tagged release.

That gap matters for how you consume the library. If you install with CocoaPods you get the published pod, which follows the 2.3.x line, while the master branch contains later work that is not in that line. If you want the newer code you would be building from the repository, and the README gives no instructions for that path, so the customisation examples and the current state of the safe area handling would need to be read in the source itself.

The licence is Apache 2.0, in a LICENSE file at the root, which is permissive and lets you use the library in a closed-source application without publishing your own code, while requiring you to keep the notice and the licence text. The repository also asks that if you publish an App Store application that uses the library, you send a link so the maintainers can add it to a list of applications that use it.

## Conclusion

Adopt InteractiveSideMenu if your iOS app needs a slide-out menu and you want control over the transition, since the transitionOptions model exposes duration, visible content width, content scale and per-orientation settings that a hand-rolled drawer would take a day to reproduce. Do not adopt it for a new project without reading the known issues section, because the content scale value in a narrow range leaves safeAreaInsets.top at zero and shifts the layout when the menu closes, and do not expect SwiftUI support, which the documentation does not mention. Before you commit, check the sample project for the patterns the README does not spell out, keep contentScale out of the 0.87 to 0.91 range, verify the pod update step during version migration, and note that the last push was on 2026-08-15 while the last tagged release was 2.3 in February 2018, so the code is newer than the release history suggests.

## FAQ

### How do I install InteractiveSideMenu in an iOS project?

With CocoaPods, add pod 'InteractiveSideMenu' to your Podfile, and with Carthage, add github "raw-materials/InteractiveSideMenu" to your Cartfile. The README also asks you to run pod update when migrating from one version to another so your local specs repository is refreshed.

### How is the side menu wired into a Swift view controller?

Subclass MenuContainerViewController as the host and MenuViewController as the menu, assign the menu to the host's menuViewController property, set the host's contentViewControllers array with SideMenuItemContent controllers, then call selectContentViewController from the host. A content controller opens the menu with showSideMenu().

### How do I change the animation of the InteractiveSideMenu open and close?

Update the transitionOptions property on your MenuContainerViewController subclass, setting values such as duration and visibleContentWidth. For different orientations, override viewWillTransition(to:with:) and rebuild the options, or use traitCollectionDidChange(_:).

### What is the known safe area issue in InteractiveSideMenu?

The content controller's view does not always have its safeAreaInsets set, so the layout shifts when the side menu is closed, and the issue is tied to the contentScale transition option. A contentScale value between 0.87 and 0.91 causes safeAreaInsets.top to be set to 0.0, and the library default is no longer in that range.

### Can InteractiveSideMenu be used with a UITabBarController or UINavigationController?

Yes, but the tab bar controller or navigation controller itself must be the item content conforming to SideMenuItemContent, not the view controllers inside them. The README points to the Sample project for the UITabBarController implementation details.

## Sources

- [Issues](https://github.com/raw-materials/InteractiveSideMenu/issues)
- [License: Apache-2.0](https://github.com/raw-materials/InteractiveSideMenu/blob/master/LICENSE)
- [raw-materials/InteractiveSideMenu on GitHub](https://github.com/raw-materials/InteractiveSideMenu)
- [README](https://github.com/raw-materials/InteractiveSideMenu/blob/master/README.md)
- [Releases](https://github.com/raw-materials/InteractiveSideMenu/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/raw-materials-interactivesidemenu
