refactor(home): extract shared card kit -> components/HomeActionStyle.kt

Step 1/9 of the HomeScreen decomposition. Moves the 6 shared style decls
(homeActionGlyph, HomeGlyphIcon, homePrimaryArt, HomeActionColors,
HomeActionTone.actionColors, HomePill) verbatim into ui/home/components/, made
public per the components/ visibility idiom. No behavior change. compileDebugKotlin green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
null 2026-07-11 19:26:08 -05:00
parent 047185134e
commit 5f39194c00
2 changed files with 168 additions and 140 deletions

View File

@ -87,6 +87,12 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.hilt.navigation.compose.hiltViewModel
import app.closer.R
import app.closer.ui.home.components.HomeActionColors
import app.closer.ui.home.components.HomeGlyphIcon
import app.closer.ui.home.components.HomePill
import app.closer.ui.home.components.actionColors
import app.closer.ui.home.components.homeActionGlyph
import app.closer.ui.home.components.homePrimaryArt
@Composable
fun HomeScreen(
@ -411,37 +417,6 @@ private fun HomeContent(
}
}
@DrawableRes
private fun homeActionGlyph(target: HomeActionTarget): Int = when (target) {
HomeActionTarget.InvitePartner -> R.drawable.glyph_couple
HomeActionTarget.DailyQuestion -> R.drawable.glyph_daily_card
HomeActionTarget.AnswerHistory -> R.drawable.glyph_paired_cards
HomeActionTarget.QuestionPacks -> R.drawable.glyph_question_packs
HomeActionTarget.Settings -> R.drawable.glyph_settings
HomeActionTarget.AnswerReveal -> R.drawable.glyph_sealed_answer
HomeActionTarget.Game -> R.drawable.glyph_closer_heart_keyhole
HomeActionTarget.Challenge -> R.drawable.glyph_connection_challenge
HomeActionTarget.DatePlan -> R.drawable.glyph_date_card_heart
HomeActionTarget.MemoryCapsule -> R.drawable.glyph_memory_capsule
HomeActionTarget.DateMemories -> R.drawable.glyph_date_replay
HomeActionTarget.WeeklyRecap -> R.drawable.glyph_paired_cards
}
@Composable
private fun HomeGlyphIcon(
@DrawableRes resId: Int,
contentDescription: String?,
tint: Color,
modifier: Modifier = Modifier
) {
Icon(
imageVector = ImageVector.vectorResource(resId),
contentDescription = contentDescription,
tint = tint,
modifier = modifier
)
}
@Composable
private fun HomeStatusStrip(
streakCount: Int,
@ -1201,14 +1176,6 @@ private fun PrimaryHomeActionCard(
}
}
@DrawableRes
private fun homePrimaryArt(target: HomeActionTarget): Int? = when (target) {
HomeActionTarget.DailyQuestion,
HomeActionTarget.AnswerReveal -> R.drawable.illustration_home_tonight_ritual
HomeActionTarget.Challenge -> R.drawable.illustration_connection_challenges_header
else -> null
}
@Composable
private fun ActionFeedSection(
actions: List<HomeAction>,
@ -1343,94 +1310,6 @@ private fun MomentCueCard() {
}
}
private data class HomeActionColors(
val soft: Color,
val accent: Color,
val deep: Color,
val onAccent: Color
)
@Composable
private fun HomeActionTone.actionColors(): HomeActionColors {
val scheme = MaterialTheme.colorScheme
if (isCloserDarkTheme()) {
return when (this) {
HomeActionTone.Daily,
HomeActionTone.Ritual,
HomeActionTone.Starter,
HomeActionTone.Pack -> HomeActionColors(
soft = scheme.secondaryContainer,
accent = scheme.secondary,
deep = scheme.secondary,
onAccent = scheme.onSecondary
)
HomeActionTone.Reflection -> HomeActionColors(
soft = scheme.tertiaryContainer,
accent = scheme.tertiary,
deep = scheme.tertiary,
onAccent = scheme.onTertiary
)
else -> HomeActionColors(
soft = scheme.primaryContainer,
accent = scheme.primary,
deep = scheme.primary,
onAccent = scheme.onPrimary
)
}
}
return when (this) {
HomeActionTone.Invite -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = MaterialTheme.colorScheme.primary,
deep = CloserPalette.PurpleDeep,
onAccent = MaterialTheme.colorScheme.onPrimary
)
HomeActionTone.Daily -> HomeActionColors(
soft = CloserPalette.PinkSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Reflection -> HomeActionColors(
soft = CloserPalette.PurpleGlow,
accent = CloserPalette.PurpleRich,
deep = CloserPalette.PurpleDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Ritual -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Starter -> HomeActionColors(
soft = CloserPalette.PinkSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Pack -> HomeActionColors(
soft = CloserPalette.PinkSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Utility -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = MaterialTheme.colorScheme.primary,
deep = CloserPalette.PurpleDeep,
onAccent = MaterialTheme.colorScheme.onPrimary
)
HomeActionTone.Pending -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = MaterialTheme.colorScheme.primary,
deep = CloserPalette.PurpleDeep,
onAccent = MaterialTheme.colorScheme.onPrimary
)
}
}
@Composable
private fun CategoryPreviewGrid(
categories: List<HomeCategorySummary>,
@ -1664,19 +1543,6 @@ private fun EmptyHomeContent(
}
}
@Composable
private fun HomePill(label: String) {
CloserPill(
label = label,
containerColor = if (isCloserDarkTheme()) {
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.78f)
} else {
CloserPalette.PinkMist.copy(alpha = 0.72f)
},
contentColor = MaterialTheme.colorScheme.onSurface
)
}
@Preview
@Composable
fun HomeScreenPreview() {

View File

@ -0,0 +1,162 @@
package app.closer.ui.home.components
import androidx.annotation.DrawableRes
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import app.closer.R
import app.closer.ui.components.CloserPill
import app.closer.ui.home.HomeActionTarget
import app.closer.ui.home.HomeActionTone
import app.closer.ui.theme.CloserPalette
import app.closer.ui.theme.isCloserDarkTheme
/**
* Shared low-level style kit for the Home cards glyph/art resolution, the icon wrapper, the pill,
* and the per-tone color set. Extracted from HomeScreen.kt so every Home component cluster
* (`HomePrimaryCards`, `HomeStatusStrip`, `HomeActionFeed`, ) can reuse it. Pure/theme-only, no state.
*/
@DrawableRes
fun homeActionGlyph(target: HomeActionTarget): Int = when (target) {
HomeActionTarget.InvitePartner -> R.drawable.glyph_couple
HomeActionTarget.DailyQuestion -> R.drawable.glyph_daily_card
HomeActionTarget.AnswerHistory -> R.drawable.glyph_paired_cards
HomeActionTarget.QuestionPacks -> R.drawable.glyph_question_packs
HomeActionTarget.Settings -> R.drawable.glyph_settings
HomeActionTarget.AnswerReveal -> R.drawable.glyph_sealed_answer
HomeActionTarget.Game -> R.drawable.glyph_closer_heart_keyhole
HomeActionTarget.Challenge -> R.drawable.glyph_connection_challenge
HomeActionTarget.DatePlan -> R.drawable.glyph_date_card_heart
HomeActionTarget.MemoryCapsule -> R.drawable.glyph_memory_capsule
HomeActionTarget.DateMemories -> R.drawable.glyph_date_replay
HomeActionTarget.WeeklyRecap -> R.drawable.glyph_paired_cards
}
@Composable
fun HomeGlyphIcon(
@DrawableRes resId: Int,
contentDescription: String?,
tint: Color,
modifier: Modifier = Modifier
) {
Icon(
imageVector = ImageVector.vectorResource(resId),
contentDescription = contentDescription,
tint = tint,
modifier = modifier
)
}
@DrawableRes
fun homePrimaryArt(target: HomeActionTarget): Int? = when (target) {
HomeActionTarget.DailyQuestion,
HomeActionTarget.AnswerReveal -> R.drawable.illustration_home_tonight_ritual
HomeActionTarget.Challenge -> R.drawable.illustration_connection_challenges_header
else -> null
}
data class HomeActionColors(
val soft: Color,
val accent: Color,
val deep: Color,
val onAccent: Color
)
@Composable
fun HomeActionTone.actionColors(): HomeActionColors {
val scheme = MaterialTheme.colorScheme
if (isCloserDarkTheme()) {
return when (this) {
HomeActionTone.Daily,
HomeActionTone.Ritual,
HomeActionTone.Starter,
HomeActionTone.Pack -> HomeActionColors(
soft = scheme.secondaryContainer,
accent = scheme.secondary,
deep = scheme.secondary,
onAccent = scheme.onSecondary
)
HomeActionTone.Reflection -> HomeActionColors(
soft = scheme.tertiaryContainer,
accent = scheme.tertiary,
deep = scheme.tertiary,
onAccent = scheme.onTertiary
)
else -> HomeActionColors(
soft = scheme.primaryContainer,
accent = scheme.primary,
deep = scheme.primary,
onAccent = scheme.onPrimary
)
}
}
return when (this) {
HomeActionTone.Invite -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = MaterialTheme.colorScheme.primary,
deep = CloserPalette.PurpleDeep,
onAccent = MaterialTheme.colorScheme.onPrimary
)
HomeActionTone.Daily -> HomeActionColors(
soft = CloserPalette.PinkSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Reflection -> HomeActionColors(
soft = CloserPalette.PurpleGlow,
accent = CloserPalette.PurpleRich,
deep = CloserPalette.PurpleDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Ritual -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Starter -> HomeActionColors(
soft = CloserPalette.PinkSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Pack -> HomeActionColors(
soft = CloserPalette.PinkSoft,
accent = CloserPalette.PinkBright,
deep = CloserPalette.PinkAccentDeep,
onAccent = Color(0xFF24122F)
)
HomeActionTone.Utility -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = MaterialTheme.colorScheme.primary,
deep = CloserPalette.PurpleDeep,
onAccent = MaterialTheme.colorScheme.onPrimary
)
HomeActionTone.Pending -> HomeActionColors(
soft = CloserPalette.PurpleSoft,
accent = MaterialTheme.colorScheme.primary,
deep = CloserPalette.PurpleDeep,
onAccent = MaterialTheme.colorScheme.onPrimary
)
}
}
@Composable
fun HomePill(label: String) {
CloserPill(
label = label,
containerColor = if (isCloserDarkTheme()) {
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.78f)
} else {
CloserPalette.PinkMist.copy(alpha = 0.72f)
},
contentColor = MaterialTheme.colorScheme.onSurface
)
}