diff --git a/gravatar-ui/src/main/java/com/gravatar/ui/GravatarTheme.kt b/gravatar-ui/src/main/java/com/gravatar/ui/GravatarTheme.kt new file mode 100644 index 00000000..8e6ca3dd --- /dev/null +++ b/gravatar-ui/src/main/java/com/gravatar/ui/GravatarTheme.kt @@ -0,0 +1,57 @@ +package com.gravatar.ui + +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Shapes +import androidx.compose.material3.Typography +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ProvidableCompositionLocal +import androidx.compose.runtime.staticCompositionLocalOf + +/** + * [GravatarTheme] is a composable that wraps the content of the application with the Gravatar theme. + */ +@Composable +public fun GravatarTheme(content: @Composable () -> Unit) { + MaterialTheme( + colorScheme = gravatarTheme.colorScheme, + typography = gravatarTheme.typography, + shapes = gravatarTheme.shapes, + ) { + content() + } +} + +/** + * [GravatarTheme] contains the colors, typography, and shapes to be used in the Gravatar UI components. + * Those values follow the Gravatar style guide but can be customized by the user. + * In order to customize the theme, the user can provide a custom [GravatarTheme] using [Composition Local](https://developer.android.com/develop/ui/compose/compositionlocal) + * + * [colorScheme] The color scheme to be used in the Gravatar UI components + * [typography] The typography to be used in the Gravatar UI components + * [shapes] The shapes to be used in the Gravatar UI components + */ +public interface GravatarTheme { + public val colorScheme: ColorScheme + @Composable + get() = MaterialTheme.colorScheme + + public val typography: Typography + @Composable + get() = MaterialTheme.typography + + public val shapes: Shapes + @Composable + get() = MaterialTheme.shapes +} + +/** + * [LocalGravatarTheme] is a CompositionLocal that provides the current [GravatarTheme]. + */ +public val LocalGravatarTheme: ProvidableCompositionLocal = + staticCompositionLocalOf { object : GravatarTheme {} } + +/** The current [GravatarTheme]. */ +public val gravatarTheme: GravatarTheme + @Composable + get() = LocalGravatarTheme.current diff --git a/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfile.kt b/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfile.kt index 2703a16f..76216940 100644 --- a/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfile.kt +++ b/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfile.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.unit.dp import com.gravatar.api.models.Account import com.gravatar.api.models.Email import com.gravatar.api.models.UserProfile +import com.gravatar.ui.GravatarTheme import com.gravatar.ui.components.atomic.AboutMe import com.gravatar.ui.components.atomic.Avatar import com.gravatar.ui.components.atomic.DisplayName @@ -31,26 +32,28 @@ import com.gravatar.ui.components.atomic.ViewProfileButton */ @Composable public fun LargeProfile(profile: UserProfile, modifier: Modifier = Modifier) { - Column( - modifier = modifier, - ) { - Avatar( - profile = profile, - size = 132.dp, - modifier = Modifier.clip(CircleShape), - ) - DisplayName(profile, modifier = Modifier.padding(top = 16.dp)) - UserInfo(profile) - AboutMe(profile, modifier = Modifier.padding(top = 8.dp)) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = 4.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, + GravatarTheme { + Column( + modifier = modifier, ) { - SocialIconRow(profile, maxIcons = 4) - ViewProfileButton(profile, Modifier.padding(0.dp)) + Avatar( + profile = profile, + size = 132.dp, + modifier = Modifier.clip(CircleShape), + ) + DisplayName(profile, modifier = Modifier.padding(top = 16.dp)) + UserInfo(profile) + AboutMe(profile, modifier = Modifier.padding(top = 8.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 4.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + SocialIconRow(profile, maxIcons = 4) + ViewProfileButton(profile, Modifier.padding(0.dp)) + } } } } diff --git a/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfileSummary.kt b/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfileSummary.kt index 04a184fe..be127b2b 100644 --- a/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfileSummary.kt +++ b/gravatar-ui/src/main/java/com/gravatar/ui/components/LargeProfileSummary.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.unit.dp import com.gravatar.api.models.Account import com.gravatar.api.models.Email import com.gravatar.api.models.UserProfile +import com.gravatar.ui.GravatarTheme import com.gravatar.ui.components.atomic.Avatar import com.gravatar.ui.components.atomic.DisplayName import com.gravatar.ui.components.atomic.UserInfo @@ -29,24 +30,26 @@ import com.gravatar.ui.components.atomic.ViewProfileButton */ @Composable public fun LargeProfileSummary(profile: UserProfile, modifier: Modifier = Modifier) { - Column( - modifier = modifier, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Avatar( - profile = profile, - size = 132.dp, - modifier = Modifier.clip(CircleShape), - ) - DisplayName(profile, modifier = Modifier.padding(top = 16.dp)) - UserInfo( - profile, - textStyle = MaterialTheme.typography.bodyMedium.copy( - color = MaterialTheme.colorScheme.outline, - textAlign = TextAlign.Center, - ), - ) - ViewProfileButton(profile, Modifier.padding(0.dp), inlineContent = null) + GravatarTheme { + Column( + modifier = modifier, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Avatar( + profile = profile, + size = 132.dp, + modifier = Modifier.clip(CircleShape), + ) + DisplayName(profile, modifier = Modifier.padding(top = 16.dp)) + UserInfo( + profile, + textStyle = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.outline, + textAlign = TextAlign.Center, + ), + ) + ViewProfileButton(profile, Modifier.padding(0.dp), inlineContent = null) + } } } diff --git a/gravatar-ui/src/main/java/com/gravatar/ui/components/MiniProfileCard.kt b/gravatar-ui/src/main/java/com/gravatar/ui/components/MiniProfileCard.kt index 47edc6fd..271b257b 100644 --- a/gravatar-ui/src/main/java/com/gravatar/ui/components/MiniProfileCard.kt +++ b/gravatar-ui/src/main/java/com/gravatar/ui/components/MiniProfileCard.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.gravatar.api.models.UserProfile +import com.gravatar.ui.GravatarTheme import com.gravatar.ui.components.atomic.Avatar import com.gravatar.ui.components.atomic.DisplayName import com.gravatar.ui.components.atomic.Location @@ -27,21 +28,26 @@ import com.gravatar.ui.components.atomic.ViewProfileButton */ @Composable public fun MiniProfileCard(profile: UserProfile, modifier: Modifier = Modifier) { - Row(modifier = modifier) { - Avatar( - profile = profile, - size = 72.dp, - modifier = Modifier.clip(CircleShape), - ) - Column(modifier = Modifier.padding(start = 14.dp)) { - DisplayName(profile, textStyle = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)) - if (!profile.currentLocation.isNullOrBlank()) { - Location(profile) - } - ViewProfileButton( - profile, - modifier = Modifier.height(32.dp), + GravatarTheme { + Row(modifier = modifier) { + Avatar( + profile = profile, + size = 72.dp, + modifier = Modifier.clip(CircleShape), ) + Column(modifier = Modifier.padding(start = 14.dp)) { + DisplayName( + profile, + textStyle = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold), + ) + if (!profile.currentLocation.isNullOrBlank()) { + Location(profile) + } + ViewProfileButton( + profile, + modifier = Modifier.height(32.dp), + ) + } } } } diff --git a/gravatar-ui/src/main/java/com/gravatar/ui/components/ProfileCard.kt b/gravatar-ui/src/main/java/com/gravatar/ui/components/ProfileCard.kt index 3029a2f4..ea292dbe 100644 --- a/gravatar-ui/src/main/java/com/gravatar/ui/components/ProfileCard.kt +++ b/gravatar-ui/src/main/java/com/gravatar/ui/components/ProfileCard.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.unit.dp import com.gravatar.api.models.Account import com.gravatar.api.models.Email import com.gravatar.api.models.UserProfile +import com.gravatar.ui.GravatarTheme import com.gravatar.ui.components.atomic.AboutMe import com.gravatar.ui.components.atomic.Avatar import com.gravatar.ui.components.atomic.DisplayName @@ -35,35 +36,37 @@ import com.gravatar.ui.components.atomic.ViewProfileButton */ @Composable public fun ProfileCard(profile: UserProfile, modifier: Modifier = Modifier) { - Column( - modifier = modifier, - horizontalAlignment = Alignment.Start, - verticalArrangement = Arrangement.Top, - ) { - Row { - Avatar( - profile = profile, - size = 72.dp, - modifier = Modifier.clip(CircleShape), - ) - Column(modifier = Modifier.padding(14.dp, 0.dp, 0.dp, 0.dp)) { - DisplayName( - profile, - textStyle = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold), + GravatarTheme { + Column( + modifier = modifier, + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Top, + ) { + Row { + Avatar( + profile = profile, + size = 72.dp, + modifier = Modifier.clip(CircleShape), ) - UserInfo(profile) + Column(modifier = Modifier.padding(14.dp, 0.dp, 0.dp, 0.dp)) { + DisplayName( + profile, + textStyle = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold), + ) + UserInfo(profile) + } + } + Spacer(modifier = Modifier.height(16.dp)) + AboutMe(profile) + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + SocialIconRow(profile, maxIcons = 4) + ViewProfileButton(profile, Modifier.padding(0.dp)) } - } - Spacer(modifier = Modifier.height(16.dp)) - AboutMe(profile) - Spacer(modifier = Modifier.height(4.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - SocialIconRow(profile, maxIcons = 4) - ViewProfileButton(profile, Modifier.padding(0.dp)) } } }