diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt
index 0df41d106d..a2a242a3d9 100644
--- a/vector/src/main/java/im/vector/app/AppStateHandler.kt
+++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt
@@ -24,6 +24,7 @@ import im.vector.app.core.di.ActiveSessionHolder
 import im.vector.app.core.utils.BehaviorDataSource
 import im.vector.app.features.ui.UiStateRepository
 import io.reactivex.disposables.CompositeDisposable
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.extensions.tryOrNull
@@ -68,7 +69,7 @@ class AppStateHandler @Inject constructor(
         val spaceSum = spaceId?.let { uSession?.getRoomSummary(spaceId) }
         selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum)))
         if (spaceId != null) {
-            GlobalScope.launch {
+            GlobalScope.launch(Dispatchers.IO) {
                 tryOrNull {
                     uSession?.getRoom(spaceId)?.loadRoomMembersIfNeeded()
                 }
diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
index b6c75beb02..c16c602530 100644
--- a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
@@ -81,6 +81,7 @@ import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
 import im.vector.app.features.spaces.ShareSpaceBottomSheet
 import im.vector.app.features.spaces.SpaceCreationActivity
 import im.vector.app.features.spaces.SpaceExploreActivity
+import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
 import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
 import im.vector.app.features.spaces.manage.SpaceManageActivity
 import im.vector.app.features.terms.ReviewTermsActivity
@@ -185,6 +186,7 @@ interface ScreenComponent {
     fun inject(bottomSheet: ShareSpaceBottomSheet)
     fun inject(bottomSheet: SpaceSettingsMenuBottomSheet)
     fun inject(bottomSheet: InviteRoomSpaceChooserBottomSheet)
+    fun inject(bottomSheet: SpaceInviteBottomSheet)
 
     /* ==========================================================================================
      * Others
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
index f01c27c30e..1de1ff1c3e 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
@@ -62,6 +62,7 @@ import im.vector.app.features.spaces.ShareSpaceBottomSheet
 import im.vector.app.features.spaces.SpaceCreationActivity
 import im.vector.app.features.spaces.SpacePreviewActivity
 import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
+import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
 import im.vector.app.features.themes.ThemeUtils
 import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
 import im.vector.app.features.workers.signout.ServerBackupStatusViewState
@@ -88,7 +89,8 @@ class HomeActivity :
         UnknownDeviceDetectorSharedViewModel.Factory,
         ServerBackupStatusViewModel.Factory,
         UnreadMessagesSharedViewModel.Factory,
-        NavigationInterceptor {
+        NavigationInterceptor,
+        SpaceInviteBottomSheet.InteractionListener {
 
     private lateinit var sharedActionViewModel: HomeSharedActionViewModel
 
@@ -210,6 +212,10 @@ class HomeActivity :
                                     })
                                     .show(supportFragmentManager, "SPACE_SETTINGS")
                         }
+                        is HomeActivitySharedAction.OpenSpaceInvite -> {
+                            SpaceInviteBottomSheet.newInstance(sharedAction.spaceId)
+                                    .show(supportFragmentManager, "SPACE_INVITE")
+                        }
                     }.exhaustive
                 }
                 .disposeOnDestroy()
@@ -514,6 +520,14 @@ class HomeActivity :
         return true
     }
 
+    override fun spaceInviteBottomSheetOnAccept(spaceId: String) {
+        navigator.switchToSpace(this, spaceId, Navigator.PostSwitchSpaceAction.None)
+    }
+
+    override fun spaceInviteBottomSheetOnDecline(spaceId: String) {
+        // nop
+    }
+
     companion object {
         fun newIntent(context: Context, clearNotification: Boolean = false, accountCreation: Boolean = false): Intent {
             val args = HomeActivityArgs(
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt
index db0a9ba9eb..d79f24fc4c 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt
@@ -27,5 +27,6 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
     data class OpenGroup(val clearFragment: Boolean) : HomeActivitySharedAction()
     object AddSpace : HomeActivitySharedAction()
     data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
+    data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction()
     data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
 }
diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt
index 7d303cfc5e..7a5a740b93 100644
--- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt
@@ -20,6 +20,7 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.core.view.isGone
 import androidx.core.view.isInvisible
 import androidx.core.view.isVisible
 import com.airbnb.mvrx.Fail
@@ -71,8 +72,10 @@ class MatrixToRoomSpaceFragment @Inject constructor(
                     is RoomInfoResult.FullInfo     -> {
                         val matrixItem = peek.roomItem
                         if (peek.roomType == RoomType.SPACE) {
+                            views.matrixToBetaTag.isVisible = true
                             avatarRenderer.renderSpace(matrixItem, views.matrixToCardAvatar)
                         } else {
+                            views.matrixToBetaTag.isVisible = false
                             avatarRenderer.render(matrixItem, views.matrixToCardAvatar)
                         }
                         views.matrixToCardNameText.setTextOrHide(peek.name)
@@ -97,19 +100,19 @@ class MatrixToRoomSpaceFragment @Inject constructor(
                             Membership.LEAVE,
                             Membership.NONE   -> {
                                 views.matrixToCardMainButton.isVisible = true
-                                views.matrixToCardMainButton.text = getString(joinTextRes)
+                                views.matrixToCardMainButton.button.text = getString(joinTextRes)
                                 views.matrixToCardSecondaryButton.isVisible = false
                             }
                             Membership.INVITE -> {
                                 views.matrixToCardMainButton.isVisible = true
                                 views.matrixToCardSecondaryButton.isVisible = true
-                                views.matrixToCardMainButton.text = getString(joinTextRes)
-                                views.matrixToCardSecondaryButton.text = getString(R.string.decline)
+                                views.matrixToCardMainButton.button.text = getString(joinTextRes)
+                                views.matrixToCardSecondaryButton.button.text = getString(R.string.decline)
                             }
                             Membership.JOIN   -> {
                                 views.matrixToCardMainButton.isVisible = true
                                 views.matrixToCardSecondaryButton.isVisible = false
-                                views.matrixToCardMainButton.text = getString(R.string.action_open)
+                                views.matrixToCardMainButton.button.text = getString(R.string.action_open)
                             }
                             Membership.KNOCK,
                             Membership.BAN    -> {
@@ -126,7 +129,7 @@ class MatrixToRoomSpaceFragment @Inject constructor(
                         views.matrixToMemberPills.isVisible = false
                         views.matrixToCardDescText.setTextOrHide(getString(R.string.room_preview_no_preview))
 
-                        views.matrixToCardMainButton.text = getString(R.string.join_anyway)
+                        views.matrixToCardMainButton.button.text = getString(R.string.join_anyway)
                         views.matrixToCardSecondaryButton.isVisible = false
                     }
                     RoomInfoResult.NotFound        -> {
@@ -156,12 +159,10 @@ class MatrixToRoomSpaceFragment @Inject constructor(
             }
         }
 
+        val images = listOf(views.knownMember1, views.knownMember2, views.knownMember3, views.knownMember4, views.knownMember5)
+                .onEach { it.isGone = true }
         when (state.peopleYouKnow) {
             is Success -> {
-                views.matrixToCardPeopleYouKnowVisibility.isVisible = true
-                val images = listOf(views.knownMember1, views.knownMember2, views.knownMember3, views.knownMember4, views.knownMember5)
-                        .onEach { it.isVisible = false }
-
                 val someYouKnow = state.peopleYouKnow.invoke()
                 someYouKnow.forEachIndexed { index, item ->
                     images[index].isVisible = true
@@ -175,7 +176,7 @@ class MatrixToRoomSpaceFragment @Inject constructor(
                 )
             }
             else       -> {
-                views.matrixToCardPeopleYouKnowVisibility.isVisible = false
+                views.peopleYouMayKnowText.isVisible = false
             }
         }
 
diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt
index 672fb28928..f1627cc6b6 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt
@@ -60,6 +60,7 @@ class SpaceListFragment @Inject constructor(
                 is SpaceListViewEvents.OpenSpace        -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged))
                 is SpaceListViewEvents.AddSpace         -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace)
                 is SpaceListViewEvents.OpenGroup        -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged))
+                is SpaceListViewEvents.OpenSpaceInvite  -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id))
             }.exhaustive
         }
     }
diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt
index b7e31d28f2..582f6cd144 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewEvents.kt
@@ -24,6 +24,7 @@ import im.vector.app.core.platform.VectorViewEvents
 sealed class SpaceListViewEvents : VectorViewEvents {
     data class OpenSpace(val groupingMethodHasChanged: Boolean) : SpaceListViewEvents()
     data class OpenSpaceSummary(val id: String) : SpaceListViewEvents()
+    data class OpenSpaceInvite(val id: String) : SpaceListViewEvents()
     object AddSpace : SpaceListViewEvents()
     data class OpenGroup(val groupingMethodHasChanged: Boolean) : SpaceListViewEvents()
 }
diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt
index 90ab771342..c79f6b12a4 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpacesListViewModel.kt
@@ -181,7 +181,7 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
     }
 
     private fun handleSelectSpaceInvite(action: SpaceListAction.OpenSpaceInvite) {
-        _viewEvents.post(SpaceListViewEvents.OpenSpaceSummary(action.spaceSummary.roomId))
+        _viewEvents.post(SpaceListViewEvents.OpenSpaceInvite(action.spaceSummary.roomId))
     }
 
     private fun handleToggleExpand(action: SpaceListAction.ToggleExpand) = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt
new file mode 100644
index 0000000000..8e536459a3
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2021 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.app.features.spaces.invite
+
+import android.content.Context
+import android.os.Bundle
+import android.os.Parcelable
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.isGone
+import androidx.core.view.isVisible
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Loading
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
+import com.airbnb.mvrx.args
+import com.airbnb.mvrx.fragmentViewModel
+import com.airbnb.mvrx.withState
+import im.vector.app.R
+import im.vector.app.core.di.ScreenComponent
+import im.vector.app.core.extensions.setTextOrHide
+import im.vector.app.core.platform.ButtonStateView
+import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
+import im.vector.app.core.utils.toast
+import im.vector.app.databinding.BottomSheetInvitedToSpaceBinding
+import im.vector.app.features.home.AvatarRenderer
+import kotlinx.parcelize.Parcelize
+import org.matrix.android.sdk.api.util.toMatrixItem
+import javax.inject.Inject
+
+class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetInvitedToSpaceBinding>(), SpaceInviteBottomSheetViewModel.Factory {
+
+    interface InteractionListener {
+        fun spaceInviteBottomSheetOnAccept(spaceId: String)
+        fun spaceInviteBottomSheetOnDecline(spaceId: String)
+    }
+
+    var interactionListener: InteractionListener? = null
+
+    @Parcelize
+    data class Args(
+            val spaceId: String
+    ) : Parcelable
+
+    @Inject
+    lateinit var avatarRenderer: AvatarRenderer
+
+    private val viewModel: SpaceInviteBottomSheetViewModel by fragmentViewModel(SpaceInviteBottomSheetViewModel::class)
+
+    @Inject lateinit var viewModelFactory: SpaceInviteBottomSheetViewModel.Factory
+
+    override fun create(initialState: SpaceInviteBottomSheetState) = viewModelFactory.create(initialState)
+
+    override fun injectWith(injector: ScreenComponent) {
+        injector.inject(this)
+    }
+
+    override val showExpanded = true
+
+    private val inviteArgs: Args by args()
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        views.spaceCard.matrixToCardMainButton.callback = object : ButtonStateView.Callback {
+            override fun onButtonClicked() {
+                // quick local echo
+                views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Loading)
+                views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = false
+                viewModel.handle(SpaceInviteBottomSheetAction.DoJoin)
+            }
+
+            override fun onRetryClicked() = onButtonClicked()
+        }
+        views.spaceCard.matrixToCardSecondaryButton.callback = object : ButtonStateView.Callback {
+            override fun onButtonClicked() {
+                views.spaceCard.matrixToCardMainButton.button.isEnabled = false
+                views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Loading)
+                viewModel.handle(SpaceInviteBottomSheetAction.DoReject)
+            }
+
+            override fun onRetryClicked() = onButtonClicked()
+        }
+
+        viewModel.observeViewEvents {
+            when (it) {
+                is SpaceInviteBottomSheetEvents.ShowError -> requireActivity().toast(it.message)
+            }
+        }
+    }
+
+    override fun onAttach(context: Context) {
+        super.onAttach(context)
+        if (context is InteractionListener) {
+            interactionListener = context
+        }
+    }
+
+    override fun onDetach() {
+        interactionListener = null
+        super.onDetach()
+    }
+
+    override fun invalidate() = withState(viewModel) { state ->
+        super.invalidate()
+        val summary = state.summary.invoke()
+        val inviter = state.inviterUser.invoke()?.toMatrixItem()
+        if (inviter != null) {
+            views.inviterAvatarImage.isVisible = true
+            views.inviterText.isVisible = true
+            views.inviterMxid.isVisible = true
+            avatarRenderer.render(inviter, views.inviterAvatarImage)
+            views.inviterText.text = getString(R.string.user_invites_you, inviter.getBestName())
+            views.inviterMxid.text = inviter.id
+        } else {
+            views.inviterAvatarImage.isVisible = false
+            views.inviterText.isVisible = false
+            views.inviterMxid.isVisible = false
+        }
+
+        views.spaceCard.matrixToCardContentVisibility.isVisible = true
+        summary?.toMatrixItem()?.let { avatarRenderer.renderSpace(it, views.spaceCard.matrixToCardAvatar) }
+        views.spaceCard.matrixToCardNameText.text = summary?.displayName
+        views.spaceCard.matrixToBetaTag.isVisible = true
+        views.spaceCard.matrixToCardAliasText.setTextOrHide(summary?.canonicalAlias)
+        views.spaceCard.matrixToCardDescText.setTextOrHide(summary?.topic)
+
+        views.spaceCard.matrixToCardMainButton.button.text = getString(R.string.accept)
+        views.spaceCard.matrixToCardSecondaryButton.button.text = getString(R.string.decline)
+
+        when (state.joinActionState) {
+            Uninitialized -> {
+                views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Button)
+            }
+            is Loading -> {
+                views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Loading)
+                views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = false
+            }
+            is Success -> {
+                interactionListener?.spaceInviteBottomSheetOnAccept(inviteArgs.spaceId)
+                dismiss()
+            }
+            is Fail -> {
+                views.spaceCard.matrixToCardMainButton.render(ButtonStateView.State.Error)
+                views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = true
+            }
+        }
+
+        when (state.rejectActionState) {
+            Uninitialized -> {
+                views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Button)
+            }
+            is Loading -> {
+                views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Loading)
+                views.spaceCard.matrixToCardMainButton.button.isEnabled = false
+            }
+            is Success -> {
+                interactionListener?.spaceInviteBottomSheetOnDecline(inviteArgs.spaceId)
+                dismiss()
+            }
+            is Fail -> {
+                views.spaceCard.matrixToCardSecondaryButton.render(ButtonStateView.State.Error)
+                views.spaceCard.matrixToCardSecondaryButton.button.isEnabled = true
+            }
+        }
+
+        val memberCount = summary?.otherMemberIds?.size ?: 0
+        if (memberCount != 0) {
+            views.spaceCard.matrixToMemberPills.isVisible = true
+            views.spaceCard.spaceChildMemberCountText.text = resources.getQuantityString(R.plurals.room_title_members, memberCount, memberCount)
+        } else {
+            // hide the pill
+            views.spaceCard.matrixToMemberPills.isVisible = false
+        }
+
+        val peopleYouKnow = state.peopleYouKnow.invoke().orEmpty()
+
+        val images = listOf(
+                views.spaceCard.knownMember1,
+                views.spaceCard.knownMember2,
+                views.spaceCard.knownMember3,
+                views.spaceCard.knownMember4,
+                views.spaceCard.knownMember5
+        ).onEach { it.isGone = true }
+
+        if (peopleYouKnow.isEmpty()) {
+            views.spaceCard.peopleYouMayKnowText.isVisible = false
+        } else {
+            peopleYouKnow.forEachIndexed { index, item ->
+                images[index].isVisible = true
+                avatarRenderer.render(item.toMatrixItem(), images[index])
+            }
+            views.spaceCard.peopleYouMayKnowText.setTextOrHide(
+                    resources.getQuantityString(R.plurals.space_people_you_know,
+                            peopleYouKnow.count(),
+                            peopleYouKnow.count()
+                    )
+            )
+        }
+    }
+
+    override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetInvitedToSpaceBinding {
+        return BottomSheetInvitedToSpaceBinding.inflate(inflater, container, false)
+    }
+
+    companion object {
+
+        fun newInstance(spaceId: String)
+                : SpaceInviteBottomSheet {
+            return SpaceInviteBottomSheet().apply {
+                setArguments(Args(spaceId))
+            }
+        }
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetAction.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetAction.kt
new file mode 100644
index 0000000000..b8e3283aff
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetAction.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 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.app.features.spaces.invite
+
+import im.vector.app.core.platform.VectorViewModelAction
+
+sealed class SpaceInviteBottomSheetAction : VectorViewModelAction {
+    object DoJoin : SpaceInviteBottomSheetAction()
+    object DoReject : SpaceInviteBottomSheetAction()
+}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetEvents.kt
new file mode 100644
index 0000000000..b097d19d9e
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetEvents.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 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.app.features.spaces.invite
+
+import im.vector.app.core.platform.VectorViewEvents
+
+sealed class SpaceInviteBottomSheetEvents : VectorViewEvents {
+    data class ShowError(val message: String) : SpaceInviteBottomSheetEvents()
+}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetState.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetState.kt
new file mode 100644
index 0000000000..d712cf9e8a
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetState.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 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.app.features.spaces.invite
+
+import com.airbnb.mvrx.Async
+import com.airbnb.mvrx.MvRxState
+import com.airbnb.mvrx.Uninitialized
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.user.model.User
+
+data class SpaceInviteBottomSheetState(
+        val spaceId: String,
+        val summary: Async<RoomSummary> = Uninitialized,
+        val inviterUser: Async<User> = Uninitialized,
+        val peopleYouKnow: Async<List<User>> = Uninitialized,
+        val joinActionState: Async<Unit> = Uninitialized,
+        val rejectActionState: Async<Unit> = Uninitialized
+) : MvRxState {
+    constructor(args: SpaceInviteBottomSheet.Args) : this(
+            spaceId = args.spaceId
+    )
+}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt
new file mode 100644
index 0000000000..4524b57004
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021 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.app.features.spaces.invite
+
+import com.airbnb.mvrx.ActivityViewModelContext
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.FragmentViewModelContext
+import com.airbnb.mvrx.Loading
+import com.airbnb.mvrx.MvRxViewModelFactory
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
+import com.airbnb.mvrx.ViewModelContext
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import im.vector.app.core.error.ErrorFormatter
+import im.vector.app.core.platform.VectorViewModel
+import im.vector.app.features.session.coroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import org.matrix.android.sdk.api.session.Session
+
+class SpaceInviteBottomSheetViewModel @AssistedInject constructor(
+        @Assisted private val initialState: SpaceInviteBottomSheetState,
+        private val session: Session,
+        private val errorFormatter: ErrorFormatter
+) : VectorViewModel<SpaceInviteBottomSheetState, SpaceInviteBottomSheetAction, SpaceInviteBottomSheetEvents>(initialState) {
+
+    init {
+        session.getRoomSummary(initialState.spaceId)?.let { roomSummary ->
+
+            val knownMembers = roomSummary.otherMemberIds.filter {
+                session.getExistingDirectRoomWithUser(it) != null
+            }.mapNotNull { session.getUser(it) }
+            // put one with avatar first, and take 5
+            val peopleYouKnow = (knownMembers.filter { it.avatarUrl != null } + knownMembers.filter { it.avatarUrl == null })
+                    .take(5)
+
+            setState {
+                copy(
+                        summary = Success(roomSummary),
+                        inviterUser = roomSummary.inviterId?.let { session.getUser(it) }?.let { Success(it) } ?: Uninitialized,
+                        peopleYouKnow = Success(peopleYouKnow)
+                )
+            }
+        }
+    }
+
+    @AssistedFactory
+    interface Factory {
+        fun create(initialState: SpaceInviteBottomSheetState): SpaceInviteBottomSheetViewModel
+    }
+
+    companion object : MvRxViewModelFactory<SpaceInviteBottomSheetViewModel, SpaceInviteBottomSheetState> {
+
+        override fun create(viewModelContext: ViewModelContext, state: SpaceInviteBottomSheetState): SpaceInviteBottomSheetViewModel? {
+            val factory = when (viewModelContext) {
+                is FragmentViewModelContext -> viewModelContext.fragment as? Factory
+                is ActivityViewModelContext -> viewModelContext.activity as? Factory
+            }
+            return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
+        }
+    }
+
+    override fun handle(action: SpaceInviteBottomSheetAction) {
+        when (action) {
+            SpaceInviteBottomSheetAction.DoJoin   -> {
+                setState { copy(joinActionState = Loading()) }
+                session.coroutineScope.launch(Dispatchers.IO) {
+                    try {
+                        session.getRoom(initialState.spaceId)?.join()
+                        setState { copy(joinActionState = Success(Unit)) }
+                    } catch (failure: Throwable) {
+                        setState { copy(joinActionState = Fail(failure)) }
+                        _viewEvents.post(SpaceInviteBottomSheetEvents.ShowError(errorFormatter.toHumanReadable(failure)))
+                    }
+                }
+            }
+            SpaceInviteBottomSheetAction.DoReject -> {
+                setState { copy(rejectActionState = Loading()) }
+                session.coroutineScope.launch(Dispatchers.IO) {
+                    try {
+                        session.getRoom(initialState.spaceId)?.leave()
+                        setState { copy(rejectActionState = Success(Unit)) }
+                    } catch (failure: Throwable) {
+                        setState { copy(rejectActionState = Fail(failure)) }
+                        _viewEvents.post(SpaceInviteBottomSheetEvents.ShowError(errorFormatter.toHumanReadable(failure)))
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt
index eee8d1241f..8f2e7379c4 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt
@@ -37,16 +37,15 @@ class SpacePreviewController @Inject constructor(
     var interactionListener: InteractionListener? = null
 
     override fun buildModels(data: SpacePreviewState?) {
-        val result = data?.childInfoList?.invoke() ?: return
-
-        val memberCount = data.spaceInfo.invoke()?.memberCount ?: 0
+        val memberCount = data?.spaceInfo?.invoke()?.memberCount ?: 0
 
         spaceTopSummaryItem {
             id("info")
             formattedMemberCount(stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount))
-            topic(data.spaceInfo.invoke()?.topic ?: data.topic ?: "")
+            topic(data?.spaceInfo?.invoke()?.topic ?: data?.topic ?: "")
         }
 
+        val result = data?.childInfoList?.invoke() ?: return
         if (result.isNotEmpty()) {
             genericItemHeader {
                 id("header_rooms")
diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt
index 563b4f39e0..b6f1fb6a4e 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt
@@ -119,14 +119,17 @@ class SpacePreviewFragment @Inject constructor(
             }
         }
         updateToolbar(it)
+
+        when (it.inviteTermination) {
+            is Loading -> sharedActionViewModel.post(SpacePreviewSharedAction.ShowModalLoading)
+            else       -> sharedActionViewModel.post(SpacePreviewSharedAction.HideModalLoading)
+        }
     }
 
     private fun handleViewEvents(viewEvents: SpacePreviewViewEvents) {
         when (viewEvents) {
             SpacePreviewViewEvents.Dismiss -> {
-            }
-            SpacePreviewViewEvents.StartJoining -> {
-                sharedActionViewModel.post(SpacePreviewSharedAction.ShowModalLoading)
+                sharedActionViewModel.post(SpacePreviewSharedAction.DismissAction)
             }
             SpacePreviewViewEvents.JoinSuccess -> {
                 sharedActionViewModel.post(SpacePreviewSharedAction.HideModalLoading)
diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewState.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewState.kt
index cf64672046..d31d05cf96 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewState.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewState.kt
@@ -26,7 +26,8 @@ data class SpacePreviewState(
         val topic: String?  = null,
         val avatarUrl: String? = null,
         val spaceInfo: Async<ChildInfo> = Uninitialized,
-        val childInfoList: Async<List<ChildInfo>> = Uninitialized
+        val childInfoList: Async<List<ChildInfo>> = Uninitialized,
+        val inviteTermination: Async<Unit> = Uninitialized
 ) : MvRxState {
     constructor(args: SpacePreviewArgs) : this(idOrAlias = args.idOrAlias)
 }
diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewEvents.kt
index 04645e59ad..2f0eddb189 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewEvents.kt
@@ -20,7 +20,6 @@ import im.vector.app.core.platform.VectorViewEvents
 
 sealed class SpacePreviewViewEvents : VectorViewEvents {
     object Dismiss: SpacePreviewViewEvents()
-    object StartJoining: SpacePreviewViewEvents()
     object JoinSuccess: SpacePreviewViewEvents()
     data class JoinFailure(val message: String?): SpacePreviewViewEvents()
 }
diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt
index 7da6c8a053..61328d2a1c 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt
@@ -28,6 +28,7 @@ import com.airbnb.mvrx.ViewModelContext
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import im.vector.app.core.error.ErrorFormatter
 import im.vector.app.core.platform.VectorViewModel
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
@@ -41,6 +42,7 @@ import timber.log.Timber
 
 class SpacePreviewViewModel @AssistedInject constructor(
         @Assisted private val initialState: SpacePreviewState,
+        private val errorFormatter: ErrorFormatter,
         private val session: Session
 ) : VectorViewModel<SpacePreviewState, SpacePreviewViewAction, SpacePreviewViewEvents>(initialState) {
 
@@ -80,13 +82,15 @@ class SpacePreviewViewModel @AssistedInject constructor(
 
     private fun handleDismissInvite() {
         // Here we need to join the space himself as well as the default rooms in that space
-        // TODO modal loading
+        setState { copy(inviteTermination = Loading()) }
         viewModelScope.launch(Dispatchers.IO) {
             try {
                 session.spaceService().rejectInvite(initialState.idOrAlias, null)
             } catch (failure: Throwable) {
                 Timber.e(failure, "## Space: Failed to reject invite")
+                _viewEvents.post(SpacePreviewViewEvents.JoinFailure(errorFormatter.toHumanReadable(failure)))
             }
+            setState { copy(inviteTermination = Uninitialized) }
         }
     }
 
@@ -98,18 +102,25 @@ class SpacePreviewViewModel @AssistedInject constructor(
         val spaceVia = spaceInfo?.viaServers ?: emptyList()
 
         // trigger modal loading
-        _viewEvents.post(SpacePreviewViewEvents.StartJoining)
+        setState { copy(inviteTermination = Loading()) }
         viewModelScope.launch(Dispatchers.IO) {
-            val joinResult = session.spaceService().joinSpace(initialState.idOrAlias, null, spaceVia)
-            when (joinResult) {
-                JoinSpaceResult.Success,
-                is JoinSpaceResult.PartialSuccess -> {
-                    // For now we don't handle partial success, it's just success
-                    _viewEvents.post(SpacePreviewViewEvents.JoinSuccess)
-                }
-                is JoinSpaceResult.Fail           -> {
-                    _viewEvents.post(SpacePreviewViewEvents.JoinFailure(joinResult.error.toString()))
+            try {
+                val joinResult = session.spaceService().joinSpace(initialState.idOrAlias, null, spaceVia)
+                setState { copy(inviteTermination = Uninitialized) }
+                when (joinResult) {
+                    JoinSpaceResult.Success,
+                    is JoinSpaceResult.PartialSuccess -> {
+                        // For now we don't handle partial success, it's just success
+                        _viewEvents.post(SpacePreviewViewEvents.JoinSuccess)
+                    }
+                    is JoinSpaceResult.Fail -> {
+                        _viewEvents.post(SpacePreviewViewEvents.JoinFailure(errorFormatter.toHumanReadable(joinResult.error)))
+                    }
                 }
+            } catch (failure: Throwable) {
+                // should not throw
+                Timber.w(failure, "## Failed to join space")
+                _viewEvents.post(SpacePreviewViewEvents.JoinFailure(errorFormatter.toHumanReadable(failure)))
             }
         }
     }
@@ -221,7 +232,21 @@ class SpacePreviewViewModel @AssistedInject constructor(
             }
         } catch (failure: Throwable) {
             setState {
-                copy(spaceInfo = Fail(failure), childInfoList = Fail(failure))
+                copy(
+                        spaceInfo = session.getRoomSummary(initialState.idOrAlias)?.let {
+                            Success(
+                                    ChildInfo(
+                                            roomId = it.roomId,
+                                            avatarUrl = it.avatarUrl,
+                                            name = it.displayName,
+                                            topic = it.topic,
+                                            memberCount = it.joinedMembersCount,
+                                            isSubSpace = false,
+                                            viaServers = null,
+                                            children = Uninitialized
+                                    )
+                            )
+                        } ?: Fail(failure), childInfoList = Fail(failure))
             }
         }
     }
diff --git a/vector/src/main/res/layout/bottom_sheet_invited_to_space.xml b/vector/src/main/res/layout/bottom_sheet_invited_to_space.xml
new file mode 100644
index 0000000000..6730a585db
--- /dev/null
+++ b/vector/src/main/res/layout/bottom_sheet_invited_to_space.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/bottomSheetScrollView"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:animateLayoutChanges="true"
+    android:background="?riotx_bottom_sheet_background"
+    android:fadeScrollbars="false"
+    android:scrollbars="vertical">
+
+    <!-- Inviter info-->
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:padding="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <ImageView
+                android:id="@+id/inviterAvatarImage"
+                android:layout_width="40dp"
+                android:layout_height="40dp"
+                android:contentDescription="@string/avatar"
+                android:transitionName="profile"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintHorizontal_bias="0"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                tools:src="@tools:sample/avatars" />
+
+
+            <TextView
+                android:id="@+id/inviterText"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:textColor="?riotx_text_primary"
+                android:textStyle="bold"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toEndOf="@id/inviterAvatarImage"
+                app:layout_constraintTop_toTopOf="@id/inviterAvatarImage"
+                tools:text="@string/user_invites_you" />
+
+            <TextView
+                android:id="@+id/inviterMxid"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:ellipsize="end"
+                android:maxLines="1"
+                android:textColor="?riotx_text_secondary"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toEndOf="@id/inviterAvatarImage"
+                app:layout_constraintTop_toBottomOf="@id/inviterText"
+                tools:text="@sample/matrix.json/data/mxid" />
+
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="?attr/vctr_list_divider_color" />
+
+        <include
+            android:id="@+id/spaceCard"
+            layout="@layout/fragment_matrix_to_room_space_card" />
+
+    </LinearLayout>
+
+</androidx.core.widget.NestedScrollView>
\ No newline at end of file
diff --git a/vector/src/main/res/layout/fragment_matrix_to_room_space_card.xml b/vector/src/main/res/layout/fragment_matrix_to_room_space_card.xml
index c87a0d9e4b..85ec04ba50 100644
--- a/vector/src/main/res/layout/fragment_matrix_to_room_space_card.xml
+++ b/vector/src/main/res/layout/fragment_matrix_to_room_space_card.xml
@@ -1,224 +1,257 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="200dp"
-    android:padding="16dp">
+    android:layout_height="wrap_content">
 
-    <ImageView
-        android:id="@+id/matrixToCardAvatar"
-        android:layout_width="60dp"
-        android:layout_height="60dp"
-        android:layout_marginTop="@dimen/layout_vertical_margin_big"
-        android:contentDescription="@string/avatar"
-        android:elevation="4dp"
-        android:transitionName="profile"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="0"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:src="@tools:sample/avatars" />
-
-    <TextView
-        android:id="@+id/matrixToCardNameText"
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/matrixToCardContentVisibility"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/layout_vertical_margin"
-        android:maxLines="1"
-        android:singleLine="true"
-        android:textAlignment="textStart"
-        android:textColor="?riotx_text_primary"
-        android:textSize="15sp"
-        android:textStyle="bold"
-        app:layout_constraintTop_toBottomOf="@+id/matrixToCardAvatar"
-        tools:text="@sample/matrix.json/data/roomName" />
-
-    <TextView
-        android:id="@+id/matrixToCardAliasText"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="4dp"
-        android:maxLines="1"
-        android:singleLine="true"
-        android:textAlignment="textStart"
-        android:textColor="?riotx_text_secondary"
-        android:textSize="15sp"
+        android:minHeight="200dp"
+        android:padding="16dp"
         android:visibility="gone"
-        app:layout_constraintTop_toBottomOf="@id/matrixToCardNameText"
-        app:layout_goneMarginTop="0dp"
-        tools:text="@sample/matrix.json/data/roomAlias" />
-
-    <LinearLayout
-        android:id="@+id/matrixToMemberPills"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:background="@drawable/pill_receipt"
-        android:gravity="center"
-        android:orientation="horizontal"
-        android:paddingStart="12dp"
-        android:paddingTop="8dp"
-        android:paddingEnd="12dp"
-        android:paddingBottom="8dp"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="0"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText">
+        tools:visibility="visible">
 
         <ImageView
-            android:id="@+id/spaceChildMemberCountIcon"
-            android:layout_width="18dp"
-            android:layout_height="18dp"
-            android:layout_gravity="center_vertical"
-            android:layout_marginEnd="4dp"
-            android:importantForAccessibility="no"
-            android:src="@drawable/ic_room_profile_member_list"
-            app:tint="?riotx_text_primary"
-            tools:ignore="MissingPrefix" />
+            android:id="@+id/matrixToCardAvatar"
+            android:layout_width="60dp"
+            android:layout_height="60dp"
+            android:layout_marginTop="20dp"
+            android:contentDescription="@string/avatar"
+            android:elevation="4dp"
+            android:transitionName="profile"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            tools:src="@tools:sample/avatars" />
 
-        <TextView
-            android:id="@+id/spaceChildMemberCountText"
+        <ImageView
+            android:id="@+id/matrixToBetaTag"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
+            android:layout_marginTop="@dimen/layout_vertical_margin_big"
+            android:importantForAccessibility="no"
+            android:src="@drawable/ic_beta_pill"
+            android:visibility="gone"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            tools:visibility="visible" />
+
+        <TextView
+            android:id="@+id/matrixToCardNameText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/layout_vertical_margin"
             android:maxLines="1"
+            android:singleLine="true"
+            android:textAlignment="textStart"
             android:textColor="?riotx_text_primary"
-            tools:text="123 members" />
-    </LinearLayout>
+            android:textSize="15sp"
+            android:textStyle="bold"
+            app:layout_constraintTop_toBottomOf="@+id/matrixToCardAvatar"
+            tools:text="@sample/matrix.json/data/roomName" />
 
-    <TextView
-        android:id="@+id/matrixToCardDescText"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:maxLines="4"
-        android:textAlignment="textStart"
-        android:textColor="?riotx_text_secondary"
-        android:textSize="15sp"
-        app:layout_constraintTop_toBottomOf="@id/matrixToMemberPills"
-        tools:text="@sample/matrix.json/data/roomTopic" />
+        <TextView
+            android:id="@+id/matrixToCardAliasText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:maxLines="1"
+            android:singleLine="true"
+            android:textAlignment="textStart"
+            android:textColor="?riotx_text_secondary"
+            android:textSize="15sp"
+            android:visibility="gone"
+            app:layout_constraintTop_toBottomOf="@id/matrixToCardNameText"
+            app:layout_goneMarginTop="0dp"
+            tools:text="@sample/matrix.json/data/roomAlias" />
 
-    <ImageView
-        android:id="@+id/knownMember5"
-        android:layout_width="30dp"
-        android:layout_height="30dp"
-        android:contentDescription="@string/avatar"
-        app:layout_constraintCircle="@id/knownMember4"
-        app:layout_constraintCircleAngle="90"
-        app:layout_constraintCircleRadius="20dp"
-        tools:ignore="MissingConstraints"
-        tools:src="@tools:sample/avatars" />
+        <LinearLayout
+            android:id="@+id/matrixToMemberPills"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:background="@drawable/pill_receipt"
+            android:gravity="center"
+            android:orientation="horizontal"
+            android:paddingStart="12dp"
+            android:paddingTop="8dp"
+            android:paddingEnd="12dp"
+            android:paddingBottom="8dp"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/matrixToCardAliasText">
 
-    <ImageView
-        android:id="@+id/knownMember4"
-        android:layout_width="30dp"
-        android:layout_height="30dp"
-        android:contentDescription="@string/avatar"
-        app:layout_constraintCircle="@id/knownMember3"
-        app:layout_constraintCircleAngle="90"
-        app:layout_constraintCircleRadius="20dp"
-        tools:ignore="MissingConstraints"
-        tools:src="@tools:sample/avatars" />
+            <ImageView
+                android:id="@+id/spaceChildMemberCountIcon"
+                android:layout_width="18dp"
+                android:layout_height="18dp"
+                android:layout_gravity="center_vertical"
+                android:layout_marginEnd="4dp"
+                android:importantForAccessibility="no"
+                android:src="@drawable/ic_room_profile_member_list"
+                app:tint="?riotx_text_primary"
+                tools:ignore="MissingPrefix" />
 
-    <ImageView
-        android:id="@+id/knownMember3"
-        android:layout_width="30dp"
-        android:layout_height="30dp"
-        android:contentDescription="@string/avatar"
-        app:layout_constraintCircle="@id/knownMember2"
-        app:layout_constraintCircleAngle="90"
-        app:layout_constraintCircleRadius="20dp"
-        tools:ignore="MissingConstraints"
-        tools:src="@tools:sample/avatars" />
+            <TextView
+                android:id="@+id/spaceChildMemberCountText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:maxLines="1"
+                android:textColor="?riotx_text_primary"
+                tools:text="123 members" />
+        </LinearLayout>
 
-    <ImageView
-        android:id="@+id/knownMember2"
-        android:layout_width="30dp"
-        android:layout_height="30dp"
-        android:contentDescription="@string/avatar"
-        app:layout_constraintCircle="@id/knownMember1"
-        app:layout_constraintCircleAngle="90"
-        app:layout_constraintCircleRadius="20dp"
-        tools:ignore="MissingConstraints"
-        tools:src="@tools:sample/avatars" />
+        <TextView
+            android:id="@+id/matrixToCardDescText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:maxLines="4"
+            android:textAlignment="textStart"
+            android:textColor="?riotx_text_secondary"
+            android:textSize="15sp"
+            app:layout_constraintTop_toBottomOf="@id/matrixToMemberPills"
+            tools:text="@sample/matrix.json/data/roomTopic" />
 
-    <ImageView
-        android:id="@+id/knownMember1"
-        android:layout_width="30dp"
-        android:layout_height="30dp"
-        android:layout_marginTop="8dp"
-        android:contentDescription="@string/avatar"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/matrixToCardDescText"
-        tools:src="@tools:sample/avatars" />
+        <ImageView
+            android:id="@+id/knownMember5"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:contentDescription="@string/avatar"
+            app:layout_constraintCircle="@id/knownMember4"
+            app:layout_constraintCircleAngle="90"
+            app:layout_constraintCircleRadius="20dp"
+            tools:ignore="MissingConstraints"
+            tools:src="@tools:sample/avatars"
+            tools:visibility="gone" />
 
-    <TextView
-        android:id="@+id/peopleYouMayKnowText"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="20dp"
-        android:textColor="?riotx_text_secondary"
-        android:textSize="15sp"
-        app:layout_constraintBottom_toBottomOf="@id/knownMember1"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toEndOf="@id/knownMember5"
-        app:layout_constraintTop_toTopOf="@id/knownMember1"
-        tools:text="7 people you may know" />
+        <ImageView
+            android:id="@+id/knownMember4"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:contentDescription="@string/avatar"
+            app:layout_constraintCircle="@id/knownMember3"
+            app:layout_constraintCircleAngle="90"
+            app:layout_constraintCircleRadius="20dp"
+            tools:ignore="MissingConstraints"
+            tools:src="@tools:sample/avatars"
+            tools:visibility="gone" />
 
-    <com.google.android.material.button.MaterialButton
-        android:id="@+id/matrixToCardMainButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:layout_marginBottom="@dimen/layout_vertical_margin_big"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/knownMember1"
-        app:layout_constraintWidth_max="400dp"
-        tools:text="@string/join" />
+        <ImageView
+            android:id="@+id/knownMember3"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:contentDescription="@string/avatar"
+            app:layout_constraintCircle="@id/knownMember2"
+            app:layout_constraintCircleAngle="90"
+            app:layout_constraintCircleRadius="20dp"
+            tools:ignore="MissingConstraints"
+            tools:src="@tools:sample/avatars" />
 
-    <com.google.android.material.button.MaterialButton
-        android:id="@+id/matrixToCardSecondaryButton"
-        style="@style/VectorButtonStyleOutlined"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:layout_marginBottom="@dimen/layout_vertical_margin_big"
-        android:textAllCaps="true"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/matrixToCardMainButton"
-        app:layout_constraintWidth_max="400dp"
-        tools:text="@string/dismiss" />
+        <ImageView
+            android:id="@+id/knownMember2"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:contentDescription="@string/avatar"
+            app:layout_constraintCircle="@id/knownMember1"
+            app:layout_constraintCircleAngle="90"
+            app:layout_constraintCircleRadius="20dp"
+            tools:ignore="MissingConstraints"
+            tools:src="@tools:sample/avatars" />
+
+        <ImageView
+            android:id="@+id/knownMember1"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:layout_marginTop="8dp"
+            android:contentDescription="@string/avatar"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/matrixToCardDescText"
+            tools:src="@tools:sample/avatars" />
+
+        <TextView
+            android:id="@+id/peopleYouMayKnowText"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="20dp"
+            android:textColor="?riotx_text_secondary"
+            android:textSize="15sp"
+            app:layout_constraintBottom_toBottomOf="@id/knownMember1"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/knownMember5"
+            app:layout_constraintTop_toTopOf="@id/knownMember1"
+            tools:text="7 people you may know" />
+
+        <im.vector.app.core.platform.ButtonStateView
+            android:id="@+id/matrixToCardMainButton"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:layout_marginBottom="@dimen/layout_vertical_margin_big"
+            app:bsv_button_text="@string/accept"
+            app:bsv_loaded_image_src="@drawable/ic_tick"
+            app:bsv_use_flat_button="false"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/knownMember1"
+            app:layout_constraintWidth_max="400dp" />
+
+        <!--        <com.google.android.material.button.MaterialButton-->
+        <!--            android:id="@+id/matrixToCardMainButton"-->
+        <!--            android:layout_width="0dp"-->
+        <!--            android:layout_height="wrap_content"-->
+        <!--            android:layout_marginTop="16dp"-->
+        <!--            android:layout_marginBottom="@dimen/layout_vertical_margin_big"-->
+        <!--            app:layout_constraintEnd_toEndOf="parent"-->
+        <!--            app:layout_constraintStart_toStartOf="parent"-->
+        <!--            app:layout_constraintTop_toBottomOf="@id/knownMember1"-->
+        <!--            app:layout_constraintWidth_max="400dp"-->
+        <!--            tools:text="@string/join" />-->
+
+        <!--        <com.google.android.material.button.MaterialButton-->
+        <!--            android:id="@+id/matrixToCardSecondaryButton"-->
+        <!--            style="@style/VectorButtonStyleOutlined"-->
+        <!--            android:layout_width="0dp"-->
+        <!--            android:layout_height="wrap_content"-->
+        <!--            android:layout_marginTop="8dp"-->
+        <!--            android:layout_marginBottom="@dimen/layout_vertical_margin_big"-->
+        <!--            android:textAllCaps="true"-->
+        <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+        <!--            app:layout_constraintEnd_toEndOf="parent"-->
+        <!--            app:layout_constraintStart_toStartOf="parent"-->
+        <!--            app:layout_constraintTop_toBottomOf="@id/matrixToCardMainButton"-->
+        <!--            app:layout_constraintWidth_max="400dp"-->
+        <!--            tools:text="@string/dismiss" />-->
+
+        <im.vector.app.core.platform.ButtonStateView
+            android:id="@+id/matrixToCardSecondaryButton"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:layout_marginBottom="@dimen/layout_vertical_margin_big"
+            app:bsv_button_text="@string/dismiss"
+            app:bsv_loaded_image_src="@drawable/ic_tick"
+            app:bsv_use_flat_button="true"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/matrixToCardMainButton"
+            app:layout_constraintWidth_max="400dp" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
     <ProgressBar
         android:id="@+id/matrixToCardButtonLoading"
         style="?android:attr/progressBarStyleSmall"
         android:layout_width="20dp"
         android:layout_height="20dp"
+        android:layout_centerInParent="true"
         android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="@id/matrixToCardMainButton"
-        app:layout_constraintEnd_toEndOf="@id/matrixToCardMainButton"
-        app:layout_constraintStart_toStartOf="@id/matrixToCardMainButton"
-        app:layout_constraintTop_toTopOf="@id/matrixToCardMainButton"
         tools:visibility="visible" />
 
-    <androidx.constraintlayout.widget.Group
-        android:id="@+id/matrixToCardPeopleYouKnowVisibility"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        app:constraint_referenced_ids="knownMember1,knownMember2,knownMember3,knownMember4,knownMember5,peopleYouMayKnowText"
-        tools:visibility="visible" />
-
-    <androidx.constraintlayout.widget.Group
-        android:id="@+id/matrixToCardContentVisibility"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:visibility="gone"
-        app:constraint_referenced_ids="matrixToCardNameText,matrixToCardAvatar,matrixToCardNameText,matrixToCardDescText, matrixToCardMainButton, matrixToCardAliasText, matrixToCardSecondaryButton, matrixToMemberPills,matrixToCardPeopleYouKnowVisibility"
-        tools:visibility="visible" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
+</RelativeLayout>
diff --git a/vector/src/main/res/layout/view_button_state.xml b/vector/src/main/res/layout/view_button_state.xml
index 28a3f066e5..1e22d79b5e 100644
--- a/vector/src/main/res/layout/view_button_state.xml
+++ b/vector/src/main/res/layout/view_button_state.xml
@@ -1,14 +1,14 @@
 <?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="wrap_content"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     tools:parentTag="android.widget.FrameLayout">
 
     <com.google.android.material.button.MaterialButton
         android:id="@+id/buttonStateButtonFlat"
         style="@style/VectorButtonStyleText"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         tools:layout_gravity="center_horizontal"
@@ -16,7 +16,7 @@
 
     <com.google.android.material.button.MaterialButton
         android:id="@+id/buttonStateButtonBig"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:minWidth="120dp"
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index bfd91a6707..f8b04ef3a6 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -3352,4 +3352,5 @@
 
     <string name="labs_use_restricted_join_rule">Experimental Space - Restricted Room.</string>
     <string name="labs_use_restricted_join_rule_desc">Warning requires server support and experimental room version</string>
+    <string name="user_invites_you">%s invites you</string>
 </resources>
diff --git a/vector/src/main/res/values/styles_riot.xml b/vector/src/main/res/values/styles_riot.xml
index 89d5ac12e2..a265727522 100644
--- a/vector/src/main/res/values/styles_riot.xml
+++ b/vector/src/main/res/values/styles_riot.xml
@@ -152,7 +152,7 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:background">@null</item>
-        <!--item name="android:textColor">?colorAccent</item-->
+        <item name="android:textColor">?colorAccent</item>
         <item name="colorControlHighlight">?colorAccent</item>
     </style>
 
@@ -162,7 +162,7 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:background">@null</item>
-        <!--item name="android:textColor">?colorAccent</item-->
+        <item name="android:textColor">?colorAccent</item>
         <item name="colorControlHighlight">?colorAccent</item>
         <item name="strokeColor">@color/button_background_tint_selector</item>
         <item name="strokeWidth">1dp</item>