[#50] Preliminary design guide
Known issues - We cannot use downloadable fonts with Compose, so the fonts must be embedded with the app Questions - How does the transparent button show a disabled state? - Are the navigation buttons and secondary buttons supposed to be effectively the same style but one is smaller? TODO - Add gradients. Gradients are not implemented for background, progress bar, etc. Currently they simply use the start color for the gradient - Icons are using Material Icons, pending decision on how to leverage the vectors in the design - Add the border for hero images - Add shapes for the callout, which is currently square - Add padding - Add drop shadows - Double-check colors for correctness
This commit is contained in:
parent
4f513932a6
commit
575b3063bf
|
@ -18,3 +18,5 @@ local.properties
|
||||||
/.idea/deploymentTargetDropDown.xml
|
/.idea/deploymentTargetDropDown.xml
|
||||||
*.hprof
|
*.hprof
|
||||||
/.idea/artifacts
|
/.idea/artifacts
|
||||||
|
/.idea/assetWizardSettings.xml
|
||||||
|
/.idea/inspectionProfiles/Project_Default.xml
|
||||||
|
|
|
@ -35,3 +35,4 @@ If you plan to fork the project to create a new app of your own, please make the
|
||||||
1. When the code coverage Gradle property `IS_COVERAGE_ENABLED` is enabled, the debug app APK cannot be run. The coverage flag should therefore only be set when running automated tests.
|
1. When the code coverage Gradle property `IS_COVERAGE_ENABLED` is enabled, the debug app APK cannot be run. The coverage flag should therefore only be set when running automated tests.
|
||||||
1. Test coverage for Compose code will be low, due to [known limitations](https://github.com/jacoco/jacoco/issues/1208) in the interaction between Compose and Jacoco.
|
1. Test coverage for Compose code will be low, due to [known limitations](https://github.com/jacoco/jacoco/issues/1208) in the interaction between Compose and Jacoco.
|
||||||
1. Adding the `espresso-contrib` dependency will cause builds to fail, due to conflicting classes. This is a [known issue](https://github.com/zcash/zcash-android-wallet-sdk/issues/306) with the Zcash Android SDK.
|
1. Adding the `espresso-contrib` dependency will cause builds to fail, due to conflicting classes. This is a [known issue](https://github.com/zcash/zcash-android-wallet-sdk/issues/306) with the Zcash Android SDK.
|
||||||
|
1. Android Studio will warn about the Gradle checksum. This is a [known issue](https://github.com/gradle/gradle/issues/9361) and can be safely ignored.
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Third Party Licenses
|
||||||
|
|
||||||
|
The majority of the contents of this Git repository are covered under the [LICENSE](../LICENSE). However certain items, as described below, are under different license.
|
||||||
|
|
||||||
|
## Electric Coin Company copyrights trademarks
|
||||||
|
|
||||||
|
|
||||||
|
## Rubik Font
|
||||||
|
The fonts under the [font](../ui-lib/src/main/res/ui/common/font) directory are downloaded from [Google Fonts](https://fonts.google.com/specimen/Rubik) and are licensed under the [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL).
|
|
@ -78,6 +78,7 @@ dependencyResolutionManagement {
|
||||||
alias("androidx-compose-foundation").to("androidx.compose.foundation:foundation:$androidxComposeVersion")
|
alias("androidx-compose-foundation").to("androidx.compose.foundation:foundation:$androidxComposeVersion")
|
||||||
alias("androidx-compose-material").to("androidx.compose.material:material:$androidxComposeVersion")
|
alias("androidx-compose-material").to("androidx.compose.material:material:$androidxComposeVersion")
|
||||||
alias("androidx-compose-material-icons-core").to("androidx.compose.material:material-icons-core:$androidxComposeVersion")
|
alias("androidx-compose-material-icons-core").to("androidx.compose.material:material-icons-core:$androidxComposeVersion")
|
||||||
|
alias("androidx-compose-material-icons-extended").to("androidx.compose.material:material-icons-extended:$androidxComposeVersion")
|
||||||
alias("androidx-compose-tooling").to("androidx.compose.ui:ui-tooling:$androidxComposeVersion")
|
alias("androidx-compose-tooling").to("androidx.compose.ui:ui-tooling:$androidxComposeVersion")
|
||||||
alias("androidx-compose-ui").to("androidx.compose.ui:ui:$androidxComposeVersion")
|
alias("androidx-compose-ui").to("androidx.compose.ui:ui:$androidxComposeVersion")
|
||||||
alias("androidx-compose-compiler").to("androidx.compose.compiler:compiler:$androidxComposeCompilerVersion")
|
alias("androidx-compose-compiler").to("androidx.compose.compiler:compiler:$androidxComposeCompilerVersion")
|
||||||
|
@ -113,6 +114,7 @@ dependencyResolutionManagement {
|
||||||
"androidx-compose-foundation",
|
"androidx-compose-foundation",
|
||||||
"androidx-compose-material",
|
"androidx-compose-material",
|
||||||
"androidx-compose-material-icons-core",
|
"androidx-compose-material-icons-core",
|
||||||
|
"androidx-compose-material-icons-extended",
|
||||||
"androidx-compose-tooling",
|
"androidx-compose-tooling",
|
||||||
"androidx-compose-ui",
|
"androidx-compose-ui",
|
||||||
"androidx-viewmodel-compose"
|
"androidx-viewmodel-compose"
|
||||||
|
|
|
@ -20,6 +20,18 @@ android {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = libs.versions.java.get()
|
jvmTarget = libs.versions.java.get()
|
||||||
allWarningsAsErrors = project.property("IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
|
allWarningsAsErrors = project.property("IS_TREAT_WARNINGS_AS_ERRORS").toString().toBoolean()
|
||||||
|
freeCompilerArgs = freeCompilerArgs.plus("-Xopt-in=kotlin.RequiresOptIn")
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
getByName("main").apply {
|
||||||
|
res.setSrcDirs(
|
||||||
|
setOf(
|
||||||
|
"src/main/res/ui/common",
|
||||||
|
"src/main/res/ui/onboarding"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import cash.z.ecc.ui.R
|
||||||
import cash.z.ecc.ui.screen.onboarding.model.OnboardingStage
|
import cash.z.ecc.ui.screen.onboarding.model.OnboardingStage
|
||||||
import cash.z.ecc.ui.screen.onboarding.state.OnboardingState
|
import cash.z.ecc.ui.screen.onboarding.state.OnboardingState
|
||||||
import cash.z.ecc.ui.screen.onboarding.test.getStringResource
|
import cash.z.ecc.ui.screen.onboarding.test.getStringResource
|
||||||
import cash.z.ecc.ui.theme.MyApplicationTheme
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -263,7 +263,7 @@ class OnboardingViewTest {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
composeTestRule.setContent {
|
composeTestRule.setContent {
|
||||||
MyApplicationTheme {
|
ZcashTheme {
|
||||||
Onboarding(
|
Onboarding(
|
||||||
onboardingState,
|
onboardingState,
|
||||||
onCreateWallet = { onCreateWalletCallbackCount++ },
|
onCreateWallet = { onCreateWalletCallbackCount++ },
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name="cash.z.ecc.ui.MainActivity"
|
android:name="cash.z.ecc.ui.MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.MyApplication"
|
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import androidx.activity.compose.setContent
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import cash.z.ecc.ui.screen.onboarding.view.Onboarding
|
import cash.z.ecc.ui.screen.onboarding.view.Onboarding
|
||||||
import cash.z.ecc.ui.screen.onboarding.viewmodel.OnboardingViewModel
|
import cash.z.ecc.ui.screen.onboarding.viewmodel.OnboardingViewModel
|
||||||
import cash.z.ecc.ui.theme.MyApplicationTheme
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContent {
|
setContent {
|
||||||
MyApplicationTheme {
|
ZcashTheme {
|
||||||
Onboarding(
|
Onboarding(
|
||||||
onboardingState = onboardingViewModel.onboardingState,
|
onboardingState = onboardingViewModel.onboardingState,
|
||||||
onImportWallet = { TODO("Implement wallet import") },
|
onImportWallet = { TODO("Implement wallet import") },
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
package cash.z.ecc.ui.screen.common
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.ButtonDefaults.buttonColors
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PrimaryButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier.then(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
),
|
||||||
|
colors = buttonColors(backgroundColor = MaterialTheme.colors.primary)
|
||||||
|
) {
|
||||||
|
Text(style = MaterialTheme.typography.button, text = text, color = MaterialTheme.colors.onPrimary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SecondaryButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier.then(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
),
|
||||||
|
colors = buttonColors(backgroundColor = MaterialTheme.colors.secondary)
|
||||||
|
) {
|
||||||
|
Text(style = MaterialTheme.typography.button, text = text, color = MaterialTheme.colors.onSecondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NavigationButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier.then(
|
||||||
|
Modifier
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
),
|
||||||
|
colors = buttonColors(backgroundColor = MaterialTheme.colors.secondary)
|
||||||
|
) {
|
||||||
|
Text(style = MaterialTheme.typography.button, text = text, color = MaterialTheme.colors.onSecondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TertiaryButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier.then(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
),
|
||||||
|
elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp),
|
||||||
|
colors = buttonColors(backgroundColor = ZcashTheme.colors.tertiary)
|
||||||
|
) {
|
||||||
|
Text(style = MaterialTheme.typography.button, text = text, color = ZcashTheme.colors.onTertiary)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package cash.z.ecc.ui.screen.common
|
||||||
|
|
||||||
|
import androidx.compose.material.LinearProgressIndicator
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import cash.z.ecc.ui.screen.onboarding.model.Progress
|
||||||
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
|
|
||||||
|
// Eventually rename to GradientLinearProgressIndicator
|
||||||
|
@Composable
|
||||||
|
fun PinkProgress(progress: Progress, modifier: Modifier = Modifier) {
|
||||||
|
// Needs custom implementation to apply gradient
|
||||||
|
LinearProgressIndicator(
|
||||||
|
progress = progress.percent().decimal, modifier,
|
||||||
|
ZcashTheme.colors.progressStart, ZcashTheme.colors.progressBackground
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cash.z.ecc.ui.screen.common
|
||||||
|
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Header(
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
style = MaterialTheme.typography.h1,
|
||||||
|
color = ZcashTheme.colors.onBackgroundHeader,
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Body(
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
style = MaterialTheme.typography.body1,
|
||||||
|
color = MaterialTheme.colors.onBackground,
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package cash.z.ecc.ui.screen.debug.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.material.Surface
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.List
|
||||||
|
import androidx.compose.material.icons.filled.Person
|
||||||
|
import androidx.compose.material.icons.filled.Shield
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import cash.z.ecc.ui.screen.common.Body
|
||||||
|
import cash.z.ecc.ui.screen.common.Header
|
||||||
|
import cash.z.ecc.ui.screen.common.NavigationButton
|
||||||
|
import cash.z.ecc.ui.screen.common.PinkProgress
|
||||||
|
import cash.z.ecc.ui.screen.common.PrimaryButton
|
||||||
|
import cash.z.ecc.ui.screen.common.SecondaryButton
|
||||||
|
import cash.z.ecc.ui.screen.common.TertiaryButton
|
||||||
|
import cash.z.ecc.ui.screen.onboarding.model.Index
|
||||||
|
import cash.z.ecc.ui.screen.onboarding.model.Progress
|
||||||
|
import cash.z.ecc.ui.screen.onboarding.view.Callout
|
||||||
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun ComposablePreview() {
|
||||||
|
ZcashTheme(darkTheme = false) {
|
||||||
|
DesignGuide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
// Allowing magic numbers since this is debug-only
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
fun DesignGuide() {
|
||||||
|
Surface {
|
||||||
|
Column {
|
||||||
|
Header(text = "H1")
|
||||||
|
Body(text = "body")
|
||||||
|
NavigationButton(onClick = { }, text = "Back")
|
||||||
|
NavigationButton(onClick = { }, text = "Next")
|
||||||
|
PrimaryButton(onClick = { }, text = "Primary button")
|
||||||
|
SecondaryButton(onClick = { }, text = "Secondary button")
|
||||||
|
TertiaryButton(onClick = { }, text = "Tertiary button")
|
||||||
|
Callout(Icons.Filled.Shield, contentDescription = "Shield")
|
||||||
|
Callout(Icons.Filled.Person, contentDescription = "Person")
|
||||||
|
Callout(Icons.Filled.List, contentDescription = "List")
|
||||||
|
PinkProgress(progress = Progress(Index(1), Index(4)), Modifier.fillMaxWidth())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,37 +1,49 @@
|
||||||
package cash.z.ecc.ui.screen.onboarding.view
|
package cash.z.ecc.ui.screen.onboarding.view
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.material.Button
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.LinearProgressIndicator
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.material.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.painter.ColorPainter
|
import androidx.compose.ui.graphics.painter.ColorPainter
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import cash.z.ecc.ui.R
|
import cash.z.ecc.ui.R
|
||||||
|
import cash.z.ecc.ui.screen.common.Body
|
||||||
|
import cash.z.ecc.ui.screen.common.Header
|
||||||
|
import cash.z.ecc.ui.screen.common.NavigationButton
|
||||||
|
import cash.z.ecc.ui.screen.common.PinkProgress
|
||||||
|
import cash.z.ecc.ui.screen.common.PrimaryButton
|
||||||
|
import cash.z.ecc.ui.screen.common.SecondaryButton
|
||||||
|
import cash.z.ecc.ui.screen.common.TertiaryButton
|
||||||
import cash.z.ecc.ui.screen.onboarding.model.OnboardingStage
|
import cash.z.ecc.ui.screen.onboarding.model.OnboardingStage
|
||||||
import cash.z.ecc.ui.screen.onboarding.model.Progress
|
import cash.z.ecc.ui.screen.onboarding.model.Progress
|
||||||
import cash.z.ecc.ui.screen.onboarding.state.OnboardingState
|
import cash.z.ecc.ui.screen.onboarding.state.OnboardingState
|
||||||
import cash.z.ecc.ui.theme.MINIMAL_WEIGHT
|
import cash.z.ecc.ui.theme.MINIMAL_WEIGHT
|
||||||
|
import cash.z.ecc.ui.theme.ZcashTheme
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun ComposablePreview() {
|
fun ComposablePreview() {
|
||||||
|
ZcashTheme(darkTheme = true) {
|
||||||
Onboarding(
|
Onboarding(
|
||||||
OnboardingState(OnboardingStage.UnifiedAddresses),
|
OnboardingState(OnboardingStage.UnifiedAddresses),
|
||||||
onImportWallet = {},
|
onImportWallet = {},
|
||||||
onCreateWallet = {}
|
onCreateWallet = {}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +56,7 @@ fun Onboarding(
|
||||||
onImportWallet: () -> Unit,
|
onImportWallet: () -> Unit,
|
||||||
onCreateWallet: () -> Unit
|
onCreateWallet: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
Surface {
|
||||||
Column {
|
Column {
|
||||||
TopNavButtons(onboardingState)
|
TopNavButtons(onboardingState)
|
||||||
|
|
||||||
|
@ -61,23 +74,24 @@ fun Onboarding(
|
||||||
|
|
||||||
BottomNav(onboardingStage.getProgress(), onboardingState::goNext)
|
BottomNav(onboardingStage.getProgress(), onboardingState::goNext)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopNavButtons(onboardingState: OnboardingState) {
|
private fun TopNavButtons(onboardingState: OnboardingState) {
|
||||||
Row {
|
Row {
|
||||||
if (onboardingState.hasPrevious()) {
|
if (onboardingState.hasPrevious()) {
|
||||||
Button(onboardingState::goPrevious) {
|
NavigationButton(onboardingState::goPrevious, stringResource(R.string.onboarding_back))
|
||||||
Text(stringResource(R.string.onboarding_back))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.fillMaxWidth().weight(MINIMAL_WEIGHT, true))
|
Spacer(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(MINIMAL_WEIGHT, true)
|
||||||
|
)
|
||||||
|
|
||||||
if (onboardingState.hasNext()) {
|
if (onboardingState.hasNext()) {
|
||||||
Button(onboardingState::goToEnd) {
|
NavigationButton(onboardingState::goToEnd, stringResource(R.string.onboarding_skip))
|
||||||
Text(stringResource(R.string.onboarding_skip))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,14 +100,12 @@ private fun TopNavButtons(onboardingState: OnboardingState) {
|
||||||
private fun BottomNav(progress: Progress, onNext: () -> Unit) {
|
private fun BottomNav(progress: Progress, onNext: () -> Unit) {
|
||||||
if (progress.current != progress.last) {
|
if (progress.current != progress.last) {
|
||||||
Column {
|
Column {
|
||||||
Button(onNext, Modifier.fillMaxWidth()) {
|
SecondaryButton(onNext, stringResource(R.string.onboarding_next), Modifier.fillMaxWidth())
|
||||||
Text(stringResource(R.string.onboarding_next))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts from index to human numbering
|
// Converts from index to human numbering
|
||||||
Text((progress.current.value + 1).toString())
|
Body((progress.current.value + 1).toString())
|
||||||
|
|
||||||
LinearProgressIndicator(progress = progress.percent().decimal, Modifier.fillMaxWidth())
|
PinkProgress(progress, Modifier.fillMaxWidth())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,12 +149,11 @@ private fun More() {
|
||||||
@Composable
|
@Composable
|
||||||
private fun Wallet(onCreateWallet: () -> Unit, onImportWallet: () -> Unit) {
|
private fun Wallet(onCreateWallet: () -> Unit, onImportWallet: () -> Unit) {
|
||||||
Column {
|
Column {
|
||||||
Button(onCreateWallet, Modifier.fillMaxWidth()) {
|
PrimaryButton(onCreateWallet, stringResource(R.string.onboarding_4_create_new_wallet), Modifier.fillMaxWidth())
|
||||||
Text(stringResource(R.string.onboarding_4_create_new_wallet))
|
TertiaryButton(
|
||||||
}
|
onImportWallet, stringResource(R.string.onboarding_4_import_existing_wallet),
|
||||||
Button(onImportWallet, Modifier.fillMaxWidth()) {
|
Modifier.fillMaxWidth()
|
||||||
Text(stringResource(R.string.onboarding_4_import_existing_wallet))
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +170,14 @@ private fun Content(
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
Image(image, imageContentDescription, Modifier.fillMaxSize(0.50f))
|
Image(image, imageContentDescription, Modifier.fillMaxSize(0.50f))
|
||||||
}
|
}
|
||||||
Text(headline)
|
Header(headline)
|
||||||
Text(body)
|
Body(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Callout(imageVector: ImageVector, contentDescription: String) {
|
||||||
|
Box(modifier = Modifier.background(ZcashTheme.colors.callout)) {
|
||||||
|
Icon(imageVector, contentDescription, tint = ZcashTheme.colors.onCallout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,75 @@
|
||||||
|
@file:Suppress("MagicNumber")
|
||||||
|
|
||||||
package cash.z.ecc.ui.theme
|
package cash.z.ecc.ui.theme
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
object Dark {
|
||||||
val Purple200 = Color(0xFFBB86FC)
|
val backgroundStart = Color(0xff243155)
|
||||||
|
val backgroundEnd = Color(0xff29365A)
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
val textHeaderOnBackground = Color(0xffCBDCF2)
|
||||||
val Purple500 = Color(0xFF6200EE)
|
val textBodyOnBackground = Color(0xFF93A4BE)
|
||||||
|
val textPrimaryButton = Color(0xFF0F2341)
|
||||||
|
val textSecondaryButton = Color(0xFF0F2341)
|
||||||
|
val textTertiaryButton = Color.White
|
||||||
|
val textNavigationButton = Color.Black
|
||||||
|
val textCaption = Color(0xFF68728B)
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
val primaryButton = Color(0xFFFFB900)
|
||||||
val Purple700 = Color(0xFF3700B3)
|
val primaryButtonPressed = Color(0xFFFFD800)
|
||||||
|
val primaryButtonDisabled = Color(0x33F4B728)
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
val secondaryButton = Color(0xFFA7C0D9)
|
||||||
val Teal200 = Color(0xFF03DAC5)
|
val secondaryButtonPressed = Color(0xFFC8DCEF)
|
||||||
|
val secondaryButtonDisabled = Color(0x33C8DCEF)
|
||||||
|
|
||||||
|
val tertiaryButton = Color.Transparent
|
||||||
|
val tertiaryButtonPressed = Color(0xB0C3D2BA)
|
||||||
|
// TODO how does the invisible button show a disabled state?
|
||||||
|
|
||||||
|
val navigationButton = Color(0xFFA7C0D9)
|
||||||
|
val navigationButtonPressed = Color(0xFFC8DCEF)
|
||||||
|
|
||||||
|
val progressStart = Color(0xFFF364CE)
|
||||||
|
val progressEnd = Color(0xFFF8964F)
|
||||||
|
val progressBackground = Color(0xFF929bb3)
|
||||||
|
|
||||||
|
val callout = Color(0xFFa7bed8)
|
||||||
|
val onCallout = Color(0xFF3d698f)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Light {
|
||||||
|
val backgroundStart = Color(0xFFE3EFF9)
|
||||||
|
val backgroundEnd = Color(0xFFD2E4F3)
|
||||||
|
|
||||||
|
val textHeaderOnBackground = Color(0xff2D3747)
|
||||||
|
val textBodyOnBackground = Color(0xFF7B8897)
|
||||||
|
val textNavigationButton = Color(0xFF7B8897)
|
||||||
|
val textPrimaryButton = Color(0xFFF2F7FC)
|
||||||
|
val textSecondaryButton = Color(0xFF2E476E)
|
||||||
|
val textTertiaryButton = Color(0xFF283559)
|
||||||
|
val textCaption = Color(0xFF2D3747)
|
||||||
|
|
||||||
|
// TODO The button colors are wrong for light
|
||||||
|
val primaryButton = Color(0xFF263357)
|
||||||
|
val primaryButtonPressed = Color(0xFFFFD800)
|
||||||
|
val primaryButtonDisabled = Color(0x33F4B728)
|
||||||
|
|
||||||
|
val secondaryButton = Color(0xFFE8F3FA)
|
||||||
|
val secondaryButtonPressed = Color(0xFFFAFBFD)
|
||||||
|
val secondaryButtonDisabled = Color(0xFFE6EFF8)
|
||||||
|
|
||||||
|
val tertiaryButton = Color.Transparent
|
||||||
|
val tertiaryButtonPressed = Color(0xFFFFFFFF)
|
||||||
|
|
||||||
|
val navigationButton = Color(0xFFE3EDF7)
|
||||||
|
val navigationButtonPressed = Color(0xFFE3EDF7)
|
||||||
|
|
||||||
|
val progressStart = Color(0xFFF364CE)
|
||||||
|
val progressEnd = Color(0xFFF8964F)
|
||||||
|
val progressBackground = Color(0xFFbeccdf)
|
||||||
|
|
||||||
|
val callout = Color(0xFFe6f0f9)
|
||||||
|
val onCallout = Color(0xFFa1b8d0)
|
||||||
|
}
|
||||||
|
|
|
@ -5,43 +5,110 @@ import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.darkColors
|
import androidx.compose.material.darkColors
|
||||||
import androidx.compose.material.lightColors
|
import androidx.compose.material.lightColors
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
private val DarkColorPalette = darkColors(
|
private val DarkColorPalette = darkColors(
|
||||||
primary = Purple200,
|
primary = Dark.primaryButton,
|
||||||
primaryVariant = Purple700,
|
secondary = Dark.secondaryButton,
|
||||||
secondary = Teal200
|
onPrimary = Dark.textPrimaryButton,
|
||||||
|
onSecondary = Dark.textSecondaryButton,
|
||||||
|
surface = Dark.backgroundStart,
|
||||||
|
onSurface = Dark.textBodyOnBackground,
|
||||||
|
background = Dark.backgroundStart,
|
||||||
|
onBackground = Dark.textBodyOnBackground
|
||||||
)
|
)
|
||||||
|
|
||||||
private val LightColorPalette = lightColors(
|
private val LightColorPalette = lightColors(
|
||||||
primary = Purple500,
|
primary = Light.primaryButton,
|
||||||
primaryVariant = Purple700,
|
secondary = Light.secondaryButton,
|
||||||
secondary = Teal200
|
onPrimary = Light.textPrimaryButton,
|
||||||
|
onSecondary = Light.textSecondaryButton,
|
||||||
/* Other default colors to override
|
surface = Light.backgroundStart,
|
||||||
background = Color.White,
|
onSurface = Light.textBodyOnBackground,
|
||||||
surface = Color.White,
|
background = Light.backgroundStart,
|
||||||
onPrimary = Color.White,
|
onBackground = Light.textBodyOnBackground
|
||||||
onSecondary = Color.Black,
|
|
||||||
onBackground = Color.Black,
|
|
||||||
onSurface = Color.Black,
|
|
||||||
*/
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class ExtendedColors(
|
||||||
|
val onBackgroundHeader: Color,
|
||||||
|
val tertiary: Color,
|
||||||
|
val onTertiary: Color,
|
||||||
|
val callout: Color,
|
||||||
|
val onCallout: Color,
|
||||||
|
val progressStart: Color,
|
||||||
|
val progressEnd: Color,
|
||||||
|
val progressBackground: Color
|
||||||
|
)
|
||||||
|
|
||||||
|
val DarkExtendedColorPalette = ExtendedColors(
|
||||||
|
onBackgroundHeader = Dark.textHeaderOnBackground,
|
||||||
|
tertiary = Dark.tertiaryButton,
|
||||||
|
onTertiary = Dark.textTertiaryButton,
|
||||||
|
callout = Dark.callout,
|
||||||
|
onCallout = Dark.onCallout,
|
||||||
|
progressStart = Dark.progressStart,
|
||||||
|
progressEnd = Dark.progressEnd,
|
||||||
|
progressBackground = Dark.progressBackground
|
||||||
|
)
|
||||||
|
|
||||||
|
val LightExtendedColorPalette = ExtendedColors(
|
||||||
|
onBackgroundHeader = Light.textHeaderOnBackground,
|
||||||
|
tertiary = Light.tertiaryButton,
|
||||||
|
onTertiary = Light.textTertiaryButton,
|
||||||
|
callout = Light.callout,
|
||||||
|
onCallout = Light.onCallout,
|
||||||
|
progressStart = Light.progressStart,
|
||||||
|
progressEnd = Light.progressEnd,
|
||||||
|
progressBackground = Light.progressBackground
|
||||||
|
)
|
||||||
|
|
||||||
|
val LocalExtendedColors = staticCompositionLocalOf {
|
||||||
|
ExtendedColors(
|
||||||
|
onBackgroundHeader = Color.Unspecified,
|
||||||
|
tertiary = Color.Unspecified,
|
||||||
|
onTertiary = Color.Unspecified,
|
||||||
|
callout = Color.Unspecified,
|
||||||
|
onCallout = Color.Unspecified,
|
||||||
|
progressStart = Color.Unspecified,
|
||||||
|
progressEnd = Color.Unspecified,
|
||||||
|
progressBackground = Color.Unspecified
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MyApplicationTheme(
|
fun ZcashTheme(
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val colors = if (darkTheme) {
|
val baseColors = if (darkTheme) {
|
||||||
DarkColorPalette
|
DarkColorPalette
|
||||||
} else {
|
} else {
|
||||||
LightColorPalette
|
LightColorPalette
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val extendedColors = if (darkTheme) {
|
||||||
|
DarkExtendedColorPalette
|
||||||
|
} else {
|
||||||
|
LightExtendedColorPalette
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositionLocalProvider(LocalExtendedColors provides extendedColors) {
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colors = colors,
|
colors = baseColors,
|
||||||
typography = Typography,
|
typography = Typography,
|
||||||
shapes = Shapes,
|
shapes = Shapes,
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use with eg. ZcashTheme.colors.tertiary
|
||||||
|
object ZcashTheme {
|
||||||
|
val colors: ExtendedColors
|
||||||
|
@Composable
|
||||||
|
get() = LocalExtendedColors.current
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
package cash.z.ecc.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.material.Typography
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
|
|
||||||
// Set of Material typography styles to start with
|
|
||||||
val Typography = Typography(
|
|
||||||
body1 = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
/* Other default text styles to override
|
|
||||||
button = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.W500,
|
|
||||||
fontSize = 14.sp
|
|
||||||
),
|
|
||||||
caption = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 12.sp
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
)
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cash.z.ecc.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.material.Typography
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.ExperimentalUnitApi
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cash.z.ecc.ui.R
|
||||||
|
|
||||||
|
private val Rubik = FontFamily(
|
||||||
|
Font(R.font.rubik_regular, FontWeight.W400),
|
||||||
|
Font(R.font.rubik_medium, FontWeight.W500)
|
||||||
|
)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnitApi::class)
|
||||||
|
val Typography = Typography(
|
||||||
|
h1 = TextStyle(
|
||||||
|
fontFamily = Rubik,
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
),
|
||||||
|
body1 = TextStyle(
|
||||||
|
fontFamily = Rubik,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
caption = TextStyle(
|
||||||
|
fontFamily = Rubik,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
button = TextStyle(
|
||||||
|
fontFamily = Rubik,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
)
|
Binary file not shown.
Binary file not shown.
|
@ -1,11 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="purple_200">#FFBB86FC</color>
|
|
||||||
<color name="purple_500">#FF6200EE</color>
|
|
||||||
<color name="purple_700">#FF3700B3</color>
|
|
||||||
<color name="teal_200">#FF03DAC5</color>
|
|
||||||
<color name="teal_700">#FF018786</color>
|
|
||||||
<color name="black">#FF000000</color>
|
|
||||||
<color name="white">#FFFFFFFF</color>
|
|
||||||
|
|
||||||
</resources>
|
|
|
@ -1,25 +0,0 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
<!-- Base application theme. -->
|
|
||||||
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
|
||||||
<!-- Primary brand color. -->
|
|
||||||
<item name="colorPrimary">@color/purple_500</item>
|
|
||||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
|
||||||
<item name="colorOnPrimary">@color/white</item>
|
|
||||||
<!-- Secondary brand color. -->
|
|
||||||
<item name="colorSecondary">@color/teal_200</item>
|
|
||||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
|
||||||
<item name="colorOnSecondary">@color/black</item>
|
|
||||||
<!-- Status bar color. -->
|
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="Theme.MyApplication.NoActionBar">
|
|
||||||
<item name="windowActionBar">false</item>
|
|
||||||
<item name="windowNoTitle">true</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="Theme.MyApplication.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
|
||||||
|
|
||||||
<style name="Theme.MyApplication.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
|
||||||
</resources>
|
|
Loading…
Reference in New Issue