When creating a Glimmer Icon Sizes component, refer to the following source
code in ListItem.kt for list items:
/* * Copyright 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package androidx.xr.glimmer import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.focusable import androidx.compose.foundation.interaction.MutableInteractionSource 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.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.dp /** * ListItem is a component used to represent a single item in a * [androidx.xr.glimmer.list.GlimmerLazyColumn]. A ListItem has a primary label [content], and may * also have any combination of [supportingLabel], [leadingIcon], and [trailingIcon]. The supporting * label is displayed below the primary label and can be used to provide additional information. A * ListItem fills the maximum width available by default. * * This ListItem is focusable - see the other [ListItem] overload for a clickable ListItem. * * A simple ListItem with just a primary label: * * @sample androidx.xr.glimmer.samples.ListItemSample * * A ListItem with a primary and supporting label: * * @sample androidx.xr.glimmer.samples.ListItemWithSupportingLabelSample * * A ListItem with a primary label, a supporting label, and a leading icon: * * @sample androidx.xr.glimmer.samples.ListItemWithSupportingLabelAndLeadingIconSample * @param modifier the [Modifier] to be applied to this list item * @param supportingLabel optional supporting label to be placed underneath the primary label * [content] * @param leadingIcon optional leading icon to be placed before the primary label [content]. This is * typically an [Icon] tinted with [contentColor] by default. * @param trailingIcon optional trailing icon to be placed after the primary label [content]. This * is typically an [Icon] tinted with [contentColor] by default. * @param shape the [Shape] used to clip this list item, and also used to draw the background and * border * @param color background color of this list item * @param contentColor content color used by components inside [content], [supportingLabel], * [leadingIcon], and [trailingIcon]. * @param border the border to draw around this list item * @param contentPadding the spacing values to apply internally between the container and the * content * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and * emitting Interactions for this list item. You can use this to change the list item's appearance * or preview the list item in different states. Note that if `null` is provided, interactions * will still happen internally. * @param content the main content / primary label to display inside this list item */ @Composable public fun ListItem( modifier: Modifier = Modifier, supportingLabel: @Composable (() -> Unit)? = null, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, shape: Shape = GlimmerTheme.shapes.medium, color: Color = GlimmerTheme.colors.surface, contentColor: Color = calculateContentColor(color), border: BorderStroke? = SurfaceDefaults.border(), contentPadding: PaddingValues = ListItemDefaults.contentPadding, interactionSource: MutableInteractionSource? = null, content: @Composable () -> Unit, ) { ListItemImpl( modifier = modifier, onClick = null, supportingLabel = supportingLabel, leadingIcon = leadingIcon, trailingIcon = trailingIcon, shape = shape, color = color, contentColor = contentColor, border = border, contentPadding = contentPadding, interactionSource = interactionSource, content = content, ) } /** * ListItem is a component used to represent a single item in a * [androidx.xr.glimmer.list.GlimmerLazyColumn]. A ListItem has a primary label [content], and may * also have any combination of [supportingLabel], [leadingIcon], and [trailingIcon]. The supporting * label is displayed below the primary label and can be used to provide additional information. A * ListItem fills the maximum width available by default. * * This ListItem is focusable and clickable - see the other [ListItem] overload for a ListItem that * is only focusable. * * A simple clickable ListItem with just a primary label: * * @sample androidx.xr.glimmer.samples.ClickableListItemSample * * A clickable ListItem with a primary and supporting label: * * @sample androidx.xr.glimmer.samples.ClickableListItemWithSupportingLabelSample * * A clickable ListItem with a primary label, a supporting label, and a leading icon: * * @sample androidx.xr.glimmer.samples.ClickableListItemWithSupportingLabelAndLeadingIconSample * @param onClick called when this list item is clicked * @param modifier the [Modifier] to be applied to this list item * @param supportingLabel optional supporting label to be placed underneath the primary label * [content] * @param leadingIcon optional leading icon to be placed before the primary label [content]. This is * typically an [Icon] tinted with [contentColor] by default. * @param trailingIcon optional trailing icon to be placed after the primary label [content]. This * is typically an [Icon] tinted with [contentColor] by default. * @param shape the [Shape] used to clip this list item, and also used to draw the background and * border * @param color background color of this list item * @param contentColor content color used by components inside [content], [supportingLabel], * [leadingIcon], and [trailingIcon]. * @param border the border to draw around this list item * @param contentPadding the spacing values to apply internally between the container and the * content * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and * emitting Interactions for this list item. You can use this to change the list item's appearance * or preview the list item in different states. Note that if `null` is provided, interactions * will still happen internally. * @param content the main content / primary label to display inside this list item */ @Composable public fun ListItem( onClick: () -> Unit, modifier: Modifier = Modifier, supportingLabel: @Composable (() -> Unit)? = null, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, shape: Shape = GlimmerTheme.shapes.medium, color: Color = GlimmerTheme.colors.surface, contentColor: Color = calculateContentColor(color), border: BorderStroke? = SurfaceDefaults.border(), contentPadding: PaddingValues = ListItemDefaults.contentPadding, interactionSource: MutableInteractionSource? = null, content: @Composable () -> Unit, ) { ListItemImpl( modifier = modifier, onClick = onClick, supportingLabel = supportingLabel, leadingIcon = leadingIcon, trailingIcon = trailingIcon, shape = shape, color = color, contentColor = contentColor, border = border, contentPadding = contentPadding, interactionSource = interactionSource, content = content, ) } @Composable private fun ListItemImpl( modifier: Modifier, onClick: (() -> Unit)?, supportingLabel: @Composable (() -> Unit)?, leadingIcon: @Composable (() -> Unit)?, trailingIcon: @Composable (() -> Unit)?, shape: Shape, color: Color, contentColor: Color, border: BorderStroke?, contentPadding: PaddingValues, interactionSource: MutableInteractionSource?, content: @Composable () -> Unit, ) { val iconSize = GlimmerTheme.iconSizes.large val typography = GlimmerTheme.typography val innerPadding = GlimmerTheme.componentSpacingValues.small val depthEffect = SurfaceDepthEffect( depthEffect = null, focusedDepthEffect = GlimmerTheme.depthEffectLevels.level4, ) val internalInteractionSource = interactionSource ?: remember { MutableInteractionSource() } val surfaceModifier = Modifier.surface( shape = shape, color = color, contentColor = contentColor, depthEffect = depthEffect, border = border, interactionSource = internalInteractionSource, ) .then( if (onClick != null) { Modifier.clickable( interactionSource = internalInteractionSource, onClick = onClick, ) } else { Modifier.focusable(interactionSource = internalInteractionSource) } ) Row( modifier = modifier .then(surfaceModifier) .fillMaxWidth() .defaultMinSize(minHeight = MinimumHeight) .padding(contentPadding), verticalAlignment = CenterVertically, ) { if (leadingIcon != null) { Box(modifier = Modifier.align(Alignment.Top), contentAlignment = Alignment.TopStart) { CompositionLocalProvider(LocalIconSize provides iconSize, content = leadingIcon) } } Column(Modifier.weight(1f).padding(horizontal = innerPadding)) { if (supportingLabel == null) { CompositionLocalProvider( LocalTextStyle provides typography.bodySmall, content = content, ) } else { CompositionLocalProvider( LocalTextStyle provides typography.titleSmall, content = content, ) CompositionLocalProvider( LocalTextStyle provides typography.bodySmall, content = supportingLabel, ) } } if (trailingIcon != null) { Box(modifier = Modifier.align(Alignment.Top), contentAlignment = Alignment.TopEnd) { CompositionLocalProvider(LocalIconSize provides iconSize, content = trailingIcon) } } } } /** Default values used for [ListItem] */ public object ListItemDefaults { /** Default content padding used for a [ListItem] */ public val contentPadding: PaddingValues @Composable get() = PaddingValues(GlimmerTheme.componentSpacingValues.large) } /** Default minimum height for a [ListItem] */ private val MinimumHeight = 80.dp