         }
     }
     
-   
-    
-    func open() {
+    func open(animated: Bool = true) {
+        guard let superview = self.superview else {
+            return
+        }
         isOpen = true
-    }
-    
-    func close() {
+        
+        insertSubview(overlayView, belowSubview: buttonView)
+        overlayView.snp.makeConstraints { make in
+            make.edges.equalTo(superview)
+        }
+        
+        let animations: () -> Void = {
+            self.overlayView.alpha = 1
+        }
+        
+        animate(animations, animated: animated)
+        
+    }
+    
+    func close(animated: Bool = true) {
         isOpen = false
-    }
+        
+        let animations: () -> Void = {
+            self.overlayView.alpha = 0
+        }
+        let completion: (Bool) -> Void = { finished in
+            self.overlayView.removeFromSuperview()
+        }
+        
+        animate(animations, completion: completion, animated: animated)
+    }
+    
+    func animate(_ animations: @escaping () -> Swift.Void, completion: ((Bool) -> Swift.Void)? = nil, animated: Bool) {
+        if animated {
+            UIView.animate(withDuration: 0.3,
+                           delay: 0,
+                           options: [.beginFromCurrentState, .curveEaseOut],
+                           animations: animations,
+                           completion: completion)
+        } else {
+            animations()
+            if let completion = completion {
+                completion(true)
+            }
+        }
+    }
+    
     
     func executeAction(at index: Int) {
         guard index >= 0 && index < items.count else {

        super.init(coder: aDecoder)
        setup()
    }
    
}

fileprivate extension JJFloatingActionButton {
    
    
    open override func updateConstraints() {
        buttonView.snp.remakeConstraints { make in
            make.center.equalTo(self)
            make.width.equalTo(buttonView.snp.height)
            make.size.lessThanOrEqualTo(self)
            make.size.equalTo(self).priority(.high)
        }
        
        super.updateConstraints()
    }
}
    
    
fileprivate extension JJFloatingActionButton {

    // MARK: Touches
    
    open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
    }
    
    open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard touches.count == 1 else {
            return
        }
        guard let touch = touches.first else {
            return
        }
        let point = touch.location(in: self)
        guard self.bounds.contains(point) else {
            return
        }
        
        didTap()
    }
    
    open override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
        
    }
    
    open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        return super.hitTest(point, with: event)
    }
    
}

fileprivate extension JJFloatingActionButton {
    
    func setup() {
        backgroundColor = UIColor.clear
        clipsToBounds = false
        
        addSubview(buttonView)
        configure()
    }
    

        }
    }
    
    @objc public var buttonIconColor = UIColor.white {
        didSet {
            buttonView.iconColor = buttonIconColor
        }
    }
    
    
    @objc public var itemColor = UIColor.white {
        didSet {
            
        }
