Skip to content

Commit

Permalink
UI: Improve TransportModeChip text contrast accessibility (#611)
Browse files Browse the repository at this point in the history
### TL;DR
Enhanced color contrast handling for transport mode chips to ensure better accessibility

### What changed?
- Added contrast ratio checking for transport mode chip text colors
- Introduced constants for WCAG AA contrast requirements
- Enhanced `getForegroundColor` function to accept an optional foreground color parameter
- Improved text color handling in `TransportModeChip` component

### How to test?
1. Navigate to the trip planner screen
2. Verify that transport mode chip text remains readable when selected
3. Check text contrast against different transport mode background colors
4. Test with both light and dark themes

### Why make this change?
To improve accessibility by ensuring text remains readable across all transport mode chips, regardless of their background color. This change follows WCAG AA guidelines for text contrast ratios, making the app more accessible to users with visual impairments.
  • Loading branch information
ksharma-xyz authored Feb 13, 2025
1 parent 5018501 commit 3941394
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ fun TransportModeChip(
)

val textColor by animateColorAsState(
targetValue = if (selected) Color.White else Color.Gray,
targetValue = if (selected) getForegroundColor(
backgroundColor = transportMode.colorCode.hexToComposeColor(),
foregroundColor = Color.White,
) else Color.Gray,
animationSpec = tween(200),
)

Expand Down Expand Up @@ -80,11 +83,7 @@ fun TransportModeChip(
adaptiveSize = true,
)

CompositionLocalProvider(
LocalTextColor provides textColor,
) {
Text(text = transportMode.name)
}
Text(text = transportMode.name, color = textColor)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ package xyz.ksharma.krail.taj.theme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance

// https://www.w3.org/TR/WCAG21/#contrast-minimum
private const val DEFAULT_TEXT_SIZE_CONTRAST_AA = 4.5f

// when font scale greater than 1.2f. Text size is 18dp default and 14dp bold.
private const val LARGE_TEXT_SIZE_CONTRAST_AA = 3.0f


/**
* Calculates the contrast ratio between two colors
*/
Expand All @@ -16,17 +23,38 @@ fun Color.contrastRatio(other: Color): Float {
* Returns a foreground color that has a contrast ratio of at least 4.0 with the provided background
* color.
*/
fun getForegroundColor(backgroundColor: Color): Color {
/**
* Determines the appropriate foreground color based on the provided background color.
* If a foreground color is provided, it checks the contrast ratio between the foreground
* and background colors. If the contrast ratio is sufficient (>= 4.0), it returns the
* provided foreground color. Otherwise, it defaults to checking predefined light and dark
* theme colors and returns the one with a sufficient contrast ratio.
*
* @param backgroundColor The background color to compare against.
* @param foregroundColor An optional foreground color to check for contrast ratio.
* @return The appropriate foreground color with sufficient contrast ratio.
*/
fun getForegroundColor(
backgroundColor: Color,
foregroundColor: Color? = null,
): Color {
// If a foreground color is provided, check its contrast ratio
foregroundColor?.let { color ->
if (color.contrastRatio(backgroundColor) >= DEFAULT_TEXT_SIZE_CONTRAST_AA) return color
}

// Default to predefined light and dark theme colors
val lightForegroundColor = md_theme_dark_onSurface
val darkForegroundColor = md_theme_light_onSurface

return if (lightForegroundColor.contrastRatio(backgroundColor) >= 4.0f) {
// Return the color with a sufficient contrast ratio
return if (lightForegroundColor.contrastRatio(backgroundColor) >= DEFAULT_TEXT_SIZE_CONTRAST_AA) {
lightForegroundColor
} else {
darkForegroundColor
}
}

fun shouldUseDarkIcons(backgroundColor: Color): Boolean {
return getForegroundColor(backgroundColor) == md_theme_dark_onSurface
return getForegroundColor(backgroundColor = backgroundColor) == md_theme_dark_onSurface
}

0 comments on commit 3941394

Please sign in to comment.