DEV Community

Cover image for Building High-Contrast Finance UIs in Jetpack Compose Without a Design Team
DEVANSHU PATIL
DEVANSHU PATIL

Posted on

Building High-Contrast Finance UIs in Jetpack Compose Without a Design Team

Building High-Contrast Finance UIs in Jetpack Compose Without a Design Team

Designing user interfaces for personal finance applications presents a unique visual challenge: every color carries immediate emotional meaning.

In consumer fintech:

  • Green typically signals positive income, cash inflows, and healthy budget surpluses.
  • Red or orange signals expenses, debt liabilities, overdue statements, and budget deficits.
  • Amber signals caution, warnings, and approaching credit limits.

If a developer simply picks standard Material 3 primary and secondary theme colors, they quickly encounter serious usability and accessibility issues.

A vibrant neon green that looks stunning on a dark theme background will become completely illegible when rendered against a white light-mode card. Conversely, a deep crimson red that satisfies contrast ratios on white backgrounds becomes a dull, muddy brown when rendered on OLED dark surfaces.

Here is how FinLedger solved theme contrast across light and dark modes by engineering dedicated fintech design tokens in Jetpack Compose compliant with WCAG AA accessibility standards.

The Pitfall of Hardcoded Financial Colors

When mobile projects start small, developers often hardcode color constants in their UI:

  • val IncomeGreen = Color(0xFF00C853)
  • val ExpenseRed = Color(0xFFFF3D00)
flowchart TD
    subgraph Problem["The Hardcoded Color Problem"]
        direction TB
        ColorC["Hardcoded Color(0xFF00C853)"]
        DarkBG["OLED Dark Theme Background"]
        LightBG["Bright Light Theme Background"]
        ColorC -->|"Looks Great (High Contrast)"| DarkBG
        ColorC -->|"Fails WCAG AA (Low Contrast / Unreadable)"| LightBG
    end

This works well in dark mode, but as soon as the user switches to a light theme:

  1. Bright mint greens fail the Web Content Accessibility Guidelines (WCAG) AA minimum contrast ratio of 4.5:1 against light gray or white card surfaces. Users with vision impairments or those using their phones outdoors in direct sunlight literally cannot read their account balances.
  2. If the developer darkens the green so it is readable on white, that same dark green becomes invisible against a dark surface.

Financial software cannot afford illegible numbers. A user must never misread an account balance or confuse a positive inflow with an expense due to poor screen contrast.

The Solution: Semantic Theme-Aware Tokens

During FinLedger's hardening sprints (Sprint H7), we overhauled the entire design token architecture.

Instead of binding UI widgets directly to static colors, all financial cards, transaction rows, and charts consume semantic design tokens that automatically adapt based on the active Material 3 color scheme.

classDiagram
    class FinColorTokens {
        +Color finMintPrimary
        +Color finOnMint
        +Color finOrangePrimary
        +Color finOnOrange
        +Color finRedNegative
        +Color finCardContainer
        +Color finTextPrimary
    }
    class DarkThemePalette {
        finMintPrimary: #10B981 (Vibrant Mint)
        finOnMint: #064E3B (Deep Emerald)
        finCardContainer: #1E293B (Slate 800)
    }
    class LightThemePalette {
        finMintPrimary: #059669 (Deep Forest Mint)
        finOnMint: #FFFFFF (Crisp White)
        finCardContainer: #F8FAFC (Slate 50)
    }
    FinColorTokens <|-- DarkThemePalette : Active in Dark Mode
    FinColorTokens <|-- LightThemePalette : Active in Light Mode

1. Dual-Sided Inflow Tokens: FinMint and FinOnMint

For positive income, credit cashbacks, and budget surpluses, the design system defines paired tokens:

  • Light Theme: Uses a deeper, saturated emerald tone (#059669) providing a 5.2:1 contrast ratio against light backgrounds, paired with pure white (#FFFFFF) for text rendered on colored badge chips.
  • Dark Theme: Uses a crisp, luminescent mint (#10B981) providing a 7.8:1 contrast ratio against slate and charcoal OLED backgrounds (#0F172A), paired with deep forest green (#064E3B) for badge interiors.

2. Liability and Warning Tokens: FinOrange and FinOnOrange

Credit card debt and warning thresholds (such as reaching 85% of a monthly budget) require clear differentiation from catastrophic errors:

  • We introduced dynamic FinOrange and FinOnOrange tokens that maintain high visibility without blending into red expense alerts.
  • This prevents "alert fatigue," allowing users to distinguish an approaching credit statement from an overdue bill at a glance.

3. Expense and Deficit Tokens: FinRedNegative

Negative outflows and overdrafts consume a calibrated negative token (FinRedNegative) that maintains crisp legibility on both pure white and OLED true-black backgrounds without triggering eye strain during late-night reviews.

High-Contrast Card Containers and Dynamic Elevation

Beyond individual numbers, the containers that house financial information must provide visual depth without causing visual clutter.

flowchart LR
    subgraph DarkMode["Dark Mode Layering"]
        direction TB
        D_BG["OLED Scaffold (0F172A)"] --> D_Card["Elevated Card Container (1E293B)"]
        D_Card --> D_Text["High-Emphasis Primary Text (F8FAFC)"]
    end
    subgraph LightMode["Light Mode Layering"]
        direction TB
        L_BG["Surface Scaffold (F1F5F9)"] --> L_Card["Card Container with Subtle Border (FFFFFF)"]
        L_Card --> L_Text["High-Emphasis Primary Text (0F172A)"]
    end

In dark themes, elevated cards do not rely on drop shadows because shadows are invisible on black backgrounds. Instead, cards use surface tonal elevation—subtly shifting the background color from slate charcoal (#0F172A) to a lighter surface gray (#1E293B) with a 1dp hairline border (Color.White.copy(alpha = 0.08f)).

In light themes, the card background shifts to crisp white (#FFFFFF) sitting on a soft cool-gray canvas (#F1F5F9), paired with a subtle, non-distracting border.

Testing Accessibility in Jetpack Compose

Design tokens are only effective if they are verified. FinLedger includes automated Compose visual regression tests and unit verification to ensure that:

  1. Every semantic token maintains a minimum 4.5:1 contrast ratio across both light and dark themes.
  2. Icons, text subtitles, and masked amounts never drop below WCAG AA thresholds.
  3. Rapid theme toggling (such as following system auto-night mode) recomposes all active screens smoothly without flickering or frame jank.

Key Takeaway

Financial user interfaces are high-stakes environments. When money is on the line, visual clarity is an essential usability requirement.

By building semantic, theme-aware tokens in Jetpack Compose rather than hardcoding static colors, you guarantee that your application remains readable, accessible, and beautiful in any lighting environment.


FinLedger is a privacy-first, offline-first personal finance application for Android that models bank accounts, credit cards, and cash without double-counting.

Explore FinLedger on Google Play: https://play.google.com/store/apps/details?id=com.devanshufinance.app

Top comments (0)