Skip to content

Pp 2078 provide color keys per element#883

Open
abolfazlimahdi wants to merge 2 commits intomainfrom
PP-2078-provide-color-keys-per-element
Open

Pp 2078 provide color keys per element#883
abolfazlimahdi wants to merge 2 commits intomainfrom
PP-2078-provide-color-keys-per-element

Conversation

@abolfazlimahdi
Copy link
Copy Markdown
Contributor

@abolfazlimahdi abolfazlimahdi commented Feb 17, 2026

Atruvia supports 25–30 color themes for their banking customers. They currently manually override colors for multiple UI components. They requested more (ideally all) components be color-customizable to speed up publishing the photo payment module.

This is my proposal for providing color keys per element.

Transition to Element-Specific Color Keys (XML)
In commit c0e5abe, the project moved away from using generic color primitives directly in layouts. Previously, UI elements like the camera title in gc_fragment_camera.xml were hardcoded to use general colors like @color/gc_light_01.
The update introduced element_colors.xml, which defines semantic color keys such as gc_camera_title_color. This allows developers to theme specific UI elements without affecting others that might share the same base color. For example, changing the camera title color no longer requires changing the global gc_light_01 value, providing much better flexibility for white-labeling and customization.

Integration with Jetpack Compose
In commit 76943d8, this semantic approach was extended to the Compose-based elements. A new class, GiniColorElementsPrimitives, was introduced to act as a bridge. It reads these new semantic XML color keys and maps them into the Compose GiniColorScheme.
Key technical changes include:
• GiniColorElementsPrimitives: A new data class that holds element-specific colors (e.g., skontoSectionTitleTextColor) and initializes them from Android resources.
• Theme Expansion: The GiniColorScheme and GiniTheme were updated to include a SkontoSection color group. This ensures that even the most specific UI components (like the Skonto section titles) are now part of the unified theme state.
• Dynamic Updating: The giniLightColorScheme and giniDarkColorScheme functions now accept these element primitives, ensuring that both light and dark modes respect the new specific color overrides.

How the clients can use:

For clients who are used to the old color mapping: no changes will happen. They can still override our color palette and customize our SDK.

For clients who need more detailed and customizable SDK, they need to override the elements that they need. This still uses our color palette and if clients don’t override some colors, we’ll use the colors from our color palette.

Copy link
Copy Markdown

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

Introduces element-specific color “keys” (resource names) so SDK consumers can override colors per UI element, and wires one of these element overrides into the Compose GiniTheme for the Skonto section.

Changes:

  • Added new element_colors.xml with element-level color resources (e.g., camera title, Skonto section title).
  • Updated camera fragment layout to use the new gc_camera_title_color resource key.
  • Extended Compose theming (GiniColorScheme) with a skontoSection group sourced from a new GiniColorElementsPrimitives, and switched the Bank SDK Skonto title to use it.

Reviewed changes

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

Show a summary per file
File Description
capture-sdk/sdk/src/main/res/values/element_colors.xml Adds element-level color resources to be overridden by consumers
capture-sdk/sdk/src/main/res/layout/gc_fragment_camera.xml Uses gc_camera_title_color instead of a primitive color directly
capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/theme/colors/GiniColorPalette.kt Extends GiniColorScheme and maps element primitives into light/dark schemes
capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/theme/colors/GiniColorElementsPrimitives.kt Introduces resource-to-Compose bridge for element colors
capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/theme/GiniTheme.kt Builds and passes element primitives into the Compose color scheme
bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/colors/section/SkontoSectionColors.kt Defaults Skonto title color to the new element-specific scheme color
bank-sdk/example-app/src/main/res/values/colors.xml Demonstrates overriding the new element-level color resources

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

val skontoSection: SkontoSection = SkontoSection()

) {

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

GiniColorScheme is a public data class, and adding the new skontoSection constructor parameter changes the generated constructor/copy/componentN signatures. This is a binary-incompatible API change for any already-compiled consumers of the published SDK. To avoid breaking clients, consider a non-constructor property, or provide a compatibility secondary constructor matching the previous signature (or confirm this ships only with a major version bump).

Suggested change
// Binary-compatibility secondary constructor matching the previous signature (without skontoSection)
constructor(
background: Background = Background(),
bottomBar: BottomBar = BottomBar(),
topAppBar: TopAppBar = TopAppBar(),
placeholder: Placeholder = Placeholder(),
text: Text = Text(),
card: Card = Card(),
badge: Badge = Badge(),
button: Button = Button(),
buttonOutlined: ButtonOutlined = ButtonOutlined(),
progressBarButton: ProgressBarButton = ProgressBarButton(),
textField: TextField = TextField(),
toggles: Toggles = Toggles(),
dialogs: Dialogs = Dialogs(),
icons: Icons = Icons(),
datePicker: DatePicker = DatePicker(),
checkbox: Checkbox = Checkbox(),
contextMenu: ContextMenu = ContextMenu(),
logo: Logo = Logo(),
) : this(
background = background,
bottomBar = bottomBar,
topAppBar = topAppBar,
placeholder = placeholder,
text = text,
card = card,
badge = badge,
button = button,
buttonOutlined = buttonOutlined,
progressBarButton = progressBarButton,
textField = textField,
toggles = toggles,
dialogs = dialogs,
icons = icons,
datePicker = datePicker,
checkbox = checkbox,
contextMenu = contextMenu,
logo = logo,
skontoSection = SkontoSection(),
)

Copilot uses AI. Check for mistakes.
}
@Immutable
data class SkontoSection(
val skontoSectionTitleTextColor: Color = Color.Unspecified,
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The property name skontoSectionTitleTextColor inside SkontoSection is redundant/inconsistent with the rest of GiniColorScheme (e.g., Text.primary, Logo.tint). Renaming it to something like titleTextColor would avoid the skontoSection.skontoSectionTitleTextColor repetition and make the API easier to read.

Suggested change
val skontoSectionTitleTextColor: Color = Color.Unspecified,
val titleTextColor: Color = Color.Unspecified,

Copilot uses AI. Check for mistakes.
<resources>

<color name="gc_camera_title_color">@color/gc_light_01</color>
<color name="skonto_section_title_text_color">@color/gc_dark_02</color>
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

skonto_section_title_text_color defaults to @color/gc_dark_02, but in the dark Compose color scheme the Skonto section title is rendered on a card with containerColor = dark02 (see GiniColorScheme.card.container). This results in very low contrast/unreadable text in dark mode. Consider providing a dark-mode default (e.g., values-night/element_colors.xml mapping it to a light color) or selecting different defaults in giniLightColorScheme vs giniDarkColorScheme while still keeping the override hook.

Suggested change
<color name="skonto_section_title_text_color">@color/gc_dark_02</color>
<color name="skonto_section_title_text_color">@color/gc_light_01</color>

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +19
/**
* Bridge between old way of defining colors by overridden resources and Compose
*
* This function will define color primitives based on resources value at res/colors.xml
*/
internal fun buildColorPrimitivesBasedOnResources(context: Context) = GiniColorElementsPrimitives(
skontoSectionTitleTextColor = Color(context.getColor(R.color.skonto_section_title_text_color)),
)
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The KDoc for buildColorPrimitivesBasedOnResources() says the values come from res/colors.xml, but these element overrides are defined in res/values/element_colors.xml (and may also be overridden elsewhere). Updating the comment would prevent confusion for anyone trying to override the resources.

Copilot uses AI. Check for mistakes.
@sonarqubecloud
Copy link
Copy Markdown

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed for 'Android Bank SDK'

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)
B Reliability Rating on New Code (required ≥ A)
41 New Code Smells (required ≤ 0)
6 New Critical Issues (required ≤ 0)
1 New Bugs (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@obaidgini obaidgini self-requested a review February 18, 2026 13:23
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.

2 participants