This repository provides Material 3 wrapper components for Compose HTML based on Material Web. It's a Kotlin Multiplatform library targeting JavaScript/Browser, allowing developers to use Material Design 3 components in Compose HTML applications.
Key Points:
- Type: Kotlin/JS library (not an application)
- Size: Small to medium (~4 main modules)
- Language: Kotlin 2.3.20
- Frameworks: Compose HTML 1.10.3, Kobweb 0.24.0
- Build System: Gradle 9.4.1 with Kotlin DSL
- Target Runtime: JavaScript/Browser (Kotlin/JS)
- Published to: Maven Central
build.gradle.kts- Root build configuration (Dokka, API validation)settings.gradle.kts- Multi-module project settingsgradle.properties- Gradle configuration cache enabledgradlew/gradlew.bat- Gradle wrapper scriptsCONTRIBUTING.md- Development guidelinesREADME.md- User documentationCHANGELOG.md- Version history
-
compose-html-common- Common utilities and attributes for Compose HTML- Location:
/compose-html-common/ - Source:
src/jsMain/kotlin/com/huanshankeji/compose/web/ - Key packages:
attributes,css, layouts
- Location:
-
compose-html-material3- Material 3 component wrappers (primary module)- Location:
/compose-html-material3/ - Source:
src/jsMain/kotlin/com/huanshankeji/compose/html/material3/ - Components: MdButton, MdCheckbox, MdIcon, MdTextField, MdMenu, MdProgress, etc.
- Depends on:
compose-html-common, npm package@material/web
- Location:
-
compose-html-material-legacy- Legacy Material 2 components (NO LONGER MAINTAINED - DO NOT MAKE CHANGES)- Location:
/compose-html-material-legacy/ - This module is obsolete and not actively maintained
- Do not apply updates, bug fixes, or improvements to this module
- For Material 2 components, users should use KMDC instead
- Location:
-
compose-html-material3-maicol07-material-web-additions- Additional Material 3 components from maicol07's Material Web Additions- Location:
/compose-html-material3-maicol07-material-web-additions/ - Source:
src/jsMain/kotlin/com/huanshankeji/compose/html/material3/maicol07/materialwebadditions/ - Components: MdSnackbar, MdSmallTopAppBar, MdCenterAlignedTopAppBar, MdMediumTopAppBar, MdLargeTopAppBar
- Depends on:
compose-html-common,compose-html-material3, npm package@maicol07/material-web-additions - Uses
@MaterialWebAdditionsApiopt-in annotation for all components - This library was chosen because its style closely follows the original Material Web library's API patterns
- Location:
-
gradle-plugins- Legacy gradle plugins- Location:
/gradle-plugins/ - Published as:
compose-html-material-gradle-plugins-legacy
- Location:
-
buildSrc- Build logic and convention plugins- Location:
/buildSrc/ - Key file:
src/main/kotlin/VersionsAndDependencies.kt- contains version constants - Convention plugins:
lib-conventions.gradle.kts,lib-conventions-without-publishing.gradle.kts
- Location:
- API validation: Each published module has an
api/directory with.klib.apifiles for binary compatibility checking - Kotlin/JS store:
kotlin-js-store/yarn.lock- JavaScript dependencies cache - Site generation:
site/directory contains static files for documentation site
- JDK 17 (Temurin distribution recommended) - CRITICAL: The CI uses JDK 17, always ensure compatibility
- Gradle 9.4.1 (via wrapper, automatically downloaded)
- Internet access for downloading dependencies from Maven Central
IMPORTANT: Always use ./gradlew (or gradlew.bat on Windows), never install Gradle separately.
-
Check/Test (Primary validation)
./gradlew check
- Runs all checks including API validation
- This is the main command used in CI
- Expected time: 1-3 minutes (after initial setup)
- No unit tests exist currently; this primarily validates compilation and API compatibility
-
Build All Modules
./gradlew build
- Compiles all modules
- Generates artifacts in each module's
build/directory
-
Publish to Maven Local (for testing changes locally)
./gradlew publishToMavenLocal
- Publishes artifacts to
~/.m2/repository/ - Use this to test your changes in dependent projects
- Publishes artifacts to
-
Generate API Documentation Site
./gradlew generateSite
- Generates Dokka documentation
- Output:
build/site/directory - Used by GitHub Pages deployment workflow
-
Clean Build
./gradlew clean build
- Removes all build artifacts first
- Use when troubleshooting build issues
- First build: 3-10 minutes (downloads Gradle, dependencies, builds buildSrc)
- Subsequent builds: 30 seconds - 2 minutes
- Clean builds: 1-3 minutes
-
Gradle Daemon startup delays: First build in a session takes longer while Gradle daemon starts. Subsequent builds are much faster.
-
Kotlin compiler warnings about version mismatch: You may see warnings like "WARNING: Unsupported Kotlin plugin version" in the buildSrc compilation. These are typically non-fatal and relate to the Kotlin version mismatch between buildSrc (2.3.20) and Gradle's embedded Kotlin version.
.github/workflows/
-
kotlin-multiplatform-ci.yml(Main CI)- Trigger: Push to any branch, manual dispatch
- Jobs:
test-and-check: Runs./gradlew checkwith JDK 17dependency-submission: Submits dependency graph to GitHub
- Action: Uses
huanshankeji/.github/actions/gradle-test-and-check@v0.2.0 - CRITICAL: Your code changes MUST pass
./gradlew checklocally before pushing. Ifcheckfails solely due toapiCheckfailures, use./gradlew publishToMavenLocalas an alternative validation and leave runningapiDumpfor the human developer.
-
site-gh-pages.yml(Documentation Deployment)- Trigger: Push/PR to
releasebranch, manual dispatch - Job: Builds and deploys documentation site to GitHub Pages
- Build command:
./gradlew generateSite - Output:
build/site/uploaded to GitHub Pages
- Trigger: Push/PR to
To replicate CI locally:
./gradlew clean checkThis ensures:
- All modules compile successfully
- API compatibility is maintained (binary compatibility validator)
- No breaking changes to public APIs
If check fails solely due to apiCheck failures (public APIs changed), use ./gradlew publishToMavenLocal as the alternative validation and leave apiDump for the human developer.
-
Before starting:
- Check which module your change affects (usually
compose-html-material3orcompose-html-common) - Review existing similar components for patterns and conventions
- Check which module your change affects (usually
-
After making changes:
- Run
./gradlew checkto validate - Do NOT run
apiDumpautomatically — even ifcheckfails due toapiCheckfailures on.klib.apifiles. Leave runningapiDumpfor the human developer after they have reviewed the API changes. RunningapiDumpautomatically generates unnecessary Git-tracked churn before the developer has had a chance to review the API surface. The only exception is if you are very confident you have completely and correctly finished all the task goals, the API changes are exactly as intended, and no further API edits from the developer will be needed. - If
checkfails solely due toapiCheckfailures (because public APIs have changed), validate using:Then leave running./gradlew publishToMavenLocal
apiDumpfor the human developer to perform after reviewing API changes. - If changing existing APIs, review
.klib.apidiffs carefully (breaking changes require version bumps)
- Run
-
Testing changes locally:
- Use
./gradlew publishToMavenLocal - Create/update a test project that depends on
com.huanshankeji:compose-html-material3:0.5.0-SNAPSHOT - Verify the component works in a real Compose HTML application
- Use
This project uses Kotlin's binary compatibility validator (kotlinx.validation):
- Public API signatures are tracked in
api/*.klib.apifiles - Breaking changes will fail the
checktask - To update API files after intentional changes:
./gradlew apiDump— but do NOT run this automatically. Leave it for the human developer to run after reviewing the API surface. Only run it yourself if you are very confident all task goals are complete and no further API edits will be needed. - ALWAYS review API changes carefully before committing
- Current version defined in:
buildSrc/src/main/kotlin/VersionsAndDependencies.kt - Current version:
0.5.0-SNAPSHOT - Release versions should not have
-SNAPSHOTsuffix
- Official Material Design 3 site: https://m3.material.io/
- Component guidelines: https://m3.material.io/components/ (e.g., https://m3.material.io/components/buttons/overview for buttons)
- Use these resources to understand the visual effects, behavior, and design guidelines of each component
- Component documentation comments should include links to:
- Material Web GitHub component documentation
- Material Web demo site
- Material Web stories
- Material Design 3 component guidelines (https://m3.material.io/components/)
- Always verify that all links are accessible (not 404) before adding them to documentation comments
- For parameters or slots that cannot be found in the official component documentation, always add a reference link (e.g., to the component source code, demo code, or stories/Storyboard source code) in an inline comment immediately before those parameters. Use GitHub permalinks with precisely selected lines.
Material 3 components follow a consistent pattern (see compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/):
// Common pattern for Material Web components
@Composable
fun MdComponentName(
disabled: Boolean? = null,
// ... component-specific parameters
attrs: AttrBuilderContext<HTMLElement>? = null,
content: ContentBuilder<HTMLElement>? = null
) {
TagElement("md-component-name", {
disabled(disabled)
// ... set attributes
attrs?.invoke(this)
}, content)
}- Nullable parameters for optional attributes (not defaulting to false/empty)
- Attrs parameter for custom attributes (always nullable, applied last)
- Content lambda for component children (nullable, last parameter)
- Components that conventionally always have content (e.g., buttons, FABs, cards, icon buttons, navigation bars) should have a non-null, required
contentparameter (no= nulldefault) — an empty button or card makes no sense - Components that do not inherently require content (e.g., checkbox, switch, divider, progress, radio) should have a nullable content parameter with
= nulldefault, used for optional effects
- Components that conventionally always have content (e.g., buttons, FABs, cards, icon buttons, navigation bars) should have a non-null, required
- kebab-case for HTML element names (e.g.,
md-elevated-button) - Extension functions in
compose-html-commonfor common attribute patterns - Attribute order should follow the original component documentation (https://github.com/material-components/material-web/blob/main/docs/components/*, or https://github.com/material-components/material-web/blob/main/labs/*/internal/*.ts for a labs components) order exactly
- One component type per file (e.g.,
MdButton.ktcontains all button variants) - Attributes extensions in
attributes/subdirectory - Common utilities in
compose-html-commonmodule - Patterns follow Compose HTML conventions - see Compose Multiplatform README and Compose HTML directory
- Kotlin: 2.3.20
- Compose Multiplatform: 1.10.3
- Kobweb: 0.24.0 (provides Compose HTML extensions, now published to Maven Central)
- Material Web: 2.4.1 (NPM dependency)
- Material Web Additions: 1.8.0 (NPM dependency for
compose-html-material3-maicol07-material-web-additionsmodule) - Dokka: 2.1.0 (documentation generation)
Dependencies are declared in module build.gradle.kts files using the convention:
kotlin {
sourceSets {
jsMain {
dependencies {
implementation(project(":compose-html-common"))
implementation(npm("package-name", "version"))
}
}
}
}Version constants should be added to buildSrc/src/main/kotlin/VersionsAndDependencies.kt.
IMPORTANT: This project currently has NO automated tests. The validation relies on:
- Successful compilation
- API compatibility checking
- Manual testing via
publishToMavenLocal
When adding components:
- Manually test in a real Compose HTML application
- Verify component renders correctly in a browser
- Test attribute bindings and event handlers
- Check Material Symbols/Icons display correctly (requires separate setup)
You can test changes in the demo module of compose-multiplatform-html-unified:
- Clone that repository and check out the
devbranch if available (likely has updated dependencies) - Update dependencies to use the snapshot version of this project via
publishToMavenLocal - See the hosted demo site for visual effects of released versions
- Interact with the demo (click buttons, etc.) to verify component behavior
| Task | Command | When to Use |
|---|---|---|
| Validate all changes | ./gradlew check |
Before every commit |
| Build everything | ./gradlew build |
Verify all modules compile |
| Clean build | ./gradlew clean build |
Troubleshooting |
| Update API signatures | ./gradlew apiDump |
Human developer only — after reviewing API surface changes; do NOT run automatically |
| Test locally / fallback validation | ./gradlew publishToMavenLocal |
Test changes in other projects; also use as fallback when check fails solely due to apiCheck failures |
| Generate docs | ./gradlew generateSite |
Build documentation (auto-deployed by GitHub Actions) |
| List all tasks | ./gradlew tasks |
Discover available tasks |
- Ensure internet connectivity to Maven Central
- Try
./gradlew build --refresh-dependencies
- Review the API diff:
git diff */api/*.klib.api - Do NOT run
apiDumpautomatically — leave it for the human developer to run after reviewing the API changes - If
checkfails solely due toapiCheck, use./gradlew publishToMavenLocalas an alternative validation instead - If changes are breaking, consider if version bump is needed
- Stop daemon:
./gradlew --stop - Clear cache:
rm -rf ~/.gradle/caches/(last resort)
- Run
./gradlew checkto validate before committing. If it fails solely due toapiCheckfailures, use./gradlew publishToMavenLocalas an alternative validation, and leaveapiDumpfor the human developer to run after reviewing the API changes. - Never commit changes to
.gradle/,build/,.kotlin/, or.idea/directories (already in .gitignore) - This is a library, not an application - there's no main method or runnable app
- Material 2 components are legacy - focus work on Material 3 (
compose-html-material3) - DO NOT make changes to
compose-html-material-legacy- this module is obsolete and no longer maintained - Trust these instructions first - only search/explore if information here is incomplete or incorrect