diff --git a/app/src/main/java/hu/bme/kszk/szobatarsch/composable/Matches.kt b/app/src/main/java/hu/bme/kszk/szobatarsch/composable/Matches.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cc304f6c8a9f1978d2d65bb789144bb778f7929c
--- /dev/null
+++ b/app/src/main/java/hu/bme/kszk/szobatarsch/composable/Matches.kt
@@ -0,0 +1,119 @@
+package hu.bme.kszk.szobatarsch.composable
+
+import androidx.compose.animation.Crossfade
+import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Person
+import androidx.compose.material3.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import hu.bme.kszk.szobatarsch.firebase.User
+import hu.bme.kszk.szobatarsch.firebase.matchedUsersData
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+@Composable
+fun Matches() {
+    var loaded by remember { mutableStateOf(false) }
+    val matchedList = remember { mutableStateListOf<User>() }
+
+    LaunchedEffect(Unit) {
+        launch(Dispatchers.IO) {
+            matchedUsersData.collect { newList ->
+                matchedList.removeAll { old ->
+                    newList.none { old.id == it.id }
+                }
+
+                newList.forEach { new ->
+                    val oldIdx = matchedList.indexOfFirst { it.id == new.id }
+                    if (oldIdx == -1) return@forEach
+
+                    val old = matchedList[oldIdx]
+
+                    if (new != old) {
+                        matchedList[oldIdx] = new
+                    }
+                }
+
+                newList.forEach { new ->
+                    if (matchedList.none { it.id == new.id }) {
+                        matchedList += new
+                    }
+                }
+
+                matchedList.sortBy { newList.indexOf(it) }
+                loaded = true
+            }
+        }
+
+    }
+
+    Crossfade(loaded) { load ->
+        if (load) {
+            LazyColumn(
+                modifier = Modifier
+                    .fillMaxSize(),
+                contentPadding = PaddingValues(16.dp),
+                verticalArrangement = Arrangement.spacedBy(16.dp),
+                horizontalAlignment = Alignment.CenterHorizontally,
+            ) {
+                this.items(
+                    items = matchedList,
+                    key = { user -> user.id },
+                    itemContent = { user ->
+                        UserCard(
+                            user = user
+                        )
+                    }
+                )
+            }
+        } else {
+            Column(
+                modifier = Modifier.fillMaxSize(),
+                verticalArrangement = Arrangement.Center,
+                horizontalAlignment = Alignment.CenterHorizontally,
+            ) {
+                CircularProgressIndicator()
+            }
+        }
+
+    }
+}
+
+@Composable
+fun UserCard(user: User) {
+    Row(modifier = Modifier.padding(all = 8.dp)) {
+        Icon(Icons.Default.Person, contentDescription = null)
+        Spacer(modifier = Modifier.width(8.dp))
+
+        var isExpanded by remember { mutableStateOf(false) }
+
+        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
+            Text(
+                text = user.name,
+            )
+
+            Spacer(modifier = Modifier.height(4.dp))
+
+            Surface(
+                shape = MaterialTheme.shapes.medium,
+                tonalElevation = 1.dp,
+                modifier = Modifier
+                    .animateContentSize()
+                    .padding(1.dp)
+            ) {
+                Text(
+                    text = user.description,
+                    modifier = Modifier.padding(all = 4.dp),
+                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
+                )
+            }
+        }
+    }
+}
\ No newline at end of file