Building Own Design System¶
You can use JetTheme to implement your own design system.
Example¶
For example, we want to create a Simple Design System which has different color scheme from Material Design. The color scheme contains two colors, the background color and text color.
Usage¶
Define the ThemeSpec
of our Simple Design System:
data class SimpleThemeSpec(
override val id: String,
val colors: SimpleColors,
val typography: Typography = Typography(),
val shapes: Shapes = Shapes(),
) : ThemeSpec
class SimpleColors(
background: Color,
text: Color,
isDark: Boolean,
) {
var background by mutableStateOf(background)
private set
var text by mutableStateOf(text)
private set
var isDark by mutableStateOf(isDark)
private set
fun update(other: SimpleColors) {
background = other.background
text = other.text
isDark = other.isDark
}
}
Construct a ThemePack
of our SimpleThemeSpec
:
val AppTheme = buildThemePack {
theme(
SimpleThemeSpec(
id = defaultId,
colors = LightColorPalette,
)
)
theme(
SimpleThemeSpec(
id = darkId,
colors = DarkColorPalette,
)
)
}
Create a SimpleTheme
object which can retrieve current theme colors:
private val AmbientSimpleColors = staticAmbientOf<SimpleColors>()
object SimpleTheme {
@Composable
val colors: SimpleColors
get() = AmbientSimpleColors.current
}
Create a Simple Design System provider by the ProvideAppTheme
:
@Composable
fun ProvideSimpleTheme(
content: @Composable () -> Unit,
) {
ProvideAppTheme<SimpleThemeSpec>(
themePack = AppTheme,
) { theme ->
val colorPalette = remember { theme.colors }
colorPalette.update(theme.colors)
Providers(AmbientSimpleColors provides colorPalette) {
MaterialTheme(
colors = debugColors(theme.colors.isDark),
typography = theme.typography,
shapes = theme.shapes,
content = content,
)
}
}
}
// Sets all colors to [debugColor] to discourage usage of [MaterialTheme.colors]
// in preference to [SimpleTheme.colors].
private fun debugColors(
darkTheme: Boolean,
debugColor: Color = Color.Magenta
) = Colors(
primary = debugColor,
primaryVariant = debugColor,
secondary = debugColor,
secondaryVariant = debugColor,
background = debugColor,
surface = debugColor,
error = debugColor,
onPrimary = debugColor,
onSecondary = debugColor,
onBackground = debugColor,
onSurface = debugColor,
onError = debugColor,
isLight = !darkTheme
)
Access current theme values from SimpleTheme
and change themes using ThemeController
:
@Composable
fun CustomDesignSystemApp() {
ProvideSimpleTheme {
Box {
val (themeId, setThemeId) = ThemeControllerAmbient.current
Text(
"Custom Design System",
modifier = Modifier.clickable(onClick = { setThemeId(AppTheme.nextThemeId(themeId)) }),
color = SimpleTheme.colors.text
)
}
}
}