An opinionated design system for Compose Multiplatform.
Published on Maven Central:
implementation("glass.yasan.kepko:component:<version>")
implementation("glass.yasan.kepko:foundation:<version>")Wrap your app content with KepkoTheme:
| Code | Preview |
|---|---|
KepkoTheme {
Text("Hello, Kepko!")
TextPill(
text = "Yasan Glass",
containerColor = KepkoTheme.colors.information,
)
} |
![]() |
| Light | Dark |
|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
See the full list of components here.
An optional module that automatically persists and restores theme preferences across the app launches.
implementation("glass.yasan.kepko:persistence:<version>")Use PersistentKepkoTheme instead of KepkoTheme to automatically persist and restore theme preferences:
@OptIn(ExperimentalKepkoApi::class)
PersistentKepkoTheme {
// your app content
}To let users change the persisted theme setting, use PersistentPreferenceThemeScreen:
PersistentPreferenceThemeScreen(
onBackClick = { /* navigate back */ },
)PersistentPreferenceThemeScreen lets users pick between system-based or manual theme selection. In system mode, separate light and dark style pickers are shown:
PersistentKepkoTheme provides the following CompositionLocal values inside its content:
LocalKepkoColorPalette: the currently activeColorPaletteLocalKepkoPersistenceManager: thePersistenceManagerinstance for direct access to persistence state
An optional experimental module with Navigation 3 scenes for large windows. On Android it needs API 23 or later.
implementation("glass.yasan.kepko:navigation:<version>")ListDetailSceneStrategy shows the entry marked with list() beside the detail() entry above it on large windows, with a divider that can be dragged. The divider's position is saved across launches, so wrap the content in PersistentKepkoTheme:
NavDisplay(
backStack = backStack,
sceneStrategies = listOf(
rememberListDetailSceneStrategy(
isLargeWindow = isLargeWindow(),
isTwoPane = isTwoPaneWindow(),
),
),
entryProvider = { route ->
val metadata = if (route == Home) ListDetailSceneStrategy.list() else ListDetailSceneStrategy.detail()
NavEntry(route, metadata = metadata) { /* screen */ }
},
)An optional experimental module that allows constructing Kepko components from JSON strings by providing serialization contracts for the components.
implementation("glass.yasan.kepko:serialization:<version>")Simple JSON:
{
"on_click": "on-click",
"text": "Text Value",
"leading_icon": "info"
}Result (decoded contract → composable):
val contract = Json(from = kepkoJson).decodeFromString<ButtonContract>(jsonString)
ContractButton(
contract = contract,
onClick = { action: String -> println(action) },
)Equivalent to using Button directly:
Button(
text = "Text Value",
onClick = { println("on-click") },
leadingIcon = NamedIcon.INFO.painter(),
)Explore Kepko in a real project with the included sample project.
You can also try the sample project in your browser: WebAssembly or JavaScript

































