Form icons replace letter avatars in med and lager lists

Seven hand-drawn 24dp vectors (tablet/capsule/liquid/injection/drops/
spray/other) so what-you-take reads at a glance. Icons are decorative;
the rows' merged contentDescription now includes the form label so
TalkBack gains the same information the icon conveys visually.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-06-11 16:50:20 +02:00
commit 747a87a570
10 changed files with 111 additions and 9 deletions

View file

@ -84,11 +84,11 @@ fun InventoryScreen(nav: Nav) {
.clickable { nav.push(Screen.ItemEdit(item.id)) }
.semantics(mergeDescendants = true) {
contentDescription =
"${item.name} ${item.strength}, ${ScheduleText.amountText(item.stockUnits, item.unit)} på lager. Trykk for å redigere."
"${item.name} ${item.strength}, ${FORM_LABELS[item.form]}, ${ScheduleText.amountText(item.stockUnits, item.unit)} på lager. Trykk for å redigere."
},
) {
Row(Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically) {
LetterAvatar(item.name)
FormAvatar(item.form)
Column(Modifier.padding(start = 12.dp).weight(1f)) {
Text("${item.name} ${item.strength}".trim(), style = MaterialTheme.typography.titleMedium)
Text(

View file

@ -73,9 +73,23 @@ fun guessForm(festForm: String): MedForm = when {
fun parseAmount(s: String): Double? = s.trim().replace(',', '.').toDoubleOrNull()
/** Tonal circle with the preparation's initial — cheap visual anchor in lists. */
/** Pharmaceutical-form icon for list rows. */
fun iconForForm(form: MedForm): Int = when (form) {
MedForm.TABLET -> no.naiv.meddetsamme.R.drawable.ic_form_tablet
MedForm.CAPSULE -> no.naiv.meddetsamme.R.drawable.ic_form_capsule
MedForm.LIQUID -> no.naiv.meddetsamme.R.drawable.ic_form_liquid
MedForm.INJECTION -> no.naiv.meddetsamme.R.drawable.ic_form_injection
MedForm.DROPS -> no.naiv.meddetsamme.R.drawable.ic_form_drops
MedForm.SPRAY -> no.naiv.meddetsamme.R.drawable.ic_form_spray
MedForm.OTHER -> no.naiv.meddetsamme.R.drawable.ic_form_other
}
/**
* Tonal circle with the form's icon what-am-I-taking at a glance.
* Decorative: rows carry a full merged contentDescription including the form.
*/
@Composable
fun LetterAvatar(name: String) {
fun FormAvatar(form: MedForm) {
androidx.compose.material3.Surface(
shape = androidx.compose.foundation.shape.CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
@ -83,9 +97,10 @@ fun LetterAvatar(name: String) {
modifier = Modifier.size(40.dp),
) {
Box(contentAlignment = Alignment.Center) {
Text(
name.firstOrNull()?.uppercase() ?: "?",
style = MaterialTheme.typography.titleMedium,
androidx.compose.material3.Icon(
androidx.compose.ui.res.painterResource(iconForForm(form)),
contentDescription = null,
modifier = Modifier.size(22.dp),
)
}
}

View file

@ -80,11 +80,11 @@ fun MedListScreen(nav: Nav) {
.clickable { nav.push(Screen.MedEdit(med.med.id)) }
.semantics(mergeDescendants = true) {
contentDescription =
"${med.displayName}, lager ${ScheduleText.amountText(med.item.stockUnits, med.item.unit)}. Trykk for å redigere."
"${med.displayName}, ${FORM_LABELS[med.item.form]}, lager ${ScheduleText.amountText(med.item.stockUnits, med.item.unit)}. Trykk for å redigere."
},
) {
Row(Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically) {
LetterAvatar(med.item.name)
FormAvatar(med.item.form)
Column(Modifier.padding(start = 12.dp).weight(1f)) {
Text(med.displayName, style = MaterialTheme.typography.titleMedium)
Text(