From 63c61916764bd5855b596672399467b90b91bf59 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Sun, 28 Jun 2026 14:16:56 +0200 Subject: [PATCH] onboarding: draw the onboarding scaffold from floret-kit Use components' OnboardingScaffold / BenefitRow / OnboardingSpace and drop the in-app copies; keep Agendula's own SquircleHero (now in OnboardingHero.kt). Bumps the floret-kit submodule. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agendula/ui/permission/OnboardingHero.kt | 36 +++++ .../ui/permission/OnboardingScaffold.kt | 136 ------------------ .../ui/permission/ReminderOnboardingScreen.kt | 3 + floret-kit | 2 +- 4 files changed, 40 insertions(+), 137 deletions(-) create mode 100644 app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingHero.kt delete mode 100644 app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingScaffold.kt diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingHero.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingHero.kt new file mode 100644 index 0000000..8795a00 --- /dev/null +++ b/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingHero.kt @@ -0,0 +1,36 @@ +package de.jeanlucmakiola.agendula.ui.permission + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +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.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp + +/** + * Agendula's onboarding hero: an icon in the brand squircle. Each app keeps its + * own hero; the surrounding shell comes from floret-kit's OnboardingScaffold. + */ +@Composable +internal fun SquircleHero(icon: ImageVector) { + Box( + modifier = Modifier + .size(128.dp) + .clip(RoundedCornerShape(34.dp)) + .background(MaterialTheme.colorScheme.primaryContainer), + contentAlignment = Alignment.Center, + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.size(56.dp), + ) + } +} diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingScaffold.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingScaffold.kt deleted file mode 100644 index 5e02212..0000000 --- a/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/OnboardingScaffold.kt +++ /dev/null @@ -1,136 +0,0 @@ -package de.jeanlucmakiola.agendula.ui.permission - -import androidx.compose.foundation.background -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.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.navigationBarsPadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -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.graphics.vector.ImageVector -import androidx.compose.ui.unit.dp - -/** MD3 8dp spacing scale shared by the onboarding screens. */ -internal object OnboardingSpace { - val xs = 8.dp - val sm = 16.dp - val md = 24.dp - val lg = 32.dp - val xl = 48.dp -} - -/** - * Shared onboarding shell: a scrollable, centred hero + body with the call(s) - * to action pinned to the bottom (clear of the navigation bar). The content - * slot is centred horizontally; benefit rows fill the width so their own - * content left-aligns. Ported from Calendula so the two apps read as one family. - */ -@Composable -internal fun OnboardingScaffold( - hero: @Composable () -> Unit, - actions: @Composable ColumnScope.() -> Unit, - modifier: Modifier = Modifier, - body: @Composable ColumnScope.() -> Unit, -) { - Scaffold( - modifier = modifier, - containerColor = MaterialTheme.colorScheme.surface, - bottomBar = { - Column( - modifier = Modifier - .fillMaxWidth() - .navigationBarsPadding() - .padding(horizontal = OnboardingSpace.md, vertical = OnboardingSpace.sm), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(4.dp), - content = actions, - ) - }, - ) { innerPadding -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - .verticalScroll(rememberScrollState()) - .padding(horizontal = OnboardingSpace.md), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(Modifier.height(OnboardingSpace.xl)) - hero() - Spacer(Modifier.height(OnboardingSpace.lg)) - body() - Spacer(Modifier.height(OnboardingSpace.md)) - } - } -} - -/** An icon in the brand squircle — the shared onboarding hero silhouette. */ -@Composable -internal fun SquircleHero(icon: ImageVector) { - Box( - modifier = Modifier - .size(128.dp) - .clip(RoundedCornerShape(34.dp)) - .background(MaterialTheme.colorScheme.primaryContainer), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = MaterialTheme.colorScheme.onPrimaryContainer, - modifier = Modifier.size(56.dp), - ) - } -} - -/** One trust point: a tonal icon chip on the left, title + supporting text right. */ -@Composable -internal fun BenefitRow(icon: ImageVector, title: String, body: String) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier - .size(44.dp) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.secondaryContainer), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondaryContainer, - modifier = Modifier.size(22.dp), - ) - } - Spacer(Modifier.width(OnboardingSpace.sm)) - Column(modifier = Modifier.weight(1f)) { - Text(text = title, style = MaterialTheme.typography.titleMedium) - Text( - text = body, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - } -} diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/ReminderOnboardingScreen.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/ReminderOnboardingScreen.kt index be88022..80242d0 100644 --- a/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/ReminderOnboardingScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/agendula/ui/permission/ReminderOnboardingScreen.kt @@ -22,6 +22,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import de.jeanlucmakiola.agendula.R +import de.jeanlucmakiola.floret.components.BenefitRow +import de.jeanlucmakiola.floret.components.OnboardingScaffold +import de.jeanlucmakiola.floret.components.OnboardingSpace /** * One-time onboarding step after the tasks-provider grant: explains that Agendula diff --git a/floret-kit b/floret-kit index 4eb9809..10e0ca0 160000 --- a/floret-kit +++ b/floret-kit @@ -1 +1 @@ -Subproject commit 4eb9809993a715d58d5d13860cfa31a0f0b496fd +Subproject commit 10e0ca0b06fc73a36189c042f4dc0d6d3b669cfa