fix(icons): render MaterialSymbol Icons that rely on defaultMinSize

The Canvas-based MaterialSymbol Icon collapsed to 0x0 whenever callers
didn't pass an explicit size modifier (e.g. ArrowBackIcon, ClearTextIcon).

Canvas is a Spacer + drawBehind, and Spacer's measure policy only uses
maxWidth/maxHeight when the incoming constraints are fixed. Inside an
IconButton (state layer 40dp, content constraints 0..40), defaultMinSize
only lifts minWidth/minHeight, leaving the constraints unfixed - so
Spacer picked 0x0 and the glyph never drew. Icons that passed
Modifier.size(N.dp) worked only because size(...) produces fixed
constraints.

Swap Canvas for an empty Box with drawBehind. Box's EmptyBoxMeasurePolicy
uses minWidth/minHeight, so defaultMinSize(24, 24) now takes effect when
no size modifier is supplied - matching Material3's own Icon behavior.

https://claude.ai/code/session_01V9esGUFH72ujCQNWCAnjKN
This commit is contained in:
Claude
2026-04-24 02:00:11 +00:00
parent 81819b6fbe
commit 6a9e0a79a6
@@ -20,11 +20,12 @@
*/
package com.vitorpamplona.amethyst.commons.icons.symbols
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.scale
@@ -66,32 +67,32 @@ fun Icon(
Modifier
}
Canvas(
Box(
modifier =
modifier
.defaultMinSize(IconDefaultSize, IconDefaultSize)
.then(semanticsModifier),
) {
val sizePx = size.minDimension
val fontSize = with(density) { sizePx.toSp() }
val layout =
textMeasurer.measure(
text = symbol.glyph,
style =
TextStyle(
fontFamily = fontFamily,
fontSize = fontSize,
color = tint,
),
)
val tx = (size.width - layout.size.width) / 2f
val ty = (size.height - layout.size.height) / 2f
if (mirror) {
scale(scaleX = -1f, scaleY = 1f, pivot = Offset(size.width / 2f, size.height / 2f)) {
translate(tx, ty) { drawText(layout) }
}
} else {
translate(tx, ty) { drawText(layout) }
}
}
.drawBehind {
val sizePx = size.minDimension
val fontSize = with(density) { sizePx.toSp() }
val layout =
textMeasurer.measure(
text = symbol.glyph,
style =
TextStyle(
fontFamily = fontFamily,
fontSize = fontSize,
color = tint,
),
)
val tx = (size.width - layout.size.width) / 2f
val ty = (size.height - layout.size.height) / 2f
if (mirror) {
scale(scaleX = -1f, scaleY = 1f, pivot = Offset(size.width / 2f, size.height / 2f)) {
translate(tx, ty) { drawText(layout) }
}
} else {
translate(tx, ty) { drawText(layout) }
}
}.then(semanticsModifier),
)
}