taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

066-wallet-color-scheme.rst (18994B)


      1 DD 66: Wallet UI Color Scheme
      2 =============================
      3 
      4 :Design status: Accepted
      5 :Implementation status: Partial
      6 :DD shepherd: TBD
      7 :Historical contributors: Vlada Svirsh
      8 :First published: 2025-07-16
      9 :Last substantive change: 2026-07-05
     10 :Implementation evidence: taler-android (2025-07-10), taler-ios (2026-06-05)
     11 :Normative references: :doc:`../developer/taler-wallet-developer`
     12 
     13 .. note::
     14 
     15    Native-wallet adoption is in progress.  WebExtension dark-mode support,
     16    complete semantic-token adoption, contrast verification and developer
     17    onboarding remain incomplete.
     18 
     19 Summary
     20 -------
     21 
     22 This design document defines the unified color scheme for the GNU Taler Wallet, based on the Material Design 3 color system. It provides semantic color roles used across the wallet UI for consistency, accessibility, and maintainability.
     23 
     24 The document outlines the purpose and application of each color role in the UI design system.
     25 
     26 Motivation
     27 ----------
     28 
     29 The wallet UI currently lacks a consistent and documented color strategy. As the application grows and adds more features, visual coherence and accessibility become increasingly important.
     30 
     31 By adopting Material 3 semantics and defining roles like ``primary``, ``onPrimary``, ``success``, ``errorContainer``, etc., the UI gains:
     32 
     33 - Consistent appearance across features
     34 - Easier onboarding for new contributors
     35 
     36 Requirements
     37 ------------
     38 
     39 - Colors must be defined semantically, not by hex codes directly in UI components.
     40 - The theme must support both light and dark modes.
     41 - Roles must maintain WCAG 2.1 AA contrast ratios.
     42 - Roles must cover error, warning, and success states.
     43 
     44 Proposed solution
     45 -----------------
     46 
     47 The color system will be structured using semantic **Material 3 color roles**. Each role is explained below with its usage and associated hex values.
     48 
     49 General concepts
     50 ~~~~~~~~~~~~~~~~
     51 
     52 - **Primary / Secondary / Tertiary**: Accent colors used to emphasize UI elements.
     53 - **Container**: A lighter or darker version of an accent color used for background fills (e.g. buttons, chips).
     54 - **On \***: A foreground color (text/icon) to be placed on top of its paired color.
     55 - **Surface / Background**: Base UI areas or layout surfaces.
     56 - **Outline**: Used for strokes, borders, and dividers.
     57 - **Error / Warning / Success**: Semantic feedback colors.
     58 - **Dark \***: Role variants used in dark mode.
     59 
     60 Color role definitions
     61 ~~~~~~~~~~~~~~~~~~~~~~
     62 
     63 Primary
     64 ^^^^^^^
     65 
     66 Used for the most important UI elements.
     67 
     68 .. list-table::
     69    :widths: 20 30 50
     70    :header-rows: 1
     71 
     72    * - Role
     73      - Hex
     74      - Usage
     75 
     76    * - primary
     77      - .. raw:: html
     78 
     79           <code>#0042b3</code> <div style="display:inline-block;width:14px;height:14px;
     80           background:#0042b3;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
     81      - Main action color (e.g. filled buttons, tabs, icons), incoming amount
     82 
     83    * - onPrimary
     84      - .. raw:: html
     85 
     86           <code>#ffffff</code> <div style="display:inline-block;width:14px;height:14px;
     87           background:#ffffff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
     88      - Text/icons placed on top of ``primary``
     89 
     90    * - primaryContainer
     91      - .. raw:: html
     92 
     93           <code>#d3deff</code> <div style="display:inline-block;width:14px;height:14px;
     94           background:#d3deff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
     95      - Background for FABs, cards, filled fields
     96 
     97    * - onPrimaryContainer
     98      - .. raw:: html
     99 
    100           <code>#00134a</code> <div style="display:inline-block;width:14px;height:14px;
    101           background:#00134a;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    102      - Foreground for ``primaryContainer``
    103 
    104    * - darkPrimary
    105      - .. raw:: html
    106 
    107           <code>#b4c5ff</code> <div style="display:inline-block;width:14px;height:14px;
    108           background:#b4c5ff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    109      - ``primary`` in dark mode
    110 
    111    * - darkOnPrimary
    112      - .. raw:: html
    113 
    114           <code>#002a78</code> <div style="display:inline-block;width:14px;height:14px;
    115           background:#002a78;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    116      - Text/icons on ``darkPrimary``
    117 
    118    * - darkPrimaryContainer
    119      - .. raw:: html
    120 
    121           <code>#0042b3</code> <div style="display:inline-block;width:14px;height:14px;
    122           background:#0042b3;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    123      - Container in dark mode
    124 
    125    * - darkOnPrimaryContainer
    126      - .. raw:: html
    127 
    128           <code>#e5ebff</code> <div style="display:inline-block;width:14px;height:14px;
    129           background:#e5ebff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    130      - Foreground on container in dark
    131 
    132 
    133 
    134 Secondary
    135 ^^^^^^^^^
    136 
    137 Used for less prominent or supporting elements.
    138 
    139 .. list-table::
    140    :widths: 20 30 50
    141    :header-rows: 1
    142 
    143    * - Role
    144      - Hex
    145      - Usage
    146 
    147    * - secondary
    148      - .. raw:: html
    149 
    150           <code>#586a88</code> <div style="display:inline-block;width:14px;height:14px;
    151           background:#586a88;border:1px solid #aaa;margin-left:6px;
    152           vertical-align:middle;"></div>
    153      - Secondary buttons, chips, and passive UI states
    154 
    155    * - onSecondary
    156      - .. raw:: html
    157 
    158           <code>#ffffff</code> <div style="display:inline-block;width:14px;height:14px;
    159           background:#ffffff;border:1px solid #aaa;margin-left:6px;
    160           vertical-align:middle;"></div>
    161      - Foreground on ``secondary``
    162 
    163    * - secondaryContainer
    164      - .. raw:: html
    165 
    166           <code>#d9e3f9</code> <div style="display:inline-block;width:14px;height:14px;
    167           background:#d9e3f9;border:1px solid #aaa;margin-left:6px;
    168           vertical-align:middle;"></div>
    169      - Background for secondary surfaces
    170 
    171    * - onSecondaryContainer
    172      - .. raw:: html
    173 
    174           <code>#111c2b</code> <div style="display:inline-block;width:14px;height:14px;
    175           background:#111c2b;border:1px solid #aaa;margin-left:6px;
    176           vertical-align:middle;"></div>
    177      - Foreground on ``secondaryContainer``
    178 
    179    * - darkSecondary
    180      - .. raw:: html
    181 
    182           <code>#a4c9ff</code> <div style="display:inline-block;width:14px;height:14px;
    183           background:#a4c9ff;border:1px solid #aaa;margin-left:6px;
    184           vertical-align:middle;"></div>
    185      - Secondary color in dark mode
    186 
    187    * - darkOnSecondary
    188      - .. raw:: html
    189 
    190           <code>#00315d</code> <div style="display:inline-block;width:14px;height:14px;
    191           background:#00315d;border:1px solid #aaa;margin-left:6px;
    192           vertical-align:middle;"></div>
    193      - Foreground in dark mode
    194 
    195    * - darkSecondaryContainer
    196      - .. raw:: html
    197 
    198           <code>#72a3e5</code> <div style="display:inline-block;width:14px;height:14px;
    199           background:#72a3e5;border:1px solid #aaa;margin-left:6px;
    200           vertical-align:middle;"></div>
    201      - Background container in dark
    202 
    203    * - darkOnSecondaryContainer
    204      - .. raw:: html
    205 
    206           <code>#003869</code> <div style="display:inline-block;width:14px;height:14px;
    207           background:#003869;border:1px solid #aaa;margin-left:6px;
    208           vertical-align:middle;"></div>
    209      - Foreground for container in dark
    210 
    211 
    212 
    213 
    214 
    215 Tertiary
    216 ^^^^^^^^
    217 
    218 Used for accents, badges, or attention-grabbing components.
    219 
    220 .. list-table::
    221    :widths: 20 30 50
    222    :header-rows: 1
    223 
    224    * - Role
    225      - Hex
    226      - Usage
    227 
    228    * - tertiary
    229      - .. raw:: html
    230 
    231           <code>#338af0</code> <div style="display:inline-block;width:14px;height:14px;
    232           background:#338af0;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    233      - Used for tags, emphasis markers
    234 
    235    * - onTertiary
    236      - .. raw:: html
    237 
    238           <code>#ffffff</code> <div style="display:inline-block;width:14px;height:14px;
    239           background:#ffffff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    240      - Text/icons on ``tertiary``
    241 
    242    * - tertiaryContainer
    243      - .. raw:: html
    244 
    245           <code>#d1e4ff</code> <div style="display:inline-block;width:14px;height:14px;
    246           background:#d1e4ff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    247      - Input field backgrounds, selected indicators
    248 
    249    * - onTertiaryContainer
    250      - .. raw:: html
    251 
    252           <code>#001c39</code> <div style="display:inline-block;width:14px;height:14px;
    253           background:#001c39;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    254      - Text/icons on ``tertiaryContainer``
    255 
    256    * - darkTertiary
    257      - .. raw:: html
    258 
    259           <code>#8dd1e5</code> <div style="display:inline-block;width:14px;height:14px;
    260           background:#8dd1e5;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    261      - Accent color in dark mode
    262 
    263    * - darkOnTertiary
    264      - .. raw:: html
    265 
    266           <code>#003641</code> <div style="display:inline-block;width:14px;height:14px;
    267           background:#003641;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    268      - Foreground in dark
    269 
    270    * - darkTertiaryContainer
    271      - .. raw:: html
    272 
    273           <code>#166577</code> <div style="display:inline-block;width:14px;height:14px;
    274           background:#166577;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    275      - Container fill in dark
    276 
    277    * - darkOnTertiaryContainer
    278      - .. raw:: html
    279 
    280           <code>#9ce0f5</code> <div style="display:inline-block;width:14px;height:14px;
    281           background:#9ce0f5;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    282      - Text/icons on dark container
    283 
    284 
    285 Error
    286 ^^^^^
    287 
    288 .. list-table::
    289    :widths: 20 30 50
    290    :header-rows: 1
    291 
    292    * - Role
    293      - Hex
    294      - Usage
    295 
    296    * - error
    297      - .. raw:: html
    298 
    299           <code>#b3261e</code> <div style="display:inline-block;width:14px;height:14px;
    300           background:#b3261e;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    301      - Main error color for messages or outlines
    302 
    303    * - onError
    304      - .. raw:: html
    305 
    306           <code>#ffffff</code> <div style="display:inline-block;width:14px;height:14px;
    307           background:#ffffff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    308      - Text/icons on error surfaces
    309 
    310    * - errorContainer
    311      - .. raw:: html
    312 
    313           <code>#f9dedc</code> <div style="display:inline-block;width:14px;height:14px;
    314           background:#f9dedc;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    315      - Background fill for error components
    316 
    317    * - onErrorContainer
    318      - .. raw:: html
    319 
    320           <code>#410e0b</code> <div style="display:inline-block;width:14px;height:14px;
    321           background:#410e0b;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    322      - Text/icons on error container
    323 
    324    * - darkError
    325      - .. raw:: html
    326 
    327           <code>#ffb4aa</code> <div style="display:inline-block;width:14px;height:14px;
    328           background:#ffb4aa;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    329      - Error color in dark mode
    330 
    331    * - darkOnError
    332      - .. raw:: html
    333 
    334           <code>#690003</code> <div style="display:inline-block;width:14px;height:14px;
    335           background:#690003;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    336      - Foreground in dark mode
    337 
    338    * - darkErrorContainer
    339      - .. raw:: html
    340 
    341           <code>#b3261e</code> <div style="display:inline-block;width:14px;height:14px;
    342           background:#b3261e;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    343      - Background container in dark
    344 
    345    * - darkOnErrorContainer
    346      - .. raw:: html
    347 
    348           <code>#ffcbc4</code> <div style="display:inline-block;width:14px;height:14px;
    349           background:#ffcbc4;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    350      - Foreground on dark container
    351 
    352 
    353 Success
    354 ^^^^^^^
    355 
    356 .. list-table::
    357    :widths: 20 30 50
    358    :header-rows: 1
    359 
    360    * - Role
    361      - Hex
    362      - Usage
    363 
    364    * - success
    365      - .. raw:: html
    366 
    367           <code>#337a40</code> <div style="display:inline-block;width:14px;height:14px;
    368           background:#337a40;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    369      - Status indicators, confirmation icons
    370 
    371    * - onSuccess
    372      - .. raw:: html
    373 
    374           <code>#ffffff</code> <div style="display:inline-block;width:14px;height:14px;
    375           background:#ffffff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    376      - Foreground on success
    377 
    378    * - successContainer
    379      - .. raw:: html
    380 
    381           <code>#2e8534</code> <div style="display:inline-block;width:14px;height:14px;
    382           background:#2e8534;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    383      - Background for success banners or chips
    384 
    385    * - onSuccessContainer
    386      - .. raw:: html
    387 
    388           <code>#f7fff1</code> <div style="display:inline-block;width:14px;height:14px;
    389           background:#f7fff1;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    390      - Text/icons on success container
    391 
    392    * - darkSuccess
    393      - .. raw:: html
    394 
    395           <code>#337a40</code> <div style="display:inline-block;width:14px;height:14px;
    396           background:#337a40;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    397      - Same in dark mode (stable tone)
    398 
    399    * - darkOnSuccess
    400      - .. raw:: html
    401 
    402           <code>#ffffff</code> <div style="display:inline-block;width:14px;height:14px;
    403           background:#ffffff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    404      - Foreground for dark mode
    405 
    406    * - darkSuccessContainer
    407      - .. raw:: html
    408 
    409           <code>#1d3522</code> <div style="display:inline-block;width:14px;height:14px;
    410           background:#1d3522;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    411      - Background container in dark
    412 
    413    * - darkOnSuccessContainer
    414      - .. raw:: html
    415 
    416           <code>#eaf6ec</code> <div style="display:inline-block;width:14px;height:14px;
    417           background:#eaf6ec;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    418      - Text/icons on dark container
    419 
    420 
    421 Warning
    422 ^^^^^^^
    423 
    424 .. list-table::
    425    :widths: 20 30 50
    426    :header-rows: 1
    427 
    428    * - Role
    429      - Hex
    430      - Usage
    431 
    432    * - warning
    433      - .. raw:: html
    434 
    435           <code>#f99c06</code> <div style="display:inline-block;width:14px;height:14px;
    436           background:#f99c06;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    437      - Alert banners, passive warnings
    438 
    439    * - onWarning
    440      - .. raw:: html
    441 
    442           <code>#000000</code> <div style="display:inline-block;width:14px;height:14px;
    443           background:#000000;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    444      - Foreground text on warning
    445 
    446    * - warningContainer
    447      - .. raw:: html
    448 
    449           <code>#fdedd3</code> <div style="display:inline-block;width:14px;height:14px;
    450           background:#fdedd3;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    451      - Background fill for warning containers
    452 
    453    * - onWarningContainer
    454      - .. raw:: html
    455 
    456           <code>#6b4706</code> <div style="display:inline-block;width:14px;height:14px;
    457           background:#6b4706;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    458      - Foreground on warning container
    459 
    460    * - darkWarning
    461      - .. raw:: html
    462 
    463           <code>#f99c06</code> <div style="display:inline-block;width:14px;height:14px;
    464           background:#f99c06;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    465      - Warning in dark mode
    466 
    467    * - darkOnWarning
    468      - .. raw:: html
    469 
    470           <code>#000000</code> <div style="display:inline-block;width:14px;height:14px;
    471           background:#000000;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    472      - Foreground in dark
    473 
    474    * - darkWarningContainer
    475      - .. raw:: html
    476 
    477           <code>#664200</code> <div style="display:inline-block;width:14px;height:14px;
    478           background:#664200;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    479      - Background in dark
    480 
    481    * - darkOnWarningContainer
    482      - .. raw:: html
    483 
    484           <code>#fdedd3</code> <div style="display:inline-block;width:14px;height:14px;
    485           background:#fdedd3;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    486      - Foreground on container in dark
    487 
    488 
    489 Background
    490 ^^^^^^^^^^
    491 
    492 .. list-table::
    493    :widths: 20 30 50
    494    :header-rows: 1
    495 
    496    * - Role
    497      - Hex
    498      - Usage
    499 
    500    * - background
    501      - .. raw:: html
    502 
    503           <code>#fdfdff</code> <div style="display:inline-block;width:14px;height:14px;
    504           background:#fdfdff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    505      - App-wide background color
    506 
    507    * - onBackground
    508      - .. raw:: html
    509 
    510           <code>#1a1c1f</code> <div style="display:inline-block;width:14px;height:14px;
    511           background:#1a1c1f;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    512      - Foreground text/icons on background
    513 
    514    * - darkBackground
    515      - .. raw:: html
    516 
    517           <code>#11131a</code> <div style="display:inline-block;width:14px;height:14px;
    518           background:#11131a;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    519      - Background in dark mode
    520 
    521    * - darkOnBackground
    522      - .. raw:: html
    523 
    524           <code>#e2e2eb</code> <div style="display:inline-block;width:14px;height:14px;
    525           background:#e2e2eb;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    526      - Text/icons in dark mode background
    527 
    528 
    529 Outline
    530 ^^^^^^^
    531 
    532 .. list-table::
    533    :widths: 20 30 50
    534    :header-rows: 1
    535 
    536    * - Role
    537      - Hex
    538      - Usage
    539 
    540    * - outline
    541      - .. raw:: html
    542 
    543           <code>#767880</code> <div style="display:inline-block;width:14px;height:14px;
    544           background:#767880;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    545      - Used for input borders, field outlines
    546 
    547    * - outlineVariant
    548      - .. raw:: html
    549 
    550           <code>#c4c6d0</code> <div style="display:inline-block;width:14px;height:14px;
    551           background:#c4c6d0;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div>
    552      - Decorative borders, dividers
    553 
    554 
    555 
    556 Definition of Done
    557 ------------------
    558 
    559 - [x] Android theming system supports the defined Material 3 roles
    560 - [x] native-wallet themes switch between light and dark mode
    561 - [ ] WebExtension supports dark mode and the complete role set
    562 - [ ] all components use semantic color tokens
    563 - [ ] WCAG 2.1 AA contrast verified across all wallet screens
    564 - [ ] color role documentation added to developer onboarding
    565 
    566 Alternatives
    567 ------------
    568 
    569 - Use raw hex codes per component (violates consistency and accessibility)
    570 - Derive from OS/system color settings (limits branding control)
    571 
    572 Drawbacks
    573 ---------
    574 
    575 - To be fully and correctly implemented, all ui screeens must be updated with references to the new color roles.
    576 - Might requires UI refactor to override system styles
    577 - Slight learning curve for developers unfamiliar with semantic roles
    578 
    579 Discussion / Q&A
    580 ----------------