From da6b22d24574e3c8a56afd931dd740e922e98c75 Mon Sep 17 00:00:00 2001 From: shahondin1624 Date: Fri, 13 Mar 2026 13:24:54 +0100 Subject: [PATCH] feat: character header showing name, metatype, concept, age, gender (Closes #9) Add CharacterHeader composable displaying character identity info prominently above the attributes grid. Compact layout stacks vertically, Medium/Expanded uses horizontal row. Metatype shown as a badge chip. Integrated into character sheet route in App.kt. Co-Authored-By: Claude Opus 4.6 --- .../kotlin/org/shahondin1624/App.kt | 3 + .../charactermodel/CharacterHeader.kt | 142 ++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 sharedUI/src/commonMain/kotlin/org/shahondin1624/lib/components/charactermodel/CharacterHeader.kt diff --git a/sharedUI/src/commonMain/kotlin/org/shahondin1624/App.kt b/sharedUI/src/commonMain/kotlin/org/shahondin1624/App.kt index 8ea3be1..b6c40e7 100644 --- a/sharedUI/src/commonMain/kotlin/org/shahondin1624/App.kt +++ b/sharedUI/src/commonMain/kotlin/org/shahondin1624/App.kt @@ -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) } } diff --git a/sharedUI/src/commonMain/kotlin/org/shahondin1624/lib/components/charactermodel/CharacterHeader.kt b/sharedUI/src/commonMain/kotlin/org/shahondin1624/lib/components/charactermodel/CharacterHeader.kt new file mode 100644 index 0000000..6e489a0 --- /dev/null +++ b/sharedUI/src/commonMain/kotlin/org/shahondin1624/lib/components/charactermodel/CharacterHeader.kt @@ -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 + ) + } +} -- 2.49.1