Skip to content

Commit

Permalink
Merge pull request #308 from Spendesk/release/1.19.0
Browse files Browse the repository at this point in the history
Release 1.19.0
  • Loading branch information
RomainGF authored Dec 1, 2023
2 parents 05c477c + c5d2de1 commit 1b5c62d
Show file tree
Hide file tree
Showing 9 changed files with 510 additions and 85 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
grapes-version = '1.18.3'
grapes-version = '1.19.0'
androidMinSdk = "21"
androidTargetSdk = "34"
androidCompileSdk = "34"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package com.spendesk.grapes.compose.actionmenu

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.spendesk.grapes.compose.R
import com.spendesk.grapes.compose.theme.GrapesTheme

/**
* @author : RomainGF
* @since : 09/10/2023
**/
private val iconMaxSize = 16.dp
private val verticalInnerPadding = 20.dp
private const val ACTION_TEXT_MAX_LINES = 2

/**
* ActionMenuItem is a button with an icon and a text.
*
* @param text Text to display on the button
* @param icon Slot for the icon to display on the left of the text. Size is constrained to 16dp.
* @param onClick Callback when the button is clicked
* @param modifier Modifier
* @param enabled Whether the button is enabled or not
*/
@Composable
fun ActionMenuItem(
text: String,
icon: @Composable () -> Unit,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
) {
Button(
onClick = onClick,
enabled = enabled,
colors = ButtonDefaults.buttonColors(
containerColor = GrapesTheme.colors.neutralLightest,
contentColor = GrapesTheme.colors.primaryNormal,
disabledContainerColor = GrapesTheme.colors.neutralLightest,
disabledContentColor = GrapesTheme.colors.neutralNormal,
),
contentPadding = PaddingValues(
start = GrapesTheme.dimensions.paddingXLarge,
end = GrapesTheme.dimensions.paddingLarge,
top = verticalInnerPadding,
bottom = verticalInnerPadding,
),
shape = GrapesTheme.shapes.small,
modifier = modifier,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
ActionMenuItemIcon(
enabled = enabled,
icon = icon,
)
Spacer(Modifier.width(GrapesTheme.dimensions.paddingXLarge))
Text(
text = text,
maxLines = ACTION_TEXT_MAX_LINES,
overflow = TextOverflow.Ellipsis,
style = GrapesTheme.typography.titleS,
modifier = Modifier.weight(1f),
)
if (enabled) {
Spacer(Modifier.width(GrapesTheme.dimensions.paddingLarge))
Icon(
painter = painterResource(R.drawable.ic_chevron_right),
contentDescription = null,
tint = GrapesTheme.colors.primaryLighter,
)
}
}
}
}

@Composable
private fun ActionMenuItemIcon(
enabled: Boolean,
icon: @Composable () -> Unit,
) {
Box(
modifier = Modifier.sizeIn(
maxWidth = iconMaxSize,
maxHeight = iconMaxSize,
),
) {
val iconContentColor = if (enabled) {
GrapesTheme.colors.primaryNormal
} else {
GrapesTheme.colors.neutralNormal
}
CompositionLocalProvider(LocalContentColor provides iconContentColor) {
icon()
}
}
}

@Preview
@Preview(fontScale = 2f)
@Composable
private fun ActionMenuItemPreview() {
GrapesTheme {
val icon = @Composable {
Icon(
painter = painterResource(R.drawable.ic_neutral),
contentDescription = null,
modifier = Modifier.size(48.dp)
)
}
val text = "Action"
val longText = "Action with a very long title which will not fit in one line. Event two lines will not be enough"
val modifier = Modifier.fillMaxWidth()
Column(
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
ActionMenuItem(
text = text,
icon = icon,
onClick = {},
modifier = modifier,
)
ActionMenuItem(
text = longText,
icon = icon,
onClick = {},
modifier = modifier,
)
ActionMenuItem(
text = text,
icon = icon,
onClick = {},
enabled = false,
modifier = modifier,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.spendesk.grapes.compose.actionmenu

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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.spendesk.grapes.compose.R
import com.spendesk.grapes.compose.theme.GrapesTheme

/**
* @author : RomainGF
* @since : 09/10/2023
**/

private val iconMaxSize = 56.dp
private val sectionShape = RoundedCornerShape(16.dp)
private const val TITLE_MAX_LINES = 2
private const val DESCRIPTION_MAX_LINES = 3

@Composable
fun ActionMenuSection(
title: String,
description: String,
illustration: @Composable () -> Unit,
modifier: Modifier = Modifier,
content: @Composable ColumnScope.() -> Unit,
) {
Card(
modifier = modifier,
colors = CardDefaults.cardColors(
containerColor = GrapesTheme.colors.structureSurface,
),
shape = sectionShape,
) {
Column(
verticalArrangement = Arrangement.spacedBy(GrapesTheme.dimensions.paddingSmall),
modifier = Modifier.padding(GrapesTheme.dimensions.paddingSmall),
) {
ActionMenuSectionHeader(
title = title,
description = description,
illustration = illustration,
)
content()
}
}
}

@Composable
private fun ActionMenuSectionHeader(
title: String,
description: String,
illustration: @Composable () -> Unit,
modifier: Modifier = Modifier,
) {
Row(
horizontalArrangement = Arrangement.spacedBy(GrapesTheme.dimensions.paddingSmall),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier,
) {
Box(
content = { illustration() },
contentAlignment = Alignment.Center,
modifier = Modifier.sizeIn(
maxWidth = iconMaxSize,
maxHeight = iconMaxSize,
),
)
Column(
verticalArrangement = Arrangement.spacedBy(GrapesTheme.dimensions.paddingXSmall),
modifier = Modifier.padding(
bottom = GrapesTheme.dimensions.paddingSmall,
top = GrapesTheme.dimensions.paddingSmall,
end = GrapesTheme.dimensions.paddingSmall,
)
) {
Text(
text = title,
style = GrapesTheme.typography.titleM,
color = GrapesTheme.colors.structureComplementary,
maxLines = TITLE_MAX_LINES,
overflow = TextOverflow.Ellipsis,
)
Text(
text = description,
style = GrapesTheme.typography.bodyS,
color = GrapesTheme.colors.neutralDark,
maxLines = DESCRIPTION_MAX_LINES,
overflow = TextOverflow.Ellipsis,
)
}
}
}

@Preview
@Preview(fontScale = 2f)
@Composable
private fun ActionMenuSectionPreview() {
GrapesTheme {
ActionMenuSection(
title = "Make a purchase request",
description = "Order a virtual card to directly use company money online",
illustration = {
Icon(painterResource(R.drawable.ic_neutral), null, Modifier.fillMaxSize())
},
modifier = Modifier.fillMaxWidth(),
) {
ActionMenuItem(
text = "Ask for a virtual card",
icon = { Icon(painterResource(R.drawable.ic_neutral), null) },
onClick = {},
)
ActionMenuItem(
text = "Ask for a virtual card",
icon = { Icon(painterResource(R.drawable.ic_neutral), null) },
onClick = {},
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private fun RowScope.GrapesNavigationBarItem(
tab: GrapesNavigationItem,
onSelected: (GrapesNavigationItem) -> Unit,
) {
val textStyle = GrapesTheme.typography.titleS.copy(fontSize = 12.sp)
val textStyle = GrapesTheme.typography.titleXs
val colors = NavigationBarItemDefaults.colors(
indicatorColor = GrapesTheme.colors.mainWhite,
selectedIconColor = GrapesTheme.colors.mainPrimaryNormal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fun GrapesTopAppBarTitle(
Text(
modifier = modifier,
text = title,
color = GrapesTheme.colors.mainComplementary,
color = GrapesTheme.colors.structureComplementary,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
style = GrapesTheme.typography.titleL,
Expand Down Expand Up @@ -106,7 +106,7 @@ fun GrapesTopAppBarBackIcon(
modifier = modifier.size(24.dp),
imageVector = ImageVector.vectorResource(R.drawable.ic_arrow_back),
contentDescription = stringResource(id = R.string.grapes_top_app_bar_back_icon_description),
tint = GrapesTheme.colors.mainComplementary
tint = GrapesTheme.colors.structureComplementary,
)
}

Expand All @@ -118,7 +118,7 @@ fun GrapesTopAppBarCloseIcon(
modifier = modifier.size(24.dp),
imageVector = ImageVector.vectorResource(R.drawable.ic_close),
contentDescription = stringResource(id = R.string.grapes_top_app_bar_close_icon_description),
tint = GrapesTheme.colors.mainComplementary
tint = GrapesTheme.colors.structureComplementary
)
}

Expand All @@ -130,7 +130,7 @@ fun GrapesTopAppBarMoreIcon(
modifier = modifier.size(24.dp),
imageVector = ImageVector.vectorResource(R.drawable.ic_more_vertical),
contentDescription = stringResource(id = R.string.grapes_top_app_bar_more_icon_description),
tint = GrapesTheme.colors.mainComplementary
tint = GrapesTheme.colors.structureComplementary
)
}

Expand All @@ -142,7 +142,7 @@ fun GrapesSimpleTopAppBarPreview() {
Column(
modifier = Modifier
.fillMaxSize()
.background(GrapesTheme.colors.mainNeutralLighter)
.background(GrapesTheme.colors.structureBackground)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Expand Down
Loading

0 comments on commit 1b5c62d

Please sign in to comment.