Skip to content

[SR] Android - Add SourceTextButton#333

Merged
james-dudhi merged 22 commits intomainfrom
jdp/source_text_button
Feb 17, 2026
Merged

[SR] Android - Add SourceTextButton#333
james-dudhi merged 22 commits intomainfrom
jdp/source_text_button

Conversation

@james-dudhi
Copy link
Contributor

@james-dudhi james-dudhi commented Feb 11, 2026

Description

Adds a SourceTextButton composable, this represents the TextButton UI component found in our Figma design library.

Figma source of truth: Figma
Figma example in use: Figma

Testing notes/instructions:

  • Open the sample app
  • Open the "Text button previews"
  • Check the text buttons match the Figma source of truth linked above
  • In dark mode the colours of the content (the text) should match the tertiary button content colours
  • If you want to check it out in the Android news app, update the source version to 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1023.dd2c2400

Checklist

  • Changes have been checked by the developer
  • Changes have been checked by the reviewers
  • Unit tested

For pull requests introducing UI changes:

  • Sign-off by Design: @CameronArmstrong-1 @guardian/design-system @akemitakagi @dan-covill
  • Dark Mode From what I see there are no dark mode designs specified in Figma
  • Tablet
  • Accessibility (e.g. VoiceOver): Turn on talk back and check if the button title is read out followed by "button, double tap to activate" - this is standard for Android
Screenshots or videos:
Demo video Light screen shot Dark screen shot
Screen.Recording.2026-02-17.at.09.30.34.mov
Screenshot_20260217_092808 Screenshot_20260217_092748

Pressed states

Example one Example two Example three Example four Example Five
Screenshot_20260217_125927 Screenshot_20260217_125952 Screenshot_20260217_130003 Screenshot_20260217_130012 Screenshot_20260217_130024

@james-dudhi james-dudhi changed the title [SR] Add SourceTextButton to Android source [SR] Android - Add SourceTextButton Feb 11, 2026
@james-dudhi james-dudhi added feature Departmental tracking: work on a new feature Android Android specific PRs labels Feb 12, 2026
gu-gradle-library-release bot added a commit that referenced this pull request Feb 12, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-12T1219.17737eb3
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-12T1219.17737eb3
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/21946342423
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #234, based on commit 17737eb:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-12T1219.17737eb3

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

gu-gradle-library-release bot added a commit that referenced this pull request Feb 12, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-12T1343.1043d1af
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-12T1343.1043d1af
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/21949056489
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #235, based on commit 1043d1a:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-12T1343.1043d1af

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

@james-dudhi james-dudhi marked this pull request as ready for review February 13, 2026 09:55
@james-dudhi james-dudhi requested a review from a team as a code owner February 13, 2026 09:55
Copilot AI review requested due to automatic review settings February 13, 2026 09:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new SourceTextButton composable to the Android Source design system and wires it into both snapshot testing and the sample app so it can be previewed across themes and variants.

Changes:

  • Introduces SourceTextButton (with Size, Priority, optional underline) plus preview composables.
  • Adds Paparazzi snapshot tests and baseline images for the new text button variants.
  • Adds a new “Text buttons” preview surface to the sample app and bottom-sheet navigation.

Reviewed changes

Copilot reviewed 4 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
android/source/src/main/kotlin/com/gu/source/components/buttons/SourceTextButton.kt New SourceTextButton component, enums, and previews.
android/source/src/test/kotlin/com/gu/source/components/buttons/SourceButtonTest.kt Adds Paparazzi snapshot tests for underline / no-underline variants.
android/source/src/test/snapshots/images/com.gu.source.components.buttons_SourceButtonTest_sourceTextButton[NOTNIGHT].png Adds snapshot baseline image (see comments re: naming/usage).
android/source/src/test/snapshots/images/com.gu.source.components.buttons_SourceButtonTest_sourceTextButton[NIGHT].png Adds snapshot baseline image (see comments re: naming/usage).
android/source/src/test/snapshots/images/com.gu.source.components.buttons_SourceButtonTest_sourceTextButtonNoUnderline[NOTNIGHT].png Adds snapshot baseline image for no-underline variant.
android/source/src/test/snapshots/images/com.gu.source.components.buttons_SourceButtonTest_sourceTextButtonNoUnderline[NIGHT].png Adds snapshot baseline image for no-underline variant.
android/sample/src/main/kotlin/com/gu/source/previews/TextButtonPreview.kt Adds sample preview UI for text button variants.
android/sample/src/main/kotlin/com/gu/source/MainActivity.kt Adds a new bottom-sheet destination and launcher button for text button previews.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

gu-gradle-library-release bot added a commit that referenced this pull request Feb 13, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-13T0955.137c240b
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-13T0955.137c240b
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/21982493907
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #236, based on commit 137c240:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-13T0955.137c240b

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

@adi-gnm adi-gnm self-assigned this Feb 13, 2026
gu-gradle-library-release bot added a commit that referenced this pull request Feb 13, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-13T1025.a9b26d67
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-13T1025.a9b26d67
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/21983384103
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #237, based on commit a9b26d6:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-13T1025.a9b26d67

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

gu-gradle-library-release bot added a commit that referenced this pull request Feb 16, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1023.dd2c2400
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1023.dd2c2400
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/22058927160
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #238, based on commit dd2c240:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1023.dd2c2400

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

Comment on lines 55 to 56
val textStyle: TextStyle,
val minButtonHeight: Dp,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When working on a library, visibility is very important. We don't want to expose anything that the end user should not use. And changing visibility later is an ABI change so will be counted as a major version release.

Suggested change
val textStyle: TextStyle,
val minButtonHeight: Dp,
internal val textStyle: TextStyle,
internal val minButtonHeight: Dp,

/**
* Use this priority when the button is on a blue background, such as the brand color.
*/
ON_BLUE_BACKGROUND,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename these to match other button priorities, i.e. PrimaryOnBlue instead of ON_BLUE_BACKGROUND.

Comment on lines 140 to 142
ON_BLUE_BACKGROUND -> Source.Palette.Brand400
ON_WHITE_BACKGROUND -> Source.Palette.Neutral100
ON_YELLOW_BACKGROUND -> Source.Palette.BrandAlt400
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy/reuse this instead. It provides correct background for both light and dark modes. Currently dark mode previews don't look right.

internal fun getBackdropColour() = when {
name.endsWith("OnWhite") -> AppColour(
light = Source.Palette.Neutral100,
dark = Source.Palette.Neutral7,
)
name.endsWith("OnBlue") -> AppColour(
light = Source.Palette.Brand400,
dark = Source.Palette.Neutral7,
)
else -> AppColour.Unspecified
}

Comment on lines 166 to 168
hasUnderline: Boolean = false,
) {
val currentTheme = LocalSourceTheme.current
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theme should be a function argument so it can be overridden on a button by button basis too.

Suggested change
hasUnderline: Boolean = false,
) {
val currentTheme = LocalSourceTheme.current
hasUnderline: Boolean = false,
currentTheme: Source.Theme = LocalSourceTheme.current,
) {

) {
val currentTheme = LocalSourceTheme.current

TextButton(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, let's see whether we can replace this with a PlainSourceButton or PlainSourceContentButton.

@PreviewPhoneBothMode
@PreviewTabletBothMode
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal fun CoreTextButtonNoUnderlinePreview() = AppColourMode {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's marginally cheaper to have a single preview with all variants in a column. That way we commit and maintain 2 screenshots (light+dark) for the component instead of 8.

    AppColourMode {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            SourceCoreTheme {
                SourceTextButton.Priority.entries.forEach { priority ->
                    Row(
                        horizontalArrangement = Arrangement.SpaceEvenly,
                        modifier = Modifier
                            .background(color = priority.demoBackgroundColor())
                            .fillMaxWidth(),
                    ) {
                        SourceTextButton.Size.entries.forEach { size ->
                            SourceTextButton(
                                text = size.name.lowercase(),
                                priority = priority,
                                size = size,
                                onClick = {},
                            )
                        }
                    }
                }
                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 {
                    SourceTextButton.Priority.entries.forEach { priority ->
                        Row(
                            horizontalArrangement = Arrangement.SpaceEvenly,
                            modifier = Modifier
                                .background(color = priority.demoBackgroundColor())
                                .fillMaxWidth(),
                        ) {
                            SourceTextButton.Size.entries.forEach { size ->
                                SourceTextButton(
                                    text = size.name.lowercase(),
                                    priority = priority,
                                    size = size,
                                    onClick = {},
                                )
                            }
                        }
                    }

                    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 = {},
                                )
                            }
                        }
                    }
                }
            }
        }
    }

Comment on lines 62 to 65
textStyle = Source.Typography.TextSansBold17.copy(
fontSize = 15.sp,
lineHeight = 20.25.sp,
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use the existing typography preset. We really don't want to modify the presets - it defeats the purpose of them.

Suggested change
textStyle = Source.Typography.TextSansBold17.copy(
fontSize = 15.sp,
lineHeight = 20.25.sp,
),
textStyle = Source.Typography.TextSansBold15,

Comment on lines 73 to 75
textStyle = Source.Typography.TextSansBold17.copy(
lineHeight = 22.95.sp,
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. This also reminds me - the text button should not support multiline text, maxLines = 1 with ellipsize. And since line height is only relevant for spacing between lines, it becomes irrelevant.

Suggested change
textStyle = Source.Typography.TextSansBold17.copy(
lineHeight = 22.95.sp,
),
textStyle = Source.Typography.TextSansBold17,

@james-dudhi james-dudhi force-pushed the jdp/source_text_button branch from 09fae6f to 97376b9 Compare February 16, 2026 17:28
@james-dudhi james-dudhi force-pushed the jdp/source_text_button branch from 97376b9 to 7d11e97 Compare February 16, 2026 17:34
gu-gradle-library-release bot added a commit that referenced this pull request Feb 16, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1833.6ae2b1fb
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1833.6ae2b1fb
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/22073893090
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #239, based on commit 6ae2b1f:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-16T1833.6ae2b1fb

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

) {
Text(
text = text,
style = size.textStyle,
Copy link
Member

@adi-gnm adi-gnm Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Small button text size is different for regular (17) and text buttons (15). Either define additional property in Size - textButtonTextStyle - or create a local extension property Size.textButtonTextStyle in this file.

textButtonTextStyle.patch

gu-gradle-library-release bot added a commit that referenced this pull request Feb 17, 2026
… by james-dudhi

james-dudhi published release version 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-17T0935.bd99969d
using gha-gradle-library-release-workflow: https://github.com/guardian/gha-gradle-library-release-workflow

Release-Version: 8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-17T0935.bd99969d
Release-Initiated-By: https://github.com/james-dudhi
Release-Workflow-Run: https://github.com/guardian/source-apps/actions/runs/22093214996
Release-Notes: #333
@gu-gradle-library-release
Copy link
Contributor

@james-dudhi has published a preview version of this PR with release workflow run #240, based on commit bd99969:

8.0.0-PREVIEW.jdpsourcetextbutton.2026-02-17T0935.bd99969d

Want to make another preview release?

Click 'Run workflow' in the GitHub UI, specifying the jdp/source_text_button branch, or use the GitHub CLI command:

gh workflow run release.yml --ref jdp/source_text_button

Want to make a full release after this PR is merged?

Click 'Run workflow' in the GitHub UI, leaving the branch as the default, or use the GitHub CLI command:

gh workflow run release.yml

Copy link
Member

@adi-gnm adi-gnm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work.

One suggestion (for separate PR): Instead of adding another destination in the sample for Text button, we should refactor the existing Buttons preview screen into four parts

  • regular button,
  • text button,
  • icon button,
  • custom button

@james-dudhi
Copy link
Contributor Author

Nice work.

One suggestion (for separate PR): Instead of adding another destination in the sample for Text button, we should refactor the existing Buttons preview screen into four parts

  • regular button,
  • text button,
  • icon button,
  • custom button

Thanks for reviewing, I will take this up!

@james-dudhi james-dudhi added this pull request to the merge queue Feb 17, 2026
Merged via the queue into main with commit c9568e4 Feb 17, 2026
13 checks passed
@james-dudhi james-dudhi deleted the jdp/source_text_button branch February 17, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Android Android specific PRs feature Departmental tracking: work on a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants