feat: add visible edit affordances to clickable cards (Closes #143) (#145)

This commit was merged in pull request #145.
This commit is contained in:
2026-04-06 17:43:32 +02:00
parent 8a0625dc3e
commit c17adb4936
5 changed files with 79 additions and 14 deletions
@@ -169,6 +169,10 @@
<string name="language_expert">Expert</string>
<string name="language_native">Native</string>
<!-- Edit affordances -->
<string name="edit_content_desc">Tap to edit</string>
<string name="resource_edit_hint">Tap Character Header above to edit</string>
<!-- Dice roll content descriptions -->
<string name="roll_dice_content_desc">Roll dice</string>
@@ -2,6 +2,8 @@ package org.shahondin1624.lib.components.charactermodel
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -39,9 +41,22 @@ fun CharacterHeader(
else Modifier
)
) {
when (windowSizeClass) {
WindowSizeClass.Compact -> CompactHeader(characterData, spacing)
WindowSizeClass.Medium, WindowSizeClass.Expanded -> ExpandedHeader(characterData, spacing)
Box(modifier = Modifier.fillMaxWidth()) {
when (windowSizeClass) {
WindowSizeClass.Compact -> CompactHeader(characterData, spacing)
WindowSizeClass.Medium, WindowSizeClass.Expanded -> ExpandedHeader(characterData, spacing)
}
if (onEdit != null) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(Res.string.edit_content_desc),
modifier = Modifier
.align(Alignment.TopEnd)
.padding(8.dp)
.size(20.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
@@ -110,9 +125,10 @@ private fun ExpandedHeader(characterData: CharacterData, spacing: androidx.compo
color = MaterialTheme.colorScheme.onSurfaceVariant
)
// Right: Age and gender
// Right: Age and gender (add right padding to avoid overlapping edit icon)
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp)
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.padding(end = 28.dp)
) {
DetailChip(label = stringResource(Res.string.label_age), value = characterData.age.toString())
DetailChip(label = stringResource(Res.string.label_gender), value = characterData.gender)
@@ -9,6 +9,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.shahondin1624.lib.components.TestTags
import org.shahondin1624.lib.components.UiConstants
@@ -34,9 +35,25 @@ fun ResourcePanel(characterData: CharacterData, edge: Int) {
.fillMaxWidth()
.testTag(TestTags.PANEL_RESOURCES)
) {
when (windowSizeClass) {
WindowSizeClass.Compact -> CompactResources(characterData, edge, spacing)
WindowSizeClass.Medium, WindowSizeClass.Expanded -> ExpandedResources(characterData, edge, spacing)
Column {
when (windowSizeClass) {
WindowSizeClass.Compact -> CompactResources(characterData, edge, spacing)
WindowSizeClass.Medium, WindowSizeClass.Expanded -> ExpandedResources(
characterData,
edge,
spacing
)
}
// Hint text pointing users to the Character Header for editing
Text(
text = stringResource(Res.string.resource_edit_hint),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 6.dp)
)
}
}
}
@@ -4,8 +4,11 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -49,14 +52,14 @@ fun Attribute(
modifier = cardModifier,
elevation = elevation
) {
AttributeCardContent(attribute, textColor, onRoll)
AttributeCardContent(attribute, textColor, onRoll, showEditIcon = true)
}
} else {
Card(
modifier = cardModifier,
elevation = elevation
) {
AttributeCardContent(attribute, textColor, onRoll)
AttributeCardContent(attribute, textColor, onRoll, showEditIcon = false)
}
}
}
@@ -65,13 +68,24 @@ fun Attribute(
private fun AttributeCardContent(
attribute: Attribute,
textColor: Color,
onRoll: (DiceRoll) -> Unit
onRoll: (DiceRoll) -> Unit,
showEditIcon: Boolean
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
modifier = Modifier.fillMaxWidth()
) {
if (showEditIcon) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(Res.string.edit_content_desc),
modifier = Modifier
.padding(start = SMALL_PADDING)
.size(16.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Row(
modifier = Modifier
.weight(1f)
@@ -9,10 +9,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -62,14 +65,14 @@ fun Talent(
modifier = cardModifier,
elevation = elevation
) {
TalentCardContent(talent, attributes, textColor, onRoll)
TalentCardContent(talent, attributes, textColor, onRoll, showEditIcon = true)
}
} else {
Card(
modifier = cardModifier,
elevation = elevation
) {
TalentCardContent(talent, attributes, textColor, onRoll)
TalentCardContent(talent, attributes, textColor, onRoll, showEditIcon = false)
}
}
}
@@ -79,7 +82,8 @@ private fun TalentCardContent(
talent: TalentDefinition,
attributes: Attributes,
textColor: Color,
onRoll: (DiceRoll) -> Unit
onRoll: (DiceRoll) -> Unit,
showEditIcon: Boolean
) {
var showSpecMenu by remember { mutableStateOf(false) }
val hasSpec = talent.specialization != null
@@ -89,6 +93,16 @@ private fun TalentCardContent(
horizontalArrangement = Arrangement.Start,
modifier = Modifier.fillMaxWidth()
) {
if (showEditIcon) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(Res.string.edit_content_desc),
modifier = Modifier
.padding(start = SMALL_PADDING)
.size(16.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Row(
modifier = Modifier
.weight(1f)