7.1 KiB
Shared Composables Catalog
This catalog documents shared UI components in commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/.
Directory Structure
commons/src/commonMain/kotlin/.../commons/ui/
├── components/ # Reusable UI components
├── screens/ # Screen-level composables
├── theme/ # Theming and styling
└── feed/ # Feed-specific components
Components (ui/components/)
State Visualization
LoadingState - Centered loading indicator with message
@Composable
fun LoadingState(message: String, modifier: Modifier = Modifier)
- Use for: Async operations, data fetching
- Pattern: fillMaxSize, centered Column, CircularProgressIndicator
- Works on: Android, Desktop
EmptyState - Centered empty state with optional refresh
@Composable
fun EmptyState(
title: String,
modifier: Modifier = Modifier,
description: String? = null,
onRefresh: (() -> Unit)? = null,
refreshLabel: String = "Refresh"
)
- Use for: Empty lists, no data scenarios
- Pattern: Centered Column, optional OutlinedButton
- Works on: Android, Desktop
ErrorState - Centered error message with retry
@Composable
fun ErrorState(
message: String,
modifier: Modifier = Modifier,
onRetry: (() -> Unit)? = null,
retryLabel: String = "Try Again"
)
- Use for: Error handling, failed operations
- Pattern: error color, optional Button
- Works on: Android, Desktop
Feed-Specific States
FeedEmptyState - Pre-configured empty state for feeds
@Composable
fun FeedEmptyState(
modifier: Modifier = Modifier,
title: String = "Feed is empty",
onRefresh: (() -> Unit)? = null
)
FeedErrorState - Pre-configured error state for feeds
@Composable
fun FeedErrorState(
errorMessage: String,
modifier: Modifier = Modifier,
onRetry: (() -> Unit)? = null
)
Action Buttons
Shared Constants:
val ActionButtonShape = RoundedCornerShape(20.dp)
val ActionButtonPadding = PaddingValues(vertical = 0.dp, horizontal = 16.dp)
AddButton - Consistent "Add" action button
@Composable
fun AddButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
text: String = "Add",
enabled: Boolean = true
)
- Pattern: OutlinedButton with consistent shape/padding
- Works on: Android, Desktop
RemoveButton - Consistent "Remove" action button
@Composable
fun RemoveButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
text: String = "Remove",
enabled: Boolean = true
)
Custom Images
RobohashImage - Deterministic avatar generation
@Composable
fun RobohashImage(
robot: String, // Seed (e.g., pubkey)
modifier: Modifier = Modifier,
contentDescription: String? = null,
loadRobohash: Boolean = true
)
// Overload with more options
@Composable
fun RobohashImage(
robot: String,
modifier: Modifier = Modifier,
contentDescription: String? = null,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
colorFilter: ColorFilter? = null,
loadRobohash: Boolean = true
)
- Use for: User avatars, deterministic graphics
- Pattern: Uses CachedRobohash.get(), isLightTheme() detection
- Fallback: Icons.Default.Face
- Works on: Android, Desktop (pure ImageVector)
Theme Detection Helper:
@Composable
private fun isLightTheme(): Boolean {
val background = MaterialTheme.colorScheme.background
return (background.red + background.green + background.blue) / 3 > 0.5f
}
Feed Components (ui/feed/)
FeedHeader
FeedHeader - Screen header with title and relay status
@Composable
fun FeedHeader(
title: String,
connectedRelayCount: Int,
onRefresh: () -> Unit,
modifier: Modifier = Modifier
)
- Pattern: Row with SpaceBetween, title + RelayStatusIndicator
- Works on: Android, Desktop
RelayStatusIndicator - Compact relay connection indicator
@Composable
fun RelayStatusIndicator(
connectedCount: Int,
onRefresh: () -> Unit,
modifier: Modifier = Modifier
)
- Pattern: Status icon + count text + refresh button
- Colors: RelayStatusColors.{Disconnected, Connecting, Connected}
- Visual cues: Check icon (connected), Close icon (disconnected)
Screens (ui/screens/)
Placeholder Pattern
PlaceholderScreen - Generic placeholder
@Composable
fun PlaceholderScreen(
title: String,
description: String,
modifier: Modifier = Modifier
)
- Pattern: Column with title (headlineMedium) + description
- Use for: Unimplemented screens, coming soon features
Specific Placeholders:
SearchPlaceholder()- Search screenMessagesPlaceholder()- DMs screenNotificationsPlaceholder()- Notifications screen
Pattern: Specific implementations wrap PlaceholderScreen with preset text.
Custom Icons (robohash/parts/)
ImageVector Builder Pattern
Amethyst uses a custom DSL for building ImageVector assets:
@Composable
fun Face0C3po() {
Image(
painter = rememberVectorPainter(
roboBuilder {
face0C3po(SolidColor(Color.Blue), this)
}
),
contentDescription = ""
)
}
fun face0C3po(fgColor: SolidColor, builder: Builder) {
builder.addPath(pathData1, fill = fgColor, stroke = Black, strokeLineWidth = 1.5f)
builder.addPath(pathData2, fill = Black, fillAlpha = 0.4f)
// ...
}
private val pathData1 = PathData {
moveTo(144.5f, 87.5f)
reflectiveCurveToRelative(-51.0f, 3.0f, -53.0f, 55.0f)
// ... path commands
}
roboBuilder - Custom ImageVector.Builder DSL
- Located in:
commons/robohash/ - Pattern: Builder-based, composable paths
- Parts: Face, Eyes, Mouth, Body, Accessory (0-9 variants each)
- Colors: Dynamic (fgColor parameter) + Black constants
CachedRobohash
CachedRobohash.get(seed: String, isLight: Boolean): ImageVector
- Deterministic: Same seed → same avatar
- Theme-aware: Different colors for light/dark
- Cached: Performance optimization
- Pure ImageVector: Works on all platforms
Sharing Guidelines
Always Share
- State visualization (Loading, Empty, Error)
- Action buttons with consistent styling
- Generic placeholders
- Custom ImageVector icons
- Material3 themed components
- Theme utilities (isLightTheme)
Platform-Specific (Delegate to Experts)
- Navigation structure (android-expert, desktop-expert)
- Screen layouts and scaffolds
- Platform system integrations
- Gesture handling specifics
Decision Framework
- Can it use Material3 primitives? → Share
- Does it need platform system APIs? → Platform-specific
- Is it a visual component without navigation? → Share
- Does it require platform UX patterns? → Ask platform expert
Material3 Usage
All shared composables use Material3:
MaterialTheme.colorScheme.*for colorsMaterialTheme.typography.*for text stylesOutlinedButton,Button,IconButtonfor actionsCircularProgressIndicatorfor loadingIcon,Imagefor visuals
This ensures consistent theming across Android and Desktop.