UI Component Skill
Create reusable UI components in ui/ modules.
Common Tasks
code
/ui-component create LoadingButton # Create new component /ui-component add UserAvatar # Add avatar component /ui-component explain patterns # Understand component patterns
When to Create UI Components
Create in ui/ when:
- •Component is used by 2+ screen modules
- •Component is a design system element
Keep in screen module when:
- •Only used by one screen
- •Screen-specific behavior
Component Pattern
kotlin
@Composable
fun LoadingButton(
onClick: () -> Unit, // Required callbacks first
text: String, // Required params
modifier: Modifier = Modifier, // Modifier
isLoading: Boolean = false, // Optional params
enabled: Boolean = true,
) {
Button(
onClick = onClick,
modifier = modifier,
enabled = enabled && !isLoading,
) {
if (isLoading) {
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
strokeWidth = 2.dp,
)
} else {
Text(text = text)
}
}
}
@PreviewJellyfinScreen
@Composable
private fun LoadingButtonPreview(
@PreviewParameter(LoadingButtonPreviewProvider::class)
state: LoadingButtonState,
) {
JellyfinPreviewTheme {
LoadingButton(
onClick = {},
text = state.text,
isLoading = state.isLoading,
)
}
}
private class LoadingButtonPreviewProvider : NamedPreviewParameterProvider<LoadingButtonState>(
"default" to LoadingButtonState("Submit"),
"loading" to LoadingButtonState("Submit", isLoading = true),
"disabled" to LoadingButtonState("Submit", enabled = false),
)
private data class LoadingButtonState(
val text: String,
val isLoading: Boolean = false,
val enabled: Boolean = true,
)
Module Structure
code
ui/<component-type>/
├── src/main/kotlin/com/eygraber/jellyfin/ui/<type>/
│ └── LoadingButton.kt
└── src/test/kotlin/com/eygraber/jellyfin/ui/<type>/
└── LoadingButtonScreenshotTest.kt
Screenshot Tests
See /screenshot-tests skill for testing UI components.
Documentation
- •.docs/compose/ - Compose patterns
- •.claude/rules/compose.md - Compose rules