diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index 2b86b1fde4..27da38acd5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -42,6 +42,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
     private var threadID: Long = -1
     private var actionMode: ActionMode? = null
     private var isLockViewExpanded = false
+    private var isShowingAttachmentOptions = false
 
     // TODO: Selected message background color
     // TODO: Overflow menu background + text color
@@ -155,6 +156,22 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
         conversationRecyclerView.layoutParams = recyclerViewLayoutParams
     }
 
+    override fun toggleAttachmentOptions() {
+        val targetAlpha = if (isShowingAttachmentOptions) 0.0f else 1.0f
+        val allButtons = listOf( cameraButtonContainer, libraryButtonContainer, documentButtonContainer, gifButtonContainer)
+        allButtons.indices.forEach { index ->
+            val view = allButtons[index]
+            val animation = ValueAnimator.ofObject(FloatEvaluator(), view.alpha, targetAlpha)
+            animation.duration = 250L
+            animation.startDelay = 50L * index.toLong()
+            animation.addUpdateListener { animator ->
+                view.alpha = animator.animatedValue as Float
+            }
+            animation.start()
+        }
+        isShowingAttachmentOptions = !isShowingAttachmentOptions
+    }
+
     override fun showVoiceMessageUI() {
         inputBarRecordingView.show()
         inputBar.alpha = 0.0f
@@ -167,7 +184,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
     }
 
     override fun handleInputBarRecordingViewHidden() {
-        Log.d("Test", "Here")
         inputBar.alpha = 1.0f
         val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f)
         animation.duration = 250L
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt
index 86ff46a647..1db4a5c2af 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.conversation.v2.input_bar
 
 import android.content.Context
 import android.util.AttributeSet
+import android.util.Log
 import android.view.LayoutInflater
 import android.view.MotionEvent
 import android.widget.RelativeLayout
@@ -29,12 +30,11 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate {
         // Attachments button
         attachmentsButtonContainer.addView(attachmentsButton)
         attachmentsButton.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
+        attachmentsButton.onPress = { toggleAttachmentOptions() }
         // Microphone button
         microphoneOrSendButtonContainer.addView(microphoneButton)
         microphoneButton.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
-        microphoneButton.onLongPress = {
-            showVoiceMessageUI()
-        }
+        microphoneButton.onLongPress = { showVoiceMessageUI() }
         microphoneButton.onMove = { delegate?.onMicrophoneButtonMove(it) }
         microphoneButton.onCancel = { delegate?.onMicrophoneButtonCancel(it) }
         microphoneButton.onUp = { delegate?.onMicrophoneButtonUp(it) }
@@ -63,6 +63,10 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate {
         delegate?.inputBarHeightChanged(newHeight)
     }
 
+    private fun toggleAttachmentOptions() {
+        delegate?.toggleAttachmentOptions()
+    }
+
     private fun showVoiceMessageUI() {
         delegate?.showVoiceMessageUI()
     }
@@ -72,6 +76,7 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate {
 interface InputBarDelegate {
 
     fun inputBarHeightChanged(newValue: Int)
+    fun toggleAttachmentOptions()
     fun showVoiceMessageUI()
     fun onMicrophoneButtonMove(event: MotionEvent)
     fun onMicrophoneButtonCancel(event: MotionEvent)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt
index 7a76efc473..5d7eefb07a 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt
@@ -40,7 +40,8 @@ class InputBarButton : RelativeLayout {
     var onLongPress: (() -> Unit)? = null
 
     companion object {
-        val animationDuration = 250.toLong()
+        const val animationDuration = 250.toLong()
+        const val longPressDurationThreshold = 250L // ms
     }
 
     private val expandedImageViewPosition by lazy { PointF(0.0f, 0.0f) }
@@ -148,7 +149,7 @@ class InputBarButton : RelativeLayout {
         longPressCallback?.let { gestureHandler.removeCallbacks(it) }
         val newLongPressCallback = Runnable { onLongPress?.invoke() }
         this.longPressCallback = newLongPressCallback
-        gestureHandler.postDelayed(newLongPressCallback, VisibleMessageView.longPressDurationThreshold)
+        gestureHandler.postDelayed(newLongPressCallback, InputBarButton.longPressDurationThreshold)
         onDownTimestamp = Date().time
     }
 
@@ -165,7 +166,7 @@ class InputBarButton : RelativeLayout {
     private fun onUp(event: MotionEvent) {
         onUp?.invoke(event)
         collapse()
-        if ((Date().time - onDownTimestamp) < VisibleMessageView.longPressDurationThreshold) {
+        if ((Date().time - onDownTimestamp) < InputBarButton.longPressDurationThreshold) {
             longPressCallback?.let { gestureHandler.removeCallbacks(it) }
             onPress?.invoke()
         }
diff --git a/app/src/main/res/layout/activity_conversation_v2.xml b/app/src/main/res/layout/activity_conversation_v2.xml
index 0c7582aca9..d5fcbc49f4 100644
--- a/app/src/main/res/layout/activity_conversation_v2.xml
+++ b/app/src/main/res/layout/activity_conversation_v2.xml
@@ -24,25 +24,29 @@
         
+            android:layout_height="@dimen/input_bar_button_expanded_size"
+            android:alpha="0" />
 
         
+            android:layout_height="@dimen/input_bar_button_expanded_size"
+            android:alpha="0" />
 
         
+            android:layout_height="@dimen/input_bar_button_expanded_size"
+            android:alpha="0" />
 
         
+            android:layout_height="@dimen/input_bar_button_expanded_size"
+            android:alpha="0" />