Light dark theming
Skill almasumdev/awesome-mobile-design-system-agent-skills/.github/skills/theming/light-dark-theming
Agent skills for building and maintaining mobile design systems, tokens, and component libraries.
npx -y skills add almasumdev/awesome-mobile-design-system-agent-skills --skill light-dark-themingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Light and dark theming via system integration, per-surface semantics, and elevation overlays. Use this when wiring color themes to the platform or adding a new surface.
SKILL.md
5.1 KB, as published. Nobody here has run it
Light / Dark Theming
Instructions
Dark mode is not a palette swap. It is a different alias mapping of the same tonal palettes with its own contrast and elevation rules.
1. System Integration
Follow the OS. Never ship an in-app toggle that ignores prefers-color-scheme — only an override.
- Android:
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM)by default; apps readConfiguration.UI_MODE_NIGHT_YESorisSystemInDarkTheme()in Compose. - iOS:
UITraitCollection.userInterfaceStyle/ SwiftUI@Environment(\.colorScheme). - Flutter:
MediaQuery.of(context).platformBrightnessorThemeMode.system. - React Native:
Appearance.getColorScheme()anduseColorScheme().
2. Per-Surface Semantics
Ship tokens for a small, named set of surfaces — not a single "background."
| Token | Light | Dark | Use |
|---|---|---|---|
color.surface.default | neutral.99 | neutral.10 | App background |
color.surface.subtle | neutral.95 | neutral.15 | Cards, sheets |
color.surface.raised | neutral.99 | neutral.20 | Elevated cards |
color.surface.overlay | neutral.99 α 95% | neutral.10 α 90% | Modals, popovers |
color.surface.inverse | neutral.10 | neutral.95 | Tooltips, toasts |
Each surface has a paired content token (color.content.*) whose contrast against the surface is verified AA.
3. Dark Elevation: Tint Over Shadow
On dark themes, shadows become invisible. Convey elevation with surface tint (Material 3) — a subtle tonal wash at higher levels.
val DarkColorScheme = darkColorScheme(
surface = ds.color.surface.default,
surfaceContainer = ds.color.surface.subtle,
surfaceContainerHigh = ds.color.surface.raised,
surfaceTint = ds.color.action.primary.bg, // Material 3 applies this at elevation
)
4. Compose Wiring
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val scheme = if (darkTheme) DarkColorScheme else LightColorScheme
MaterialTheme(colorScheme = scheme, typography = AppTypography, content = content)
}
5. SwiftUI Wiring
Use asset catalog color sets with separate Any Appearance + Dark Appearance values, referenced semantically:
extension Color {
static let dsSurfaceDefault = Color("surface/default")
static let dsContentDefault = Color("content/default")
}
To force a theme locally:
ContentView().preferredColorScheme(.dark)
6. Flutter Wiring
MaterialApp(
themeMode: ThemeMode.system,
theme: AppTheme.light(),
darkTheme: AppTheme.dark(),
);
class AppTheme {
static ThemeData light() => ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme,
extensions: [AppColors.light, AppSpacing.standard],
);
static ThemeData dark() => ThemeData(
useMaterial3: true,
colorScheme: darkColorScheme,
extensions: [AppColors.dark, AppSpacing.standard],
);
}
7. React Native Wiring
const scheme = useColorScheme();
const theme = scheme === 'dark' ? darkTheme : lightTheme;
return <ThemeProvider value={theme}>{children}</ThemeProvider>;
8. Edge Cases
- Images and illustrations: ship light and dark variants or use monochrome assets that inherit
color.content.default. - Status bar / navigation bar: set to match surface color and icon contrast (
WindowCompaton Android,preferredStatusBarStyle/UIStatusBarStyleon iOS,StatusBaron RN). - System keyboards and sheets: inherit dark mode automatically — do not override unless the design explicitly requires it.
- Screenshots and sharing: use
color.surface.defaultso exports are consistent.
9. Anti-Patterns
- Hardcoded
Color(0xFFFFFFFF)anywhere. - Using
Colors.white.withOpacity(0.7)as muted text — fails contrast in light mode. - A single "background" token used for app, card, and modal.
- Dark-only shadows; they are invisible and waste layout cost.
- Manual theme toggles that ignore the system preference as a default.
Checklist
- The app follows the system color scheme by default; any override persists but does not override system as initial state.
- Multiple named surface tokens exist (default, subtle, raised, overlay, inverse) with paired content tokens.
- Dark elevation uses surface tint, not shadows alone.
- Status bar / nav bar colors match the current surface on every screen.
- Contrast is verified AA for every content-on-surface pair in both themes.
- Images and illustrations have dark variants or inherit from tokens.