commit bbb2e65899298803516ab4d46c4fb0d14e7e22f0
parent cf3a9532c038f8dc6dcdaafff9279fdf40eacb0e
Author: t-p-white <towhite@mozilla.com>
Date: Mon, 24 Nov 2025 17:19:34 +0000
Bug 2001968 - Part 4: Ensure consistency in the cards layout. r=android-reviewers,mavduevskiy
Differential Revision: https://phabricator.services.mozilla.com/D273838
Diffstat:
5 files changed, 103 insertions(+), 104 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/notification/NotificationMainImage.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/notification/NotificationMainImage.kt
@@ -7,17 +7,13 @@ package org.mozilla.fenix.onboarding.notification
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.PreviewLightDark
-import androidx.compose.ui.unit.dp
import org.mozilla.fenix.R
import org.mozilla.fenix.theme.FirefoxTheme
-private val IMAGE_HEIGHT = 200.dp
-
/**
* Renders the main image for the "Notification" onboarding screen.
*
@@ -28,7 +24,6 @@ fun NotificationMainImage() {
Image(
painter = painterResource(R.drawable.ic_notification_permission),
contentDescription = null, // Decorative only
- modifier = Modifier.height(IMAGE_HEIGHT),
)
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/MarketingDataOnboardingPageRedesign.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/MarketingDataOnboardingPageRedesign.kt
@@ -5,11 +5,11 @@
package org.mozilla.fenix.onboarding.redesign.view
import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
@@ -70,44 +70,44 @@ fun MarketingDataOnboardingPageRedesign(
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp),
) {
Column(
- modifier = Modifier
- .padding(horizontal = 36.dp, vertical = 24.dp)
- .fillMaxHeight()
- .verticalScroll(rememberScrollState()),
+ modifier = Modifier.padding(horizontal = 16.dp, vertical = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.weight(TITLE_TOP_SPACER_WEIGHT))
- Text(
- text = state.title,
- textAlign = TextAlign.Start,
- style = FirefoxTheme.typography.headline5,
- )
-
- Spacer(modifier = Modifier.height(40.dp))
-
- Image(
- painter = painterResource(id = state.imageRes),
- contentDescription = null,
- )
-
- Spacer(modifier = Modifier.height(32.dp))
-
var checkboxChecked by remember { mutableStateOf(true) }
- state.marketingData?.let {
- MarketingDataView(
- marketingData = it,
- checkboxChecked = checkboxChecked,
- onMarketingDataLearnMoreClick = onMarketingDataLearnMoreClick,
- onMarketingOptInToggle = { isChecked ->
- checkboxChecked = isChecked
- onMarketingOptInToggle(isChecked)
- },
+ Column(
+ modifier = Modifier
+ .padding(horizontal = 20.dp)
+ .weight(CONTENT_WEIGHT)
+ .verticalScroll(rememberScrollState()),
+ verticalArrangement = Arrangement.spacedBy(36.dp),
+ ) {
+ Text(
+ text = state.title,
+ textAlign = TextAlign.Start,
+ style = MaterialTheme.typography.headlineSmall,
)
- }
- Spacer(modifier = Modifier.weight(BODY_BUTTON_SPACER_WEIGHT))
+ Image(
+ modifier = Modifier.height(CONTENT_IMAGE_HEIGHT),
+ painter = painterResource(id = state.imageRes),
+ contentDescription = null,
+ )
+
+ state.marketingData?.let {
+ MarketingDataView(
+ marketingData = it,
+ checkboxChecked = checkboxChecked,
+ onMarketingDataLearnMoreClick = onMarketingDataLearnMoreClick,
+ onMarketingOptInToggle = { isChecked ->
+ checkboxChecked = isChecked
+ onMarketingOptInToggle(isChecked)
+ },
+ )
+ }
+ }
FilledButton(
text = state.primaryButton.text,
@@ -176,7 +176,7 @@ private fun MarketingDataView(
linkTextDecoration = TextDecoration.Underline,
)
}
- }
+ }
}
@FlexibleWindowLightDarkPreview
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/OnboardingPageRedesign.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/OnboardingPageRedesign.kt
@@ -5,9 +5,12 @@
package org.mozilla.fenix.onboarding.redesign.view
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
@@ -36,8 +39,10 @@ import org.mozilla.fenix.onboarding.view.OnboardingPageState
import org.mozilla.fenix.onboarding.widget.SetSearchWidgetMainImage
import org.mozilla.fenix.theme.FirefoxTheme
-const val TITLE_TOP_SPACER_WEIGHT = 0.3f
-const val BODY_BUTTON_SPACER_WEIGHT = 1f
+const val TITLE_TOP_SPACER_WEIGHT = 0.1f
+const val CONTENT_WEIGHT = 1f
+
+val CONTENT_IMAGE_HEIGHT = 176.dp
/**
* A composable for displaying onboarding page content.
@@ -50,19 +55,10 @@ fun OnboardingPageRedesign(
pageState: OnboardingPageState,
mainImage: @Composable () -> Unit = {},
) {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .verticalScroll(rememberScrollState()),
- verticalArrangement = Arrangement.spacedBy(12.dp),
- horizontalAlignment = Alignment.CenterHorizontally,
- ) {
- CardView(
- modifier = Modifier.weight(1f),
- pageState = pageState,
- mainImage = mainImage,
- )
- }
+ CardView(
+ pageState = pageState,
+ mainImage = mainImage,
+ )
LaunchedEffect(pageState) {
pageState.onRecordImpressionEvent()
@@ -87,12 +83,10 @@ private fun SecondaryButton(
@Composable
private fun CardView(
- modifier: Modifier = Modifier,
pageState: OnboardingPageState,
mainImage: @Composable () -> Unit,
) {
Card(
- modifier = modifier,
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface),
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp),
) {
@@ -104,8 +98,6 @@ private fun CardView(
Content(pageState) { mainImage() }
- Spacer(modifier = Modifier.weight(BODY_BUTTON_SPACER_WEIGHT))
-
FilledButton(
modifier = Modifier
.width(width = FirefoxTheme.layout.size.maxWidth.small)
@@ -124,26 +116,35 @@ private fun CardView(
}
@Composable
-private fun Content(
+private fun ColumnScope.Content(
pageState: OnboardingPageState,
mainImage: @Composable () -> Unit,
) {
Column(
- modifier = Modifier.padding(horizontal = 20.dp),
- verticalArrangement = Arrangement.spacedBy(32.dp),
- horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier
+ .padding(horizontal = 20.dp)
+ .weight(CONTENT_WEIGHT)
+ .verticalScroll(rememberScrollState()),
+ verticalArrangement = Arrangement.spacedBy(36.dp),
) {
Text(
text = pageState.title,
style = MaterialTheme.typography.headlineSmall,
)
- mainImage()
+ Box(
+ modifier = Modifier
+ .height(CONTENT_IMAGE_HEIGHT)
+ .fillMaxWidth(),
+ contentAlignment = Alignment.Center,
+ ) {
+ mainImage()
+ }
Text(
text = pageState.description,
color = MaterialTheme.colorScheme.onSurfaceVariant,
- style = FirefoxTheme.typography.body1,
+ style = FirefoxTheme.typography.subtitle1,
)
}
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/ToolbarOnboardingPageRedesign.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/ToolbarOnboardingPageRedesign.kt
@@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
-import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -73,35 +72,45 @@ fun ToolbarOnboardingPageRedesign(
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp),
) {
Column(
- modifier = Modifier
- .padding(horizontal = 32.dp, vertical = 24.dp)
- .fillMaxHeight()
- .verticalScroll(rememberScrollState()),
+ modifier = Modifier.padding(horizontal = 16.dp, vertical = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.weight(TITLE_TOP_SPACER_WEIGHT))
- Text(
- text = pageState.title,
- textAlign = TextAlign.Start,
- style = MaterialTheme.typography.headlineSmall,
- )
-
- Spacer(Modifier.height(36.dp))
-
- ToolbarPositionOptions(
- onboardingStore = onboardingStore,
- pageState = pageState,
- onToolbarSelectionClicked = onToolbarSelectionClicked,
- )
+ Column(
+ modifier = Modifier
+ .padding(horizontal = 20.dp)
+ .weight(CONTENT_WEIGHT)
+ .verticalScroll(rememberScrollState()),
+ verticalArrangement = Arrangement.spacedBy(36.dp),
+ ) {
+ Text(
+ text = pageState.title,
+ textAlign = TextAlign.Start,
+ style = MaterialTheme.typography.headlineSmall,
+ )
- Spacer(modifier = Modifier.weight(BODY_BUTTON_SPACER_WEIGHT))
+ Box(
+ modifier = Modifier
+ .height(CONTENT_IMAGE_HEIGHT)
+ .fillMaxWidth(),
+ contentAlignment = Alignment.Center,
+ ) {
+ ToolbarPositionOptions(
+ onboardingStore = onboardingStore,
+ pageState = pageState,
+ onToolbarSelectionClicked = onToolbarSelectionClicked,
+ )
+ }
+ }
FilledButton(
text = pageState.primaryButton.text,
modifier = Modifier
.width(width = FirefoxTheme.layout.size.maxWidth.small)
- .semantics { testTag = pageState.title + "onboarding_card_redesign.positive_button" },
+ .semantics {
+ testTag = pageState.title + "onboarding_card_redesign.positive_button"
+ },
onClick = pageState.primaryButton.onClick,
)
}
@@ -118,19 +127,20 @@ private fun ToolbarPositionOptions(
pageState: OnboardingPageState,
onToolbarSelectionClicked: (ToolbarOptionType) -> Unit,
) {
- val state by onboardingStore.observeAsState(initialValue = onboardingStore.state) { it }
- pageState.toolbarOptions?.let { options ->
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.spacedBy(26.dp),
- ) {
- options.forEach {
- ToolbarPositionOption(
- modifier = Modifier.weight(1f),
- option = it,
- isSelected = it.toolbarType == state.toolbarOptionSelected,
- onClick = { onToolbarSelectionClicked(it.toolbarType) },
- )
+ Box(
+ modifier = Modifier.height(CONTENT_IMAGE_HEIGHT),
+ contentAlignment = Alignment.Center,
+ ) {
+ val state by onboardingStore.observeAsState(initialValue = onboardingStore.state) { it }
+ pageState.toolbarOptions?.let { options ->
+ Row(horizontalArrangement = Arrangement.spacedBy(26.dp)) {
+ options.forEach {
+ ToolbarPositionOption(
+ option = it,
+ isSelected = it.toolbarType == state.toolbarOptionSelected,
+ onClick = { onToolbarSelectionClicked(it.toolbarType) },
+ )
+ }
}
}
}
@@ -138,12 +148,11 @@ private fun ToolbarPositionOptions(
@Composable
private fun ToolbarPositionOption(
- modifier: Modifier,
option: ToolbarOption,
isSelected: Boolean,
onClick: () -> Unit,
) {
- Column(modifier = modifier) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
ToolbarPositionImage(
option = option,
isSelected = isSelected,
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/sync/SyncMainImage.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/onboarding/redesign/view/sync/SyncMainImage.kt
@@ -5,18 +5,13 @@
package org.mozilla.fenix.onboarding.redesign.view.sync
import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.height
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.PreviewLightDark
-import androidx.compose.ui.unit.dp
import org.mozilla.fenix.R
import org.mozilla.fenix.theme.FirefoxTheme
-private val IMAGE_HEIGHT = 150.dp
-
/**
* Renders the main image for the "Sync" onboarding screen.
*
@@ -27,7 +22,6 @@ fun SyncMainImage() {
Image(
painter = painterResource(R.drawable.android_sync_illustration),
contentDescription = null, // Decorative only
- modifier = Modifier.height(IMAGE_HEIGHT),
)
}