[Compound] Implement DropdownMenu customisations. (#1050)

* Compound: implement `DropdownMenu` customisations.

* Update screenshots

* Add changelog

* Address review comments

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa 2023-08-11 15:09:51 +02:00 committed by GitHub
parent 37a4d49494
commit 53e80e6b5d
7 changed files with 71 additions and 39 deletions

1
changelog.d/1050.misc Normal file
View file

@ -0,0 +1 @@
Compound: implement `DropdownMenu` customisations.

View file

@ -67,7 +67,6 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.preview.LargeHeightPreview import io.element.android.libraries.designsystem.preview.LargeHeightPreview
import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -195,7 +194,7 @@ internal fun RoomDetailsTopBar(
onDismissRequest = { showMenu = false }, onDismissRequest = { showMenu = false },
) { ) {
DropdownMenuItem( DropdownMenuItem(
text = { DropdownMenuItemText(stringResource(id = CommonStrings.action_edit)) }, text = { Text(stringResource(id = CommonStrings.action_edit)) },
onClick = { onClick = {
// Explicitly close the menu before handling the action, as otherwise it stays open during the // Explicitly close the menu before handling the action, as otherwise it stays open during the
// transition and renders really badly. // transition and renders really badly.

View file

@ -48,7 +48,6 @@ import io.element.android.libraries.designsystem.text.toSp
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar
@ -169,7 +168,7 @@ private fun DefaultRoomListTopBar(
showMenu = false showMenu = false
onMenuActionClicked(RoomListMenuAction.InviteFriends) onMenuActionClicked(RoomListMenuAction.InviteFriends)
}, },
text = { DropdownMenuItemText(stringResource(id = CommonStrings.action_invite)) }, text = { Text(stringResource(id = CommonStrings.action_invite)) },
leadingIcon = { leadingIcon = {
Icon( Icon(
Icons.Outlined.Share, Icons.Outlined.Share,
@ -183,7 +182,7 @@ private fun DefaultRoomListTopBar(
showMenu = false showMenu = false
onMenuActionClicked(RoomListMenuAction.ReportBug) onMenuActionClicked(RoomListMenuAction.ReportBug)
}, },
text = { DropdownMenuItemText(stringResource(id = CommonStrings.common_report_a_bug)) }, text = { Text(stringResource(id = CommonStrings.common_report_a_bug)) },
leadingIcon = { leadingIcon = {
Icon( Icon(
Icons.Outlined.BugReport, Icons.Outlined.BugReport,

View file

@ -26,7 +26,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.PopupProperties import androidx.compose.ui.window.PopupProperties
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
private val minMenuWidth = 200.dp // Figma designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=1032%3A44063&mode=design&t=rsNegTbEVLYAXL76-1
@Composable @Composable
fun DropdownMenu( fun DropdownMenu(
@ -38,19 +38,17 @@ fun DropdownMenu(
properties: PopupProperties = PopupProperties(focusable = true), properties: PopupProperties = PopupProperties(focusable = true),
content: @Composable ColumnScope.() -> Unit content: @Composable ColumnScope.() -> Unit
) { ) {
val bgColor = if (ElementTheme.isLightTheme) { // Note: the internal shape corner radius should be 8dp, but there is a 4p value hardcoded in the internal Surface component
ElementTheme.materialColors.background
} else {
ElementTheme.colors.bgSubtlePrimary
}
androidx.compose.material3.DropdownMenu( androidx.compose.material3.DropdownMenu(
expanded = expanded, expanded = expanded,
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
modifier = modifier modifier = modifier
.background(color = bgColor) .background(color = ElementTheme.colors.bgCanvasDefault)
.widthIn(min = minMenuWidth), .widthIn(min = minMenuWidth),
offset = offset, offset = offset,
properties = properties, properties = properties,
content = content content = content
) )
} }
private val minMenuWidth = 200.dp

View file

@ -17,20 +17,26 @@
package io.element.android.libraries.designsystem.theme.components package io.element.android.libraries.designsystem.theme.components
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowRight
import androidx.compose.material.icons.filled.BugReport import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material.icons.filled.Share import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MenuDefaults import androidx.compose.material3.MenuDefaults
import androidx.compose.material3.MenuItemColors
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
// Figma designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=1032%3A44063&mode=design&t=rsNegTbEVLYAXL76-1
@Composable @Composable
fun DropdownMenuItem( fun DropdownMenuItem(
text: @Composable () -> Unit, text: @Composable () -> Unit,
@ -39,34 +45,37 @@ fun DropdownMenuItem(
leadingIcon: @Composable (() -> Unit)? = null, leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null,
enabled: Boolean = true, enabled: Boolean = true,
colors: MenuItemColors = MenuDefaults.itemColors(),
contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) { ) {
androidx.compose.material3.DropdownMenuItem( androidx.compose.material3.DropdownMenuItem(
text = text, text = {
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyLarge) {
text()
}
},
onClick = onClick, onClick = onClick,
modifier = modifier, modifier = modifier,
leadingIcon = leadingIcon, leadingIcon = leadingIcon,
trailingIcon = trailingIcon, trailingIcon = trailingIcon,
enabled = enabled, enabled = enabled,
colors = colors, colors = DropDownMenuItemDefaults.colors(),
contentPadding = contentPadding, contentPadding = DropDownMenuItemDefaults.contentPadding,
interactionSource = interactionSource interactionSource = interactionSource
) )
} }
@Composable internal object DropDownMenuItemDefaults {
fun DropdownMenuItemText( @Composable
text: String, fun colors() = MenuDefaults.itemColors(
modifier: Modifier = Modifier, textColor = ElementTheme.colors.textPrimary,
) { leadingIconColor = ElementTheme.colors.iconPrimary,
Text( trailingIconColor = ElementTheme.colors.iconSecondary,
text = text, disabledTextColor = ElementTheme.colors.textDisabled,
color = ElementTheme.materialColors.primary, disabledLeadingIconColor = ElementTheme.colors.iconDisabled,
style = ElementTheme.typography.fontBodyLgRegular, disabledTrailingIconColor = ElementTheme.colors.iconDisabled,
modifier = modifier,
) )
val contentPadding = PaddingValues(all = 12.dp)
} }
@Preview(group = PreviewGroup.Menus) @Preview(group = PreviewGroup.Menus)
@ -75,10 +84,36 @@ internal fun DropdownMenuItemPreview() = ElementThemedPreview { ContentToPreview
@Composable @Composable
private fun ContentToPreview() { private fun ContentToPreview() {
DropdownMenuItem( Column {
text = { DropdownMenuItemText(text = "Item") }, DropdownMenuItem(
onClick = {}, text = { Text(text = "Item") },
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) }, onClick = {},
trailingIcon = { Icon(Icons.Default.Share, contentDescription = null) }, trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
) )
Divider()
DropdownMenuItem(
text = { Text(text = "Item") },
onClick = {},
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
)
DropdownMenuItem(
text = { Text(text = "Item") },
onClick = {},
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
)
DropdownMenuItem(
text = { Text(text = "Item") },
onClick = {},
enabled = false,
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
)
Divider()
DropdownMenuItem(
text = { Text(text = "Multiline\nItem") },
onClick = {},
trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
)
}
} }

View file

@ -30,8 +30,8 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
@Preview(group = PreviewGroup.Menus) @Preview(group = PreviewGroup.Menus)
@Composable @Composable
@ -57,7 +57,7 @@ internal fun MenuPreview() {
null null
} }
DropdownMenuItem( DropdownMenuItem(
text = { DropdownMenuItemText(text = "Item $i") }, text = { Text(text = "Item $i") },
onClick = { isExpanded = false }, onClick = { isExpanded = false },
leadingIcon = leadingIcon, leadingIcon = leadingIcon,
trailingIcon = trailingIcon, trailingIcon = trailingIcon,

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1765f4842cbd6e3c1b7daa9a9cc13fc0f4c47ff73c2cb1fdd7f3d2377eea0553 oid sha256:e425d58f766655f1003c595637ab7387cdf74ba7ae7862bf2f137f3ffd33f3f3
size 9053 size 21202