Skip to content

CardFields feature#1626

Merged
noguier merged 22 commits into
mainfrom
card-fields-feature
Jun 30, 2026
Merged

CardFields feature#1626
noguier merged 22 commits into
mainfrom
card-fields-feature

Conversation

@noguier

@noguier noguier commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary of changes

  • A completed work of CardFields feature

AI Usage

Which AI Agent Was Used?

  • Copilot
  • Claude
  • Other (Type Name Here)

How was AI used?
Brainstorming, tests generation, troubleshooting

Estimated AI Code Contribution

  • less than 30%
  • 30 - 60%
  • 60 - 100%

Checklist

  • Added a changelog entry
  • Tested and confirmed payment flows affected by this change are functioning as expected

Authors

List GitHub usernames for everyone who contributed to this pull request.
@noguier , @saralvasquez , @buzzamus

noguier and others added 21 commits April 10, 2026 12:51
* custom ui for hint animation on focus, error, etc, created a basetextinputview that will be a base view for card input, cvv and expiration
* feat: add CardNumberTextInputView for CardFields

* fix: change function name to more descriptive

* fix: fix failing test in CI by increasing the timeout
…ction (#1595)

* feat: add CardNumberTextInputView for CardFields

* feat: add Vector drawables for card brands

* feat: Add CardBrand enum and LuhnValidator for CardFields feature

* feat: Add CardNumberFormatter with dynamic brand detection and formatting, add elo, mir, and verve to supported card brands

* fix: address PR feedback: remove CHANGELOG entry, added more descriptive variable names

* fix: exclude 622 prefix from UnionPay to only match with Discover

* fix: unit tests for prefix 622
* feature: add expiration functionality and unit tests

* fix: resolve lint issue

* feature: add accessability features

* fix: address PR comments

* fix: rename isValidMonth

* fix: update dependencies file
* feature: first pass at adding cvv field

* feature: add card type adjustment and change overlay style

* fix: modify overlay formatting and fix cvv length bug

* fix: replace error vector image

* fix: resolve changes in error image

* fix: lint issues

* fix: add error back to base text

* Fix for copilot pull request finding

* Fix for copilot pull request finding

* fix: fix copilot commit issues and add another review suggestion

* pr-feedback: rename hint method names

* pr-feedback: match the overlay closer to the figma

* pr-feedback: change overlay text to include 4 digit number
* feature: first pass at adding cvv field

* feature: add card type adjustment and change overlay style

* fix: modify overlay formatting and fix cvv length bug

* fix: replace error vector image

* fix: resolve changes in error image

* fix: lint issues

* fix: add error back to base text

* feat: add validation use cases for cc number, expiration date and cvv

* fix: rename UseCase file to match TextViews

* fix: restore ExpirationValidationUseCase and its tests

* fix: fix lint

---------

Co-authored-by: Sara Vasquez <saravasquez@paypal.com>
* feature: first pass at adding cvv field

* feature: add card type adjustment and change overlay style

* fix: modify overlay formatting and fix cvv length bug

* fix: replace error vector image

* fix: resolve changes in error image

* fix: lint issues

* fix: add error back to base text

* feat: add validation use cases for cc number, expiration date and cvv

* fix: rename UseCase file to match TextViews

* fix: restore ExpirationValidationUseCase and its tests

* fix: fix lint

* feat: align validation use cases with iOS three-state ValidationResult

* fix: lint

* fix: lint

* fix: align error wording with iOS

---------

Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>
Co-authored-by: Sara Vasquez <saravasquez@paypal.com>
* feature: first pass at adding cvv field

* feature: add card type adjustment and change overlay style

* fix: modify overlay formatting and fix cvv length bug

* fix: replace error vector image

* fix: resolve changes in error image

* fix: lint issues

* fix: add error back to base text

* feat: add validation use cases for cc number, expiration date and cvv

* fix: rename UseCase file to match TextViews

* fix: restore ExpirationValidationUseCase and its tests

* fix: fix lint

* feat: align validation use cases with iOS three-state ValidationResult

* fix: lint

* fix: lint

* fix: align error wording with iOS

* feat: create CardFieldsViewModel

* fix : lint

* fix: make sure that fixed date for the tests is further in the past per PR suggestion

---------

Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>
Co-authored-by: Sara Vasquez <saravasquez@paypal.com>
* feature: first pass at adding cvv field

* feature: add card type adjustment and change overlay style

* fix: modify overlay formatting and fix cvv length bug

* fix: replace error vector image

* fix: resolve changes in error image

* fix: lint issues

* fix: add error back to base text

* feat: add validation use cases for cc number, expiration date and cvv

* fix: rename UseCase file to match TextViews

* fix: restore ExpirationValidationUseCase and its tests

* fix: fix lint

* feat: align validation use cases with iOS three-state ValidationResult

* fix: lint

* fix: lint

* fix: align error wording with iOS

* feat: create CardFieldsViewModel

* fix : lint

* feat: create Card Fields class and use it in the demo

* fix: add docs, lint

* fix: PR suggestions

---------

Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>
Co-authored-by: Sara Vasquez <saravasquez@paypal.com>
* feat: add card payment end-to-end flow to CardFields

* fix: address KDoc suggestion
* Add CardFields Analytic Events
* feat: add card payment end-to-end flow to CardFields

* fix: address KDoc suggestion

* feat: beautify Demo integration and align with iOS

* fix: use `WindowInsetsCompat.ime()` to push the card-fields component up when the keyboard is shown

* [copilot]: Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>

* fix: Address Copilot's PR suggestions

---------

Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…o app (#1622)

* feat: add card payment end-to-end flow to CardFields

* fix: address KDoc suggestion

* feat: beautify Demo integration and align with iOS

* fix: use `WindowInsetsCompat.ime()` to push the card-fields component up when the keyboard is shown

* [copilot]: Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>

* fix: Address Copilot's PR suggestions

* feat: Put CardFields and PaymentButtons under the same Demo Fragment

* fix: fix tests after the merge

* fix: address Copilot suggestions

* fix: address PR comments

---------

Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* feat: update `README` with cardFields info

* fix: address PR comments

* fix: address PR comments
* feat: add card payment end-to-end flow to CardFields

* fix: address KDoc suggestion

* feat: beautify Demo integration and align with iOS

* fix: use `WindowInsetsCompat.ime()` to push the card-fields component up when the keyboard is shown

* [copilot]: Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>

* fix: Address Copilot's PR suggestions

* feature: save state for all fields

* feature: add saved state for field errors

* fix: keep amex cvv length on rotation

* fix: clean up unneeded comments

* fix: resolve unit test errors by passing analyticsClient to card fields

* feat: Put CardFields and PaymentButtons under the same Demo Fragment

* fix: fix tests after the merge

* fix: address Copilot suggestions

* fix: address PR comments

* fix: remove unnecessary error check on `ExpirationTextInputView`, now error checks only live in ViewModel. Matches iOS

* fix: make classes internal

* fix: address PR suggestions

* fix: fix failing test

---------

Signed-off-by: Anastasiia Noguier <anoguier@paypal.com>
Co-authored-by: anoguier <anoguier@paypal.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(uicomponents): Trigger CVV validation errors when card type changes and doesn't match cvv length

* Fix: keep submit button valid if all fields are valid when rotating phone
@noguier noguier requested review from a team and Copilot June 29, 2026 23:37
@noguier noguier requested a review from a team as a code owner June 29, 2026 23:37
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities found.

Scanned Files

  • settings.gradle

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 CardFields UI component to the UIComponents module, providing a prebuilt card-entry form (card number, expiration, CVV) with formatting, brand detection, validation, and tokenization via CardClient. Also updates the Demo app to surface the new UI Components screen and adds unit/instrumentation test coverage.

Changes:

  • Introduces CardFields view + supporting ViewModel/formatters/validators/resources for card input and tokenization.
  • Adds extensive unit + instrumentation tests (incl. Robolectric setup) for formatting, validation, accessibility, and state restoration.
  • Updates Demo navigation/UI to a new UIComponentsFragment and documents the feature in README/CHANGELOG/dependency docs.

Reviewed changes

Copilot reviewed 68 out of 69 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
UIComponents/src/test/resources/robolectric.properties Configures Robolectric SDK level for UIComponents unit tests.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/LuhnValidatorUnitTest.kt Unit tests for Luhn checksum validation behavior.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/ExpirationValidationUseCaseUnitTest.kt Unit tests for expiration validation rules.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/ExpirationTextInputViewUnitTest.kt Robolectric tests for expiration input formatting and accessibility.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/ExpirationDateFormatterUnitTest.kt Unit tests for expiration formatter behavior and cursor logic.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CvvValidationUseCaseUnitTest.kt Unit tests for CVV validation per brand.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CvvTextInputViewUnitTest.kt Robolectric tests for CVV input constraints and hint overlay behavior.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CardNumberValidationUseCaseUnitTest.kt Unit tests for card number validation + brand detection integration.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CardNumberTextInputViewUnitTest.kt Robolectric tests for card number input formatting, icon updates, and listener behavior.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CardNumberFormatterUnitTest.kt Unit tests for card number formatting and cursor preservation logic.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CardFieldsViewModelUnitTest.kt Unit tests for ViewModel validation state machine and form validity aggregation.
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/CardBrandUnitTest.kt Unit tests for brand detection and brand metadata (lengths/gaps/cvv rules).
UIComponents/src/test/java/com/braintreepayments/api/uicomponents/cardfields/BaseTextInputViewUnitTest.kt Robolectric tests for base input view hint/error behavior.
UIComponents/src/main/res/values/strings_card_fields.xml Adds CardFields strings (hints, errors, brand labels, overlay text).
UIComponents/src/main/res/values/dimens.xml Adds CardFields sizing/spacing dimensions and overlay dimensions.
UIComponents/src/main/res/values/colors.xml Adds CardFields colors (borders, text, background, error).
UIComponents/src/main/res/layout/cvv_hint_overlay.xml Layout for the CVV hint popup overlay.
UIComponents/src/main/res/layout/card_fields_view.xml Layout composing card number + expiration + CVV subviews.
UIComponents/src/main/res/layout/base_text_input.xml Base input layout used by all CardFields subviews.
UIComponents/src/main/res/drawable/ic_card_field_error.xml Error icon vector for inline validation UI.
UIComponents/src/main/res/drawable/cvv_hint.xml CVV hint icon vector.
UIComponents/src/main/res/drawable/cvv_hint_close.xml Close icon vector for the CVV overlay.
UIComponents/src/main/res/drawable/card_fields_cc_visa.xml Visa brand icon vector.
UIComponents/src/main/res/drawable/card_fields_cc_unknown.xml Default/unknown card brand icon vector.
UIComponents/src/main/res/drawable/card_fields_cc_union_pay.xml UnionPay brand icon vector.
UIComponents/src/main/res/drawable/card_fields_cc_mastercard.xml Mastercard brand icon vector.
UIComponents/src/main/res/drawable/card_fields_cc_jcb.xml JCB brand icon vector.
UIComponents/src/main/res/drawable/card_fields_cc_amex.xml Amex brand icon vector.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/UIComponentsAnalytics.kt Adds analytics event constants for CardFields presented/validated.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/ValidationResult.kt Adds ValidationResult sealed type used by view model and UI.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/LuhnValidator.kt Adds Luhn checksum validator implementation.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/ExpirationValidationUseCase.kt Adds expiration MMYY validation logic.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/ExpirationTextInputView.kt Adds expiration input view with formatter/autofill hints.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/ExpirationDateFormatter.kt Adds expiration formatter (MM/YY) + cursor management.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CvvValidationUseCase.kt Adds CVV validation logic keyed to card brand.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CvvTextInputView.kt Adds CVV input view with length filtering and hint overlay wiring.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CvvHintOverlay.kt Adds PopupWindow overlay implementation for CVV hint.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CvvFormatter.kt Adds digit-only CVV formatter with truncation + length filter updates.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardNumberValidationUseCase.kt Adds card number validation + brand detection + UnionPay Luhn exception.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardNumberTextInputView.kt Adds card number input view with brand icon updates and formatting.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardNumberFormatter.kt Adds card number formatter inserting spaces per brand gaps + cursor preservation.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardFieldsViewModel.kt Adds ViewModel coordinating validation, blur rules, and overall form validity.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardFieldsResultCallback.kt Adds callback interface for CardFields submission results.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardFieldsResult.kt Adds result type (Success/Failure) for CardFields submission.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardFields.kt Adds the public CardFields view that wires UI + ViewModel + tokenization + state saving.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardField.kt Adds enum identifying fields for focus/blur validation.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/CardBrand.kt Adds card brand detection rules, formatting gaps, icon mapping, and CVV rules.
UIComponents/src/main/java/com/braintreepayments/api/uicomponents/cardfields/BaseTextInputView.kt Adds reusable input widget with floating label, icons, and error presentation.
UIComponents/src/androidTest/java/com/braintreepayments/api/uicomponents/cardfields/CardFieldsTestActivity.kt Adds test harness Activity for CardFields instrumentation tests.
UIComponents/src/androidTest/java/com/braintreepayments/api/uicomponents/cardfields/CardFieldsTest.kt Adds instrumentation tests for validation UI, brand detection, rotation state, and submit-before-init.
UIComponents/src/androidTest/AndroidManifest.xml Declares the CardFields test Activity for androidTest.
UIComponents/build.gradle Adds :Card dependency, Autofill, and Robolectric/androidx-test-core for tests.
README.md Documents CardFields integration steps and usage example.
gradle/libs.versions.toml Adds androidx.autofill:autofill dependency entry and version.
DEPENDENCIES.md Updates dependency list to include :Card and androidx.autofill.
Demo/src/main/res/values/styles.xml Adds a compact toggle button style for demo UI.
Demo/src/main/res/values/strings.xml Adds new demo strings and removes the Payment Buttons label.
Demo/src/main/res/navigation/nav_graph.xml Replaces PaymentButtonsFragment route with UIComponentsFragment route.
Demo/src/main/res/layout/fragment_ui_components.xml Updates demo screen layout to include CardFields and reorganize toggles/buttons.
Demo/src/main/res/drawable/card_fields_pay_button_background.xml Adds a custom background selector for the CardFields demo “Pay” button.
Demo/src/main/java/com/braintreepayments/demo/UIComponentsFragment.kt Adds the demo fragment showcasing CardFields + existing buttons.
Demo/src/main/java/com/braintreepayments/demo/PaymentButtonsFragment.java Removes the old PaymentButtonsFragment implementation.
Demo/src/main/java/com/braintreepayments/demo/MainFragment.kt Updates main menu to launch the new UI Components screen.
Demo/src/main/java/com/braintreepayments/demo/DemoActivity.java Updates insets handling to include IME and to not consume insets.
Demo/src/androidTest/java/com/braintreepayments/demo/test/UIInteractionStatesTest.kt Updates UI automation to navigate via “UI Components”.
Demo/src/androidTest/java/com/braintreepayments/demo/test/PaymentButtonsColorTest.kt Updates UI automation to navigate via “UI Components”.
CHANGELOG.md Adds changelog entry announcing CardFields in UIComponents.

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

Comment thread UIComponents/src/main/res/layout/base_text_input.xml
Comment thread UIComponents/src/main/res/drawable/ic_card_field_error.xml

@buzzamus buzzamus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pulled down and tested a bunch of scenarios. All looks good great work!

@tdchow

tdchow commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Very excited to see the card fields feature complete! 🙌

@agedd agedd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

amazing work @noguier!! 🚀

@noguier noguier merged commit e057a59 into main Jun 30, 2026
11 of 24 checks passed
@noguier noguier deleted the card-fields-feature branch June 30, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants