diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png new file mode 100644 index 0000000000..5f545757c9 Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png new file mode 100644 index 0000000000..d34c9969d5 Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png new file mode 100644 index 0000000000..ce0bab429c Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png new file mode 100644 index 0000000000..4027a12565 Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png new file mode 100644 index 0000000000..54a3485909 Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png new file mode 100644 index 0000000000..405ceb6e55 Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png new file mode 100644 index 0000000000..e9291e761e Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png new file mode 100644 index 0000000000..4e786a2296 Binary files /dev/null and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png differ diff --git a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.text.BpkTextTest_hero2.png b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.text.BpkTextTest_hero2.png index fe805b0916..dc63da4ae6 100644 Binary files a/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.text.BpkTextTest_hero2.png and b/app/screenshots/oss/debug/default/net.skyscanner.backpack.compose.text.BpkTextTest_hero2.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png new file mode 100644 index 0000000000..49ceb7c073 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png new file mode 100644 index 0000000000..e04e9e6a6c Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png new file mode 100644 index 0000000000..4372f3c714 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png new file mode 100644 index 0000000000..96b4e9afd8 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png new file mode 100644 index 0000000000..1a118b1066 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png new file mode 100644 index 0000000000..b772335887 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png new file mode 100644 index 0000000000..aa835eb9b3 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png differ diff --git a/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png new file mode 100644 index 0000000000..258954ca55 Binary files /dev/null and b/app/screenshots/oss/debug/dm/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png new file mode 100644 index 0000000000..26c89e814d Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerAvailable.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png new file mode 100644 index 0000000000..819efdbbf0 Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineAvailable.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png new file mode 100644 index 0000000000..f145df7e00 Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_bottomAlignedKickerSubHeadlineSponsoredAvailable.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png new file mode 100644 index 0000000000..3e19e191ba Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_default.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png new file mode 100644 index 0000000000..57f9f1a223 Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_defaultWithOverlay.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png new file mode 100644 index 0000000000..82b5388e84 Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerAvailable.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png new file mode 100644 index 0000000000..9023258256 Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineAvailable.png differ diff --git a/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png new file mode 100644 index 0000000000..b69fa78234 Binary files /dev/null and b/app/screenshots/oss/debug/rtl/net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoTest_topAlignedKickerSubHeadlineSponsoredAvailable.png differ diff --git a/app/src/androidTest/java/net/skyscanner/backpack/compose/graphicpromotion/BpkGraphicPromoTest.kt b/app/src/androidTest/java/net/skyscanner/backpack/compose/graphicpromotion/BpkGraphicPromoTest.kt new file mode 100644 index 0000000000..688d3c0b2f --- /dev/null +++ b/app/src/androidTest/java/net/skyscanner/backpack/compose/graphicpromotion/BpkGraphicPromoTest.kt @@ -0,0 +1,80 @@ +/** + * Backpack for Android - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.skyscanner.backpack.compose.graphicpromotion + +import net.skyscanner.backpack.compose.BpkSnapshotTest +import net.skyscanner.backpack.compose.overlay.BpkOverlayType +import net.skyscanner.backpack.demo.compose.BpkGraphicPromoSample +import net.skyscanner.backpack.demo.compose.GraphicPromoStoryAlignmentBottomSponsored +import net.skyscanner.backpack.demo.compose.GraphicPromoStoryAlignmentBottomWithText +import net.skyscanner.backpack.demo.compose.GraphicPromoStoryAlignmentTopSponsored +import net.skyscanner.backpack.demo.compose.GraphicPromoStoryAlignmentTopWithKicker +import net.skyscanner.backpack.demo.compose.GraphicPromoStoryDefault +import org.junit.Test + +class BpkGraphicPromoTest : BpkSnapshotTest() { + + @Test + fun default() = snap { + GraphicPromoStoryDefault() + } + + @Test + fun defaultWithOverlay() = snap { + BpkGraphicPromoSample( + headline = "Three Parks Challenge", + overlayType = BpkOverlayType.SolidHigh, + ) + } + + @Test + fun topAlignedKickerAvailable() = snap { + BpkGraphicPromoSample( + subHeadline = "How to complete the climb in 3 days", + ) + } + + @Test + fun topAlignedKickerSubHeadlineAvailable() = snap { + GraphicPromoStoryAlignmentTopWithKicker() + } + + @Test + fun topAlignedKickerSubHeadlineSponsoredAvailable() = snap { + GraphicPromoStoryAlignmentTopSponsored() + } + + @Test + fun bottomAlignedKickerAvailable() = snap { + BpkGraphicPromoSample( + subHeadline = "How to complete the climb in 3 days", + verticalAlignment = BpkGraphicPromoVerticalAlignment.Bottom, + ) + } + + @Test + fun bottomAlignedKickerSubHeadlineAvailable() = snap { + GraphicPromoStoryAlignmentBottomWithText() + } + + @Test + fun bottomAlignedKickerSubHeadlineSponsoredAvailable() = snap { + GraphicPromoStoryAlignmentBottomSponsored() + } +} diff --git a/app/src/main/java/net/skyscanner/backpack/demo/components/GraphicPromoComponent.kt b/app/src/main/java/net/skyscanner/backpack/demo/components/GraphicPromoComponent.kt new file mode 100644 index 0000000000..6cec8da5e0 --- /dev/null +++ b/app/src/main/java/net/skyscanner/backpack/demo/components/GraphicPromoComponent.kt @@ -0,0 +1,24 @@ +/** + * Backpack for Android - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.skyscanner.backpack.demo.components + +import net.skyscanner.backpack.meta.ComponentMarker + +@ComponentMarker("GraphicPromo") +annotation class GraphicPromoComponent diff --git a/app/src/main/java/net/skyscanner/backpack/demo/compose/GraphicPromoStory.kt b/app/src/main/java/net/skyscanner/backpack/demo/compose/GraphicPromoStory.kt new file mode 100644 index 0000000000..06c7dfab68 --- /dev/null +++ b/app/src/main/java/net/skyscanner/backpack/demo/compose/GraphicPromoStory.kt @@ -0,0 +1,144 @@ +/** + * Backpack for Android - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.skyscanner.backpack.demo.compose + +import android.util.Log +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromo +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicsPromoSponsor +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoVerticalAlignment +import net.skyscanner.backpack.compose.overlay.BpkOverlayType +import net.skyscanner.backpack.compose.tokens.BpkSpacing +import net.skyscanner.backpack.demo.R +import net.skyscanner.backpack.demo.components.GraphicPromoComponent +import net.skyscanner.backpack.demo.meta.ComposeStory + +@Composable +@GraphicPromoComponent +@ComposeStory +internal fun GraphicPromoStoryDefault(modifier: Modifier = Modifier) { + Column(modifier) { + BpkGraphicPromoSample() + } +} + +@Composable +@GraphicPromoComponent +@ComposeStory("Top align with text") +internal fun GraphicPromoStoryAlignmentTopWithKicker() { + BpkGraphicPromoSample( + kicker = "Travel tips", + subHeadline = "How to complete the climb in 3 days", + ) +} + +@Composable +@GraphicPromoComponent +@ComposeStory("Bottom align with text") +internal fun GraphicPromoStoryAlignmentBottomWithText() { + BpkGraphicPromoSample( + kicker = "Travel tips", + subHeadline = "How to complete the climb in 3 days", + verticalAlignment = BpkGraphicPromoVerticalAlignment.Bottom, + ) +} + +@Composable +@GraphicPromoComponent +@ComposeStory("Top align Sponsored") +internal fun GraphicPromoStoryAlignmentTopSponsored() { + BpkGraphicPromoSample( + kicker = "Travel tips", + subHeadline = "How to complete the climb in 3 days", + sponsor = BpkGraphicsPromoSponsor( + accessibilityLabel = "Sponsored", + logo = "https://images.kiwi.com/airlines/64/FR.png", + title = "Sponsored", + ), + ) +} + +@Composable +@GraphicPromoComponent +@ComposeStory("Bottom align Sponsored") +internal fun GraphicPromoStoryAlignmentBottomSponsored() { + BpkGraphicPromoSample( + kicker = "Travel tips", + subHeadline = "How to complete the climb in 3 days", + verticalAlignment = BpkGraphicPromoVerticalAlignment.Bottom, + sponsor = BpkGraphicsPromoSponsor( + accessibilityLabel = "Sponsored", + logo = "https://images.kiwi.com/airlines/64/FR.png", + title = "Sponsored", + ), + ) +} + +@Composable +internal fun BpkGraphicPromoSample( + modifier: Modifier = Modifier, + headline: String = "Three Parks Challenge", + subHeadline: String? = null, + kicker: String? = null, + verticalAlignment: BpkGraphicPromoVerticalAlignment = BpkGraphicPromoVerticalAlignment.Top, + overlayType: BpkOverlayType? = null, + sponsor: BpkGraphicsPromoSponsor? = null, +) { + BpkGraphicPromo( + modifier = modifier + .fillMaxSize() + .padding(BpkSpacing.Base), + kicker = kicker, + headline = headline, + subHeadline = subHeadline, + verticalAlignment = verticalAlignment, + overlayType = overlayType, + sponsor = sponsor, + image = { + Image( + modifier = Modifier.matchParentSize(), + painter = painterResource( + id = R.drawable.graphic_promo, + ), + contentDescription = "Image", + contentScale = ContentScale.Crop, + ) + }, sponsorLogo = { + if (sponsor != null) { + Image( + painter = painterResource( + id = R.drawable.skyland, + ), + contentDescription = "Image", + contentScale = ContentScale.Fit, + ) + } + }, + tapAction = { + Log.d("BpkGraphicPromo", "Tap on graphic promo") + }, + ) +} diff --git a/app/src/main/res/drawable-nodpi/graphic_promo.jpg b/app/src/main/res/drawable-nodpi/graphic_promo.jpg new file mode 100644 index 0000000000..3c30bc6e28 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/graphic_promo.jpg differ diff --git a/app/src/main/res/drawable/skyairlines.xml b/app/src/main/res/drawable/skyairlines.xml new file mode 100644 index 0000000000..5638b338ec --- /dev/null +++ b/app/src/main/res/drawable/skyairlines.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/skyland.xml b/app/src/main/res/drawable/skyland.xml new file mode 100644 index 0000000000..d2010f219f --- /dev/null +++ b/app/src/main/res/drawable/skyland.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion/BpkGraphicPromo.kt b/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion/BpkGraphicPromo.kt new file mode 100644 index 0000000000..a4a9060fbe --- /dev/null +++ b/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion/BpkGraphicPromo.kt @@ -0,0 +1,63 @@ +/** + * Backpack for Android - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.skyscanner.backpack.compose.graphicpromotion + +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import net.skyscanner.backpack.compose.graphicpromotion.internal.BpkGraphicPromoImpl +import net.skyscanner.backpack.compose.overlay.BpkOverlayType + +enum class BpkGraphicPromoVariant { OnDark, OnLight, } +enum class BpkGraphicPromoVerticalAlignment { Top, Bottom, } + +data class BpkGraphicsPromoSponsor( + val title: String, + val logo: String, + val accessibilityLabel: String, +) + +@Composable +fun BpkGraphicPromo( + headline: String, + image: @Composable BoxScope.() -> Unit, + modifier: Modifier = Modifier, + kicker: String? = null, + subHeadline: String? = null, + overlayType: BpkOverlayType? = null, + variant: BpkGraphicPromoVariant = BpkGraphicPromoVariant.OnDark, + verticalAlignment: BpkGraphicPromoVerticalAlignment = BpkGraphicPromoVerticalAlignment.Top, + sponsor: BpkGraphicsPromoSponsor? = null, + sponsorLogo: (@Composable () -> Unit)? = null, + tapAction: () -> Unit = {}, +) { + BpkGraphicPromoImpl( + headline = headline, + modifier = modifier, + kicker = kicker, + subHeadline = subHeadline, + overlayType = overlayType, + variant = variant, + verticalAlignment = verticalAlignment, + sponsor = sponsor, + image = image, + sponsorLogo = sponsorLogo, + tapAction = tapAction, + ) +} diff --git a/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion/internal/BpkGraphicPromoImpl.kt b/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion/internal/BpkGraphicPromoImpl.kt new file mode 100644 index 0000000000..ee4ec72414 --- /dev/null +++ b/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion/internal/BpkGraphicPromoImpl.kt @@ -0,0 +1,287 @@ +/** + * Backpack for Android - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.skyscanner.backpack.compose.graphicpromotion.internal + +import androidx.compose.animation.core.AnimationSpec +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.spring +import androidx.compose.foundation.Indication +import androidx.compose.foundation.IndicationInstance +import androidx.compose.foundation.clickable +import androidx.compose.foundation.indication +import androidx.compose.foundation.interaction.InteractionSource +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +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.remember +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.graphics.drawscope.ContentDrawScope +import androidx.compose.ui.graphics.drawscope.scale +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicsPromoSponsor +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoVariant +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromoVerticalAlignment +import net.skyscanner.backpack.compose.overlay.BpkOverlay +import net.skyscanner.backpack.compose.overlay.BpkOverlayType +import net.skyscanner.backpack.compose.text.BpkText +import net.skyscanner.backpack.compose.theme.BpkTheme +import net.skyscanner.backpack.compose.tokens.BpkBorderRadius +import net.skyscanner.backpack.compose.tokens.BpkSpacing + +@Composable +internal fun BpkGraphicPromoImpl( + headline: String, + image: @Composable BoxScope.() -> Unit, + modifier: Modifier = Modifier, + kicker: String? = null, + subHeadline: String? = null, + overlayType: BpkOverlayType? = null, + variant: BpkGraphicPromoVariant = BpkGraphicPromoVariant.OnDark, + verticalAlignment: BpkGraphicPromoVerticalAlignment = BpkGraphicPromoVerticalAlignment.Top, + sponsor: BpkGraphicsPromoSponsor? = null, + sponsorLogo: (@Composable () -> Unit)? = null, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + tapAction: () -> Unit = {}, +) { + val roundedCornerShape = RoundedCornerShape(BpkBorderRadius.Md) + val contentDescription = listOfNotNull(kicker, headline, subHeadline, sponsor?.accessibilityLabel) + .joinToString(separator = ", ") + Box( + modifier = modifier + .aspectRatio(RATIO_PORTRAIT) + .clip(roundedCornerShape) + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = tapAction, + ) + .semantics(mergeDescendants = true) { + role = Role.Button + this.contentDescription = contentDescription + }, + ) { + if (overlayType != null) { + BpkOverlay( + modifier = Modifier + .matchParentSize() + .indication(interactionSource, InteractiveBackgroundIndication), + overlayType = overlayType, + foregroundContent = { + ForegroundContent( + headline = headline, + kicker = kicker, + subHeadline = subHeadline, + variant = variant, + verticalAlignment = verticalAlignment, + sponsor = sponsor, + sponsorLogo = sponsorLogo, + ) + }, + content = image, + ) + } else { + Box( + modifier = Modifier + .matchParentSize() + .indication(interactionSource, InteractiveBackgroundIndication), + content = image, + ) + ForegroundContent( + headline = headline, + kicker = kicker, + subHeadline = subHeadline, + variant = variant, + verticalAlignment = verticalAlignment, + sponsor = sponsor, + sponsorLogo = sponsorLogo, + ) + } + } +} + +@Composable +private fun SponsorOverlayView( + textColor: Color, + sponsor: BpkGraphicsPromoSponsor?, + modifier: Modifier = Modifier, + sponsorLogo: (@Composable () -> Unit)? = null, +) { + if (sponsor != null) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(BpkSpacing.Md, Alignment.Top), + ) { + BpkText( + text = sponsor.title, + style = BpkTheme.typography.label1, + color = textColor, + ) + + Box( + modifier = Modifier + .heightIn(max = SPONSOR_LOGO_HEIGHT.dp), + content = { sponsorLogo?.let { it() } }, + ) + } + } +} + +@Composable +private fun MessageOverlay( + headline: String, + kicker: String?, + subHeadline: String?, + textColor: Color, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(BpkSpacing.Md, Alignment.Top), + ) { + if (!kicker.isNullOrBlank()) { + BpkText( + text = kicker, + style = BpkTheme.typography.subheading, + color = textColor, + ) + } + + BpkText( + text = headline, + style = BpkTheme.typography.heading2, + color = textColor, + ) + if (!subHeadline.isNullOrBlank()) { + BpkText( + text = subHeadline, + style = BpkTheme.typography.heading5, + color = textColor, + ) + } + } +} + +@Composable +private fun ForegroundContent( + headline: String, + modifier: Modifier = Modifier, + kicker: String? = null, + subHeadline: String? = null, + variant: BpkGraphicPromoVariant = BpkGraphicPromoVariant.OnDark, + verticalAlignment: BpkGraphicPromoVerticalAlignment = BpkGraphicPromoVerticalAlignment.Top, + sponsor: BpkGraphicsPromoSponsor? = null, + sponsorLogo: (@Composable () -> Unit)? = null, +) { + val textColor: Color = when (variant) { + BpkGraphicPromoVariant.OnDark -> BpkTheme.colors.textOnDark + BpkGraphicPromoVariant.OnLight -> BpkTheme.colors.textOnLight + } + + Column(modifier = modifier.padding(BpkSpacing.Lg)) { + when (verticalAlignment) { + BpkGraphicPromoVerticalAlignment.Top -> { + MessageOverlay( + headline = headline, + kicker = kicker, + subHeadline = subHeadline, + textColor = textColor, + ) + + Spacer(Modifier.weight(1f)) + + SponsorOverlayView( + sponsor = sponsor, + textColor = textColor, + sponsorLogo = sponsorLogo, + ) + } + BpkGraphicPromoVerticalAlignment.Bottom -> { + SponsorOverlayView( + sponsor = sponsor, + textColor = textColor, + sponsorLogo = sponsorLogo, + ) + + Spacer(Modifier.weight(1f)) + + MessageOverlay( + headline = headline, + kicker = kicker, + subHeadline = subHeadline, + textColor = textColor, + ) + } + } + } +} + +private object InteractiveBackgroundIndication : Indication { + + @Composable + override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { + val isPressed by interactionSource.collectIsPressedAsState() + + val scale by animateFloatAsState( + targetValue = if (isPressed) 1.05f else 1.0f, + animationSpec = interactiveBackgroundAnimationSpec, + label = "background scale", + ) + + val overlayAlpha by animateFloatAsState( + targetValue = if (isPressed) 0.2f else 0f, + animationSpec = interactiveBackgroundAnimationSpec, + label = "overlay alpha", + ) + + return remember(interactionSource) { + object : IndicationInstance { + override fun ContentDrawScope.drawIndication() { + scale(scale, scale) { + this@drawIndication.drawContent() + } + drawRect(Color.Black, alpha = overlayAlpha) + } + } + } + } +} + +private const val RATIO_PORTRAIT: Float = 3 / 4f +private const val SPONSOR_LOGO_HEIGHT = 60 + +private val interactiveBackgroundAnimationSpec: AnimationSpec = spring( + stiffness = 800f, + dampingRatio = 1f, +) diff --git a/docs/compose/GraphicPromo/README.md b/docs/compose/GraphicPromo/README.md new file mode 100644 index 0000000000..5db03393e4 --- /dev/null +++ b/docs/compose/GraphicPromo/README.md @@ -0,0 +1,85 @@ +# GraphicPromo + +[![Maven Central](https://img.shields.io/maven-central/v/net.skyscanner.backpack/backpack-compose)](https://search.maven.org/artifact/net.skyscanner.backpack/backpack-compose) +[![Class reference](https://img.shields.io/badge/Class%20reference-Android-blue)](https://backpack.github.io/android/backpack-compose/net.skyscanner.backpack.compose.graphicpromotion) +[![Source code](https://img.shields.io/badge/Source%20code-GitHub-lightgrey)](https://github.com/Skyscanner/backpack-android/tree/main/backpack-compose/src/main/kotlin/net/skyscanner/backpack/compose/graphicpromotion) + +## Default + +| Day | Night | +| --- | --- | +| GraphicPromo component | GraphicPromo component - dark mode | + +## Top aligned with kicker and sub headline + +| Day | Night | +| --- | --- | +| GraphicPromo component | GraphicPromo component - dark mode | + + +## Top aligned Sponsored + +| Day | Night | +| --- | --- | +| GraphicPromo component | GraphicPromo component - dark mode | + +## Bottom aligned with kicker and sub headline + +| Day | Night | +| --- | --- | +| GraphicPromo component | GraphicPromo component - dark mode | + + +## Bottom aligned Sponsored + +| Day | Night | +| --- | --- | +| GraphicPromo component | GraphicPromo component - dark mode | + + +## Installation + +Backpack Compose is available through [Maven Central](https://search.maven.org/artifact/net.skyscanner.backpack/backpack-compose). Check the main [Readme](https://github.com/skyscanner/backpack-android#installation) for a complete installation guide. + +## Usage + +Example of a GraphicPromo: + +```Kotlin +import android.util.Log +import net.skyscanner.backpack.compose.graphicpromotion.BpkGraphicPromo +import net.skyscanner.backpack.compose.graphicpromotion.Sponsor +import net.skyscanner.backpack.compose.graphicpromotion.VerticalAlignment +import net.skyscanner.backpack.compose.overlay.BpkOverlayType + + +BpkGraphicPromo( + kicker = "Travel tips", + headline = "Three Parks Challenge", + subHeadline = "How to complete the climb in 3 days", + verticalAlignment = VerticalAlignment.Bottom, + overlayType = BpkOverlayType.SolidHigh, + sponsor = BpkGraphicsPromoSponsor( + accessibilityLabel = "Sponsored", + logo = "https://images.kiwi.com/airlines/64/FR.png", + title = "Sponsored", + ), + image = { + Image( + modifier = Modifier.matchParentSize(), + painter = painterResource(id = R.drawable.graphic_promo), + contentDescription = "Image", + contentScale = ContentScale.Crop, + ) + }, sponsorLogo = { + Image( + painter = painterResource(id = R.drawable.skyland,), + contentDescription = "Image", + contentScale = ContentScale.Fit, + ) + }, + tapAction = { + Log.d("TAG", "Tap on graphic promo") + }, +) +``` diff --git a/docs/compose/GraphicPromo/screenshots/bottom-align-sponsored.png b/docs/compose/GraphicPromo/screenshots/bottom-align-sponsored.png new file mode 100644 index 0000000000..28ecf0d391 Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/bottom-align-sponsored.png differ diff --git a/docs/compose/GraphicPromo/screenshots/bottom-align-sponsored_dm.png b/docs/compose/GraphicPromo/screenshots/bottom-align-sponsored_dm.png new file mode 100644 index 0000000000..d2c65c9f34 Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/bottom-align-sponsored_dm.png differ diff --git a/docs/compose/GraphicPromo/screenshots/bottom-align-with-text.png b/docs/compose/GraphicPromo/screenshots/bottom-align-with-text.png new file mode 100644 index 0000000000..2e10245fed Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/bottom-align-with-text.png differ diff --git a/docs/compose/GraphicPromo/screenshots/bottom-align-with-text_dm.png b/docs/compose/GraphicPromo/screenshots/bottom-align-with-text_dm.png new file mode 100644 index 0000000000..d152af482f Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/bottom-align-with-text_dm.png differ diff --git a/docs/compose/GraphicPromo/screenshots/default.png b/docs/compose/GraphicPromo/screenshots/default.png new file mode 100644 index 0000000000..0f2487494e Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/default.png differ diff --git a/docs/compose/GraphicPromo/screenshots/default_dm.png b/docs/compose/GraphicPromo/screenshots/default_dm.png new file mode 100644 index 0000000000..d13f0655d8 Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/default_dm.png differ diff --git a/docs/compose/GraphicPromo/screenshots/top-align-sponsored.png b/docs/compose/GraphicPromo/screenshots/top-align-sponsored.png new file mode 100644 index 0000000000..f8d1624240 Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/top-align-sponsored.png differ diff --git a/docs/compose/GraphicPromo/screenshots/top-align-sponsored_dm.png b/docs/compose/GraphicPromo/screenshots/top-align-sponsored_dm.png new file mode 100644 index 0000000000..5404237b7a Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/top-align-sponsored_dm.png differ diff --git a/docs/compose/GraphicPromo/screenshots/top-align-with-text.png b/docs/compose/GraphicPromo/screenshots/top-align-with-text.png new file mode 100644 index 0000000000..0835fec72e Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/top-align-with-text.png differ diff --git a/docs/compose/GraphicPromo/screenshots/top-align-with-text_dm.png b/docs/compose/GraphicPromo/screenshots/top-align-with-text_dm.png new file mode 100644 index 0000000000..6d69153b8d Binary files /dev/null and b/docs/compose/GraphicPromo/screenshots/top-align-with-text_dm.png differ