From 32158099c699c932168b1639f97f650538793ef3 Mon Sep 17 00:00:00 2001 From: editinghero <69391940+editinghero@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:49:00 +0000 Subject: [PATCH] Update UI layouts and animations to Material 3 Expressive guidelines --- .../ui/components/AiAssistantBottomSheet.kt | 2 +- .../notes/ui/components/ColorPickerDialog.kt | 2 +- .../ui/components/ExpressiveSearchBar.kt | 2 +- .../notes/ui/components/ImageUrlDialog.kt | 2 +- .../notes/ui/components/NoteCard.kt | 26 +++++++++++++++---- .../notes/ui/components/ShareNoteDialog.kt | 2 +- .../notes/ui/components/VaultAuthDialog.kt | 2 +- .../notes/ui/screens/HomeScreen.kt | 24 ++++++++++++++--- 8 files changed, 48 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/AiAssistantBottomSheet.kt b/app/src/main/java/com/astralquarks/notes/ui/components/AiAssistantBottomSheet.kt index f50a192..aaa169e 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/AiAssistantBottomSheet.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/AiAssistantBottomSheet.kt @@ -212,7 +212,7 @@ fun AiAssistantBottomSheet( ModalBottomSheet( onDismissRequest = onDismiss, sheetState = sheetState, - shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp), + shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), containerColor = MaterialTheme.colorScheme.surfaceContainerLow, modifier = Modifier.testTag("ai_assistant_bottom_sheet") ) { diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/ColorPickerDialog.kt b/app/src/main/java/com/astralquarks/notes/ui/components/ColorPickerDialog.kt index e681d70..3717f7b 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/ColorPickerDialog.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/ColorPickerDialog.kt @@ -57,7 +57,7 @@ fun ColorPickerDialog( AlertDialog( onDismissRequest = onDismiss, - shape = RoundedCornerShape(24.dp), + shape = RoundedCornerShape(32.dp), icon = { Icon( imageVector = Icons.Default.Palette, diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/ExpressiveSearchBar.kt b/app/src/main/java/com/astralquarks/notes/ui/components/ExpressiveSearchBar.kt index 49d9ed2..a00e29a 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/ExpressiveSearchBar.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/ExpressiveSearchBar.kt @@ -66,7 +66,7 @@ fun ExpressiveSearchBar( .fillMaxWidth() .height(56.dp) .testTag("expressive_search_bar"), - shape = RoundedCornerShape(28.dp), + shape = RoundedCornerShape(32.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh, tonalElevation = 6.dp, shadowElevation = 2.dp diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/ImageUrlDialog.kt b/app/src/main/java/com/astralquarks/notes/ui/components/ImageUrlDialog.kt index 5a53a85..a1de0fb 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/ImageUrlDialog.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/ImageUrlDialog.kt @@ -93,7 +93,7 @@ fun ImageUrlDialog( AlertDialog( onDismissRequest = { if (!isUploading) onDismiss() }, - shape = RoundedCornerShape(28.dp), + shape = RoundedCornerShape(32.dp), icon = { Icon( imageVector = Icons.Default.Image, diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/NoteCard.kt b/app/src/main/java/com/astralquarks/notes/ui/components/NoteCard.kt index f1bcd49..0e6daf8 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/NoteCard.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/NoteCard.kt @@ -1,5 +1,9 @@ package com.astralquarks.notes.ui.components +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.spring +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme @@ -48,6 +52,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.luminance import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.testTag @@ -123,19 +128,30 @@ fun NoteCard( } } + val interactionSource = remember { MutableInteractionSource() } + val isPressed by interactionSource.collectIsPressedAsState() + val scale by animateFloatAsState( + targetValue = if (isPressed) 0.95f else 1f, + animationSpec = spring(dampingRatio = 0.6f, stiffness = 300f), + label = "card_scale" + ) + Card( onClick = onClick, - shape = RoundedCornerShape(24.dp), + interactionSource = interactionSource, + modifier = modifier.fillMaxWidth().testTag("note_card_${note.id}").graphicsLayer { + scaleX = scale + scaleY = scale + }, + shape = RoundedCornerShape(32.dp), colors = CardDefaults.cardColors(containerColor = cardBg), border = BorderStroke( 1.dp, if (isDark) MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.2f) else MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f) ), - elevation = CardDefaults.cardElevation(defaultElevation = 1.dp, pressedElevation = 4.dp), - modifier = modifier - .fillMaxWidth() - .testTag("note_card_${note.id}") + elevation = CardDefaults.cardElevation(defaultElevation = 1.dp, pressedElevation = 4.dp) + ) { Column(modifier = Modifier.fillMaxWidth()) { // Optional image header diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/ShareNoteDialog.kt b/app/src/main/java/com/astralquarks/notes/ui/components/ShareNoteDialog.kt index 12f2a77..9769d74 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/ShareNoteDialog.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/ShareNoteDialog.kt @@ -317,7 +317,7 @@ fun ShareNoteDialog( } } }, - shape = RoundedCornerShape(24.dp) + shape = RoundedCornerShape(32.dp) ) } diff --git a/app/src/main/java/com/astralquarks/notes/ui/components/VaultAuthDialog.kt b/app/src/main/java/com/astralquarks/notes/ui/components/VaultAuthDialog.kt index 4297258..6103c2a 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/components/VaultAuthDialog.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/components/VaultAuthDialog.kt @@ -106,7 +106,7 @@ fun VaultAuthDialog( AlertDialog( onDismissRequest = { if (!isProcessing) onDismiss() }, - shape = RoundedCornerShape(28.dp), + shape = RoundedCornerShape(32.dp), icon = { Surface( shape = RoundedCornerShape(16.dp), diff --git a/app/src/main/java/com/astralquarks/notes/ui/screens/HomeScreen.kt b/app/src/main/java/com/astralquarks/notes/ui/screens/HomeScreen.kt index af0b2a3..e9a8f04 100644 --- a/app/src/main/java/com/astralquarks/notes/ui/screens/HomeScreen.kt +++ b/app/src/main/java/com/astralquarks/notes/ui/screens/HomeScreen.kt @@ -3,6 +3,11 @@ package com.astralquarks.notes.ui.screens import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.spring +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -119,6 +124,14 @@ fun HomeScreen( var noteForColorPicker by remember { mutableStateOf(null) } var noteToShare by remember { mutableStateOf(null) } var isExportingShare by remember { mutableStateOf(false) } + + val fabInteractionSource = remember { MutableInteractionSource() } + val isFabPressed by fabInteractionSource.collectIsPressedAsState() + val fabScale by animateFloatAsState( + targetValue = if (isFabPressed) 0.95f else 1f, + animationSpec = spring(dampingRatio = 0.6f, stiffness = 300f), + label = "fab_scale" + ) var shareStatusText by remember { mutableStateOf(null) } var showImageDialogForQuickNote by remember { mutableStateOf(false) } var showCreateActionSheet by remember { mutableStateOf(false) } @@ -288,7 +301,7 @@ fun HomeScreen( ) { Surface( modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(28.dp), + shape = RoundedCornerShape(32.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh, tonalElevation = 6.dp, shadowElevation = 4.dp @@ -371,7 +384,8 @@ fun HomeScreen( // Material 3 Expressive Add FAB FloatingActionButton( onClick = { showCreateActionSheet = true }, - shape = RoundedCornerShape(24.dp), + interactionSource = fabInteractionSource, + shape = RoundedCornerShape(32.dp), containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.onPrimaryContainer, elevation = FloatingActionButtonDefaults.elevation( @@ -381,6 +395,10 @@ fun HomeScreen( modifier = Modifier .size(56.dp) .testTag("fab_create_note") + .graphicsLayer { + scaleX = fabScale + scaleY = fabScale + } ) { Icon( imageVector = Icons.Default.Add, @@ -615,7 +633,7 @@ fun HomeScreen( if (showCreateActionSheet) { ModalBottomSheet( onDismissRequest = { showCreateActionSheet = false }, - shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp), + shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), containerColor = MaterialTheme.colorScheme.surfaceContainerHigh ) { Column(