diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/LicenseScreens.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/LicenseScreens.kt index 8c5c46fa..8ad4f4c9 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/LicenseScreens.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/LicenseScreens.kt @@ -287,7 +287,7 @@ private fun highlightText(text: String, highlights: List): AnnotatedSt if (!range.isEmpty()) { addStyle( style = SpanStyle( - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, background = KotlinConfTheme.colors.primaryBackground, ), start = range.first, diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Button.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Button.kt index 7314f8ba..dedaa223 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Button.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Button.kt @@ -43,7 +43,7 @@ fun Button( else KotlinConfTheme.colors.strokeHalf ) val textColor by animateColorAsState( - if (primary) KotlinConfTheme.colors.primaryTextInverted + if (primary) KotlinConfTheme.colors.primaryTextWhiteFixed else KotlinConfTheme.colors.primaryText ) val alpha by animateFloatAsState(if (enabled) 1f else 0.5f) diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/CardTag.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/CardTag.kt index 73b77d71..5e100d86 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/CardTag.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/CardTag.kt @@ -33,7 +33,7 @@ fun CardTag( ColorSpringSpec, ) val textColor by animateColorAsState( - if (selected) KotlinConfTheme.colors.primaryTextInverted + if (selected) KotlinConfTheme.colors.primaryTextWhiteFixed else KotlinConfTheme.colors.secondaryText, ColorSpringSpec, ) diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt index 96b710fa..011368aa 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt @@ -75,7 +75,7 @@ fun DayHeader( Text( day, style = DayDateStyle, - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, modifier = Modifier.widthIn(min = 72.dp), ) Text( @@ -88,7 +88,7 @@ fun DayHeader( Text( "-$day2", style = DayDateStyle, - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, modifier = Modifier.widthIn(min = 72.dp), ) } @@ -97,12 +97,12 @@ fun DayHeader( Text( line1, style = DayHeaderStyle, - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, ) Text( line2, style = DayHeaderStyle, - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, ) } } diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt index fb87dba6..69c1028e 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt @@ -135,7 +135,7 @@ fun Filters( val tagCountContentDescription = pluralStringResource(UiRes.plurals.filter_by_tags_tag_count, count, count) Text( text = count.toString(), - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, style = KotlinConfTheme.typography.text2, modifier = Modifier.semantics { contentDescription = tagCountContentDescription diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/FiltersTag.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/FiltersTag.kt index 05887b13..fe085edd 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/FiltersTag.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/FiltersTag.kt @@ -38,7 +38,7 @@ fun FilterTag( ColorSpringSpec, ) val textColor by animateColorAsState( - if (selected) KotlinConfTheme.colors.primaryTextInverted + if (selected) KotlinConfTheme.colors.primaryTextWhiteFixed else KotlinConfTheme.colors.primaryText, ColorSpringSpec, ) diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/NowButton.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/NowButton.kt index 84aeae9f..c3b3a9a0 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/NowButton.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/NowButton.kt @@ -54,7 +54,7 @@ fun NowButton( ) { val active = time != Current val textColor by animateColorAsState( - if (active) KotlinConfTheme.colors.primaryTextInverted + if (active) KotlinConfTheme.colors.primaryTextWhiteFixed else KotlinConfTheme.colors.noteText, ColorSpringSpec, ) diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt index 1b424e37..1d88131b 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt @@ -98,7 +98,7 @@ internal fun buildHighlightedString( if (!range.isEmpty()) { addStyle( style = SpanStyle( - color = KotlinConfTheme.colors.primaryTextInverted, + color = KotlinConfTheme.colors.primaryTextWhiteFixed, background = KotlinConfTheme.colors.primaryBackground, ), start = range.first, diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuButton.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuButton.kt index cabd4490..cbc83d74 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuButton.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuButton.kt @@ -1,13 +1,17 @@ package org.jetbrains.kotlinconf.ui.components import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.BasicTooltipBox +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberBasicTooltipState import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -16,9 +20,15 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.PopupPositionProvider import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.painterResource import org.jetbrains.kotlinconf.ui.generated.resources.UiRes @@ -28,6 +38,28 @@ import org.jetbrains.kotlinconf.ui.generated.resources.search_24 import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme import org.jetbrains.kotlinconf.ui.theme.PreviewHelper + +@Composable +private fun rememberPositionProvider(): PopupPositionProvider { + val tooltipAnchorSpacing = with(LocalDensity.current) { 4.dp.roundToPx() } + return remember(tooltipAnchorSpacing) { + object : PopupPositionProvider { + override fun calculatePosition( + anchorBounds: IntRect, + windowSize: IntSize, + layoutDirection: LayoutDirection, + popupContentSize: IntSize, + ): IntOffset { + val x = anchorBounds.left + (anchorBounds.width - popupContentSize.width) / 2 + var y = anchorBounds.bottom - tooltipAnchorSpacing + if (y < 0) y = anchorBounds.bottom + tooltipAnchorSpacing + return IntOffset(x, y) + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) @Composable private fun TopMenuButtonImpl( icon: DrawableResource, @@ -37,20 +69,49 @@ private fun TopMenuButtonImpl( iconColor: Color, modifier: Modifier = Modifier, ) { - Icon( - modifier = modifier - .padding(6.dp) - .size(36.dp) - .clip(CircleShape) - .then(interactionModifier) - .background(backgroundColor) - .padding(6.dp), - painter = painterResource(icon), - contentDescription = contentDescription, - tint = iconColor, + BasicTooltipBox( + positionProvider = rememberPositionProvider(), + tooltip = { Tooltip(contentDescription) }, + state = rememberBasicTooltipState() + ) { + Icon( + modifier = modifier + .padding(6.dp) + .size(36.dp) + .clip(CircleShape) + .then(interactionModifier) + .background(backgroundColor) + .padding(6.dp), + painter = painterResource(icon), + contentDescription = contentDescription, + tint = iconColor, + ) + } +} + +@Composable +fun Tooltip( + text: String, +) { + Text( + text = text, + style = KotlinConfTheme.typography.text2, + color = KotlinConfTheme.colors.primaryTextInverted, + modifier = Modifier + .clip(RoundedCornerShape(4.dp)) + .background(KotlinConfTheme.colors.tooltipBackground) + .padding(vertical = 4.dp, horizontal = 8.dp) ) } +@Preview +@Composable +fun TooltipPreview() { + PreviewHelper { + Tooltip("Tooltip") + } +} + /** * A toggleable top menu button with selection state. */ @@ -67,7 +128,7 @@ fun TopMenuButton( else Color.Transparent ) val iconColor by animateColorAsState( - if (selected) KotlinConfTheme.colors.primaryTextInverted + if (selected) KotlinConfTheme.colors.primaryTextWhiteFixed else KotlinConfTheme.colors.primaryText ) diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/ColorValues.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/ColorValues.kt index 57c4475d..1f4c8860 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/ColorValues.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/ColorValues.kt @@ -67,4 +67,9 @@ internal object UI { val greyLight = Color(0xFFA3A3A4) val greyDark = Color(0xFF757577) + + val grey100 = Color(0xFFE8E8E8) + val grey400 = Color(0xFFA3A3A4) + val grey500 = Color(0xFF757577) + val grey900 = Color(0xFF303033) } diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/Colors.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/Colors.kt index 66d94ced..b46d937d 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/Colors.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/Colors.kt @@ -16,6 +16,8 @@ import org.jetbrains.kotlinconf.ui.theme.UI.black40 import org.jetbrains.kotlinconf.ui.theme.UI.black60 import org.jetbrains.kotlinconf.ui.theme.UI.black70 import org.jetbrains.kotlinconf.ui.theme.UI.black80 +import org.jetbrains.kotlinconf.ui.theme.UI.grey100 +import org.jetbrains.kotlinconf.ui.theme.UI.grey900 import org.jetbrains.kotlinconf.ui.theme.UI.greyDark import org.jetbrains.kotlinconf.ui.theme.UI.greyLight import org.jetbrains.kotlinconf.ui.theme.UI.white05 @@ -34,6 +36,7 @@ class Colors( val mainBackground: Color, val primaryBackground: Color, val tileBackground: Color, + val tooltipBackground: Color, val cardBackgroundPast: Color, val scrollIndicatorFill: Color, @@ -50,6 +53,7 @@ class Colors( val placeholderText: Color, val primaryText: Color, val primaryTextInverted: Color, + val primaryTextWhiteFixed: Color, val purpleText: Color, val secondaryText: Color, @@ -64,6 +68,7 @@ val KotlinConfLightColors = Colors( mainBackground = white100, primaryBackground = magenta100, tileBackground = black05, + tooltipBackground = grey900, cardBackgroundPast = black05, scrollIndicatorFill = black15, @@ -80,6 +85,7 @@ val KotlinConfLightColors = Colors( placeholderText = black20, primaryText = black100, primaryTextInverted = white100, + primaryTextWhiteFixed = white100, purpleText = purple100, secondaryText = black60, @@ -94,6 +100,7 @@ val KotlinConfDarkColors = Colors( mainBackground = black100, primaryBackground = magenta100, tileBackground = white10, + tooltipBackground = grey100, cardBackgroundPast = white05, scrollIndicatorFill = white30, @@ -109,7 +116,8 @@ val KotlinConfDarkColors = Colors( orangeText = orange, placeholderText = white30, primaryText = white100, - primaryTextInverted = white100, + primaryTextInverted = black100, + primaryTextWhiteFixed = white100, purpleText = purpleTextDark, secondaryText = white70,