Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import com.adevinta.spark.ExperimentalSparkApi
import com.adevinta.spark.catalog.model.Example
import com.adevinta.spark.catalog.util.SampleSourceUrl
import com.adevinta.spark.components.tags.Highlight
import com.adevinta.spark.components.tags.HighlightBadge
import com.adevinta.spark.components.tags.Tag
import com.adevinta.spark.components.tags.TagFilled
import com.adevinta.spark.components.tags.TagHighlight
import com.adevinta.spark.components.tags.TagHighlightBadge
import com.adevinta.spark.components.tags.TagIntent
import com.adevinta.spark.components.tags.TagOutlined
import com.adevinta.spark.components.tags.TagTinted
import com.adevinta.spark.components.text.Text
import com.adevinta.spark.icons.LeboncoinIcons
import com.adevinta.spark.icons.RocketOutline
import com.adevinta.spark.icons.SparkIcon
Expand All @@ -44,7 +47,7 @@ import kotlinx.collections.immutable.persistentListOf
private const val TagsExampleDescription = "Tags examples"
private const val TagsExampleSourceUrl = "$SampleSourceUrl/TagSamples.kt"

@OptIn(ExperimentalLayoutApi::class)
@OptIn(ExperimentalLayoutApi::class, ExperimentalSparkApi::class)
public val TagsExamples: ImmutableList<Example> = persistentListOf(
Example(
id = "filled",
Expand Down Expand Up @@ -105,8 +108,18 @@ public val TagsExamples: ImmutableList<Example> = persistentListOf(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
TagHighlight()
TagHighlightBadge()
Tag.Highlight()
Tag.HighlightBadge()
}
},
Example(
id = "ai",
name = "Tag \"AI\"",
description = "The AI tag highlights content generated or curated by AI.",
sourceUrl = TagsExampleSourceUrl,
) {
Tag.Ai {
Text("À la une")
}
},
Example(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ import androidx.compose.ui.unit.dp
import com.adevinta.spark.DefaultTestDevices
import com.adevinta.spark.ExperimentalSparkApi
import com.adevinta.spark.SparkTheme
import com.adevinta.spark.components.tags.Highlight
import com.adevinta.spark.components.tags.HighlightBadge
import com.adevinta.spark.components.tags.Tag
import com.adevinta.spark.components.tags.TagFilled
import com.adevinta.spark.components.tags.TagHighlight
import com.adevinta.spark.components.tags.TagHighlightBadge
import com.adevinta.spark.components.tags.TagIntent
import com.adevinta.spark.components.tags.TagOutlined
import com.adevinta.spark.components.tags.TagTinted
import com.adevinta.spark.components.text.Text
import com.adevinta.spark.icons.FireFill
import com.adevinta.spark.icons.LeboncoinIcons
import com.adevinta.spark.paparazziRule
Expand Down Expand Up @@ -81,12 +82,19 @@ internal class TagDocumentationScreenshots {
}

@Test
fun tagHighlight() = paparazzi.sparkDocSnapshot {
TagHighlight()
fun highlight() = paparazzi.sparkDocSnapshot {
Tag.Highlight()
}

@Test
fun tagHighlightBadge() = paparazzi.sparkDocSnapshot({ SparkTheme.colors.backgroundVariant }) {
TagHighlightBadge()
fun highlightBadge() = paparazzi.sparkDocSnapshot({ SparkTheme.colors.backgroundVariant }) {
Tag.HighlightBadge()
}

@Test
fun tagAi() = paparazzi.sparkDocSnapshot {
Tag.Ai {
Text("À la une")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ import com.adevinta.spark.DefaultTestDevices
import com.adevinta.spark.ExperimentalSparkApi
import com.adevinta.spark.SparkTheme
import com.adevinta.spark.components.surface.Surface
import com.adevinta.spark.components.tags.Highlight
import com.adevinta.spark.components.tags.HighlightBadge
import com.adevinta.spark.components.tags.Tag
import com.adevinta.spark.components.tags.TagFilled
import com.adevinta.spark.components.tags.TagHighlight
import com.adevinta.spark.components.tags.TagHighlightBadge
import com.adevinta.spark.components.tags.TagIntent
import com.adevinta.spark.components.tags.TagOutlined
import com.adevinta.spark.components.tags.TagTinted
Expand Down Expand Up @@ -175,13 +176,13 @@ internal class TagsScreenshot {
text = "TagHighlight",
style = SparkTheme.typography.headline2,
)
TagHighlight()
Tag.Highlight()

Text(
text = "TagHighlightBadge",
style = SparkTheme.typography.headline2,
)
TagHighlightBadge()
Tag.HighlightBadge()
}
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,12 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.ui.unit.dp

public object ChipDefaults {
/**
* The padding between the elements in the chip.
*/
private val HorizontalElementsPadding = 8.dp

/**
* The size of the leading icon in the chip.
*/
internal val LeadingIconSize = 16.dp

/**
* Horizontal padding for chip content.
*/
internal val ChipPadding = PaddingValues(horizontal = HorizontalElementsPadding)

/**
* Spacing between the leading icon and the label.
*/
internal val LeadingIconEndSpacing = 4.dp

/**
* The outlined chip's border size
*/
Expand All @@ -59,4 +45,8 @@ public object ChipDefaults {
* The chip's default height
*/
internal val MinHeight = 32.dp

private val HorizontalElementsPadding = 8.dp

internal val ChipPadding = PaddingValues(horizontal = HorizontalElementsPadding)
}
85 changes: 68 additions & 17 deletions spark/src/main/kotlin/com/adevinta/spark/components/tags/Tag.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,19 @@ import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.adevinta.spark.ExperimentalSparkApi
import com.adevinta.spark.InternalSparkApi
import com.adevinta.spark.PreviewTheme
import com.adevinta.spark.SparkTheme
import com.adevinta.spark.components.chips.ChipDefaults.LeadingIconEndSpacing
import com.adevinta.spark.components.icons.Icon
import com.adevinta.spark.components.surface.Surface
import com.adevinta.spark.components.tags.TagDefaults.LeadingIconSize
import com.adevinta.spark.components.tags.TagTokens.LeadingIconSize
import com.adevinta.spark.components.text.Text
import com.adevinta.spark.icons.AccessoriesCriteria
import com.adevinta.spark.icons.BroomstickSparks
import com.adevinta.spark.icons.LeboncoinIcons
import com.adevinta.spark.icons.SparkIcon
import com.adevinta.spark.icons.Sparks
import com.adevinta.spark.tokens.contentColorFor
import com.adevinta.spark.tokens.highlight
import com.adevinta.spark.tools.modifiers.SlotArea
Expand Down Expand Up @@ -93,13 +95,14 @@ internal fun BaseSparkTag(
border = border,
) {
ProvideTextStyle(
value = SparkTheme.typography.caption.highlight,
value = TagTokens.contentTypo,
) {
Row(
Modifier
.defaultMinSize(minHeight = size.minHeight.dp)
.padding(vertical = size.verticalPadding.dp, horizontal = HorizontalPadding),
horizontalArrangement = Arrangement.spacedBy(LeadingIconEndSpacing, Alignment.Start),
.padding(TagTokens.contentPadding)
.padding(vertical = size.verticalPadding.dp),
horizontalArrangement = Arrangement.spacedBy(TagTokens.ContentSpacing, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
) {
AnimatedVisibility(
Expand Down Expand Up @@ -161,6 +164,44 @@ internal fun BaseSparkTag(
)
}

public object Tag {
/**
* A tag that marks AI-generated or AI-assisted content. Styled with the Spark AI colour tokens
* (`ai`, `aiContainer`, `onAiContainer`).
*
* ![Tag Ai](https://leboncoin.github.io/spark-android/images/com.adevinta.spark.tags_TagDocumentationScreenshots_tagAi.png)
*
* @param modifier Modifier for the tag container.
* @param leadingIcon The icon displayed before the content. Defaults to [TagDefaults.Ai.icon].
* @param atEnd Whether the animated vector should be rendered at the end of its animations.
* @param content The main content of the tag, usually a [Text].
*/
@ExperimentalSparkApi
@Composable
public fun Ai(
modifier: Modifier = Modifier,
leadingIcon: SparkIcon = TagDefaults.Ai.icon,
atEnd: Boolean = false,
content: @Composable RowScope.() -> Unit,
) {
BaseSparkTag(
colors = TagColors(
backgroundColor = TagTokens.Ai.containerColor,
contentColor = TagTokens.Ai.contentColor,
),
modifier = modifier,
border = BorderStroke(
TagTokens.OutlinedBorderSize,
TagTokens.Ai.borderColor,
),
tint = TagTokens.Ai.iconTint,
leadingIcon = leadingIcon,
) {
content()
}
}
}

@Composable
private fun <T> RowScope.AnimatedVisibility(
value: T?,
Expand Down Expand Up @@ -263,15 +304,6 @@ internal fun SparkTag(
public data class TagColors(val backgroundColor: Color, val contentColor: Color)

public object TagDefaults {
/**
* The outlined tag's border size
*/
internal val OutlinedBorderSize = 1.dp

/**
* The size of a tag's leading icon
*/
internal val LeadingIconSize = 12.dp

@Composable
@InternalSparkApi
Expand Down Expand Up @@ -306,16 +338,18 @@ public object TagDefaults {
contentColor = contentColor,
)
}
}

private val HorizontalPadding = 8.dp
public object Ai {
public val icon: SparkIcon = LeboncoinIcons.Sparks
}
}

@Preview(
group = "Tags",
name = "Tag",
)
@Composable
private fun SparkTagPreview() {
private fun PreviewSparkTag() {
PreviewTheme {
val colors = TagDefaults.filledColors()
BaseSparkTag(colors = colors, atEnd = false) {
Expand All @@ -332,3 +366,20 @@ private fun SparkTagPreview() {
}
}
}

@Preview(
group = "Tags",
name = "Ai",
)
@Composable
private fun PreviewAiTag() {
PreviewTheme {
val colors = TagDefaults.filledColors()
Tag.Ai(atEnd = false) {
Text("À la une")
}
Tag.Ai(leadingIcon = LeboncoinIcons.BroomstickSparks, atEnd = false) {
Text("À la deux")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,17 @@ The Highlight tag allows you to temporarily highlight new features of the produc
- Implement with an End-of-Life Remote Config to prevent indefinite production presence

```kotlin
TagHighlight()
Tag.Highlight()
```

### Tag "Ai"

The Ai tag marks AI-generated or AI-assisted content. Use it to clearly signal to users when content has been produced or enhanced by AI.

![](../../images/com.adevinta.spark.tags_TagDocumentationScreenshots_tagAi.png)

```kotlin
Tag.Ai {
Text("À la une")
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ import com.adevinta.spark.tools.modifiers.invisibleSemantic
* Ensure that this component is being used with a End of life Remote Config so that it doesn't remain in
* production indefinitely.
*
* ![Tag Highlight](https://leboncoin.github.io/spark-android/images/com.adevinta.spark.tags_TagDocumentationScreenshots_tagHighlight.png)
* ![Tag Highlight](https://leboncoin.github.io/spark-android/images/com.adevinta.spark.tags_TagDocumentationScreenshots_highlight.png)
*
* @param modifier Optional modifier for the badge container
*
* @see TagHighlightBadge
* @see Tag.HighlightBadge
*/
@ExperimentalSparkApi
@Composable
public fun TagHighlight(
public fun Tag.Highlight(
modifier: Modifier = Modifier,
) {
BaseSparkTag(
Expand All @@ -81,15 +81,15 @@ public fun TagHighlight(
* Ensure that this component is being used with a End of life Remote Config so that it doesn't remain in
* production indefinitely.
*
* ![Tag Highlight](https://leboncoin.github.io/spark-android/images/com.adevinta.spark.tags_TagDocumentationScreenshots_tagHighlightbadge.png)
* ![Tag Highlight](https://leboncoin.github.io/spark-android/images/com.adevinta.spark.tags_TagDocumentationScreenshots_highlightBadge.png)
*
* @param modifier Optional modifier for the badge container
*
* @see TagHighlight
* @see Tag.Highlight
*/
@ExperimentalSparkApi
@Composable
public fun TagHighlightBadge(
public fun Tag.HighlightBadge(
modifier: Modifier = Modifier,
) {
BaseSparkTag(
Expand Down Expand Up @@ -117,7 +117,7 @@ public fun TagHighlightBadge(
@Composable
private fun PreviewTagHighlight() {
PreviewTheme {
TagHighlight()
TagHighlightBadge()
Tag.Highlight()
Tag.HighlightBadge()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@ import com.adevinta.spark.components.IntentColors
* TagIntent is used to define the intent of the tag.
*/
public enum class TagIntent {
/**
* Used to match default color of such UI controls as toggles, Slider, etc.
*/
@Deprecated(
message = "Basic has been removed with the rebranding, use Support instead",
replaceWith = ReplaceWith("TagIntent.Support"),
level = DeprecationLevel.ERROR,
)
Basic {
@Composable
override fun colors(): IntentColor = IntentColors.Support.colors()
},

/**
* Used to make UI component visually accentuated.
Expand Down
Loading
Loading