feat: character header showing identity info (Closes #9) (#55)

This commit was merged in pull request #55.
This commit is contained in:
2026-03-13 13:25:11 +01:00
parent a6c5e2a2f9
commit 6af4120959
2 changed files with 145 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ import kotlinx.coroutines.launch
import org.jetbrains.compose.ui.tooling.preview.Preview
import org.shahondin1624.lib.components.TestTags
import org.shahondin1624.lib.components.UiConstants
import org.shahondin1624.lib.components.charactermodel.CharacterHeader
import org.shahondin1624.lib.components.charactermodel.attributespage.AttributesPage
import org.shahondin1624.lib.components.settings.SettingsPage
import org.shahondin1624.model.EXAMPLE_CHARACTER
@@ -305,6 +306,8 @@ private fun MainScaffold(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
CharacterHeader(EXAMPLE_CHARACTER.characterData)
Spacer(Modifier.height(contentPadding))
AttributesPage(EXAMPLE_CHARACTER)
}
}

View File

@@ -0,0 +1,142 @@
package org.shahondin1624.lib.components.charactermodel
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
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.unit.dp
import org.shahondin1624.lib.components.TestTags
import org.shahondin1624.lib.components.UiConstants
import org.shahondin1624.model.characterdata.CharacterData
import org.shahondin1624.theme.LocalWindowSizeClass
import org.shahondin1624.theme.WindowSizeClass
/**
* Character identity header showing name, metatype, concept, age, and gender.
* Stacks vertically on Compact, horizontal row on Expanded.
*/
@Composable
fun CharacterHeader(characterData: CharacterData) {
val windowSizeClass = LocalWindowSizeClass.current
val spacing = UiConstants.Spacing.medium(windowSizeClass)
Card(
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.PANEL_CHARACTER_HEADER)
) {
when (windowSizeClass) {
WindowSizeClass.Compact -> CompactHeader(characterData, spacing)
WindowSizeClass.Medium, WindowSizeClass.Expanded -> ExpandedHeader(characterData, spacing)
}
}
}
@Composable
private fun CompactHeader(characterData: CharacterData, spacing: androidx.compose.ui.unit.Dp) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(spacing),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = characterData.name,
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold
)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
MetatypeBadge(characterData.metatype.name)
Text(
text = characterData.concept,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
DetailChip(label = "Age", value = characterData.age.toString())
DetailChip(label = "Gender", value = characterData.gender)
}
}
}
@Composable
private fun ExpandedHeader(characterData: CharacterData, spacing: androidx.compose.ui.unit.Dp) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(spacing),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// Left: Name and metatype
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = characterData.name,
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold
)
MetatypeBadge(characterData.metatype.name)
}
// Center: Concept
Text(
text = characterData.concept,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
// Right: Age and gender
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
DetailChip(label = "Age", value = characterData.age.toString())
DetailChip(label = "Gender", value = characterData.gender)
}
}
}
@Composable
private fun MetatypeBadge(metatype: String) {
Surface(
shape = MaterialTheme.shapes.small,
color = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
) {
Text(
text = metatype,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.Medium
)
}
}
@Composable
private fun DetailChip(label: String, value: String) {
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "$label:",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = value,
style = MaterialTheme.typography.bodySmall,
fontWeight = FontWeight.Medium
)
}
}