Compose Settings: ready-made Material 3 settings tiles for Compose Multiplatform
Pre-built Material 3 Settings UI components for Compose Multiplatform. Supports Android, iOS, Desktop, JavaScript, and WebAssembly.
At a glance
- What is it?
- Compose Settings is a Kotlin library of pre-built Material 3 settings composables for Jetpack Compose Multiplatform, split into standard, extended and expressive modules and published to Maven Central. It suits a Compose developer who wants settings screens without reimplementing each row, and it supports Android, iOS, JVM desktop, JavaScript and WebAssembly targets.
- Who is it for?
- Compose Settings fits a Compose Multiplatform team that needs a settings screen to look and behave like Material 3 across every target without writing each row, and it does not fit a project that needs a bespoke settings design, since the components carry Material 3 shapes and behaviour rather than a theming system of their own.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Settings rows as a component library, not a screen framework
Compose Settings is a set of Settings like composable items for Jetpack Compose developers, with the goal of helping them build complex settings screens without all the boilerplate.
The framing is important, because this is not a settings screen framework. There is no settings page abstraction, no navigation model, no persistence layer and no preference store. What there is, is a collection of rows.
The standard Material 3 set in the ui-tiles module is six components: SettingsMenuLink, SettingsCheckbox, SettingsTriStateCheckbox, SettingsRadioButton, SettingsSwitch and SettingsGroup. The extended module adds SettingsSlider and SettingsSegmented. The expressive module, which is Material 3 Expressive rather than plain Material 3, carries all of the above plus SettingsButtonGroup and supports segmented list styling.
That is a small, deliberately scoped API. SettingsGroup is the one that changes how the rest are used, since it is the container that turns a column of independent rows into a visually coherent settings screen, and the Expressive variants of the same components exist because the Expressive design language changes how a list item is shaped and spaced rather than just adding new components.
The technology choice is Kotlin 2.3.0 on Compose Multiplatform, with the licence MIT and the default branch main. The library is published to Maven Central under the group com.github.alorma.compose-settings, and the recent releases are 3.3.0 on 2026-10-05, 3.2.0 on 2026-08-31 and 3.1.0 on 2026-03-05. The last push was on 2026-10-17, and the documentation is generated with Dokka and hosted at alorma.github.io/Compose-Settings.
The platform list is the other headline. The badges name Android, iOS and macOS, the JVM, and WASM and JS, and the repository description says the same: supports Android, iOS, Desktop, JavaScript, and WebAssembly.
Installing the right module, and the version catalog syntax
Installation is a matter of picking the module that matches what you need, and the readme gives the exact coordinates for all three.
// groovy
implementation 'com.github.alorma.compose-settings:ui-tiles:$version'
implementation 'com.github.alorma.compose-settings:ui-tiles-extended:$version'
implementation 'com.github.alorma.compose-settings:ui-tiles-expressive:$version'The same three dependencies in the Kotlin DSL.
// kotlin DSL
implementation("com.github.alorma.compose-settings:ui-tiles:$version")
implementation("com.github.alorma.compose-settings:ui-tiles-extended:$version")
implementation("com.github.alorma.compose-settings:ui-tiles-expressive:$version")And the version catalog form, which is the one worth copying if your build uses a catalog.
// Catalog versions:
[versions]
compose-settings = "{{libVersion}}"
[libraries]
composeSettings-ui = { group = "com.github.alorma.compose-settings", name = "ui-tiles", version.ref = "compose-settings" }
composeSettings-ui-extended = { group = "com.github.alorma.compose-settings", name = "ui-tiles-extended", version.ref = "compose-settings" }
composeSettings-ui-expressive = { group = "com.github.alorma.compose-settings", name = "ui-tiles-expressive", version.ref = "compose-settings" }The version placeholder in the catalog snippet is written as {{libVersion}}, which is the release tooling substituting the real version into the readme at publication time.
The three-module split is the thing to decide before you add anything. The standard ui-tiles module gives you the six core rows, ui-tiles-extended adds the slider and the segmented control, and ui-tiles-expressive carries everything plus the button group with segmented list support. If you are on Material 3 Expressive you would take the expressive module, which supersedes the other two rather than sitting on top of them.
The Maven Central badge points at the ui-tiles artefact specifically, which tells you the namespace layout: the group is com.github.alorma.compose-settings and the artefact names are the module names, so the coordinates follow the standard multiplatform convention of one publication per module.
The common parameters, and where the expressive set differs
All settings components support customization through common parameters, and the readme starts with the one that differs between the two families.
The standard Material 3 components, which are the ui-tiles and ui-tiles-extended ones, take a shape parameter. The expressive components use shapes instead, and the readme is explicit about that difference rather than letting you discover it from a compiler error.
SettingsSwitch(
state = switchState,
title = { Text("Rounded corners") },
shape = RoundedCornerShape(16.dp), // Custom shape
onCheckedChange = { switchThat snippet shows the shape of the API as well. The title is a slot taking a composable lambda, so the text content is a Text call rather than a string, which means you can put anything in it. The state is passed in rather than held, and the change callback is a lambda, so the component is stateless and the state lives wherever you keep it.
Two points follow from that design. First, because the component does not own its state, the same row can be driven by a ViewModel, a remember block, or a hoisted value from a parent, and it composes with the rest of your state management rather than imposing one. Second, because the title is a composable slot, the same SettingsSwitch can carry a plain label, a label with an icon, or a custom layout, without needing a variant of the component for each.
For the expressive components, the readme calls out two requirements explicitly. They require the Material 3 Expressive API, which means an opt-in annotation on the experimental API, and all components support segmented list styling via the shapes parameter. The latter is the substantive one: segmented list styling changes a group of rows into a joined visual unit rather than a stack of separated cards, and doing that with the standard components means building the grouping yourself.
The parameter names differ between the two families, so a codebase that migrates from standard to expressive has to rename shape to shapes at each call site. That is a small cost, and it is the kind of detail that is easier to plan for than to discover mid-migration.
The repository layout, and what the samples cover
The top-level structure is that of a Gradle multiplatform library with a convention plugin layer.
The four source modules are ui-core, ui-tiles, ui-tiles-extended and ui-tiles-expressive. ui-core is not in the published table, which means it is internal rather than something you depend on directly, and the three published modules sit on top of it. There is a build-logic/ directory, which is the modern Gradle convention plugin setup, with build.gradle.kts, settings.gradle.kts and a gradle.properties at the top level alongside the gradlew wrapper scripts.
The documentation surface is unusually thorough for a component library. There is an ARCHITECTURE.md, an AGENTS.md, a CLAUDE.md, a SECURITY.md, a CODE_OF_CONDUCT.md, a CONTRIBUTING.md and a PUBLISHING.md. The publish document tells you how releases are made, and the architecture document is the one to read before you contribute, because it explains why the module boundaries are where they are.
The most unusual entry is llms.txt together with a docs/AGENT_INSTRUCTIONS.md. The readme has a section titled For AI agents, which says that if you are using an AI coding agent such as Claude, Codex or Copilot to integrate this library, you should point it at docs/AGENT_INSTRUCTIONS.md, which is also indexed in llms.txt, and that contributors' agents should read AGENTS.md.
That is a deliberate move. Rather than leaving a coding agent to infer the API from source, the project ships instructions written for it, and the llms.txt file is the machine-readable index that a tool can load without a web fetch. For a library whose consumers are increasingly agents assembling a settings screen from documentation, that is a pragmatic piece of distribution.
The samples directory covers the platform matrix with androidApp, iosApp, desktopApp and webApp, plus shared, config and iosConfig directories. The config directories exist because each platform needs its own Compose setup, and separating them keeps the shared module free of platform-specific configuration. That gives a working reference for each of the four targets rather than one example that only compiles on Android.
Where this fits against writing the rows yourself
Two comparisons make the trade visible.
The first is against writing the settings rows by hand in your own project. A settings screen is deceptively large: a switch row, a checkbox row, a tri-state checkbox, a radio button, a slider, a menu link, a group header, and each of them needs the right Material 3 padding, icon placement, secondary text, enabled state and click handling to look native next to a stock settings app. That work is not hard, it is repetitive, and it is the kind of code that ends up subtly different on every screen because it was written fresh each time.
A library of pre-built tiles removes the repetition and gives consistency across screens and across platforms, which is the actual argument for using one. The cost is that you accept the component's behaviour, not just its layout. When the standard Material 3 look is what you want, that is a good trade. When your design is not Material 3, the library fights you: you can override the shape, but the padding model, the icon slots and the enabled and disabled behaviour are the library's.
The second is against a settings screen framework, one that gives you a whole page with sections, headers, persistence and navigation. This library deliberately does not do that, and the readme's framing of it as composable items rather than a settings page is the boundary.
That boundary has a practical consequence. You will still own where a setting is stored and how it is read at the point of use, and if you have several platforms that need to share preference state, you need a multiplatform preferences solution as well, since this library does not supply one.
The Expressive module deserves a note in this comparison. Material 3 Expressive is a newer design language with its own component set, and the fact that this library ships a parallel expressive module rather than replacing the standard one means it supports both. A team on Expressive does not have to fall back to stock Material components for their settings screens, which is the version mismatch that would otherwise be forced on them.
Editorial conclusion
Compose Settings fits a Compose Multiplatform team that needs a settings screen to look and behave like Material 3 across every target without writing each row, and it does not fit a project that needs a bespoke settings design, since the components carry Material 3 shapes and behaviour rather than a theming system of their own. Before adopting it, check the Kotlin version your build uses, since the badges point at Kotlin 2.3.0, and decide between the standard and expressive modules, where the expressive set requires opting in to ExperimentalMaterial3ExpressiveApi and supports segmented list styling through the shapes parameter.
Frequently asked questions
Which Compose Settings module should I depend on?
The ui-tiles module has the standard Material 3 set of MenuLink, Checkbox, TriStateCheckbox, RadioButton, Switch and Group. The ui-tiles-extended module adds Slider and Segmented. The ui-tiles-expressive module carries all of them plus ButtonGroup with segmented list support, and requires the Material 3 Expressive API.
How do I add Compose Settings to a Gradle build?
Use the coordinates com.github.alorma.compose-settings with the artefact name matching the module, for example implementation 'com.github.alorma.compose-settings:ui-tiles:$version', or the Kotlin DSL and version catalog forms given in the readme. The library is published on Maven Central.
Can I customize the shape of a Compose Settings component?
Yes. Standard Material 3 components take a shape parameter, so you can pass something like RoundedCornerShape(16.dp). The expressive components use shapes instead of shape, and all expressive components support segmented list styling through that parameter.
Which platforms does Compose Settings support?
It targets Compose Multiplatform and the badges name Android, iOS and macOS, the JVM, and WASM and JS, with the description listing Android, iOS, Desktop, JavaScript and WebAssembly. The samples directory has corresponding androidApp, iosApp, desktopApp and webApp projects.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/alorma-compose-settings)Was this useful?