diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlur.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlur.kt
deleted file mode 100644
index 34fd199..0000000
--- a/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlur.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Infomaniak Authenticator - Android
- * Copyright (C) 2026 Infomaniak Network SA
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.infomaniak.auth.ui.images.illus.blueBlur
-
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import com.infomaniak.auth.ui.images.AppImages
-import com.infomaniak.auth.ui.images.AppImages.AppIllus
-import com.infomaniak.auth.ui.theme.AuthenticatorTheme
-import com.infomaniak.core.ui.compose.preview.PreviewLightAndDark
-import com.infomaniak.core.ui.compose.theme.ThemedImage
-
-@Suppress("UnusedReceiverParameter")
-val AppIllus.BlueBlur: ThemedImage
- get() = _blueBlur ?: object : ThemedImage {
- override val light = AppIllus.BlueBlurLight
- override val dark = AppIllus.BlueBlurDark
- }.also { _blueBlur = it }
-
-private var _blueBlur: ThemedImage? = null
-
-@PreviewLightAndDark
-@Composable
-private fun Preview() {
- AuthenticatorTheme {
- Box {
- Image(
- imageVector = AppIllus.BlueBlur.image(),
- contentDescription = null,
- modifier = Modifier.size(AppImages.previewSize),
- )
- }
- }
-}
diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlurDark.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlurDark.kt
deleted file mode 100644
index 1f03e8a..0000000
--- a/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlurDark.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Infomaniak Authenticator - Android
- * Copyright (C) 2026 Infomaniak Network SA
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.infomaniak.auth.ui.images.illus.blueBlur
-
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
-import androidx.compose.ui.graphics.SolidColor
-import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
-import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
-import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.graphics.vector.ImageVector.Builder
-import androidx.compose.ui.graphics.vector.group
-import androidx.compose.ui.graphics.vector.path
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import com.infomaniak.auth.ui.images.AppImages
-import com.infomaniak.auth.ui.images.AppImages.AppIllus
-
-@Suppress("UnusedReceiverParameter")
-val AppIllus.BlueBlurDark: ImageVector
- get() {
- if (_blueBlurDark != null) {
- return _blueBlurDark!!
- }
- _blueBlurDark = Builder(
- name = "BlueBlurDark",
- defaultWidth = 460.0.dp,
- defaultHeight = 460.0.dp,
- viewportWidth = 460.0f,
- viewportHeight = 460.0f,
- ).apply {
- group {
- path(
- fill = SolidColor(Color(0xFF5869D9)),
- stroke = null,
- fillAlpha = 0.256f,
- strokeAlpha = 0.32f,
- strokeLineWidth = 0.0f,
- strokeLineCap = Butt,
- strokeLineJoin = Miter,
- strokeLineMiter = 4.0f,
- pathFillType = NonZero,
- ) {
- moveTo(364.18f, 230.0f)
- curveTo(364.18f, 304.11f, 304.11f, 364.18f, 230.0f, 364.18f)
- curveTo(155.89f, 364.18f, 95.82f, 304.11f, 95.82f, 230.0f)
- curveTo(95.82f, 155.89f, 155.89f, 95.82f, 230.0f, 95.82f)
- curveTo(304.11f, 95.82f, 364.18f, 155.89f, 364.18f, 230.0f)
- close()
- }
- }
- }.build()
- return _blueBlurDark!!
- }
-
-private var _blueBlurDark: ImageVector? = null
-
-@Preview
-@Composable
-private fun Preview() {
- Box {
- Image(
- imageVector = AppIllus.BlueBlurDark,
- contentDescription = null,
- modifier = Modifier.size(AppImages.previewSize),
- )
- }
-}
diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlurLight.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlurLight.kt
deleted file mode 100644
index 7dfc140..0000000
--- a/app/src/main/kotlin/com/infomaniak/auth/ui/images/illus/blueBlur/BlueBlurLight.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Infomaniak Authenticator - Android
- * Copyright (C) 2026 Infomaniak Network SA
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.infomaniak.auth.ui.images.illus.blueBlur
-
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
-import androidx.compose.ui.graphics.SolidColor
-import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
-import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
-import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.graphics.vector.ImageVector.Builder
-import androidx.compose.ui.graphics.vector.group
-import androidx.compose.ui.graphics.vector.path
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import com.infomaniak.auth.ui.images.AppImages
-import com.infomaniak.auth.ui.images.AppImages.AppIllus
-
-@Suppress("UnusedReceiverParameter")
-val AppIllus.BlueBlurLight: ImageVector
- get() {
- if (_blurLight != null) {
- return _blurLight!!
- }
- _blurLight = Builder(
- name = "BlurLight",
- defaultWidth = 460.0.dp,
- defaultHeight = 460.0.dp,
- viewportWidth = 460.0f,
- viewportHeight = 460.0f,
- ).apply {
- group {
- path(
- fill = SolidColor(Color(0xFF2F40AB)),
- stroke = null,
- fillAlpha = 0.096f,
- strokeAlpha = 0.32f,
- strokeLineWidth = 0.0f,
- strokeLineCap = Butt,
- strokeLineJoin = Miter,
- strokeLineMiter = 4.0f,
- pathFillType = NonZero,
- ) {
- moveTo(364.18f, 230.0f)
- curveTo(364.18f, 304.11f, 304.11f, 364.18f, 230.0f, 364.18f)
- curveTo(155.89f, 364.18f, 95.82f, 304.11f, 95.82f, 230.0f)
- curveTo(95.82f, 155.89f, 155.89f, 95.82f, 230.0f, 95.82f)
- curveTo(304.11f, 95.82f, 364.18f, 155.89f, 364.18f, 230.0f)
- close()
- }
- }
- }.build()
- return _blurLight!!
- }
-
-private var _blurLight: ImageVector? = null
-
-@Preview
-@Composable
-private fun Preview() {
- Box {
- Image(
- imageVector = AppIllus.BlueBlurLight,
- contentDescription = null,
- modifier = Modifier.size(AppImages.previewSize),
- )
- }
-}
diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/screen/onboarding/OnboardingPage.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/screen/onboarding/OnboardingPage.kt
index 9f9a34b..3cac74f 100644
--- a/app/src/main/kotlin/com/infomaniak/auth/ui/screen/onboarding/OnboardingPage.kt
+++ b/app/src/main/kotlin/com/infomaniak/auth/ui/screen/onboarding/OnboardingPage.kt
@@ -20,33 +20,40 @@ package com.infomaniak.auth.ui.screen.onboarding
import androidx.annotation.RawRes
import androidx.annotation.StringRes
import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.PagerState
+import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.infomaniak.auth.R
import com.infomaniak.auth.ui.images.AppImages.AppIllus
-import com.infomaniak.auth.ui.images.illus.blueBlur.BlueBlur
import com.infomaniak.auth.ui.images.illus.shieldPerson.ShieldPerson
+import com.infomaniak.auth.ui.theme.AuthenticatorTheme
import com.infomaniak.core.onboarding.OnboardingPage
+import com.infomaniak.core.onboarding.OnboardingScaffold
import com.infomaniak.core.onboarding.components.OnboardingComponents.DefaultTitleAndDescription
import com.infomaniak.core.onboarding.components.OnboardingComponents.ThemedDotLottie
import com.infomaniak.core.onboarding.models.OnboardingLottieSource
+import com.infomaniak.core.ui.compose.preview.PreviewSmallWindow
import com.infomaniak.core.ui.compose.theme.LocalIsThemeDarkMode
import com.infomaniak.core.ui.compose.theme.ThemedImage
internal enum class Page(
- val background: IllustrationResource,
val illustration: IllustrationResource,
@StringRes val titleRes: Int,
@StringRes val descriptionRes: Int,
) {
Login(
- background = IllustrationResource.Vector(AppIllus.BlueBlur),
illustration = IllustrationResource.Vector(AppIllus.ShieldPerson),
titleRes = R.string.onBoardingLoginTitle,
descriptionRes = R.string.onBoardingLoginDescription
@@ -71,7 +78,6 @@ internal fun Page.toOnboardingPage(pagerState: PagerState, index: Int) = Onboard
private fun Page.OnboardingPageIllustration(pagerState: PagerState, index: Int) {
Box {
val isCurrentPageVisible = { pagerState.currentPage == index }
- RenderIllustration(background, isCurrentPageVisible)
RenderIllustration(illustration, isCurrentPageVisible)
}
}
@@ -81,7 +87,13 @@ private fun RenderIllustration(resource: IllustrationResource, isCurrentPageVisi
when (resource) {
is IllustrationResource.Vector -> {
Image(
- modifier = Modifier.size(350.dp),
+ modifier = Modifier
+ .size(350.dp)
+ .background(
+ Brush.radialGradient(
+ colors = listOf(AuthenticatorTheme.colors.illustrationBackgroundGradient, Color.Transparent),
+ )
+ ),
imageVector = resource.themedImage.image(),
contentDescription = null,
)
@@ -104,3 +116,27 @@ internal sealed class IllustrationResource {
val themeIdDark: String? = null,
) : IllustrationResource()
}
+
+@PreviewSmallWindow
+@Composable
+private fun OnboardingPagePreview() {
+ val pagerState = rememberPagerState(pageCount = { 1 })
+ val page = Page.Login.toOnboardingPage(pagerState = pagerState, index = 0)
+
+ AuthenticatorTheme {
+ OnboardingScaffold(
+ pagerState = pagerState,
+ onboardingPages = listOf(page),
+ bottomContent = {
+ Box(
+ modifier = Modifier
+ .height(100.dp)
+ .fillMaxWidth()
+ .background(Color.LightGray)
+ ) {
+ Text("Bottom content")
+ }
+ },
+ )
+ }
+}
diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Color.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Color.kt
index 4fc6d18..f2c2587 100644
--- a/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Color.kt
+++ b/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Color.kt
@@ -2,7 +2,7 @@ package com.infomaniak.auth.ui.theme
import androidx.compose.ui.graphics.Color
-val primaryLight = Color(0xFF525A92)
+val primaryLight = Color(0xFF2B39A8)
val onPrimaryLight = Color(0xFFFFFFFF)
val primaryContainerLight = Color(0xFFDFE0FF)
val onPrimaryContainerLight = Color(0xFF3A4279)
@@ -38,7 +38,7 @@ val surfaceContainerLight = Color(0xFFEFEDF4)
val surfaceContainerHighLight = Color(0xFFE9E7EF)
val surfaceContainerHighestLight = Color(0xFFE4E1E9)
-val primaryDark = Color(0xFFBBC3FF)
+val primaryDark = Color(0xFFBCC2FF)
val onPrimaryDark = Color(0xFF232C61)
val primaryContainerDark = Color(0xFF3A4279)
val onPrimaryContainerDark = Color(0xFFDFE0FF)
@@ -73,3 +73,6 @@ val surfaceContainerLowDark = Color(0xFF1B1B21)
val surfaceContainerDark = Color(0xFF1F1F25)
val surfaceContainerHighDark = Color(0xFF29292F)
val surfaceContainerHighestDark = Color(0xFF34343A)
+
+// Custom primitives
+val productSecurity = Color(0xFF5869D9)
diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/theme/CustomColor.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/theme/CustomColor.kt
new file mode 100644
index 0000000..35908b2
--- /dev/null
+++ b/app/src/main/kotlin/com/infomaniak/auth/ui/theme/CustomColor.kt
@@ -0,0 +1,37 @@
+/*
+ * Infomaniak Authenticator - Android
+ * Copyright (C) 2026 Infomaniak Network SA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.infomaniak.auth.ui.theme
+
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.graphics.Color
+
+@Immutable
+data class CustomColorScheme(
+ val illustrationBackgroundGradient: Color = Color.Unspecified
+)
+
+private val illustrationBackgroundGradientLight = lightScheme.primary.copy(alpha = 0.28f)
+private val illustrationBackgroundGradientDark = productSecurity.copy(alpha = 0.6f)
+
+val lightCustomScheme = CustomColorScheme(
+ illustrationBackgroundGradient = illustrationBackgroundGradientLight
+)
+
+val darkCustomScheme = CustomColorScheme(
+ illustrationBackgroundGradient = illustrationBackgroundGradientDark
+)
diff --git a/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Theme.kt b/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Theme.kt
index b02ddd3..23ea6af 100644
--- a/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Theme.kt
+++ b/app/src/main/kotlin/com/infomaniak/auth/ui/theme/Theme.kt
@@ -3,6 +3,7 @@ package com.infomaniak.auth.ui.theme
import android.app.Activity
import android.os.Build.VERSION.SDK_INT
import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.ColorScheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
@@ -10,13 +11,16 @@ import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import com.infomaniak.core.ui.compose.theme.LocalIsThemeDarkMode
-private val lightScheme = lightColorScheme(
+// Never access it directly outside of the theme setup
+val lightScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
@@ -92,6 +96,8 @@ private val darkScheme = darkColorScheme(
surfaceContainerHighest = surfaceContainerHighestDark,
)
+val LocalCustomColorScheme: ProvidableCompositionLocal = staticCompositionLocalOf { CustomColorScheme() }
+
@Composable
fun AuthenticatorTheme(
isDarkTheme: Boolean = isSystemInDarkTheme(),
@@ -119,7 +125,10 @@ fun AuthenticatorTheme(
}
}
+ val customColors = if (isDarkTheme) darkCustomScheme else lightCustomScheme
+
CompositionLocalProvider(
+ LocalCustomColorScheme provides customColors,
LocalIsThemeDarkMode provides isDarkTheme
) {
MaterialTheme(
@@ -129,3 +138,11 @@ fun AuthenticatorTheme(
}
}
+object AuthenticatorTheme {
+ val colors: CustomColorScheme
+ @Composable
+ get() = LocalCustomColorScheme.current
+ val materialColors: ColorScheme
+ @Composable
+ get() = MaterialTheme.colorScheme
+}