-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(scaffolds): Create Vitamin scaffold component. (#133)
- Loading branch information
1 parent
fd3bdd3
commit b63cf7b
Showing
25 changed files
with
780 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 changes: 200 additions & 0 deletions
200
sample/src/main/java/com/decathlon/compose/sample/screens/Scaffold.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
package com.decathlon.compose.sample.screens | ||
|
||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.PaddingValues | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.lazy.LazyColumn | ||
import androidx.compose.foundation.text.KeyboardActions | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.MutableState | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.unit.dp | ||
import androidx.navigation.NavController | ||
import com.decathlon.vitamin.compose.VitaminIcons | ||
import com.decathlon.vitamin.compose.buttons.VitaminButtons | ||
import com.decathlon.vitamin.compose.scaffolds.BottomActionUi | ||
import com.decathlon.vitamin.compose.scaffolds.BottomActionsUi | ||
import com.decathlon.vitamin.compose.scaffolds.FabActionUi | ||
import com.decathlon.vitamin.compose.scaffolds.TabActionUi | ||
import com.decathlon.vitamin.compose.scaffolds.TabActionsUi | ||
import com.decathlon.vitamin.compose.scaffolds.TopActionUi | ||
import com.decathlon.vitamin.compose.scaffolds.TopActionsUi | ||
import com.decathlon.vitamin.compose.scaffolds.TopBarConfiguration | ||
import com.decathlon.vitamin.compose.scaffolds.VitaminScaffolds | ||
import com.decathlon.vitamin.compose.vitaminicons.Fill | ||
import com.decathlon.vitamin.compose.vitaminicons.Line | ||
import com.decathlon.vitamin.compose.vitaminicons.fill.Calendar | ||
import com.decathlon.vitamin.compose.vitaminicons.line.Add | ||
import com.decathlon.vitamin.compose.vitaminicons.line.Android | ||
import com.decathlon.vitamin.compose.vitaminicons.line.Calendar | ||
import com.decathlon.vitamin.compose.vitaminicons.line.Search | ||
|
||
object Scaffold : Screen { | ||
override val name: String | ||
get() = "Scaffold" | ||
override val navigationKey: String | ||
get() = "scaffolds" | ||
|
||
@SuppressWarnings("LongMethod") | ||
@Composable | ||
override fun Screen(navController: NavController?) { | ||
val searchValue = remember { mutableStateOf(value = "") } | ||
val topBarConfiguration: MutableState<TopBarConfiguration> = | ||
remember { mutableStateOf(TopBarConfiguration.Primary()) } | ||
val tabActionsUi = remember { mutableStateOf(TabActionsUi(scrollable = true)) } | ||
val tabSelected = remember { mutableStateOf<Int?>(null) } | ||
val topActionsUi = remember { | ||
mutableStateOf( | ||
TopActionsUi( | ||
actions = listOf( | ||
TopActionUi( | ||
id = 0, | ||
icon = VitaminIcons.Line.Search, | ||
contentDescription = "Search" | ||
) | ||
) | ||
) | ||
) | ||
} | ||
val bottomActionUi = remember { mutableStateOf(BottomActionsUi()) } | ||
val bottomSelected = remember { mutableStateOf<String?>(null) } | ||
VitaminScaffolds.Primary( | ||
title = name, | ||
topBarConfiguration = topBarConfiguration.value, | ||
topActionsUi = topActionsUi.value, | ||
onTopActionClicked = { action -> | ||
if (action.id == 0) { | ||
topBarConfiguration.value = TopBarConfiguration.Search( | ||
value = searchValue, | ||
placeholder = "Search", | ||
keyboardActions = KeyboardActions(onDone = { | ||
topBarConfiguration.value = TopBarConfiguration.Primary() | ||
}), | ||
navigationIcon = { | ||
Search(contentDescription = null) | ||
} | ||
) | ||
} | ||
}, | ||
tabActionsUi = tabActionsUi.value, | ||
onTabClicked = { action -> | ||
tabSelected.value = tabActionsUi.value.actions | ||
.indexOfFirst { it.route == action.route } | ||
}, | ||
tabSelectedIndex = tabSelected.value, | ||
onSearchValueChanged = { newValue -> | ||
searchValue.value = newValue | ||
}, | ||
fabAction = FabActionUi( | ||
id = 0, | ||
icon = VitaminIcons.Line.Add, | ||
contentDescription = "Add" | ||
), | ||
bottomActionsUi = bottomActionUi.value, | ||
bottomRouteSelected = bottomSelected.value, | ||
onBottomActionClicked = { action -> | ||
bottomSelected.value = action.route | ||
} | ||
) { | ||
LazyColumn( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.padding(it), | ||
verticalArrangement = Arrangement.spacedBy(16.dp), | ||
contentPadding = PaddingValues(16.dp) | ||
) { | ||
item { | ||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { | ||
VitaminButtons.Primary(text = "Add top action") { | ||
topActionsUi.value = topActionsUi.value.copy( | ||
actions = topActionsUi.value.actions + TopActionUi( | ||
id = topActionsUi.value.actions.size + 1, | ||
icon = VitaminIcons.Line.Android, | ||
contentDescription = "Android ${topActionsUi.value.actions.size + 1}" | ||
) | ||
) | ||
} | ||
VitaminButtons.Primary( | ||
text = "Remove top action", | ||
enabled = topActionsUi.value.actions.size > 1 | ||
) { | ||
topActionsUi.value = topActionsUi.value.copy( | ||
actions = topActionsUi.value.actions.dropLast(1) | ||
) | ||
} | ||
} | ||
} | ||
item { | ||
val hasAtLeast2Tabs = tabActionsUi.value.actions.size >= 2 | ||
val hasLessThan3Tabs = tabActionsUi.value.actions.size <= 2 | ||
val additionText = if (hasAtLeast2Tabs) "Add tab" else "Add 2 tabs" | ||
val removeText = if (hasLessThan3Tabs) "Clear tabs" else "Remove tab" | ||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { | ||
VitaminButtons.Primary(text = additionText) { | ||
if (hasAtLeast2Tabs) { | ||
tabActionsUi.value = tabActionsUi.value.copy( | ||
actions = tabActionsUi.value.actions + TabActionUi( | ||
route = "tab-${tabActionsUi.value.actions.size + 1}", | ||
label = "Tab ${tabActionsUi.value.actions.size + 1}" | ||
) | ||
) | ||
} else { | ||
tabActionsUi.value = tabActionsUi.value.copy( | ||
actions = arrayListOf( | ||
TabActionUi( | ||
route = "tab-1", | ||
label = "Tab 1" | ||
), | ||
TabActionUi( | ||
route = "tab-2", | ||
label = "Tab 2" | ||
) | ||
) | ||
) | ||
} | ||
} | ||
VitaminButtons.Primary( | ||
text = removeText, | ||
enabled = tabActionsUi.value.actions.size > 1 | ||
) { | ||
if (hasLessThan3Tabs) { | ||
tabActionsUi.value = tabActionsUi.value.copy(actions = emptyList()) | ||
} else { | ||
tabActionsUi.value = tabActionsUi.value.copy( | ||
actions = tabActionsUi.value.actions.dropLast(1) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
item { | ||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { | ||
VitaminButtons.Primary(text = "Add bottom action") { | ||
bottomActionUi.value = bottomActionUi.value.copy( | ||
actions = bottomActionUi.value.actions + BottomActionUi( | ||
route = "tab-${bottomActionUi.value.actions.size + 1}", | ||
icon = VitaminIcons.Line.Calendar, | ||
iconSelected = VitaminIcons.Fill.Calendar, | ||
label = "Bottom ${bottomActionUi.value.actions.size + 1}", | ||
contentDescription = null | ||
) | ||
) | ||
} | ||
VitaminButtons.Primary( | ||
text = "Remove bottom action", | ||
enabled = bottomActionUi.value.actions.isNotEmpty() | ||
) { | ||
bottomActionUi.value = bottomActionUi.value.copy( | ||
actions = bottomActionUi.value.actions.dropLast(1) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Scaffold components | ||
|
||
## Scaffold design specs | ||
|
||
You can find the design specs on [decathlon.design](https://www.decathlon.design/). | ||
|
||
## Usage | ||
|
||
If you want to use components of this module in your android mobile application, you should | ||
first add the Gradle dependency in your Gradle file: | ||
|
||
```kotlin | ||
implementation("com.decathlon.vitamin.compose:scaffolds:<versions>") | ||
``` | ||
|
||
### Primary | ||
|
||
```kotlin | ||
object VitaminScaffolds { | ||
@Composable | ||
fun Primary( | ||
title: String, | ||
modifier: Modifier = Modifier, | ||
topBarConfiguration: TopBarConfiguration = TopBarConfiguration.Primary(), | ||
topActionsUi: TopActionsUi = TopActionsUi(), | ||
tabActionsUi: TabActionsUi = TabActionsUi(), | ||
bottomActionsUi: BottomActionsUi = BottomActionsUi(), | ||
fabAction: FabActionUi? = null, | ||
tabSelectedIndex: Int? = null, | ||
bottomRouteSelected: String? = null, | ||
onTopActionClicked: (TopActionUi) -> Unit = {}, | ||
onTabClicked: (TabActionUi) -> Unit = {}, | ||
onBottomActionClicked: (BottomActionUi) -> Unit = {}, | ||
onFabActionClicked: (FabActionUi) -> Unit = {}, | ||
onSearchValueChanged: (String) -> Unit = {}, | ||
content: @Composable (PaddingValues) -> Unit | ||
) | ||
} | ||
``` | ||
|
||
Material design layout with Vitamin components. | ||
Scaffold implements Material design visual layout structure and this component will use Vitamin | ||
TopBar, Tabs, BottomBar and Floating Action Button according to models given in input. | ||
|
||
The minimal usage of the component is the title and content but it makes really sense to use this | ||
component when you have TopBar, Tab, BottomBar and/or FAB configuration and more when it should | ||
be dynamic at runtime. | ||
|
||
```kotlin | ||
VitaminScaffolds.Primary(title = "My title") { padding -> | ||
// content here | ||
} | ||
``` | ||
|
||
Parameters | Descriptions | ||
-- | -- | ||
`title: String` | Title specified in the Vitamin TopBar. | ||
`modifier: Modifier = Modifier` | The `Modifier` to be applied to the component | ||
`topBarConfiguration: TopBarConfiguration = TopBarConfiguration.Primary()` | Switch dynamically from primary to search configuration. | ||
`topActionsUi: TopActionsUi = TopActionsUi()` | List of the TopBar actions and maximum number of actions with icon you want to show. | ||
`tabActionsUi: TabActionsUi = TabActionsUi()` | List of the Tab actions and whether it should be used in scrollable mode. | ||
`bottomActionsUi: BottomActionsUi = BottomActionsUi()` | List of the BottomBar actions. | ||
`fabAction: FabActionUi? = null` | Display a floating action button at the bottom end of the content. | ||
`tabSelectedIndex: Int? = null` | Indicate which tab is currently selected. | ||
`bottomRouteSelected: String? = null` | Indicate which bottom action is currently selected. | ||
`onTopActionClicked: (TopActionUi) -> Unit = {}` | The callback to be called when the user click on a TopBar action. | ||
`onTabClicked: (TabActionUi) -> Unit = {}` | The callback to be called when the user click on a tab action. | ||
`onBottomActionClicked: (BottomActionUi) -> Unit = {}` | The callback to be called when the user click on a bottom action. | ||
`onFabActionClicked: (FabActionUi) -> Unit = {}` | The callback to be called when the user click on the fab. | ||
`onSearchValueChanged: (String) -> Unit = {}` | The callback to be called when the user type a character in the searchbar. | ||
`content: @Composable (PaddingValues) -> Unit` | The content of your screen. As Material design Scaffold component, the expected [PaddingValues] is passed and should be used by your root component in this api slot. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
plugins { | ||
id("com.android.library") | ||
id("kotlin-android") | ||
id("VitaminComposeLibraryPlugin") | ||
id("com.vanniktech.maven.publish") | ||
id("app.cash.paparazzi") | ||
} | ||
|
||
dependencies { | ||
api(project(":foundation:foundation")) | ||
api(project(":appbars")) | ||
api(project(":tabs")) | ||
api(project(":fabs")) | ||
implementation(AndroidX.compose.ui.tooling) | ||
testImplementation("com.google.testparameterinjector:test-parameter-injector:1.8") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
POM_ARTIFACT_ID=scaffolds | ||
POM_NAME=Vitamin Scaffold | ||
POM_DESCRIPTION=Scaffold components which use Vitamin components |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest package="com.decathlon.vitamin.compose.scaffolds" /> |
16 changes: 16 additions & 0 deletions
16
scaffolds/src/main/kotlin/com/decathlon/vitamin/compose/scaffolds/BottomActionUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.decathlon.vitamin.compose.scaffolds | ||
|
||
import androidx.compose.runtime.Immutable | ||
import androidx.compose.runtime.Stable | ||
import androidx.compose.ui.graphics.vector.ImageVector | ||
|
||
@Stable | ||
@Immutable | ||
open class BottomActionUi( | ||
val route: String, | ||
val icon: ImageVector, | ||
val iconSelected: ImageVector, | ||
val label: String, | ||
val contentDescription: String?, | ||
val selectedRoutes: List<String> = emptyList() | ||
) |
10 changes: 10 additions & 0 deletions
10
scaffolds/src/main/kotlin/com/decathlon/vitamin/compose/scaffolds/BottomActionsUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.decathlon.vitamin.compose.scaffolds | ||
|
||
import androidx.compose.runtime.Immutable | ||
import androidx.compose.runtime.Stable | ||
|
||
@Stable | ||
@Immutable | ||
data class BottomActionsUi( | ||
val actions: List<BottomActionUi> = emptyList() | ||
) |
13 changes: 13 additions & 0 deletions
13
scaffolds/src/main/kotlin/com/decathlon/vitamin/compose/scaffolds/FabActionUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.decathlon.vitamin.compose.scaffolds | ||
|
||
import androidx.compose.runtime.Immutable | ||
import androidx.compose.runtime.Stable | ||
import androidx.compose.ui.graphics.vector.ImageVector | ||
|
||
@Stable | ||
@Immutable | ||
open class FabActionUi( | ||
val id: Int, | ||
val icon: ImageVector, | ||
val contentDescription: String? | ||
) |
13 changes: 13 additions & 0 deletions
13
scaffolds/src/main/kotlin/com/decathlon/vitamin/compose/scaffolds/TabActionUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.decathlon.vitamin.compose.scaffolds | ||
|
||
import androidx.compose.runtime.Immutable | ||
import androidx.compose.runtime.Stable | ||
import androidx.compose.ui.graphics.vector.ImageVector | ||
|
||
@Stable | ||
@Immutable | ||
data class TabActionUi( | ||
val route: String, | ||
val label: String, | ||
val icon: ImageVector? = null | ||
) |
Oops, something went wrong.