Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7234747
title font
panasetskaya Aug 4, 2026
778590b
blur only for light mode
panasetskaya Aug 4, 2026
b567347
change toolbar icons
panasetskaya Aug 4, 2026
3d186a3
sheet border
panasetskaya Aug 4, 2026
9fda8c4
member reminders border
panasetskaya Aug 5, 2026
84cd769
spacers
panasetskaya Aug 5, 2026
31d4ddf
liquid button v1
panasetskaya Aug 5, 2026
0d9000d
add white rim
panasetskaya Aug 5, 2026
5599c8c
separate liquid glass, apply to toolbar icons
panasetskaya Aug 5, 2026
9d37968
change rimSheen a little bit
panasetskaya Aug 5, 2026
d87ccd4
feature-home: edit-insurance tile, home-specific copy keys, offers pr…
StylianosGakis Aug 5, 2026
094ccc1
Merge branch 'feat/home-screen-ui-adjust' of github.com:/HedvigInsura…
StylianosGakis Aug 5, 2026
27319fa
feature-home: gate Edit insurance tile on change-tier eligibility
StylianosGakis Aug 5, 2026
d8c1c87
cross-sells: honor section buttonText in the discounts path
StylianosGakis Aug 5, 2026
4d2ea84
feature-home: drop the vestigial isHelpCenterEnabled interface property
StylianosGakis Aug 5, 2026
d7dc3f4
feature-home: gate all quick-action tiles on member eligibility
StylianosGakis Aug 5, 2026
63e20f8
docs: design for Home quick-action tiles mirroring the Help Center
StylianosGakis Aug 5, 2026
f5e6dd5
docs: implementation plan for Home quick-actions mirroring Help Center
StylianosGakis Aug 5, 2026
b0809c5
member-quick-actions: scaffold shared module and move member-actions …
StylianosGakis Aug 5, 2026
a0929cf
member-quick-actions: move MemberAction + GetMemberActionsUseCase int…
StylianosGakis Aug 5, 2026
0511063
member-quick-actions: move QuickAction/QuickLinkDestination + builder…
StylianosGakis Aug 5, 2026
6849f50
feature-help-center: consume member-quick-actions shared module
StylianosGakis Aug 5, 2026
54e7e1b
feature-home: source quick-action tiles from the shared member use case
StylianosGakis Aug 5, 2026
d85b44a
member-quick-actions: harden toNavKey and tidy quick-link wiring
StylianosGakis Aug 6, 2026
183748d
Merge branch 'develop' into feature/home-sceren-polish
StylianosGakis Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ dependencies {
implementation(projects.loggingDeviceModel)
implementation(projects.loggingPublic)
implementation(projects.permissionCore)
implementation(projects.memberQuickActions)
implementation(projects.memberRemindersPublic)
implementation(projects.navigationActivity)
implementation(projects.navigationCommon)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ import com.hedvig.android.feature.travelcertificate.navigation.TravelCertificate
import com.hedvig.android.feature.travelcertificate.navigation.travelCertificateEntries
import com.hedvig.android.language.LanguageService
import com.hedvig.android.logger.logcat
import com.hedvig.android.memberquickactions.InnerHelpCenterDestination
import com.hedvig.android.memberquickactions.QuickLinkDestination
import com.hedvig.android.memberquickactions.toNavKey
import com.hedvig.android.navigation.activity.ExternalNavigator
import com.hedvig.android.navigation.common.HedvigNavKey
import com.hedvig.android.navigation.common.TopLevelTab
Expand Down Expand Up @@ -249,7 +252,14 @@ private fun EntryProviderScope<HedvigNavKey>.addHomeEntries(
backstack.add(CoInsuredAddInfoKey(contractId, type))
},
navigateToHelpCenter = { backstack.add(HelpCenterKey) },
navigateToMovingFlow = { navigateToMovingFlow(MovingSource.OTHER) },
navigateToQuickLink = { destination ->
when (destination) {
is QuickLinkDestination.OuterDestination -> backstack.add(destination.toNavKey())

// Inner destinations (FirstVet, SickAbroad) are handled by feature-home before reaching here.
is InnerHelpCenterDestination -> error("Inner quick-link destinations are routed by the feature")
}
},
navigateToClaimChat = { resumeClaim ->
backstack.add(
ClaimChatKey(
Expand All @@ -264,7 +274,6 @@ private fun EntryProviderScope<HedvigNavKey>.addHomeEntries(
openUrl = openUrl,
openCrossSellUrl = openCrossSellUrl,
imageLoader = imageLoader,
navigateToTravelCertificate = navigateToTravelCertificate,
navigateToAddonPurchaseFlow = navigateToAddonPurchaseFlow,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,9 @@
<string name="GENERAL_CHANGE_CONFIRMATION_DESCRIPTION">Din försäkring kommer att uppdateras den %1$s.</string>
<string name="GENERAL_CONFIRM">Bekräfta</string>
<string name="GENERAL_CONTACT_US_TITLE">Kontakta vårt serviceteam</string>
<string name="GENERAL_DISABLED">Inaktiverad</string>
<string name="GENERAL_DOWNLOAD">Ladda ner</string>
<string name="GENERAL_ENABLED">Aktiverad</string>
<string name="GENERAL_INVALID_INPUT">Felaktig inmatning</string>
<string name="GENERAL_NOT_SURE">Vet inte</string>
<string name="GENERAL_RETRY">Försök igen</string>
Expand Down Expand Up @@ -499,8 +501,13 @@
<string name="HC_TOPIC_NOT_FOUND">Topic not found</string>
<string name="HC_TOPIC_NO_QUESTIONS">This topic has no questions</string>
<string name="HEDVIG_NAME_TEXT">Hedvig</string>
<string name="HOME_ADDONS_READ_MORE_BUTTON">Läs mer</string>
<string name="HOME_DISCOVER_SECTION_TITLE">Upptäck våra försäkringar</string>
<string name="HOME_DISCOVER_SEE_PRICE_BUTTON">Se pris</string>
<string name="HOME_GREETING_SUBTITLE">Hur kan vi hjälpa dig?</string>
<string name="HOME_GREETING_TITLE">Hej %1$s</string>
<string name="HOME_QUICK_ACTIONS_CHANGE_ADDRESS">Ändra adress</string>
<string name="HOME_QUICK_ACTIONS_EDIT_INSURANCE">Ändra försäkring</string>
<string name="HOME_QUOTES_SECTION_TITLE">Dina prisförslag</string>
<string name="HOME_TODO_ADD_COINSURED_TITLE">Lägg till medförsäkrad</string>
<string name="HOME_TODO_MISSING_CHIP_ID_TITLE">Chip-ID för husdjur saknas</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,9 @@
<string name="GENERAL_CHANGE_CONFIRMATION_DESCRIPTION">Your insurance will be updated starting from %1$s</string>
<string name="GENERAL_CONFIRM">Confirm</string>
<string name="GENERAL_CONTACT_US_TITLE">Contact our service team</string>
<string name="GENERAL_DISABLED">Disabled</string>
<string name="GENERAL_DOWNLOAD">Download</string>
<string name="GENERAL_ENABLED">Enabled</string>
<string name="GENERAL_INVALID_INPUT">Invalid input</string>
<string name="GENERAL_NOT_SURE">Not sure</string>
<string name="GENERAL_RETRY">Try again</string>
Expand Down Expand Up @@ -499,8 +501,13 @@
<string name="HC_TOPIC_NOT_FOUND">Topic not found</string>
<string name="HC_TOPIC_NO_QUESTIONS">This topic has no questions</string>
<string name="HEDVIG_NAME_TEXT">Hedvig</string>
<string name="HOME_ADDONS_READ_MORE_BUTTON">Read more</string>
<string name="HOME_DISCOVER_SECTION_TITLE">Discover our insurances</string>
<string name="HOME_DISCOVER_SEE_PRICE_BUTTON">See price</string>
<string name="HOME_GREETING_SUBTITLE">How can we help?</string>
<string name="HOME_GREETING_TITLE">Hi %1$s</string>
<string name="HOME_QUICK_ACTIONS_CHANGE_ADDRESS">Change address</string>
<string name="HOME_QUICK_ACTIONS_EDIT_INSURANCE">Edit insurance</string>
<string name="HOME_QUOTES_SECTION_TITLE">Your quotes</string>
<string name="HOME_TODO_ADD_COINSURED_TITLE">Add co-insured</string>
<string name="HOME_TODO_MISSING_CHIP_ID_TITLE">Missing pet chip-ID</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,9 @@
<string name="GENERAL_CHANGE_CONFIRMATION_DESCRIPTION">Din försäkring kommer att uppdateras den %1$s.</string>
<string name="GENERAL_CONFIRM">Bekräfta</string>
<string name="GENERAL_CONTACT_US_TITLE">Kontakta vårt serviceteam</string>
<string name="GENERAL_DISABLED">Inaktiverad</string>
<string name="GENERAL_DOWNLOAD">Ladda ner</string>
<string name="GENERAL_ENABLED">Aktiverad</string>
<string name="GENERAL_INVALID_INPUT">Felaktig inmatning</string>
<string name="GENERAL_NOT_SURE">Vet inte</string>
<string name="GENERAL_RETRY">Försök igen</string>
Expand Down Expand Up @@ -498,8 +500,13 @@
<string name="HC_TOPIC_NOT_FOUND">Topic not found</string>
<string name="HC_TOPIC_NO_QUESTIONS">This topic has no questions</string>
<string name="HEDVIG_NAME_TEXT">Hedvig</string>
<string name="HOME_ADDONS_READ_MORE_BUTTON">Läs mer</string>
<string name="HOME_DISCOVER_SECTION_TITLE">Upptäck våra försäkringar</string>
<string name="HOME_DISCOVER_SEE_PRICE_BUTTON">Se pris</string>
<string name="HOME_GREETING_SUBTITLE">Hur kan vi hjälpa dig?</string>
<string name="HOME_GREETING_TITLE">Hej %1$s</string>
<string name="HOME_QUICK_ACTIONS_CHANGE_ADDRESS">Ändra adress</string>
<string name="HOME_QUICK_ACTIONS_EDIT_INSURANCE">Ändra försäkring</string>
<string name="HOME_QUOTES_SECTION_TITLE">Dina prisförslag</string>
<string name="HOME_TODO_ADD_COINSURED_TITLE">Lägg till medförsäkrad</string>
<string name="HOME_TODO_MISSING_CHIP_ID_TITLE">Chip-ID för husdjur saknas</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,9 @@
<string name="GENERAL_CHANGE_CONFIRMATION_DESCRIPTION">Your insurance will be updated starting from %1$s</string>
<string name="GENERAL_CONFIRM">Confirm</string>
<string name="GENERAL_CONTACT_US_TITLE">Contact our service team</string>
<string name="GENERAL_DISABLED">Disabled</string>
<string name="GENERAL_DOWNLOAD">Download</string>
<string name="GENERAL_ENABLED">Enabled</string>
<string name="GENERAL_INVALID_INPUT">Invalid input</string>
<string name="GENERAL_NOT_SURE">Not sure</string>
<string name="GENERAL_RETRY">Try again</string>
Expand Down Expand Up @@ -498,8 +500,13 @@
<string name="HC_TOPIC_NOT_FOUND">Topic not found</string>
<string name="HC_TOPIC_NO_QUESTIONS">This topic has no questions</string>
<string name="HEDVIG_NAME_TEXT">Hedvig</string>
<string name="HOME_ADDONS_READ_MORE_BUTTON">Read more</string>
<string name="HOME_DISCOVER_SECTION_TITLE">Discover our insurances</string>
<string name="HOME_DISCOVER_SEE_PRICE_BUTTON">See price</string>
<string name="HOME_GREETING_SUBTITLE">How can we help?</string>
<string name="HOME_GREETING_TITLE">Hi %1$s</string>
<string name="HOME_QUICK_ACTIONS_CHANGE_ADDRESS">Change address</string>
<string name="HOME_QUICK_ACTIONS_EDIT_INSURANCE">Edit insurance</string>
<string name="HOME_QUOTES_SECTION_TITLE">Your quotes</string>
<string name="HOME_TODO_ADD_COINSURED_TITLE">Add co-insured</string>
<string name="HOME_TODO_MISSING_CHIP_ID_TITLE">Missing pet chip-ID</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
Expand All @@ -24,14 +27,19 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.dropShadow
import androidx.compose.ui.draw.innerShadow
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.graphics.shadow.Shadow
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import com.hedvig.android.compose.ui.LayoutWithoutPlacement
import com.hedvig.android.compose.ui.withoutPlacement
Expand All @@ -43,6 +51,9 @@ import com.hedvig.android.design.system.hedvig.tokens.MiniSizeButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.PrimaryAltStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.PrimaryStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.RedStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.RoundedLargeSizeButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.RoundedLiquidGlassStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.RoundedPrimaryStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.SecondaryAltStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.SecondaryStyleButtonTokens
import com.hedvig.android.design.system.hedvig.tokens.SmallSizeButtonTokens
Expand Down Expand Up @@ -119,7 +130,9 @@ fun HedvigButton(
) {
@Suppress("NAME_SHADOWING")
val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
val buttonColors = buttonStyle.style.buttonColors
val style = buttonStyle.style
val size = buttonSize.sizeIn(style)
val buttonColors = style.buttonColors
val containerColor = buttonColors.containerColor(enabled)
val contentColor = buttonColors.contentColor(enabled)
val isHovered by interactionSource.collectIsHoveredAsState()
Expand All @@ -131,21 +144,31 @@ fun HedvigButton(
containerColor
},
)

@Suppress("NAME_SHADOWING")
val shape = shape ?: size.shape
val glass = style.glassMaterial.takeIf { enabled }
Surface(
onClick = onClick,
modifier = modifier,
modifier = if (glass == null) {
modifier
} else {
modifier.glassMaterial(glass, color, shape)
},
onClickLabel = onClickLabel,
role = Role.Button,
enabled = enabled,
shape = shape ?: buttonSize.size.shape,
shape = shape,
border = border,
color = color,
// The rim shadows have to sit on top of the container fill, which is only reachable from outside
// this Surface, so the fill moves into the modifier above and the Surface itself stays see-through.
color = if (glass == null) color else Color.Transparent,
contentColor = contentColor,
interactionSource = interactionSource,
) {
ProvideTextStyle(buttonSize.size.textStyle) {
ProvideTextStyle(size.textStyle) {
Row(
modifier = Modifier.padding(buttonSize.size.contentPadding),
modifier = Modifier.padding(size.contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content,
Expand Down Expand Up @@ -246,6 +269,31 @@ fun HedvigButtonGhostWithBorder(
)
}

@HedvigPreview
@Composable
private fun PreviewRoundedButtons() {
HedvigTheme {
// A tinted backdrop, so that the translucent liquid glass container is distinguishable from it.
Surface(color = HedvigTheme.colorScheme.surfaceSecondary) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(16.dp),
) {
for (buttonStyle in listOf(
ButtonDefaults.ButtonStyle.RoundedPrimary,
ButtonDefaults.ButtonStyle.RoundedLiquidGlass,
)) {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
HedvigButton("Make a claim", {}, enabled = true, buttonStyle = buttonStyle)
HedvigButton("Disabled", {}, enabled = false, buttonStyle = buttonStyle)
HedvigButton("Loading", {}, enabled = true, buttonStyle = buttonStyle, isLoading = true)
}
}
}
}
}
}

object ButtonDefaults {
internal val buttonStyle: ButtonStyle = ButtonStyle.Primary
internal val buttonSize: ButtonSize = ButtonSize.Large
Expand All @@ -257,6 +305,12 @@ object ButtonDefaults {
SecondaryAlt,
Ghost,
Red,

/** A filled pill with the sheen and drop shadow of the iOS glass material. */
RoundedPrimary,

/** A translucent pill of the iOS glass material, letting the backdrop show through. */
RoundedLiquidGlass,
}

enum class ButtonSize {
Expand All @@ -275,6 +329,8 @@ private val ButtonDefaults.ButtonStyle.style: Style
ButtonDefaults.ButtonStyle.SecondaryAlt -> Style.SecondaryAlt
ButtonDefaults.ButtonStyle.Ghost -> Style.Ghost
ButtonDefaults.ButtonStyle.Red -> Style.Red
ButtonDefaults.ButtonStyle.RoundedPrimary -> Style.RoundedPrimary
ButtonDefaults.ButtonStyle.RoundedLiquidGlass -> Style.RoundedLiquidGlass
}

private val ButtonSize.size: Size
Expand All @@ -285,6 +341,16 @@ private val ButtonSize.size: Size
ButtonSize.Mini -> Size.Mini
}

/**
* The metrics this size takes on within [style]. The rounded styles get their own pill metrics at
* [ButtonSize.Large]; at every smaller size they fall back to the standard button metrics.
*/
@Composable
private fun ButtonSize.sizeIn(style: Style): Size = when {
style.glassMaterial != null && this == ButtonSize.Large -> Size.LargeRounded
else -> size
}

@Immutable
private data class ButtonColors(
val containerColor: Color,
Expand Down Expand Up @@ -343,6 +409,25 @@ private sealed interface Size {
get() = LargeSizeButtonTokens.ContainerShape.value
}

object LargeRounded : Size {
override val contentPadding: PaddingValues = PaddingValues(
top = RoundedLargeSizeButtonTokens.TopPadding,
bottom = RoundedLargeSizeButtonTokens.BottomPadding,
start = RoundedLargeSizeButtonTokens.HorizontalPadding,
end = RoundedLargeSizeButtonTokens.HorizontalPadding,
)

override val textStyle: TextStyle
@Composable
@ReadOnlyComposable
get() = RoundedLargeSizeButtonTokens.LabelTextFont.value

override val shape: Shape
@Composable
@ReadOnlyComposable
get() = RoundedLargeSizeButtonTokens.ContainerShape.value
}

object Medium : Size {
override val contentPadding: PaddingValues = PaddingValues(
top = MediumSizeButtonTokens.TopPadding,
Expand Down Expand Up @@ -405,6 +490,11 @@ private sealed interface Style {
@get:Composable
val buttonColors: ButtonColors

/** Non-null on the styles that render the iOS glass material. */
val glassMaterial: GlassMaterial?
@Composable
get() = null

data object Primary : Style {
override val buttonColors: ButtonColors
@Composable
Expand Down Expand Up @@ -505,6 +595,56 @@ private sealed interface Style {
}
}

data object RoundedPrimary : Style {
// The fill inverts between themes: near-black on light, opaque white on dark.
override val glassMaterial: GlassMaterial
@Composable
get() = if (HedvigTheme.colorScheme.isLight) opaqueDarkGlassMaterial else regularGlassMaterial

override val buttonColors: ButtonColors
@Composable
get() = with(HedvigTheme.colorScheme) {
remember(this) {
ButtonColors(
containerColor = fromToken(RoundedPrimaryStyleButtonTokens.ContainerColor),
contentColor = fromToken(RoundedPrimaryStyleButtonTokens.ContentColor),
disabledContainerColor = fromToken(RoundedPrimaryStyleButtonTokens.DisabledContainerColor),
disabledContentColor = fromToken(RoundedPrimaryStyleButtonTokens.DisabledContentColor),
hoverContainerColor = fromToken(RoundedPrimaryStyleButtonTokens.HoverContainerColor),
hoverContentColor = fromToken(RoundedPrimaryStyleButtonTokens.HoverContentColor),
activeLoadingIndicatorColor = fromToken(RoundedPrimaryStyleButtonTokens.ActiveLoadingIndicatorColor),
inactiveLoadingIndicatorColor = fromToken(RoundedPrimaryStyleButtonTokens.InactiveLoadingIndicatorColor),
redTextColor = fromToken(RoundedPrimaryStyleButtonTokens.RedContentColor),
)
}
}
}

data object RoundedLiquidGlass : Style {
override val glassMaterial: GlassMaterial
@Composable
get() = regularGlassMaterial

override val buttonColors: ButtonColors
@Composable
get() = with(HedvigTheme.colorScheme) {
remember(this) {
ButtonColors(
containerColor = fromToken(RoundedLiquidGlassStyleButtonTokens.ContainerColor),
contentColor = fromToken(RoundedLiquidGlassStyleButtonTokens.ContentColor),
disabledContainerColor = fromToken(RoundedLiquidGlassStyleButtonTokens.DisabledContainerColor),
disabledContentColor = fromToken(RoundedLiquidGlassStyleButtonTokens.DisabledContentColor),
hoverContainerColor = fromToken(RoundedLiquidGlassStyleButtonTokens.HoverContainerColor),
hoverContentColor = fromToken(RoundedLiquidGlassStyleButtonTokens.HoverContentColor),
activeLoadingIndicatorColor = fromToken(RoundedLiquidGlassStyleButtonTokens.ActiveLoadingIndicatorColor),
inactiveLoadingIndicatorColor =
fromToken(RoundedLiquidGlassStyleButtonTokens.InactiveLoadingIndicatorColor),
redTextColor = fromToken(RoundedLiquidGlassStyleButtonTokens.RedContentColor),
)
}
}
}

data object Red : Style {
override val buttonColors: ButtonColors
@Composable
Expand Down
Loading
Loading