kmp-compose-unstyled — community kmp-compose-unstyled, kotlin_multiplatform_pokedex, community, ide skills, Claude Code, Cursor, Windsurf

v1.0.0
GitHub

About this Skill

Perfect for Kotlin Multiplatform Agents needing headless UI component development with unstyled UI screens and custom theme configurations. This is a small project to test how a Kotlin Multiplatform app can be developed using LLM tools

niltsiar niltsiar
[0]
[0]
Updated: 3/5/2026

Agent Capability Analysis

The kmp-compose-unstyled skill by niltsiar is an open-source community AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance.

Ideal Agent Persona

Perfect for Kotlin Multiplatform Agents needing headless UI component development with unstyled UI screens and custom theme configurations.

Core Value

Empowers agents to implement headless components with custom styling using DSLs like buildTheme or buildPlatformTheme, ensuring accessibility and state management in Kotlin Multiplatform apps, specifically for features like Button, Text, and ProgressIndicator.

Capabilities Granted for kmp-compose-unstyled

Building Unstyled UI screens in :features:<feature>:ui-unstyled modules
Configuring custom themes using buildTheme or buildPlatformTheme DSLs
Implementing headless components with custom styling for enhanced accessibility and state management

! Prerequisites & Limits

  • Requires Kotlin Multiplatform project setup
  • Limited to headless UI component development
Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

kmp-compose-unstyled

Install kmp-compose-unstyled, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly

KMP Compose Unstyled

Headless component library implementation patterns for the Pokédex project. Unstyled components handle UX logic, state, and accessibility while rendering no visual UI by default.

When to Use This Skill

  • Building Unstyled UI screens in :features:<feature>:ui-unstyled modules.
  • Configuring Themes using buildTheme or buildPlatformTheme DSLs.
  • Implementing Headless Components (Button, Text, ProgressIndicator, etc.) with custom styling.
  • Ensuring Platform-Native Accessibility using interactive size modifiers and platform-specific indications.

Mode Detection

User RequestReference FileLoad When
"Create Unstyled component" / "buildPlatformTheme"compose_unstyled_reference.mdMANDATORY - Read before implementing
"Customize tokens" / "CompositionLocal theming"component_token_customization_example.mdMANDATORY - Read before customizing
"Component not working" / "UI issues"troubleshooting.mdCheck for common issues

MANDATORY - READ ENTIRE FILE: Before implementing Unstyled components with buildPlatformTheme or buildTheme, you MUST read compose_unstyled_reference.md (~1319 lines) for comprehensive component catalog and patterns.

MANDATORY - READ ENTIRE FILE: Before customizing component tokens via CompositionLocal, you MUST read component_token_customization_example.md (~142 lines) for customization patterns.

Do NOT load component_token_customization_example.md for basic component usage - only load when implementing custom token overrides. Do NOT load troubleshooting.md unless experiencing specific UI component issues.

Core Patterns

1. buildPlatformTheme DSL

Uses platform-specific fonts, sizes, and indications automatically.

kotlin
1val PlatformTheme = buildPlatformTheme(name = "MyAppTheme") { 2 defaultContentColor = Color.Black 3 defaultTextStyle = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal) 4 // Platform fonts (Roboto, SF Pro) applied automatically 5}

2. Interactive Size Modifier

Ensures touch targets meet platform accessibility standards (Android 48dp, iOS 44dp).

kotlin
1Button( 2 onClick = {}, 3 modifier = Modifier.interactiveSize(Theme[interactiveSizes][sizeDefault]) 4) { Text("Accessible Button") }

3. Theme Access Syntax

Always use direct bracket notation for fresh theme reads. Avoid storing theme references.

kotlin
1val primary = Theme[colors][primary] // ✅ Direct access 2val body = Theme[typography][bodyMedium]

4. ProgressIndicator Wrapper

Unlike Material, Unstyled ProgressIndicator requires a wrapper to render the fill.

kotlin
1ProgressIndicator(progress = progress) { 2 Box(Modifier.fillMaxWidth(progress).fillMaxSize().background(contentColor, shape)) 3}
  • @kmp-design-systems - Token system and core component architecture.
  • @kmp-architecture - Module structure (Unstyled theme in :core:designsystem-unstyled).
  • @compose-screen - General patterns for implementing Compose screens.
  • @ui-ux-designer - Visual design and animation guidelines.

Critical Guardrails

  1. NEVER include Material Design 3 patterns or components in Unstyled modules → keep modules strictly separated (reason: maintains clean architectural boundaries and prevents visual leakage).
  2. NEVER hardcode platform-specific sizes → always use Theme[interactiveSizes][sizeDefault] (reason: ensures accessibility compliance across Android/iOS/Desktop/Web automatically).
  3. NEVER manual configure fontFamily in buildPlatformTheme → let it be automatic unless using custom fonts (reason: ensures native platform look-and-feel without extra configuration).
  4. NEVER store Theme.currentTheme in variables → always use direct bracket notation Theme[prop][token] (reason: breaks reactivity and prevents state atomicity issues).
  5. NEVER use Modifier.clickable for interactive elements → use the Button component instead (reason: Button provides built-in ARIA support and keyboard interaction logic).
  6. NEVER forget the inner fill Box for ProgressIndicator → always implement the rendering block (reason: unlike Material, Unstyled ProgressIndicator renders no UI by default).
  7. NEVER skip @Preview annotations → every UI component needs a preview with its theme (reason: essential for visual verification and developer efficiency).
  8. NEVER access tokens via MaterialTheme.tokens in unstyled modules → use the Unstyled Theme object (reason: prevents tight coupling and breaks dual-theme encapsulation).

Decision Framework

Before implementing Unstyled components, ask yourself:

  1. What level of customization is needed?

    • Platform-native defaults → Use buildPlatformTheme (automatic fonts, sizes, indications)
    • Custom styling → Use buildTheme with explicit token values
    • Component-specific → Apply Modifier chains to headless components
  2. Which headless components should I use?

    • Interactive elements → Button, IconButton (handle touch targets, accessibility)
    • Text display → Text (platform-native typography)
    • Loading states → ProgressIndicator (platform-specific animations)
    • Custom components → Build with Modifier.interactiveSize() for accessibility
  3. How do I ensure accessibility?

    • Always use Modifier.interactiveSize() for touch targets (48dp minimum)
    • Use Modifier.indication() for platform-native feedback
    • Add @Preview with theme applied for visual verification
    • Test on both Android and iOS for platform consistency

Essential Workflows

Workflow 1: Creating an Unstyled Screen with buildPlatformTheme

To implement a screen with platform-native theming:

  1. Define the theme using buildPlatformTheme in your design system module:
    kotlin
    1val UnstyledTheme = buildPlatformTheme(name = "UnstyledTheme") { 2 defaultContentColor = Color(0xFF1C1B1F) 3 defaultTextStyle = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal) 4 // Platform fonts (Roboto, SF Pro) applied automatically 5}
  2. Wrap your screen content with the theme object:
    kotlin
    1@Composable 2fun PokemonListUnstyledScreen(viewModel: PokemonListViewModel) { 3 val uiState by viewModel.uiState.collectAsStateWithLifecycle() 4 UnstyledTheme { 5 PokemonListContent(uiState = uiState) 6 } 7}
  3. Access tokens using bracket notation:
    kotlin
    1Box(modifier = Modifier.background(Theme[colors][background])) { 2 Text("Pokédex", style = Theme[typography][headlineLarge]) 3}

Related skills: @kmp-design-systems, @compose-screen

Workflow 2: Building Custom Headless Components

To create reusable components using Unstyled primitives:

  1. Use the Button component for any interactive element:
    kotlin
    1@Composable 2fun PokemonCard(pokemon: Pokemon, onClick: () -> Unit) { 3 Button( 4 onClick = onClick, 5 backgroundColor = Theme[colors][surface], 6 contentColor = Theme[colors][onSurface], 7 shape = Theme[shapes][cardShape], 8 modifier = Modifier.interactiveSize(Theme[interactiveSizes][sizeDefault]) 9 ) { 10 Column(horizontalAlignment = Alignment.CenterHorizontally) { 11 AsyncImage(model = pokemon.imageUrl, contentDescription = null) 12 Text(text = pokemon.name, style = Theme[typography][bodyLarge]) 13 } 14 } 15}
  2. Apply interactiveSize to ensure accessibility standards are met.

Related skills: @kmp-design-systems, @ui-ux-designer

Workflow 3: Implementing Interactive Size for Accessibility

To ensure your UI meets platform-specific touch target requirements:

  1. Use sizeDefault (48dp Android, 44dp iOS) for primary actions:
    kotlin
    1Button( 2 onClick = {}, 3 modifier = Modifier.interactiveSize(Theme[interactiveSizes][sizeDefault]) 4) { Text("Accessible Button") }
  2. Use sizeMinimum (32dp Android, 28dp iOS) for dense toolbars:
    kotlin
    1IconButton( 2 onClick = {}, 3 modifier = Modifier.interactiveSize(Theme[interactiveSizes][sizeMinimum]) 4) { Icon(Lucide.Settings, contentDescription = "Settings") }

Related skills: @kmp-architecture, @ui-ux-designer

Workflow 4: Using ProgressIndicator with Custom Styling

To implement a progress bar that requires manual fill rendering:

  1. Provide the rendering block inside the ProgressIndicator call:
    kotlin
    1ProgressIndicator( 2 progress = progress, 3 modifier = Modifier.fillMaxWidth().height(8.dp), 4 shape = RoundedCornerShape(8.dp), 5 backgroundColor = Theme[colors][surface], 6 contentColor = Theme[colors][primary] 7) { 8 // Manual rendering of the progress fill 9 Box( 10 Modifier 11 .fillMaxWidth(progress) 12 .fillMaxSize() 13 .background(contentColor, shape) 14 ) 15}

Related skills: @kmp-developer, @compose-screen

Quick Reference

PatternPurposeExample
buildPlatformThemePlatform-native fonts/sizesbuildPlatformTheme(name = "App") { ... }
Theme[colors][primary]Direct theme accessval primary = Theme[colors][primary]
interactiveSizeAccessibility complianceModifier.interactiveSize(Theme[interactiveSizes][sizeDefault])
ProgressIndicatorCustom fill renderingProgressIndicator(progress) { Box(...) }
ProvideTextStyleCascading text stylesProvideTextStyle(Theme[typography][body]) { ... }

Cross-References

Skills (by Category)

Design & UI

SkillPurposeLink
@kmp-design-systemsToken system and component architectureSKILL.md
@ui-ux-designerVisual design and animation guidelinesSKILL.md
@compose-screenGeneral patterns for implementing Compose screensSKILL.md

Implementation

SkillPurposeLink
@kmp-architectureModule structure and vertical slicingSKILL.md
@kmp-developerGeneral development and feature implementationSKILL.md
@kmp-critical-patterns6 core patterns quick referenceSKILL.md

Platform & Navigation

SkillPurposeLink
@kmp-navigationNavigation 3 modular architectureSKILL.md
@kmp-testing-patternsUI and screenshot testing with RoborazziSKILL.md

Documents

DocumentPurposeLink
compose_unstyled_patterns.mdDetailed patterns catalogSee @kmp-compose-unstyled skill
compose_unstyled_reference.mdCatalog and implementation referencecompose_unstyled_reference.md
component_token_customization_example.mdCustomization via CompositionLocalcomponent_token_customization_example.md
troubleshooting.mdCommon UI component issues and solutionstroubleshooting.md
@kmp-architectureArchitecture and development conventionsArchitecture skill

Troubleshooting Common Unstyled Component Issues

Clickable Component Not Responding

Symptom: Card hover/press states work, but clicking does nothing.

Cause: Missing .clickable() modifier despite having MutableInteractionSource.

Solution:

kotlin
1Column( 2 modifier = modifier 3 .clip(shape) 4 .border(...) 5 .clickable( // ← REQUIRED for actual clicks 6 interactionSource = interactionSource, 7 indication = null, // Or ripple effect 8 onClick = onClick 9 ) 10 .hoverable(interactionSource = interactionSource) // Only tracks hover 11 .padding(...) 12)

Why: hoverable() only tracks hover state, doesn't make component clickable. Must add .clickable() separately.

Order matters:

  1. .clip() - Define shape first
  2. .border() - Visual border
  3. .clickable() - Make clickable
  4. .hoverable() - Track hover state
  5. .padding() - Internal padding

Hover Effects Too Subtle

Symptom: Hover state implemented but barely visible.

Cause: Minimal effect values (brightness 1.1, border alpha 0.2).

Solution for Unstyled theme:

kotlin
1val brightness by animateFloatAsState( 2 targetValue = when { 3 isPressed -> 0.95f 4 isHovered -> 1.15f // More noticeable (was 1.1) 5 else -> 1f 6 } 7) 8 9val borderAlpha by animateFloatAsState( 10 targetValue = when { 11 isPressed -> 0.3f 12 isHovered -> 0.5f // More prominent (was 0.2) 13 else -> 0.2f 14 } 15) 16 17val scale by animateFloatAsState( 18 targetValue = when { 19 isPressed -> 0.98f 20 isHovered -> 1.02f // Slight grow (was 1.0) 21 else -> 1f 22 } 23)

Why: Minimal effects match "unstyled" aesthetic but need sufficient visibility for usability.


FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is kmp-compose-unstyled?

Perfect for Kotlin Multiplatform Agents needing headless UI component development with unstyled UI screens and custom theme configurations. This is a small project to test how a Kotlin Multiplatform app can be developed using LLM tools

How do I install kmp-compose-unstyled?

Run the command: npx killer-skills add niltsiar/kotlin_multiplatform_pokedex/kmp-compose-unstyled. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for kmp-compose-unstyled?

Key use cases include: Building Unstyled UI screens in :features:<feature>:ui-unstyled modules, Configuring custom themes using buildTheme or buildPlatformTheme DSLs, Implementing headless components with custom styling for enhanced accessibility and state management.

Which IDEs are compatible with kmp-compose-unstyled?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for kmp-compose-unstyled?

Requires Kotlin Multiplatform project setup. Limited to headless UI component development.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add niltsiar/kotlin_multiplatform_pokedex/kmp-compose-unstyled. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use kmp-compose-unstyled immediately in the current project.

Related Skills

Looking for an alternative to kmp-compose-unstyled or another community skill for your workflow? Explore these related open-source skills.

View All

widget-generator

Logo of f
f

f.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.

149.6k
0
AI

flags

Logo of vercel
vercel

flags is a Next.js feature management skill that enables developers to efficiently add or modify framework feature flags, streamlining React application development.

138.4k
0
Browser

zustand

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI

data-fetching

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI