Fix desktop theme contrast: missing on* color roles

lightColorScheme()/darkColorScheme() only overrode primary/secondary/
tertiary/*Container/surface, leaving every paired on* text/icon role at
Material3's baseline defaults — tuned for the default purple palette,
with no guaranteed contrast against Amber's custom light gold/cream
colors. This made default-styled Button() content (Copy to clipboard,
Add relay, theme toggle, Revoke all permissions, Always allow) and
NavigationRail's selected-item labels nearly invisible.

Adds explicit onPrimary/onSecondary/onTertiary/onPrimaryContainer/
onSecondaryContainer/onSurface/onSurfaceVariant/onBackground/outline
using a dark warm "ink" tone, fixing every default-styled button in one
place rather than per call site. Also fixes the dark scheme's onPrimary
(was White, same bug — primary stays light gold in dark mode too).

HomeScreen's relay-status text and ActivityScreen's approved/rejected
badge now use shared positiveColor/negativeColor instead of raw
colorScheme.primary (itself too light to read as body text) or a
locally-duplicated hardcoded green/red. Divider/border colors that used
colorScheme.primary switch to the new colorScheme.outline role.
This commit is contained in:
Claude
2026-07-01 19:19:00 +00:00
parent f6cb8f6f95
commit f71bfdc712
5 changed files with 39 additions and 7 deletions
@@ -22,6 +22,8 @@ import com.greenart7c3.nostrsigner.desktop.ui.components.LetterAvatar
import com.greenart7c3.nostrsigner.desktop.ui.components.bunkerMethodDescription
import com.greenart7c3.nostrsigner.desktop.ui.components.relativeTimeFromNow
import com.greenart7c3.nostrsigner.desktop.ui.components.shortenHex
import com.greenart7c3.nostrsigner.desktop.ui.theme.negativeColor
import com.greenart7c3.nostrsigner.desktop.ui.theme.positiveColor
@Composable
fun ActivityScreen(history: List<HistoryRow>) {
@@ -65,7 +67,7 @@ fun ActivityScreen(history: List<HistoryRow>) {
@Composable
private fun ApprovedBadge(approved: Boolean) {
val color = if (approved) Color(0xFF2E7D32) else Color(0xFFC62828)
val color = if (approved) positiveColor else negativeColor
Surface(color = color, shape = RoundedCornerShape(4.dp)) {
Text(
if (approved) "Allowed" else "Rejected",
@@ -112,7 +112,7 @@ private fun PermissionRow(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
.border(BorderStroke(1.dp, MaterialTheme.colorScheme.primary), RoundedCornerShape(6.dp))
.border(BorderStroke(1.dp, MaterialTheme.colorScheme.outline), RoundedCornerShape(6.dp))
.padding(12.dp),
) {
Text(bunkerMethodDescription(permission.method, permission.kind), style = MaterialTheme.typography.bodyLarge)
@@ -51,7 +51,7 @@ fun ConnectedAppsScreen(connectedApps: List<ConnectedApp>, onAppClick: (String)
Text("Last used ${relativeTimeFromNow(app.connectedAt)}", style = MaterialTheme.typography.bodySmall)
}
}
HorizontalDivider(color = MaterialTheme.colorScheme.primary)
HorizontalDivider(color = MaterialTheme.colorScheme.outline)
}
}
}
@@ -20,6 +20,8 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.greenart7c3.nostrsigner.desktop.ui.components.LetterAvatar
import com.greenart7c3.nostrsigner.desktop.ui.components.shortenHex
import com.greenart7c3.nostrsigner.desktop.ui.theme.negativeColor
import com.greenart7c3.nostrsigner.desktop.ui.theme.positiveColor
@Composable
fun HomeScreen(
@@ -52,7 +54,7 @@ fun HomeScreen(
"Connected to $connectedRelayCount of $totalRelays relays"
},
style = MaterialTheme.typography.bodySmall,
color = if (connectedRelayCount > 0) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error,
color = if (connectedRelayCount > 0) positiveColor else negativeColor,
)
Spacer(Modifier.height(24.dp))
@@ -15,23 +15,51 @@ val primaryVariant = Color(0xFFC8541A)
val secondaryColor = Color(0xFFFFCA62)
val orange = Color(0xFFFF6B00)
/**
* `primary`/`tertiary`/`primaryContainer`/`secondaryContainer` are all a light gold in both
* schemes, so their paired `on*` roles need an explicit dark color — Material3's baseline
* defaults (tuned for the default purple palette) don't have guaranteed contrast against a
* custom light container and were left unset here before, making button/nav-rail text
* unreadable.
*/
val inkColor = Color(0xFF3E2A0D)
val outlineColor = Color(0xFF8A6D3A)
val positiveColor = Color(0xFF2E7D32)
val negativeColor = Color(0xFFC62828)
private val DarkColorPalette = darkColorScheme(
primary = primaryColor,
onPrimary = Color.White,
onPrimary = inkColor,
secondary = primaryVariant,
onSecondary = Color.White,
tertiary = secondaryColor,
onTertiary = inkColor,
primaryContainer = secondaryColor,
onPrimaryContainer = inkColor,
secondaryContainer = secondaryColor,
onSecondaryContainer = inkColor,
)
private val surfaceColor = Color(0xFFFFDE9E)
private val LightColorPalette = lightColorScheme(
primary = primaryColor,
onPrimary = inkColor,
secondary = primaryVariant,
onSecondary = Color.White,
tertiary = secondaryColor,
onTertiary = inkColor,
primaryContainer = secondaryColor,
onPrimaryContainer = inkColor,
secondaryContainer = secondaryColor,
surface = Color(0xFFFFDE9E),
surfaceContainer = Color(0xFFFFDE9E),
onSecondaryContainer = inkColor,
surface = surfaceColor,
surfaceContainer = surfaceColor,
onSurface = inkColor,
onSurfaceVariant = inkColor,
background = surfaceColor,
onBackground = inkColor,
outline = outlineColor,
)
val DesktopShapes = Shapes(