[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:
parent
37a4d49494
commit
53e80e6b5d
7 changed files with 71 additions and 39 deletions
1
changelog.d/1050.misc
Normal file
1
changelog.d/1050.misc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Compound: implement `DropdownMenu` customisations.
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue