SuperSpinner
SuperSpinner is a dropdown selector component in Miuix that provides titles, summaries, and a list of options with icons and text. It supports click interaction and various display modes, commonly used in option settings with visual aids. This component is similar to SuperDropdown but offers richer functionality and interaction experience.
WARNING
SuperSpinner must be used within a Scaffold component!
Import
kotlin
import top.yukonga.miuix.kmp.extra.SuperSpinner
import top.yukonga.miuix.kmp.extra.SpinnerEntryBasic Usage
The SuperSpinner component provides basic dropdown selector functionality:
kotlin
var selectedIndex by remember { mutableStateOf(0) }
val options = listOf(
SpinnerEntry(title = "Option 1"),
SpinnerEntry(title = "Option 2"),
SpinnerEntry(title = "Option 3"),
)
Scaffold {
SuperSpinner(
title = "Dropdown Selector",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it }
)
}Options with Icons and Summaries
kotlin
// Create a rounded rectangle Painter
class RoundedRectanglePainter(
private val cornerRadius: Dp = 6.dp
) : Painter() {
override val intrinsicSize = Size.Unspecified
override fun DrawScope.onDraw() {
drawRoundRect(
color = Color.White,
size = Size(size.width, size.height),
cornerRadius = CornerRadius(cornerRadius.toPx(), cornerRadius.toPx())
)
}
}
var selectedIndex by remember { mutableStateOf(0) }
val options = listOf(
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFFFF5B29)) },
title = "Red Theme",
summary = "Vibrant red"
),
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFF3482FF)) },
title = "Blue Theme",
summary = "Calm blue"
),
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFF36D167)) },
title = "Green Theme",
summary = "Fresh green"
),
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFFFFB21D)) },
title = "Yellow Theme",
summary = "Bright yellow"
)
)
Scaffold {
SuperSpinner(
title = "Function Selection",
summary = "Choose the action you want to perform",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it }
)
}Component States
Disabled State
kotlin
SuperSpinner(
title = "Disabled Selector",
summary = "This selector is currently unavailable",
items = listOf(SpinnerEntry(title = "Option 1")),
selectedIndex = 0,
onSelectedIndexChange = {},
enabled = false
)Dialog Mode
Display Dropdown Menu in Dialog
kotlin
var selectedIndex by remember { mutableStateOf(0) }
val options = listOf(
SpinnerEntry(title = "Option 1"),
SpinnerEntry(title = "Option 2"),
SpinnerEntry(title = "Option 3")
)
Scaffold {
SuperSpinner(
title = "Dialog Mode",
dialogButtonString = "Cancel",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it }
)
}Properties
SuperSpinner Properties (Dropdown Mode)
| Property Name | Type | Description | Default Value | Required |
|---|---|---|---|---|
| items | List<SpinnerEntry> | Options list | - | Yes |
| selectedIndex | Int | Current selected item index | - | Yes |
| title | String | Selector title | - | Yes |
| titleColor | BasicComponentColors | Title text color config | BasicComponentDefaults.titleColor() | No |
| summary | String? | Selector description | null | No |
| summaryColor | BasicComponentColors | Summary text color config | BasicComponentDefaults.summaryColor() | No |
| spinnerColors | SpinnerColors | Color configuration for spinner | SpinnerDefaults.spinnerColors() | No |
| leftAction | @Composable (() -> Unit)? | Custom left content | null | No |
| modifier | Modifier | Component modifier | Modifier | No |
| insideMargin | PaddingValues | Internal content padding | BasicComponentDefaults.InsideMargin | No |
| maxHeight | Dp? | Maximum dropdown height | null | No |
| enabled | Boolean | Interactive state | true | No |
| showValue | Boolean | Show current selected value | true | No |
| onClick | (() -> Unit)? | Additional click callback | null | No |
| onSelectedIndexChange | ((Int) -> Unit)? | Selection change callback | - | Yes |
SuperSpinner Properties (Dialog Mode)
| Property Name | Type | Description | Default Value | Required |
|---|---|---|---|---|
| items | List<SpinnerEntry> | Options list | - | Yes |
| selectedIndex | Int | Current selected item index | - | Yes |
| title | String | Selector title | - | Yes |
| titleColor | BasicComponentColors | Title text color config | BasicComponentDefaults.titleColor() | No |
| summary | String? | Selector description | null | No |
| summaryColor | BasicComponentColors | Summary text color config | BasicComponentDefaults.summaryColor() | No |
| spinnerColors | SpinnerColors | Color configuration for spinner | SpinnerDefaults.spinnerColors() | No |
| leftAction | @Composable (() -> Unit)? | Custom left content | null | No |
| dialogButtonString | String | Dialog bottom button text | - | Yes |
| popupModifier | Modifier | Dialog popup modifier | Modifier | No |
| modifier | Modifier | Component modifier | Modifier | No |
| insideMargin | PaddingValues | Internal content padding | BasicComponentDefaults.InsideMargin | No |
| enabled | Boolean | Interactive state | true | No |
| showValue | Boolean | Show current selected value | true | No |
| onClick | (() -> Unit)? | Additional click callback | null | No |
| onSelectedIndexChange | ((Int) -> Unit)? | Selection change callback | - | Yes |
SpinnerEntry Properties
| Property Name | Type | Description |
|---|---|---|
| icon | @Composable ((Modifier) -> Unit)? | Option icon |
| title | String? | Option title |
| summary | String? | Option description |
SpinnerColors Properties
| Property Name | Type | Description |
|---|---|---|
| contentColor | Color | Option title color |
| summaryColor | Color | Option summary color |
| containerColor | Color | Option background color |
| selectedContentColor | Color | Selected item title color |
| selectedSummaryColor | Color | Selected item summary color |
| selectedContainerColor | Color | Selected item background color |
| selectedIndicatorColor | Color | Selected check icon color |
Advanced Usage
Custom Colors
kotlin
var selectedIndex by remember { mutableStateOf(0) }
val options = listOf(
SpinnerEntry(title = "Red"),
SpinnerEntry(title = "Green"),
SpinnerEntry(title = "Blue")
)
Scaffold {
SuperSpinner(
title = "Custom Colors",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it },
spinnerColors = SpinnerDefaults.spinnerColors(
contentColor = MiuixTheme.colorScheme.onSurface,
summaryColor = MiuixTheme.colorScheme.onSurfaceVariantSummary,
containerColor = MiuixTheme.colorScheme.surface,
selectedContentColor = Color.Red,
selectedSummaryColor = Color.Red,
selectedContainerColor = Color.Red.copy(alpha = 0.12f),
selectedIndicatorColor = Color.Red
)
)
}Custom Left Content
kotlin
var selectedIndex by remember { mutableStateOf(0) }
val options = listOf(
SpinnerEntry(title = "Red"),
SpinnerEntry(title = "Green"),
SpinnerEntry(title = "Blue")
)
Scaffold {
SuperSpinner(
title = "Custom Left Content",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it },
leftAction = {
Box(
modifier = Modifier
.size(20.dp)
.background(
when (selectedIndex) {
0 -> Color.Red
1 -> Color.Green
else -> Color.Blue
},
shape = CircleShape
)
)
Spacer(Modifier.width(8.dp))
}
)
}Limit Dropdown Menu Height
kotlin
var selectedIndex by remember { mutableStateOf(0) }
val options = List(20) { SpinnerEntry(title = "Option ${it + 1}") }
Scaffold {
SuperSpinner(
title = "Limit Height",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it },
maxHeight = 300.dp // Limit dropdown menu maximum height to 300dp
)
}Hide Selected Value Display
kotlin
var selectedIndex by remember { mutableStateOf(0) }
val options = listOf(
SpinnerEntry(title = "Option 1"),
SpinnerEntry(title = "Option 2"),
SpinnerEntry(title = "Option 3")
)
Scaffold {
SuperSpinner(
title = "Hide Selected Value",
items = options,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it },
showValue = false // Hide selected value display
)
}Use with Dialog
kotlin
// Create a rounded rectangle Painter
class RoundedRectanglePainter(
private val cornerRadius: Dp = 6.dp
) : Painter() {
override val intrinsicSize = Size.Unspecified
override fun DrawScope.onDraw() {
drawRoundRect(
color = Color.White,
size = Size(size.width, size.height),
cornerRadius = CornerRadius(cornerRadius.toPx(), cornerRadius.toPx())
)
}
}
var showDialog = remember { mutableStateOf(false) }
var selectedIndex by remember { mutableStateOf(0) }
val colorOptions = listOf(
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFFFF5B29)) },
title = "Red Theme",
summary = "Vibrant red"
),
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFF3482FF)) },
title = "Blue Theme",
summary = "Calm blue"
),
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFF36D167)) },
title = "Green Theme",
summary = "Fresh green"
),
SpinnerEntry(
icon = { Icon(RoundedRectanglePainter(), "Icon", Modifier.padding(end = 12.dp), Color(0xFFFFB21D)) },
title = "Yellow Theme",
summary = "Bright yellow"
)
)
Scaffold {
SuperArrow(
title = "Theme Color",
onClick = { showDialog.value = true },
holdDownState = showDialog.value
)
SuperDialog(
title = "Theme Color Settings",
show = showDialog,
onDismissRequest = { showDialog.value = false } // Close dialog
) {
Card {
SuperSpinner(
title = "Choose Theme Color",
summary = "Select your preferred theme color",
items = colorOptions,
selectedIndex = selectedIndex,
onSelectedIndexChange = { selectedIndex = it }
)
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.padding(top = 12.dp)
) {
TextButton(
text = "Cancel",
onClick = { showDialog.value = false }, // Close dialog
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(16.dp))
TextButton(
text = "Confirm",
onClick = { showDialog.value = false }, // Close dialog
modifier = Modifier.weight(1f),
colors = ButtonDefaults.textButtonColorsPrimary() // Use theme color
)
}
}
}