К основному содержанию
скилл Claude Code CX Codex Cursor GitHub Copilot

compose-multiplatform-patterns — скилл для Claude Code

Скилл подсказывает паттерны Compose Multiplatform и Jetpack Compose для KMP-проектов: состояние, навигация, темы и UI под разные платформы.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add affaan-m/ECC --skill compose-multiplatform-patterns -a claude-code
Открыть на GitHub

Что делает compose-multiplatform-patterns

Скилл помогает проектировать общий UI для Android, iOS, Desktop и Web на Compose Multiplatform и Jetpack Compose. Он разбирает состояние экрана через ViewModel и StateFlow, сбор состояния в Compose, событийную модель, type-safe navigation, диалоги и bottom sheets.

Внутри есть примеры slot-based API, порядок модификаторов, expect/actual для платформенного UI, стабильные типы, ключи для LazyColumn, derivedStateOf и приёмы для контроля recomposition. Также рассматриваются Material 3 и dynamic theming. Скилл рассчитан на KMP и Android-проекты с Compose. Его стоит ставить, если агент пишет или рефакторит Compose UI; для проекта без Compose он не нужен.

Какие задачи решает

  • спроектировать состояние экрана через ViewModel и StateFlow
  • добавить type-safe navigation в KMP-проект
  • вынести платформенный UI через expect/actual
  • снизить лишние recomposition в LazyColumn
  • собрать переиспользуемый composable через slot API

Примеры запросов агенту

  • Добавь экран списка товаров с ViewModel, StateFlow и поиском.
  • Настрой type-safe navigation для HomeRoute и DetailRoute.
  • Проверь этот LazyColumn и исправь лишние recomposition.

Как установить compose-multiplatform-patterns

1Через Skills CLI (Vercel)

npx skills add affaan-m/ECC --skill compose-multiplatform-patterns -a claude-code

2Вручную: положить файлы

~/.claude/skills/compose-multiplatform-patterns/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/compose-multiplatform-patterns/

Из того же набора146

Весь набор →
video-editing affaan-m Скилл выстраивает пайплайн монтажа реального видео через ИИ. Помогает нарезать сырые записи через FFmpeg, собрать титры в Remotion и добавить озвучку в ElevenLabs. Claude Code CX Codex Cursor +1 6 500установок docker-patterns affaan-m Скилл с проверенными шаблонами Dockerfile и Docker Compose: локальная разработка, сети, тома, безопасность контейнеров. Claude Code CX Codex Cursor +1 6 300установок frontend-patterns affaan-m Скилл подсказывает паттерны для React и Next.js: компоненты, состояние, загрузка данных и производительность. Нужен при разработке и ревью интерфейса. Claude Code CX Codex Cursor +1 5 900установок backend-patterns affaan-m Скилл с паттернами бэкенда для Node.js, Express и Next.js API routes: слои, кэш, транзакции, обработка ошибок. Claude Code CX Codex Cursor +1 5 900установок coding-standards affaan-m Базовые правила кода для проектов: проверяет именование, запрещает мутации объектов и следит за простыми конструкциями. Пригодится на ревью и рефакторинге. Claude Code CX Codex Cursor +1 5 600установок api-design affaan-m Скилл задаёт правила проектирования REST API: именование эндпоинтов, выбор статус-кодов, пагинацию и формат ошибок. Помогает при создании и ревью серверных контрактов. Claude Code CX Codex Cursor +1 5 500установок rust-testing affaan-m Скилл для написания тестов на Rust: юнит-тесты, интеграционные, async, property-based, моки и покрытие. Пригодится, когда ведёшь проект по TDD. Claude Code CX Codex Cursor +1 5 500установок laravel-security affaan-m Скилл помогает проверять безопасность Laravel-приложений: аутентификацию, Eloquent, CSRF, XSS, API и настройки production. Пригодится для ревью и деплоя. Claude Code CX Codex Cursor +1 5 400установок

Похожие

better-colors jakubkrehel Скилл проверяет палитры и строит систему цветовых токенов. Он нужен, когда в коде накопились случайные hex-значения, а контраст текста никто не считал. Claude Code CX Codex Cursor +1 32 200установок verify react Проверяет код перед коммитом в репозиторий React. Запускает форматирование, линтер, проверку типов Flow и тесты. Claude Code CX Codex Cursor +1 1 200установок web-design-reviewer официальный github Скилл осматривает работающий сайт, находит проблемы с вёрсткой, адаптивностью и доступностью, а затем может исправить их в исходном коде. Подойдёт, когда нужно проверить интерфейс и довести исправления до повторной проверки. GitHub Copilot 13 957установок better-layout jakubkrehel Скилл проверяет и правит группировку, выравнивание, порядок чтения и адаптивную структуру макета, а потом ломает её ресайзом, переводом и зеркалированием под RTL. Claude Code CX Codex Cursor +1 30 400установок frontend-design официальный anthropics Скилл задаёт осмысленное визуальное направление для новых интерфейсов и редизайна. Подойдёт, когда стандартный шаблонный UI не устраивает. Claude Code Claude.ai 1 025 790установок design-taste-frontend Leonxlnx Скилл задаёт арт-дирекцию для публичных страниц и рабочих экранов, а затем проверяет результат в браузере по скриншотам. Нужен, когда интерфейс выглядит шаблонным или недоработанным. Claude Code CX Codex Cursor +1 673 100установок prototype Matt Pocock Создаёт временный прототип, чтобы проверить логику, модель состояния или вид интерфейса до работы над основным кодом. Claude Code 986 201установок hyperframes heygen-com Скилл задаёт агенту правила рендера HTML-кода в видео через HyperFrames. Помогает собирать проморолики, эксплейнеры и титры прямо в коде проекта. Claude Code CX Codex Cursor +1 1 200 000установок

Вопросы о compose-multiplatform-patterns

Как установить compose-multiplatform-patterns в Claude Code?

Выполните npx skills add affaan-m/ECC --skill compose-multiplatform-patterns -a claude-code. Файл скилла появится по пути ~/.claude/skills/compose-multiplatform-patterns/SKILL.md.

Что делает compose-multiplatform-patterns?

Он подсказывает паттерны для состояния, навигации, темизации и производительности Compose UI в KMP-проектах, включая платформенный UI для Android, iOS, Desktop и Web.

Для каких проектов подходит этот скилл?

Для проектов на Compose Multiplatform или Jetpack Compose, где нужны ViewModel, StateFlow, type-safe navigation, переиспользуемые composable и оптимизация recomposition.

Исходный текст

SKILL.md · MIT
---
name: compose-multiplatform-patterns
description: Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI. Use when building Compose or Jetpack Compose UI, state, navigation, or theming in a KMP project.
metadata:
  origin: ECC
---

# Compose Multiplatform Patterns

Patterns for building shared UI across Android, iOS, Desktop, and Web using Compose Multiplatform and Jetpack Compose. Covers state management, navigation, theming, and performance.

## When to Activate

- Building Compose UI (Jetpack Compose or Compose Multiplatform)
- Managing UI state with ViewModels and Compose state
- Implementing navigation in KMP or Android projects
- Designing reusable composables and design systems
- Optimizing recomposition and rendering performance

## State Management

### ViewModel + Single State Object

Use a single data class for screen state. Expose it as `StateFlow` and collect in Compose:

```kotlin
data class ItemListState(
    val items: List<Item> = emptyList(),
    val isLoading: Boolean = false,
    val error: String? = null,
    val searchQuery: String = ""
)

class ItemListViewModel(
    private val getItems: GetItemsUseCase
) : ViewModel() {
    private val _state = MutableStateFlow(ItemListState())
    val state: StateFlow<ItemListState> = _state.asStateFlow()

    fun onSearch(query: String) {
        _state.update { it.copy(searchQuery = query) }
        loadItems(query)
    }

    private fun loadItems(query: String) {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true) }
            getItems(query).fold(
                onSuccess = { items -> _state.update { it.copy(items = items, isLoading = false) } },
                onFailure = { e -> _state.update { it.copy(error = e.message, isLoading = false) } }
            )
        }
    }
}
```

### Collecting State in Compose

```kotlin
@Composable
fun ItemListScreen(viewModel: ItemListViewModel = koinViewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()

    ItemListContent(
        state = state,
        onSearch = viewModel::onSearch
    )
}

@Composable
private fun ItemListContent(
    state: ItemListState,
    onSearch: (String) -> Unit
) {
    // Stateless composable — easy to preview and test
}
```

### Event Sink Pattern

For complex screens, use a sealed interface for events instead of multiple callback lambdas:

```kotlin
sealed interface ItemListEvent {
    data class Search(val query: String) : ItemListEvent
    data class Delete(val itemId: String) : ItemListEvent
    data object Refresh : ItemListEvent
}

// In ViewModel
fun onEvent(event: ItemListEvent) {
    when (event) {
        is ItemListEvent.Search -> onSearch(event.query)
        is ItemListEvent.Delete -> deleteItem(event.itemId)
        is ItemListEvent.Refresh -> loadItems(_state.value.searchQuery)
    }
}

// In Composable — single lambda instead of many
ItemListContent(
    state = state,
    onEvent = viewModel::onEvent
)
```

## Navigation

### Type-Safe Navigation (Compose Navigation 2.8+)

Define routes as `@Serializable` objects:

```kotlin
@Serializable data object HomeRoute
@Serializable data class DetailRoute(val id: String)
@Serializable data object SettingsRoute

@Composable
fun AppNavHost(navController: NavHostController = rememberNavController()) {
    NavHost(navController, startDestination = HomeRoute) {
        composable<HomeRoute> {
            HomeScreen(onNavigateToDetail = { id -> navController.navigate(DetailRoute(id)) })
        }
        composable<DetailRoute> { backStackEntry ->
            val route = backStackEntry.toRoute<DetailRoute>()
            DetailScreen(id = route.id)
        }
        composable<SettingsRoute> { SettingsScreen() }
    }
}
```

### Dialog and Bottom Sheet Navigation

Use `dialog()` and overlay patterns instead of imperative show/hide:

```kotlin
NavHost(navController, startDestination = HomeRoute) {
    composable<HomeRoute> { /* ... */ }
    dialog<ConfirmDeleteRoute> { backStackEntry ->
        val route = backStackEntry.toRoute<ConfirmDeleteRoute>()
        ConfirmDeleteDialog(
            itemId = route.itemId,
            onConfirm = { navController.popBackStack() },
            onDismiss = { navController.popBackStack() }
        )
    }
}
```

## Composable Design

### Slot-Based APIs

Design composables with slot parameters for flexibility:

```kotlin
@Composable
fun AppCard(
    modifier: Modifier = Modifier,
    header: @Composable () -> Unit = {},
    content: @Composable ColumnScope.() -> Unit,
    actions: @Composable RowScope.() -> Unit = {}
) {
    Card(modifier = modifier) {
        Column {
            header()
            Column(content = content)
            Row(horizontalArrangement = Arrangement.End, content = actions)
        }
    }
}
```

### Modifier Ordering

Modifier order matters — apply in this sequence:

```kotlin
Text(
    text = "Hello",
    modifier = Modifier
        .padding(16.dp)          // 1. Layout (padding, size)
        .clip(RoundedCornerShape(8.dp))  // 2. Shape
        .background(Color.White) // 3. Drawing (background, border)
        .clickable { }           // 4. Interaction
)
```

## KMP Platform-Specific UI

### expect/actual for Platform Composables

```kotlin
// commonMain
@Composable
expect fun PlatformStatusBar(darkIcons: Boolean)

// androidMain
@Composable
actual fun PlatformStatusBar(darkIcons: Boolean) {
    val systemUiController = rememberSystemUiController()
    SideEffect { systemUiController.setStatusBarColor(Color.Transparent, darkIcons) }
}

// iosMain
@Composable
actual fun PlatformStatusBar(darkIcons: Boolean) {
    // iOS handles this via UIKit interop or Info.plist
}
```

## Performance

### Stable Types for Skippable Recomposition

Mark classes as `@Stable` or `@Immutable` when all properties are stable:

```kotlin
@Immutable
data class ItemUiModel(
    val id: String,
    val title: String,
    val description: String,
    val progress: Float
)
```

### Use `key()` and Lazy Lists Correctly

```kotlin
LazyColumn {
    items(
        items = items,
        key = { it.id }  // Stable keys enable item reuse and animations
    ) { item ->
        ItemRow(item = item)
    }
}
```

### Defer Reads with `derivedStateOf`

```kotlin
val listState = rememberLazyListState()
val showScrollToTop by remember {
    derivedStateOf { listState.firstVisibleItemIndex > 5 }
}
```

### Avoid Allocations in Recomposition

```kotlin
// BAD — new lambda and list every recomposition
items.filter { it.isActive }.forEach { ActiveItem(it, onClick = { handle(it) }) }

// GOOD — key each item so callbacks stay attached to the right row
val activeItems = remember(items) { items.filter { it.isActive } }
activeItems.forEach { item ->
    key(item.id) {
        ActiveItem(item, onClick = { handle(item) })
    }
}
```

## Theming

### Material 3 Dynamic Theming

```kotlin
@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            if (darkTheme) dynamicDarkColorScheme(LocalContext.current)
            else dynamicLightColorScheme(LocalContext.current)
        }
        darkTheme -> darkColorScheme()
        else -> lightColorScheme()
    }

    MaterialTheme(colorScheme = colorScheme, content = content)
}
```

## Anti-Patterns to Avoid

- Using `mutableStateOf` in ViewModels when `MutableStateFlow` with `collectAsStateWithLifecycle` is safer for lifecycle
- Passing `NavController` deep into composables — pass lambda callbacks instead
- Heavy computation inside `@Composable` functions — move to ViewModel or `remember {}`
- Using `LaunchedEffect(Unit)` as a substitute for ViewModel init — it re-runs on configuration change in some setups
- Creating new object instances in composable parameters — causes unnecessary recomposition

## References

See skill: `android-clean-architecture` for module structure and layering.
See skill: `kotlin-coroutines-flows` for coroutine and Flow patterns.

© affaan-m · MIT · affaan-m/ECC

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой