diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/failure/MatrixError.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/failure/MatrixError.kt
index 1e87cfc1b2..7d433ba7ba 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/failure/MatrixError.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/failure/MatrixError.kt
@@ -26,8 +26,13 @@ import com.squareup.moshi.JsonClass
 @JsonClass(generateAdapter = true)
 data class MatrixError(
         @Json(name = "errcode") val code: String,
-        @Json(name = "error") val message: String
-) {
+        @Json(name = "error") val message: String,
+
+        @Json(name = "consent_uri") val consentUri: String? = null,
+        // RESOURCE_LIMIT_EXCEEDED data
+        @Json(name = "limit_type") val limitType: String? = null,
+        @Json(name = "admin_contact") val adminUri: String? = null) {
+
 
     companion object {
         const val FORBIDDEN = "M_FORBIDDEN"
@@ -55,5 +60,8 @@ data class MatrixError(
         const val M_CONSENT_NOT_GIVEN = "M_CONSENT_NOT_GIVEN"
         const val RESOURCE_LIMIT_EXCEEDED = "M_RESOURCE_LIMIT_EXCEEDED"
         const val WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
+
+        // Possible value for "limit_type"
+        const val LIMIT_TYPE_MAU = "monthly_active_user"
     }
 }
\ No newline at end of file
diff --git a/vector/src/debug/res/layout/view_notification_area.xml b/vector/src/debug/res/layout/view_notification_area.xml
new file mode 100644
index 0000000000..8af520c2c7
--- /dev/null
+++ b/vector/src/debug/res/layout/view_notification_area.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="42dp"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    tools:background="@color/vector_fuchsia_color"
+    tools:parentTag="android.widget.RelativeLayout">
+
+    <ImageView
+        android:id="@+id/room_notification_icon"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_centerVertical="true"
+        android:layout_marginStart="24dp"
+        android:padding="5dp"
+        tools:src="@drawable/vector_typing" />
+
+    <TextView
+        android:id="@+id/room_notification_message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_marginStart="64dp"
+        android:layout_marginEnd="16dp"
+        android:accessibilityLiveRegion="polite"
+        android:textColor="?attr/vctr_room_notification_text_color"
+        tools:text="a text here" />
+
+</merge>
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/core/error/ResourceLimitErrorFormatter.kt b/vector/src/main/java/im/vector/riotx/core/error/ResourceLimitErrorFormatter.kt
new file mode 100644
index 0000000000..b57014f142
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/core/error/ResourceLimitErrorFormatter.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.riotx.core.error
+
+import android.content.Context
+import android.text.Html
+import androidx.annotation.StringRes
+import im.vector.matrix.android.api.failure.MatrixError
+import im.vector.riotx.R
+import me.gujun.android.span.span
+
+class ResourceLimitErrorFormatter(private val context: Context) {
+
+    // 'hard' if the logged in user has been locked out, 'soft' if they haven't
+    sealed class Mode(@StringRes val mauErrorRes: Int, @StringRes val defaultErrorRes: Int, @StringRes val contactRes: Int) {
+        // User can still send message (will be used in a near future)
+        object Soft : Mode(R.string.resource_limit_soft_mau, R.string.resource_limit_soft_default, R.string.resource_limit_soft_contact)
+
+        // User cannot send message anymore
+        object Hard : Mode(R.string.resource_limit_hard_mau, R.string.resource_limit_hard_default, R.string.resource_limit_hard_contact)
+    }
+
+    fun format(matrixError: MatrixError,
+               mode: Mode,
+               separator: CharSequence = " ",
+               clickable: Boolean = false): CharSequence {
+        val error = if (MatrixError.LIMIT_TYPE_MAU == matrixError.limitType) {
+            context.getString(mode.mauErrorRes)
+        } else {
+            context.getString(mode.defaultErrorRes)
+        }
+        val contact = if (clickable && matrixError.adminUri != null) {
+            val contactSubString = uriAsLink(matrixError.adminUri!!)
+            val contactFullString = context.getString(mode.contactRes, contactSubString)
+            Html.fromHtml(contactFullString)
+        } else {
+            val contactSubString = context.getString(R.string.resource_limit_contact_admin)
+            context.getString(mode.contactRes, contactSubString)
+        }
+        return span {
+            text = error
+        }
+                .append(separator)
+                .append(contact)
+    }
+
+    /**
+     * Create a HTML link with a uri
+     */
+    private fun uriAsLink(uri: String): String {
+        val contactStr = context.getString(R.string.resource_limit_contact_admin)
+        return "<a href=\"$uri\">$contactStr</a>"
+    }
+}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotx/core/platform/NotificationAreaView.kt b/vector/src/main/java/im/vector/riotx/core/platform/NotificationAreaView.kt
new file mode 100644
index 0000000000..6a9af14937
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/core/platform/NotificationAreaView.kt
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.riotx.core.platform
+
+import android.content.Context
+import android.graphics.Color
+import android.text.SpannableString
+import android.text.TextPaint
+import android.text.TextUtils
+import android.text.method.LinkMovementMethod
+import android.text.style.ClickableSpan
+import android.util.AttributeSet
+import android.view.View
+import android.widget.ImageView
+import android.widget.RelativeLayout
+import android.widget.TextView
+import androidx.core.content.ContextCompat
+import androidx.core.text.bold
+import butterknife.BindView
+import butterknife.ButterKnife
+import im.vector.matrix.android.api.failure.MatrixError
+import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
+import im.vector.matrix.android.api.permalinks.PermalinkFactory
+import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
+import im.vector.riotx.R
+import im.vector.riotx.core.error.ResourceLimitErrorFormatter
+import im.vector.riotx.features.themes.ThemeUtils
+import me.gujun.android.span.addSpan
+import me.gujun.android.span.span
+import me.saket.bettermovementmethod.BetterLinkMovementMethod
+import timber.log.Timber
+
+/**
+ * The view used to show some information about the room
+ * It does have a unique render method
+ */
+class NotificationAreaView @JvmOverloads constructor(
+        context: Context,
+        attrs: AttributeSet? = null,
+        defStyleAttr: Int = 0
+) : RelativeLayout(context, attrs, defStyleAttr) {
+
+    @BindView(R.id.room_notification_icon)
+    lateinit var imageView: ImageView
+    @BindView(R.id.room_notification_message)
+    lateinit var messageView: TextView
+
+    var delegate: Delegate? = null
+    private var state: State = State.Initial
+
+    init {
+        setupView()
+    }
+
+    /**
+     * This methods is responsible for rendering the view according to the newState
+     *
+     * @param newState the newState representing the view
+     */
+    fun render(newState: State) {
+        if (newState == state) {
+            Timber.d("State unchanged")
+            return
+        }
+        Timber.d("Rendering $newState")
+        cleanUp()
+        state = newState
+        when (newState) {
+            is State.Default                    -> renderDefault()
+            is State.Hidden                     -> renderHidden()
+            is State.Tombstone                  -> renderTombstone(newState)
+            is State.ResourceLimitExceededError -> renderResourceLimitExceededError(newState)
+            is State.ConnectionError            -> renderConnectionError()
+            is State.Typing                     -> renderTyping(newState)
+            is State.UnreadPreview              -> renderUnreadPreview()
+            is State.ScrollToBottom             -> renderScrollToBottom(newState)
+            is State.UnsentEvents               -> renderUnsent(newState)
+        }
+    }
+
+    // PRIVATE METHODS *****************************************************************************************************************************************
+
+    private fun setupView() {
+        inflate(context, R.layout.view_notification_area, this)
+        ButterKnife.bind(this)
+    }
+
+    private fun cleanUp() {
+        messageView.setOnClickListener(null)
+        imageView.setOnClickListener(null)
+        setBackgroundColor(Color.TRANSPARENT)
+        messageView.text = null
+        imageView.setImageResource(0)
+    }
+
+    private fun renderTombstone(state: State.Tombstone) {
+        val roomTombstoneContent = state.tombstoneContent
+        val roomLink = PermalinkFactory.createPermalink(roomTombstoneContent.replacementRoom)
+                       ?: return
+
+        visibility = View.VISIBLE
+        imageView.setImageResource(R.drawable.error)
+        val textColorInt = ThemeUtils.getColor(context, R.attr.vctr_message_text_color)
+        val message = span {
+            +resources.getString(R.string.room_tombstone_versioned_description)
+            +"\n"
+            span(resources.getString(R.string.room_tombstone_continuation_link)) {
+                textDecorationLine = "underline"
+                onClick = { delegate?.onUrlClicked(roomLink) }
+            }
+        }
+        messageView.movementMethod = BetterLinkMovementMethod.getInstance()
+        messageView.text = message
+    }
+
+    private fun renderResourceLimitExceededError(state: State.ResourceLimitExceededError) {
+        visibility = View.VISIBLE
+        val resourceLimitErrorFormatter = ResourceLimitErrorFormatter(context)
+        val formatterMode: ResourceLimitErrorFormatter.Mode
+        val backgroundColor: Int
+        if (state.isSoft) {
+            backgroundColor = R.color.soft_resource_limit_exceeded
+            formatterMode = ResourceLimitErrorFormatter.Mode.Soft
+        } else {
+            backgroundColor = R.color.hard_resource_limit_exceeded
+            formatterMode = ResourceLimitErrorFormatter.Mode.Hard
+        }
+        val message = resourceLimitErrorFormatter.format(state.matrixError, formatterMode, clickable = true)
+        messageView.setTextColor(Color.WHITE)
+        messageView.text = message
+        messageView.movementMethod = LinkMovementMethod.getInstance()
+        messageView.setLinkTextColor(Color.WHITE)
+        setBackgroundColor(ContextCompat.getColor(context, backgroundColor))
+    }
+
+    private fun renderConnectionError() {
+        visibility = View.VISIBLE
+        imageView.setImageResource(R.drawable.error)
+        messageView.setTextColor(ContextCompat.getColor(context, R.color.vector_fuchsia_color))
+        messageView.text = SpannableString(resources.getString(R.string.room_offline_notification))
+    }
+
+    private fun renderTyping(state: State.Typing) {
+        visibility = View.VISIBLE
+        imageView.setImageResource(R.drawable.vector_typing)
+        messageView.text = SpannableString(state.message)
+        messageView.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_room_notification_text_color))
+    }
+
+    private fun renderUnreadPreview() {
+        visibility = View.VISIBLE
+        imageView.setImageResource(R.drawable.scrolldown)
+        messageView.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_room_notification_text_color))
+        imageView.setOnClickListener { delegate?.closeScreen() }
+    }
+
+    private fun renderScrollToBottom(state: State.ScrollToBottom) {
+        visibility = View.VISIBLE
+        if (state.unreadCount > 0) {
+            imageView.setImageResource(R.drawable.newmessages)
+            messageView.setTextColor(ContextCompat.getColor(context, R.color.vector_fuchsia_color))
+            messageView.text = SpannableString(resources.getQuantityString(R.plurals.room_new_messages_notification, state.unreadCount, state.unreadCount))
+        } else {
+            imageView.setImageResource(R.drawable.scrolldown)
+            messageView.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_room_notification_text_color))
+            if (!TextUtils.isEmpty(state.message)) {
+                messageView.text = SpannableString(state.message)
+            }
+        }
+        messageView.setOnClickListener { delegate?.jumpToBottom() }
+        imageView.setOnClickListener { delegate?.jumpToBottom() }
+    }
+
+    private fun renderUnsent(state: State.UnsentEvents) {
+        visibility = View.VISIBLE
+        imageView.setImageResource(R.drawable.error)
+        val cancelAll = resources.getString(R.string.room_prompt_cancel)
+        val resendAll = resources.getString(R.string.room_prompt_resend)
+        val messageRes = if (state.hasUnknownDeviceEvents) R.string.room_unknown_devices_messages_notification else R.string.room_unsent_messages_notification
+        val message = context.getString(messageRes, resendAll, cancelAll)
+        val cancelAllPos = message.indexOf(cancelAll)
+        val resendAllPos = message.indexOf(resendAll)
+        val spannableString = SpannableString(message)
+        // cancelAllPos should always be > 0 but a GA crash reported here
+        if (cancelAllPos >= 0) {
+            spannableString.setSpan(CancelAllClickableSpan(), cancelAllPos, cancelAllPos + cancelAll.length, 0)
+        }
+
+        // resendAllPos should always be > 0 but a GA crash reported here
+        if (resendAllPos >= 0) {
+            spannableString.setSpan(ResendAllClickableSpan(), resendAllPos, resendAllPos + resendAll.length, 0)
+        }
+        messageView.movementMethod = LinkMovementMethod.getInstance()
+        messageView.setTextColor(ContextCompat.getColor(context, R.color.vector_fuchsia_color))
+        messageView.text = spannableString
+    }
+
+    private fun renderDefault() {
+        visibility = View.GONE
+    }
+
+    private fun renderHidden() {
+        visibility = View.GONE
+    }
+
+    /**
+     * Track the cancel all click.
+     */
+    private inner class CancelAllClickableSpan : ClickableSpan() {
+        override fun onClick(widget: View) {
+            delegate?.deleteUnsentEvents()
+            render(state)
+        }
+
+        override fun updateDrawState(ds: TextPaint) {
+            super.updateDrawState(ds)
+            ds.color = ContextCompat.getColor(context, R.color.vector_fuchsia_color)
+            ds.bgColor = 0
+            ds.isUnderlineText = true
+        }
+    }
+
+    /**
+     * Track the resend all click.
+     */
+    private inner class ResendAllClickableSpan : ClickableSpan() {
+        override fun onClick(widget: View) {
+            delegate?.resendUnsentEvents()
+            render(state)
+        }
+
+        override fun updateDrawState(ds: TextPaint) {
+            super.updateDrawState(ds)
+            ds.color = ContextCompat.getColor(context, R.color.vector_fuchsia_color)
+            ds.bgColor = 0
+            ds.isUnderlineText = true
+        }
+    }
+
+    /**
+     * The state representing the view
+     * It can take one state at a time
+     * Priority of state is managed in {@link VectorRoomActivity.refreshNotificationsArea() }
+     */
+    sealed class State {
+
+        // Not yet rendered
+        object Initial : State()
+
+        // View will be Invisible
+        object Default : State()
+
+        // View will be Gone
+        object Hidden : State()
+
+        // Resource limit exceeded error will be displayed (only hard for the moment)
+        data class ResourceLimitExceededError(val isSoft: Boolean, val matrixError: MatrixError) : State()
+
+        // Server connection is lost
+        object ConnectionError : State()
+
+        // The room is dead
+        data class Tombstone(val tombstoneContent: RoomTombstoneContent) : State()
+
+        // Somebody is typing
+        data class Typing(val message: String) : State()
+
+        // Some new messages are unread in preview
+        object UnreadPreview : State()
+
+        // Some new messages are unread (grey or red)
+        data class ScrollToBottom(val unreadCount: Int, val message: String? = null) : State()
+
+        // Some event has been unsent
+        data class UnsentEvents(val hasUndeliverableEvents: Boolean, val hasUnknownDeviceEvents: Boolean) : State()
+    }
+
+    /**
+     * An interface to delegate some actions to another object
+     */
+    interface Delegate {
+        fun onUrlClicked(url: String)
+        fun resendUnsentEvents()
+        fun deleteUnsentEvents()
+        fun closeScreen()
+        fun jumpToBottom()
+    }
+
+    companion object {
+        /**
+         * Preference key.
+         */
+        private const val SHOW_INFO_AREA_KEY = "SETTINGS_SHOW_INFO_AREA_KEY"
+
+        /**
+         * Always show the info area.
+         */
+        private const val SHOW_INFO_AREA_VALUE_ALWAYS = "always"
+
+        /**
+         * Show the info area when it has messages or errors.
+         */
+        private const val SHOW_INFO_AREA_VALUE_MESSAGES_AND_ERRORS = "messages_and_errors"
+
+        /**
+         * Show the info area only when it has errors.
+         */
+        private const val SHOW_INFO_AREA_VALUE_ONLY_ERRORS = "only_errors"
+    }
+}
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
index 204dfb5d74..ab766e149d 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
@@ -76,6 +76,7 @@ import im.vector.riotx.core.extensions.observeEvent
 import im.vector.riotx.core.extensions.setTextOrHide
 import im.vector.riotx.core.files.addEntryToDownloadManager
 import im.vector.riotx.core.glide.GlideApp
+import im.vector.riotx.core.platform.NotificationAreaView
 import im.vector.riotx.core.platform.VectorBaseFragment
 import im.vector.riotx.core.utils.*
 import im.vector.riotx.features.autocomplete.command.AutocompleteCommandPresenter
@@ -203,6 +204,7 @@ class RoomDetailFragment :
         setupComposer()
         setupAttachmentButton()
         setupInviteView()
+        setupNotificationView()
         roomDetailViewModel.subscribe { renderState(it) }
         textComposerViewModel.subscribe { renderTextComposerState(it) }
         roomDetailViewModel.sendMessageResultLiveData.observeEvent(this) { renderSendMessageResult(it) }
@@ -239,6 +241,36 @@ class RoomDetailFragment :
         }
     }
 
+    private fun setupNotificationView() {
+        notificationAreaView.delegate = object : NotificationAreaView.Delegate {
+
+            override fun onUrlClicked(url: String) {
+                permalinkHandler.launch(requireActivity(), url, object : NavigateToRoomInterceptor {
+                    override fun navToRoom(roomId: String, eventId: String?): Boolean {
+                        requireActivity().finish()
+                        return false
+                    }
+                })
+            }
+
+            override fun resendUnsentEvents() {
+                TODO("not implemented")
+            }
+
+            override fun deleteUnsentEvents() {
+                TODO("not implemented")
+            }
+
+            override fun closeScreen() {
+                TODO("not implemented")
+            }
+
+            override fun jumpToBottom() {
+                TODO("not implemented")
+            }
+        }
+    }
+
     private fun exitSpecialMode() {
         commandAutocompletePolicy.enabled = true
         composerLayout.collapse()
@@ -259,17 +291,17 @@ class RoomDetailFragment :
         if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
             val parser = Parser.builder().build()
             val document = parser.parse(messageContent.formattedBody
-                    ?: messageContent.body)
+                                        ?: messageContent.body)
             formattedBody = eventHtmlRenderer.render(document)
         }
         composerLayout.composerRelatedMessageContent.text = formattedBody
-                ?: nonFormattedBody
+                                                            ?: nonFormattedBody
 
         composerLayout.composerEditText.setText(if (useText) event.getTextEditableContent() else "")
         composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), iconRes))
 
         avatarRenderer.render(event.senderAvatar, event.root.senderId
-                ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
+                                                  ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
 
         composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text.length)
         composerLayout.expand {
@@ -298,9 +330,9 @@ class RoomDetailFragment :
                 REQUEST_FILES_REQUEST_CODE, TAKE_IMAGE_REQUEST_CODE -> handleMediaIntent(data)
                 REACTION_SELECT_REQUEST_CODE                        -> {
                     val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID)
-                            ?: return
+                                  ?: return
                     val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT)
-                            ?: return
+                                   ?: return
                     //TODO check if already reacted with that?
                     roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, eventId))
                 }
@@ -335,26 +367,26 @@ class RoomDetailFragment :
 
         if (VectorPreferences.swipeToReplyIsEnabled(requireContext())) {
             val swipeCallback = RoomMessageTouchHelperCallback(requireContext(),
-                    R.drawable.ic_reply,
-                    object : RoomMessageTouchHelperCallback.QuickReplayHandler {
-                        override fun performQuickReplyOnHolder(model: EpoxyModel<*>) {
-                            (model as? AbsMessageItem)?.informationData?.let {
-                                val eventId = it.eventId
-                                roomDetailViewModel.process(RoomDetailActions.EnterReplyMode(eventId))
-                            }
-                        }
+                                                               R.drawable.ic_reply,
+                                                               object : RoomMessageTouchHelperCallback.QuickReplayHandler {
+                                                                   override fun performQuickReplyOnHolder(model: EpoxyModel<*>) {
+                                                                       (model as? AbsMessageItem)?.informationData?.let {
+                                                                           val eventId = it.eventId
+                                                                           roomDetailViewModel.process(RoomDetailActions.EnterReplyMode(eventId))
+                                                                       }
+                                                                   }
 
-                        override fun canSwipeModel(model: EpoxyModel<*>): Boolean {
-                            return when (model) {
-                                is MessageFileItem,
-                                is MessageImageVideoItem,
-                                is MessageTextItem -> {
-                                    return (model as AbsMessageItem).informationData.sendState == SendState.SYNCED
-                                }
-                                else               -> false
-                            }
-                        }
-                    })
+                                                                   override fun canSwipeModel(model: EpoxyModel<*>): Boolean {
+                                                                       return when (model) {
+                                                                           is MessageFileItem,
+                                                                           is MessageImageVideoItem,
+                                                                           is MessageTextItem -> {
+                                                                               return (model as AbsMessageItem).informationData.sendState == SendState.SYNCED
+                                                                           }
+                                                                           else               -> false
+                                                                       }
+                                                                   }
+                                                               })
             val touchHelper = ItemTouchHelper(swipeCallback)
             touchHelper.attachToRecyclerView(recyclerView)
         }
@@ -534,12 +566,14 @@ class RoomDetailFragment :
         } else if (state.asyncInviter.complete) {
             vectorBaseActivity.finish()
         }
+
         if (state.tombstoneContent == null) {
             composerLayout.visibility = View.VISIBLE
             composerLayout.setRoomEncrypted(state.isEncrypted)
+            notificationAreaView.render(NotificationAreaView.State.Hidden)
         } else {
             composerLayout.visibility = View.GONE
-            showSnackWithMessage("TOMBSTONED", duration = Snackbar.LENGTH_INDEFINITE)
+            notificationAreaView.render(NotificationAreaView.State.Tombstone(state.tombstoneContent))
         }
     }
 
@@ -636,7 +670,7 @@ class RoomDetailFragment :
         val intent = ImageMediaViewerActivity.newIntent(vectorBaseActivity, mediaData, ViewCompat.getTransitionName(view))
         val bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
                 requireActivity(), view, ViewCompat.getTransitionName(view)
-                ?: "").toBundle()
+                                         ?: "").toBundle()
         startActivity(intent, bundle)
     }
 
@@ -716,7 +750,17 @@ class RoomDetailFragment :
         ViewEditHistoryBottomSheet.newInstance(roomDetailArgs.roomId, informationData)
                 .show(requireActivity().supportFragmentManager, "DISPLAY_EDITS")
     }
-// AutocompleteUserPresenter.Callback
+
+    override fun onRoomCreateLinkClicked(url: String) {
+        permalinkHandler.launch(requireContext(), url, object : NavigateToRoomInterceptor {
+            override fun navToRoom(roomId: String, eventId: String?): Boolean {
+                requireActivity().finish()
+                return false
+            }
+        })
+    }
+
+    // AutocompleteUserPresenter.Callback
 
     override fun onQueryUsers(query: CharSequence?) {
         textComposerViewModel.process(TextComposerActions.QueryUsers(query))
@@ -730,7 +774,7 @@ class RoomDetailFragment :
             }
             MessageMenuViewModel.ACTION_VIEW_REACTIONS -> {
                 val messageInformationData = actionData.data as? MessageInformationData
-                        ?: return
+                                             ?: return
                 ViewReactionBottomSheet.newInstance(roomDetailArgs.roomId, messageInformationData)
                         .show(requireActivity().supportFragmentManager, "DISPLAY_REACTIONS")
             }
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt
index 0b78f8153f..e8268bace6 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt
@@ -54,6 +54,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
 
     interface Callback : ReactionPillCallback, AvatarCallback, BaseCallback, UrlClickCallback {
         fun onEventVisible(event: TimelineEvent)
+        fun onRoomCreateLinkClicked(url: String)
         fun onEncryptedMessageClicked(informationData: MessageInformationData, view: View)
         fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View)
         fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: VideoContentRenderer.Data, view: View)
@@ -158,7 +159,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
             synchronized(modelCache) {
                 for (i in 0 until modelCache.size) {
                     if (modelCache[i]?.eventId == eventIdToHighlight
-                            || modelCache[i]?.eventId == this.eventIdToHighlight) {
+                        || modelCache[i]?.eventId == this.eventIdToHighlight) {
                         modelCache[i] = null
                     }
                 }
@@ -219,8 +220,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
                 // Should be build if not cached or if cached but contains mergedHeader or formattedDay
                 // We then are sure we always have items up to date.
                 if (modelCache[position] == null
-                        || modelCache[position]?.mergedHeaderModel != null
-                        || modelCache[position]?.formattedDayModel != null) {
+                    || modelCache[position]?.mergedHeaderModel != null
+                    || modelCache[position]?.formattedDayModel != null) {
                     modelCache[position] = buildItemModels(position, currentSnapshot)
                 }
             }
@@ -294,7 +295,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
                 // => handle case where paginating from mergeable events and we get more
                 val previousCollapseStateKey = mergedEventIds.intersect(mergeItemCollapseStates.keys).firstOrNull()
                 val initialCollapseState = mergeItemCollapseStates.remove(previousCollapseStateKey)
-                        ?: true
+                                           ?: true
                 val isCollapsed = mergeItemCollapseStates.getOrPut(event.localId) { initialCollapseState }
                 if (isCollapsed) {
                     collapsedEventIds.addAll(mergedEventIds)
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt
index 21fe85d774..e32e2746cf 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt
@@ -18,7 +18,6 @@
 
 package im.vector.riotx.features.home.room.detail.timeline.factory
 
-import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
 import im.vector.matrix.android.api.permalinks.PermalinkFactory
 import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.model.create.RoomCreateContent
@@ -37,21 +36,16 @@ class RoomCreateItemFactory @Inject constructor(private val colorProvider: Color
 
     fun create(event: TimelineEvent, callback: TimelineEventController.Callback?): RoomCreateItem? {
         val createRoomContent = event.root.getClearContent().toModel<RoomCreateContent>()
-                ?: return null
+                                ?: return null
         val predecessor = createRoomContent.predecessor ?: return null
         val roomLink = PermalinkFactory.createPermalink(predecessor.roomId) ?: return null
-        val urlSpan = MatrixPermalinkSpan(roomLink, object : MatrixPermalinkSpan.Callback {
-            override fun onUrlClicked(url: String) {
-                callback?.onUrlClicked(roomLink)
-            }
-        })
-        val textColorInt = colorProvider.getColor(R.color.riot_primary_text_color_light)
         val text = span {
-            text = stringProvider.getString(R.string.room_tombstone_continuation_description)
-            append("\n")
-            append(
-                    stringProvider.getString(R.string.room_tombstone_predecessor_link)
-            )
+            +stringProvider.getString(R.string.room_tombstone_continuation_description)
+            +"\n"
+            span(stringProvider.getString(R.string.room_tombstone_predecessor_link)) {
+                textDecorationLine = "underline"
+                onClick = { callback?.onRoomCreateLinkClicked(roomLink) }
+            }
         }
         return RoomCreateItem_()
                 .text(text)
diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/RoomCreateItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/RoomCreateItem.kt
index 117f4bd2d0..3e5ef30d90 100644
--- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/RoomCreateItem.kt
+++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/RoomCreateItem.kt
@@ -21,10 +21,10 @@ package im.vector.riotx.features.home.room.detail.timeline.item
 import android.widget.TextView
 import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
-import com.airbnb.epoxy.EpoxyModelWithHolder
 import im.vector.riotx.R
 import im.vector.riotx.core.epoxy.VectorEpoxyHolder
 import im.vector.riotx.core.epoxy.VectorEpoxyModel
+import me.saket.bettermovementmethod.BetterLinkMovementMethod
 
 @EpoxyModelClass(layout = R.layout.item_timeline_event_create)
 abstract class RoomCreateItem : VectorEpoxyModel<RoomCreateItem.Holder>() {
@@ -32,6 +32,7 @@ abstract class RoomCreateItem : VectorEpoxyModel<RoomCreateItem.Holder>() {
     @EpoxyAttribute lateinit var text: CharSequence
 
     override fun bind(holder: Holder) {
+        holder.description.movementMethod = BetterLinkMovementMethod.getInstance()
         holder.description.text = text
     }
 
diff --git a/vector/src/main/res/layout/fragment_room_detail.xml b/vector/src/main/res/layout/fragment_room_detail.xml
index f8cec43371..ae38b51008 100644
--- a/vector/src/main/res/layout/fragment_room_detail.xml
+++ b/vector/src/main/res/layout/fragment_room_detail.xml
@@ -74,12 +74,18 @@
         android:id="@+id/recyclerView"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        app:layout_constraintBottom_toTopOf="@+id/composerLayout"
+        app:layout_constraintBottom_toTopOf="@+id/recyclerViewBarrier"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/roomToolbar"
         tools:listitem="@layout/item_timeline_event_base" />
 
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/recyclerViewBarrier"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:barrierDirection="top"
+        app:constraint_referenced_ids="composerLayout,notificationAreaView" />
 
     <im.vector.riotx.features.home.room.detail.composer.TextComposerView
         android:id="@+id/composerLayout"
@@ -89,6 +95,16 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent" />
 
+    <im.vector.riotx.core.platform.NotificationAreaView
+        android:id="@+id/notificationAreaView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
     <im.vector.riotx.features.invite.VectorInviteView
         android:id="@+id/inviteView"
         android:layout_width="0dp"
diff --git a/vector/src/main/res/layout/item_timeline_event_create.xml b/vector/src/main/res/layout/item_timeline_event_create.xml
index 80dc7d6312..d6fc5e4b5d 100644
--- a/vector/src/main/res/layout/item_timeline_event_create.xml
+++ b/vector/src/main/res/layout/item_timeline_event_create.xml
@@ -12,9 +12,8 @@
         android:layout_marginLeft="16dp"
         android:layout_marginTop="16dp"
         android:layout_marginBottom="16dp"
-        android:background="@drawable/bg_tombstone_predecessor"
+        android:background="?attr/riotx_keys_backup_banner_accent_color"
         android:drawableStart="@drawable/error"
-        android:drawableLeft="@drawable/error"
         android:drawablePadding="16dp"
         android:gravity="center|start"
         android:minHeight="80dp"