From a86896c56b53d9c680bf1546ccf32e516958bfbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Braun?= Date: Fri, 15 Nov 2024 22:55:49 +0100 Subject: [PATCH] Add second set of components --- .editorconfig | 3 + .../kotlinconf/ui/components/CardTag.kt | 68 +++++++++++++++ .../kotlinconf/ui/components/FiltersTag.kt | 78 +++++++++++++++++ .../kotlinconf/ui/components/NowButton.kt | 84 +++++++++++++++++++ .../kotlinconf/ui/components/Switcher.kt | 29 +++++-- .../kotlinconf/ui/components/TopMenuButton.kt | 66 +++++++++++++++ .../kotlinconf/ui/components/TopMenuTitle.kt | 49 +++++++++++ .../kotlinconf/ui/theme/PreviewUtil.kt | 5 +- 8 files changed, 376 insertions(+), 6 deletions(-) create mode 100644 .editorconfig create mode 100644 ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/CardTag.kt create mode 100644 ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/FiltersTag.kt create mode 100644 ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/NowButton.kt create mode 100644 ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuButton.kt create mode 100644 ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuTitle.kt diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..af88566e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*.kt] +ij_kotlin_name_count_to_use_star_import = 1024 +ij_kotlin_name_count_to_use_star_import_for_members = 1024 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 new file mode 100644 index 00000000..c4066438 --- /dev/null +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/CardTag.kt @@ -0,0 +1,68 @@ +package org.jetbrains.kotlinconf.ui.components + +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme +import org.jetbrains.kotlinconf.ui.theme.PreviewHelper + +private val CardTagShape = RoundedCornerShape(size = 4.dp) + +@Composable +fun CardTag( + label: String, + selected: Boolean, + onSelect: (Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + val backgroundColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryBackground + else KotlinConfTheme.colors.tileBackground + ) + val textColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryTextInverted + else KotlinConfTheme.colors.secondaryText + ) + + Box( + modifier = modifier + .heightIn(min = 20.dp) + .clip(CardTagShape) + .clickable(onClick = { onSelect(!selected) }) + .background(backgroundColor) + .padding(horizontal = 4.dp), + contentAlignment = Alignment.Center, + ) { + StyledText( + label, + style = KotlinConfTheme.typography.text2, + color = textColor, + ) + } +} + +@Preview +@Composable +private fun CardTagPreview() { + PreviewHelper { + var state1 by remember { mutableStateOf(false) } + CardTag("Label", state1, { state1 = it }) + + var state2 by remember { mutableStateOf(true) } + CardTag("Label", state2, { state2 = it }) + } +} 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 new file mode 100644 index 00000000..1278c7b5 --- /dev/null +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/FiltersTag.kt @@ -0,0 +1,78 @@ +package org.jetbrains.kotlinconf.ui.components + +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme +import org.jetbrains.kotlinconf.ui.theme.PreviewHelper + + +private val FilterTagShape = RoundedCornerShape(size = 3.dp) + +@Composable +fun FilterTag( + label: String, + selected: Boolean, + onSelect: (Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + val backgroundColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryBackground + else KotlinConfTheme.colors.mainBackground + ) + val textColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryTextInverted + else KotlinConfTheme.colors.primaryText + ) + val strokeColor by animateColorAsState( + if (selected) Color.Transparent + else KotlinConfTheme.colors.strokeFull + ) + + Box( + modifier = modifier + .clip(FilterTagShape) + .border( + width = 1.dp, + color = strokeColor, + shape = FilterTagShape, + ) + .clickable(onClick = { onSelect(!selected) }) + .background(backgroundColor) + .padding(horizontal = 12.dp, vertical = 6.dp), + contentAlignment = Alignment.Center, + ) { + StyledText( + label, + style = KotlinConfTheme.typography.text1, + color = textColor, + ) + } +} + +@Preview +@Composable +private fun FilterTagPreview() { + PreviewHelper { + var state1 by remember { mutableStateOf(false) } + FilterTag("Label", state1, { state1 = it }) + + var state2 by remember { mutableStateOf(true) } + FilterTag("Label", state2, { state2 = it }) + } +} 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 new file mode 100644 index 00000000..450891f3 --- /dev/null +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/NowButton.kt @@ -0,0 +1,84 @@ +package org.jetbrains.kotlinconf.ui.components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import kotlinconfapp.ui_components.generated.resources.Res +import kotlinconfapp.ui_components.generated.resources.arrow_down_16 +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme +import org.jetbrains.kotlinconf.ui.theme.PreviewHelper + +private val NowButtonShape = RoundedCornerShape( + topEndPercent = 50, + bottomEndPercent = 50, +) + +@Composable +fun NowButton( + enabled: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val textColor by animateColorAsState( + if (enabled) KotlinConfTheme.colors.primaryTextInverted + else KotlinConfTheme.colors.noteText + ) + val background by animateColorAsState( + if (enabled) KotlinConfTheme.colors.primaryBackground + else KotlinConfTheme.colors.tileBackground + ) + + Row( + modifier = modifier + .clip(NowButtonShape) + .clickable(onClick = onClick, enabled = enabled) + .background(background) + .animateContentSize() + .width(72.dp) + .heightIn(min = 36.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(2.dp, Alignment.CenterHorizontally), + ) { + StyledText( + text = "Now", + style = KotlinConfTheme.typography.text2, + color = textColor, + ) + + AnimatedVisibility(enabled) { + Icon( + // TODO review icon sizing later + painter = painterResource(Res.drawable.arrow_down_16), + contentDescription = "Now", + modifier = Modifier.size(16.dp), + tint = textColor, + ) + } + } +} + +@Preview +@Composable +private fun NowButtonPreview() { + PreviewHelper { + NowButton(true, {}) + NowButton(false, {}) + } +} diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt index e36f7c05..549f8ad0 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt @@ -4,9 +4,19 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -25,9 +35,18 @@ private fun SwitcherItem( selected: Boolean, modifier: Modifier = Modifier, ) { - val backgroundColor by animateColorAsState(if (selected) Color.Transparent else KotlinConfTheme.colors.tileBackground) - val textColor by animateColorAsState(if (selected) KotlinConfTheme.colors.primaryText else KotlinConfTheme.colors.secondaryText) - val strokeColor by animateColorAsState(if (selected) KotlinConfTheme.colors.strokeFull else Color.Transparent) + val backgroundColor by animateColorAsState( + if (selected) Color.Transparent + else KotlinConfTheme.colors.tileBackground, + ) + val textColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryText + else KotlinConfTheme.colors.secondaryText, + ) + val strokeColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.strokeFull + else Color.Transparent, + ) Box( modifier = modifier 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 new file mode 100644 index 00000000..dcaffc89 --- /dev/null +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuButton.kt @@ -0,0 +1,66 @@ +package org.jetbrains.kotlinconf.ui.components + +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +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.unit.dp +import kotlinconfapp.ui_components.generated.resources.Res +import kotlinconfapp.ui_components.generated.resources.bookmark_24 +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme +import org.jetbrains.kotlinconf.ui.theme.PreviewHelper + +@Composable +fun TopMenuButton( + selected: Boolean, + onSelect: (Boolean) -> Unit, + contentDescription: String?, + modifier: Modifier = Modifier, +) { + val backgroundColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryBackground + else Color.Transparent + ) + val iconColor by animateColorAsState( + if (selected) KotlinConfTheme.colors.primaryTextInverted + else KotlinConfTheme.colors.primaryText + ) + + Icon( + // TODO review icon sizing later + modifier = modifier + .size(30.dp) + .clip(CircleShape) + .clickable(onClick = { onSelect(!selected) }) + .background(backgroundColor) + .padding(4.dp), + painter = painterResource(Res.drawable.bookmark_24), + contentDescription = contentDescription, + tint = iconColor, + ) +} + +@Preview +@Composable +private fun TopMenuButtonPreview() { + PreviewHelper { + var state1 by remember { mutableStateOf(false) } + TopMenuButton(state1, { state1 = it }, null) + + var state2 by remember { mutableStateOf(true) } + TopMenuButton(state2, { state2 = it }, null) + } +} diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuTitle.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuTitle.kt new file mode 100644 index 00000000..d2141901 --- /dev/null +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TopMenuTitle.kt @@ -0,0 +1,49 @@ +package org.jetbrains.kotlinconf.ui.components + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme +import org.jetbrains.kotlinconf.ui.theme.PreviewHelper + +enum class TopMenuTitleState { + Header, Completed, Placeholder +} + +@Composable +fun TopMenuTitle( + text: String, + state: TopMenuTitleState, + modifier: Modifier = Modifier, +) { + StyledText( + text = text, + modifier = modifier, + style = when (state) { + TopMenuTitleState.Header -> + KotlinConfTheme.typography.h3 + + TopMenuTitleState.Completed, + TopMenuTitleState.Placeholder -> + KotlinConfTheme.typography.text1 + }, + color = when (state) { + TopMenuTitleState.Header, + TopMenuTitleState.Completed -> + KotlinConfTheme.colors.primaryText + + TopMenuTitleState.Placeholder -> + KotlinConfTheme.colors.placeholderText + }, + ) +} + +@Preview +@Composable +private fun TopMenuTitlePreview() { + PreviewHelper { + TopMenuTitle("Top Menu Title", TopMenuTitleState.Header) + TopMenuTitle("Top Menu Title", TopMenuTitleState.Completed) + TopMenuTitle("Top Menu Title", TopMenuTitleState.Placeholder) + } +} diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/PreviewUtil.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/PreviewUtil.kt index 51ed3813..14f3b2ab 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/PreviewUtil.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/theme/PreviewUtil.kt @@ -1,7 +1,10 @@ package org.jetbrains.kotlinconf.ui.theme import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp