-
Notifications
You must be signed in to change notification settings - Fork 1
[SR] Android - Add SourceTextButton #333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
james-dudhi
wants to merge
15
commits into
main
Choose a base branch
from
jdp/source_text_button
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+379
−0
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
0ebe85b
[SR] Add SourceTextButton to Android source
james-dudhi 2301ea7
[SR] Update SourceTextButton.kt
james-dudhi 25af43b
[SR] Use TextButton as the base for SourceTextButton
james-dudhi af64360
[SR] Update preview for SourceTextButton
james-dudhi daf0262
[SR] Add screen shot tests
james-dudhi c639d52
[SR] Update access modifier
james-dudhi ae95c04
[SR] Reduce duplication in SourceTextButtonPreview
james-dudhi 17737eb
[SR] Lint and detekt
james-dudhi 56f5f12
[SR] Update screen shot tests
james-dudhi 1043d1a
[SR] Add button previews to sample app
james-dudhi e405faa
[SR] Update SourceTextButton to support themes
james-dudhi bba2562
[SR] Add underline to sourcetextbutton
james-dudhi 137c240
[SR] Update names of previews
james-dudhi a9b26d6
[SR] Remove duplication
james-dudhi 35d823f
[SR] Remove irrelevant snapshots
james-dudhi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
android/sample/src/main/kotlin/com/gu/source/previews/TextButtonPreview.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| package com.gu.source.previews | ||
|
|
||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.Row | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Alignment.Companion.CenterHorizontally | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import com.gu.source.Source | ||
| import com.gu.source.components.buttons.SourceTextButton | ||
| import com.gu.source.components.buttons.SourceTextButton.Priority.ON_BLUE_BACKGROUND | ||
| import com.gu.source.components.buttons.SourceTextButton.Priority.ON_WHITE_BACKGROUND | ||
| import com.gu.source.components.buttons.SourceTextButton.Priority.ON_YELLOW_BACKGROUND | ||
| import com.gu.source.components.theme.ReaderRevenueTheme | ||
| import com.gu.source.foundation.palette.Brand400 | ||
| import com.gu.source.foundation.palette.BrandAlt400 | ||
| import com.gu.source.foundation.palette.Neutral100 | ||
| import com.gu.source.foundation.typography.TextSansBold17 | ||
|
|
||
| @Composable | ||
| internal fun TextButtonPreview(modifier: Modifier = Modifier) { | ||
| Column( | ||
| modifier = modifier.padding(8.dp), | ||
| verticalArrangement = Arrangement.spacedBy(8.dp), | ||
| ) { | ||
| Text( | ||
| text = "Core Theme text button - no underline - variants", | ||
| style = Source.Typography.TextSansBold17, | ||
| ) | ||
| TextButtonRows() | ||
| Text( | ||
| text = "Reader Revenue theme text button - no underline - variant", | ||
| style = Source.Typography.TextSansBold17, | ||
| ) | ||
| ReaderRevenueTheme { | ||
| TextButtonRows() | ||
| } | ||
| Text( | ||
| text = "Core Theme text button - underline - variants", | ||
| style = Source.Typography.TextSansBold17, | ||
| ) | ||
| TextButtonRows(textButtonHasUnderline = true) | ||
| Text( | ||
| text = "Reader Revenue theme text button - underline - variant", | ||
| style = Source.Typography.TextSansBold17, | ||
| ) | ||
| ReaderRevenueTheme { | ||
| TextButtonRows(textButtonHasUnderline = true) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| private fun TextButtonRows(textButtonHasUnderline: Boolean = false) { | ||
| Column(horizontalAlignment = CenterHorizontally) { | ||
| SourceTextButton.Priority.entries.forEach { priority -> | ||
| val backgroundColor = when (priority) { | ||
| ON_BLUE_BACKGROUND -> Source.Palette.Brand400 | ||
| ON_WHITE_BACKGROUND -> Source.Palette.Neutral100 | ||
| ON_YELLOW_BACKGROUND -> Source.Palette.BrandAlt400 | ||
| } | ||
| Row( | ||
| horizontalArrangement = Arrangement.SpaceEvenly, | ||
| modifier = Modifier | ||
| .background(color = backgroundColor) | ||
| .fillMaxWidth(), | ||
| ) { | ||
| SourceTextButton.Size.entries.forEach { size -> | ||
| SourceTextButton( | ||
| text = "text button - ${size.name.lowercase()}", | ||
| priority = priority, | ||
| size = size, | ||
| hasUnderline = textButtonHasUnderline, | ||
| onClick = {}, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Preview | ||
| @Composable | ||
| private fun TextButtonsPreview() { | ||
| TextButtonPreview() | ||
| } | ||
259 changes: 259 additions & 0 deletions
259
android/source/src/main/kotlin/com/gu/source/components/buttons/SourceTextButton.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,259 @@ | ||
| package com.gu.source.components.buttons | ||
|
|
||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.Row | ||
| import androidx.compose.foundation.layout.defaultMinSize | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.shape.CircleShape | ||
| import androidx.compose.material3.ButtonDefaults | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.material3.TextButton | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.Color | ||
| import androidx.compose.ui.text.TextStyle | ||
| import androidx.compose.ui.text.style.TextDecoration | ||
| import androidx.compose.ui.unit.Dp | ||
| import androidx.compose.ui.unit.dp | ||
| import androidx.compose.ui.unit.sp | ||
| import com.gu.source.Source | ||
| import com.gu.source.components.theme.LocalSourceTheme | ||
| import com.gu.source.components.theme.ReaderRevenueTheme | ||
| import com.gu.source.foundation.palette.Brand400 | ||
| import com.gu.source.foundation.palette.BrandAlt400 | ||
| import com.gu.source.foundation.palette.Neutral0 | ||
| import com.gu.source.foundation.palette.Neutral100 | ||
| import com.gu.source.foundation.typography.TextSansBold17 | ||
| import com.gu.source.utils.PreviewPhoneBothMode | ||
james-dudhi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import com.gu.source.utils.PreviewTabletBothMode | ||
|
|
||
| /** | ||
| * SourceTextButton is a text button component that can be used in the Source design system. | ||
| * It is a simple button that contains text and has no background. | ||
| * The color of the text is determined by the priority of the button, | ||
| * which should be chosen based on the background color of the button. | ||
| */ | ||
| object SourceTextButton { | ||
|
|
||
| /** | ||
| * The size of the button, which determines | ||
| * the typography style of the text and the minimum height of the button. | ||
| * | ||
| * @property textStyle The typography style of the text inside the button. | ||
| * @property minButtonHeight The minimum height of the button. | ||
| */ | ||
| enum class Size( | ||
| val textStyle: TextStyle, | ||
| val minButtonHeight: Dp, | ||
| ) { | ||
| /** | ||
| * The small size of the button. | ||
| */ | ||
| SMALL( | ||
| textStyle = Source.Typography.TextSansBold17.copy( | ||
| fontSize = 15.sp, | ||
| lineHeight = 20.25.sp, | ||
| ), | ||
| minButtonHeight = 20.dp, | ||
| ), | ||
|
|
||
| /** | ||
| * The medium size of the button. | ||
| */ | ||
| MEDIUM( | ||
| textStyle = Source.Typography.TextSansBold17.copy( | ||
| lineHeight = 22.95.sp, | ||
| ), | ||
| minButtonHeight = 23.dp, | ||
james-dudhi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ), | ||
| } | ||
|
|
||
| /** | ||
| * The priority of the button, which determines the color of the text. | ||
| * This should be chosen based on the background color of the button. | ||
| */ | ||
| enum class Priority { | ||
| /** | ||
| * Use this priority when the button is on a blue background, such as the brand color. | ||
| */ | ||
| ON_BLUE_BACKGROUND, | ||
|
|
||
| /** | ||
| * Use this priority when the button is on a white background. | ||
| */ | ||
| ON_WHITE_BACKGROUND, | ||
|
|
||
| /** | ||
| * Use this priority when the button is on a yellow background, such as the brand alt color. | ||
| */ | ||
| ON_YELLOW_BACKGROUND, | ||
| ; | ||
|
|
||
| internal fun textColor(theme: Source.Theme): Color = when (this) { | ||
| ON_BLUE_BACKGROUND -> if (theme == Source.Theme.ReaderRevenue) { | ||
| Source.Palette.BrandAlt400 | ||
| } else { | ||
| Source.Palette.Neutral100 | ||
| } | ||
|
|
||
| ON_WHITE_BACKGROUND -> Source.Palette.Brand400 | ||
| ON_YELLOW_BACKGROUND -> Source.Palette.Neutral0 | ||
| } | ||
|
|
||
| internal fun demoBackgroundColor(): Color = when (this) { | ||
| ON_BLUE_BACKGROUND -> Source.Palette.Brand400 | ||
| ON_WHITE_BACKGROUND -> Source.Palette.Neutral100 | ||
| ON_YELLOW_BACKGROUND -> Source.Palette.BrandAlt400 | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * A text button is a button that contains text and has no background. | ||
| * It can be used in places where a less prominent action is needed. | ||
| * | ||
| * @param text The text to display inside the button. | ||
| * @param priority The priority of the button, which determines the color of the text. | ||
| * This should be chosen based on the background color of the button. | ||
| * @param size The size of the button, which determines the typography style of the text. | ||
| * @param onClick The callback to be invoked when this button is clicked. | ||
| * @param modifier The [Modifier] to be applied to this button. | ||
| * @param hasUnderline Whether the text inside the button should have an underline. | ||
| */ | ||
| @Composable | ||
| fun SourceTextButton( | ||
| text: String, | ||
| priority: SourceTextButton.Priority, | ||
| size: SourceTextButton.Size, | ||
| onClick: () -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| hasUnderline: Boolean = false, | ||
| ) { | ||
| val currentTheme = LocalSourceTheme.current | ||
|
|
||
| TextButton( | ||
| shape = CircleShape, | ||
| elevation = ButtonDefaults.buttonElevation( | ||
| defaultElevation = 0.dp, | ||
| pressedElevation = 0.dp, | ||
| focusedElevation = 0.dp, | ||
| hoveredElevation = 0.dp, | ||
| disabledElevation = 0.dp, | ||
| ), | ||
| onClick = onClick, | ||
| modifier = modifier.defaultMinSize(minHeight = size.minButtonHeight), | ||
| ) { | ||
| Text( | ||
| text = text, | ||
| style = size.textStyle.copy( | ||
| color = priority.textColor(theme = currentTheme), | ||
| textDecoration = if (hasUnderline) { | ||
| TextDecoration.Underline | ||
| } else { | ||
| null | ||
| }, | ||
| ), | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| @PreviewPhoneBothMode | ||
| @PreviewTabletBothMode | ||
| internal fun SourceTextButtonNoUnderlinePreview() { | ||
| Column { | ||
| Column(horizontalAlignment = Alignment.CenterHorizontally) { | ||
| SourceTextButton.Priority.entries.forEach { priority -> | ||
| Row( | ||
| horizontalArrangement = Arrangement.SpaceEvenly, | ||
| modifier = Modifier | ||
| .background(priority.demoBackgroundColor()) | ||
| .fillMaxWidth(), | ||
| ) { | ||
| SourceTextButton.Size.entries.forEach { size -> | ||
| SourceTextButton( | ||
| text = size.name.lowercase(), | ||
| priority = priority, | ||
| size = size, | ||
| onClick = {}, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ReaderRevenueTheme { | ||
| Column(horizontalAlignment = Alignment.CenterHorizontally) { | ||
| SourceTextButton.Priority.entries.forEach { priority -> | ||
| Row( | ||
| horizontalArrangement = Arrangement.SpaceEvenly, | ||
| modifier = Modifier | ||
| .background(priority.demoBackgroundColor()) | ||
| .fillMaxWidth(), | ||
| ) { | ||
| SourceTextButton.Size.entries.forEach { size -> | ||
| SourceTextButton( | ||
| text = size.name.lowercase(), | ||
| priority = priority, | ||
| size = size, | ||
| onClick = {}, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| @PreviewPhoneBothMode | ||
| @PreviewTabletBothMode | ||
| internal fun SourceTextButtonUnderlinePreview() { | ||
| Column { | ||
| Column(horizontalAlignment = Alignment.CenterHorizontally) { | ||
| SourceTextButton.Priority.entries.forEach { priority -> | ||
| Row( | ||
| horizontalArrangement = Arrangement.SpaceEvenly, | ||
| modifier = Modifier | ||
| .background(priority.demoBackgroundColor()) | ||
| .fillMaxWidth(), | ||
| ) { | ||
| SourceTextButton.Size.entries.forEach { size -> | ||
| SourceTextButton( | ||
| text = size.name.lowercase(), | ||
| priority = priority, | ||
| size = size, | ||
| hasUnderline = true, | ||
| onClick = {}, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ReaderRevenueTheme { | ||
| Column(horizontalAlignment = Alignment.CenterHorizontally) { | ||
| SourceTextButton.Priority.entries.forEach { priority -> | ||
| Row( | ||
| horizontalArrangement = Arrangement.SpaceEvenly, | ||
| modifier = Modifier | ||
| .background(priority.demoBackgroundColor()) | ||
| .fillMaxWidth(), | ||
| ) { | ||
| SourceTextButton.Size.entries.forEach { size -> | ||
| SourceTextButton( | ||
| text = size.name.lowercase(), | ||
| priority = priority, | ||
| size = size, | ||
| hasUnderline = true, | ||
| onClick = {}, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.