From 94ae632bbcfae3f16a1a122eb087467cb1baef1c Mon Sep 17 00:00:00 2001 From: Ben Martin Date: Tue, 21 Jan 2025 14:29:00 +0000 Subject: [PATCH] feat: improve UI with sentiment selection, input field, and feedback submission This commit enhances the UI of the application with the following changes: - Adds sentiment selection via `FilterChip` components with leading icons and friendly names for each `Sentiment` option. - Introduces a `TextField` for user comments. - Implements feedback submission, which resets the selected sentiment and clears the comment field upon clicking the button. - Shows a snackbar to display feedback success after the button is clicked. - Improves `FilterChip` styling with `ChipDefaults` properties and uses larger font size. - Uses `Scaffold` to provide a structure for the app. --- .../kotlin/uk/sky/bob/application/App.kt | 83 +++++++++++-------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/uk/sky/bob/application/App.kt b/composeApp/src/commonMain/kotlin/uk/sky/bob/application/App.kt index 3a7cd69..407cdd3 100644 --- a/composeApp/src/commonMain/kotlin/uk/sky/bob/application/App.kt +++ b/composeApp/src/commonMain/kotlin/uk/sky/bob/application/App.kt @@ -8,24 +8,30 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.Button +import androidx.compose.material.ChipDefaults import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.FilterChip import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Send +import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.launch import org.jetbrains.compose.ui.tooling.preview.Preview @OptIn(ExperimentalMaterialApi::class) @@ -33,45 +39,56 @@ import org.jetbrains.compose.ui.tooling.preview.Preview @Preview fun App() { MaterialTheme { - Box( - modifier = Modifier.fillMaxHeight(), - contentAlignment = Alignment.Center, - ) { - Column( - Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Row(modifier = Modifier.padding(8.dp)) { - val state = remember { mutableStateOf(Sentiment.HAPPY) } - for (emotion in Sentiment.entries) { - FilterChip( - onClick = { state.value = emotion }, - selected = state.value == emotion, - modifier = Modifier.padding(8.dp), - leadingIcon = { Text(emotion.leadingIcon) }, - ) { - Text(emotion.friendlyName) - } - } - } + val scaffoldState = rememberScaffoldState() + val scope = rememberCoroutineScope() - Row(modifier = Modifier.padding(8.dp)) { - var text by rememberSaveable(stateSaver = TextFieldValue.Saver) { + Scaffold(scaffoldState = scaffoldState) { + Box( + modifier = Modifier.fillMaxHeight(), + contentAlignment = Alignment.Center, + ) { + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val sentiment = remember { mutableStateOf(Sentiment.HAPPY) } + var comment by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue("") ) } - TextField( - value = text, - onValueChange = { text = it }, - label = { Text("Your comment") }, - modifier = Modifier.height(100.dp).fillMaxWidth().padding(8.dp), - ) - } + Row(modifier = Modifier.padding(8.dp)) { + for (emotion in Sentiment.entries) { + FilterChip( + onClick = { sentiment.value = emotion }, + selected = sentiment.value == emotion, + modifier = Modifier.padding(8.dp), + leadingIcon = { Text(emotion.leadingIcon, fontSize = 20.sp) }, + colors = ChipDefaults.outlinedFilterChipColors(), + border = ChipDefaults.outlinedBorder, + ) { + Text(emotion.friendlyName, fontSize = 20.sp) + } + } + } - Row(modifier = Modifier.padding(8.dp)) { - Button(onClick = { /* Handle submit */ }, modifier = Modifier.padding(8.dp)) { - Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "Send") + Row(modifier = Modifier.padding(8.dp)) { + TextField( + value = comment, + onValueChange = { comment = it }, + label = { Text("Your comment") }, + modifier = Modifier.height(100.dp).fillMaxWidth().padding(8.dp), + ) + } + + Row(modifier = Modifier.padding(8.dp)) { + Button(onClick = { + sentiment.value = Sentiment.HAPPY + comment = TextFieldValue("") + scope.launch { scaffoldState.snackbarHostState.showSnackbar("Feedback sent") } + }, modifier = Modifier.padding(8.dp)) { + Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "Send") + } } } }