From 59471f3b69adbc355514125f73dcf46d29a42bcd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 21:43:21 +0000 Subject: [PATCH 1/2] fix(signin): prevent auth card shadow clipping Adjust the layout container structure in SignInScreen so verticalScroll is applied to the full-width outer Column. Content width constraints and padding are applied to the inner Column inside verticalScroll, preventing the FoliaryCard drop shadow from being clipped. Closes #195 --- .../foliary/feature/signin/SignInScreen.kt | 40 ++++++++++++---- .../feature/signin/SignInScreenTest.kt | 48 +++++++++++++++++++ 2 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 foliary/src/commonTest/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreenTest.kt diff --git a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreen.kt b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreen.kt index 004fba0..19ef115 100644 --- a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreen.kt +++ b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreen.kt @@ -5,12 +5,14 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -25,6 +27,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -70,17 +73,33 @@ fun SignInScreen() { modifier = Modifier.fillMaxSize(), containerColor = MaterialTheme.colorScheme.background ) { paddingValues -> - Box(modifier = Modifier.padding(paddingValues).fillMaxSize()) { + BoxWithConstraints( + modifier = Modifier.fillMaxSize().padding(paddingValues) + ) { + val viewportHeight = maxHeight + Column( - modifier = Modifier.widthInCompact(480.dp) - .align(Alignment.Center) - .padding(horizontal = 24.dp) - .verticalScroll(rememberScrollState()), + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()) + .testTag("SignInScreen:ScrollContainer"), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(24.dp) ) { - SignInHeader() - SignInForm(viewData = viewData, onEvent = viewModel::onEvent) + Column( + modifier = Modifier + .widthInCompact(SignInContentMaxWidth) + .fillMaxWidth() + .heightIn(min = viewportHeight) + .padding( + horizontal = SignInContentPadding, + vertical = SignInContentPadding, + ), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically), + ) { + SignInHeader() + SignInForm(viewData = viewData, onEvent = viewModel::onEvent) + } } } } @@ -130,7 +149,7 @@ private fun SignInForm( onEvent: (SignInEvent) -> Unit ) { FoliaryCard( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth().testTag("SignInScreen:Card") ) { AnimatedContent( targetState = viewData, @@ -228,6 +247,9 @@ private fun OrDivider() { } } +private val SignInContentMaxWidth = 480.dp +private val SignInContentPadding = 24.dp + private fun onAction(action: SignInAction, navigator: Navigator) { when (action) { SignInAction.NavigateToMain -> { diff --git a/foliary/src/commonTest/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreenTest.kt b/foliary/src/commonTest/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreenTest.kt new file mode 100644 index 0000000..f5fd566 --- /dev/null +++ b/foliary/src/commonTest/kotlin/dev/appoutlet/foliary/feature/signin/SignInScreenTest.kt @@ -0,0 +1,48 @@ +package dev.appoutlet.foliary.feature.signin + +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.getUnclippedBoundsInRoot +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.v2.runComposeUiTest +import androidx.compose.ui.unit.dp +import dev.appoutlet.foliary.FoliaryKoinApplication +import io.kotest.matchers.shouldBe +import org.koin.core.context.stopKoin +import org.koin.plugin.module.dsl.startKoin +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test + +@OptIn(ExperimentalTestApi::class) +class SignInScreenTest { + + @BeforeTest + fun setup() { + startKoin() + } + + @AfterTest + fun tearDown() { + stopKoin() + } + + @Test + fun `should render sign in screen with card inset in scroll container`() = runComposeUiTest { + setContent { + SignInScreen() + } + + onNodeWithTag("SignInScreen:ScrollContainer").assertIsDisplayed() + onNodeWithTag("SignInScreen:Card").assertIsDisplayed() + + val scrollContainerBounds = onNodeWithTag("SignInScreen:ScrollContainer").getUnclippedBoundsInRoot() + val cardBounds = onNodeWithTag("SignInScreen:Card").getUnclippedBoundsInRoot() + + val leftInset = cardBounds.left - scrollContainerBounds.left + val rightInset = scrollContainerBounds.right - cardBounds.right + + (leftInset.value >= 24.dp.value) shouldBe true + (rightInset.value >= 24.dp.value) shouldBe true + } +} From 90ea5b9c2c9e72f62b1aef953977c18dfab0113d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 21:48:37 +0000 Subject: [PATCH 2/2] fix(signin): prevent auth card shadow clipping Adjust the layout container structure in SignInScreen so verticalScroll is applied to the full-width outer Column. Content width constraints and padding are applied to the inner Column inside verticalScroll, preventing the FoliaryCard drop shadow from being clipped. Closes #195