Stylish Speed Dial
A floating action button that expands a fan of actions around itself when tapped, mirroring Material UI's SpeedDial.
The component is a compact stateful shell: expanded and onExpandedChange are hoisted, and the main button (the existing StylishFab atom) toggles the state. actionCount actions are composed via actions, each receiving its SpeedDialScope.index; render each action as its own small button (e.g. a circular androidx.compose.material3.Surface with an icon) and call onActionClick with the index from its click handler.
The actions fan out along direction (up/down/start/end) with a fade + expand/shrink animation driven by StylishTheme.animation.durationShort. When the platform requests reduced motion (see isStylishReducedMotionEnabled) the actions snap in and out without animation, and the container does not animate its size.
Usage pattern
Anchor the dial in the corner of a Box (typically bottom-end) and let it float above the content:
Box(Modifier.fillMaxSize()) {
var expanded by remember { mutableStateOf(false) }
StylishSpeedDial(
expanded = expanded,
onExpandedChange = { expanded = it },
actionCount = 2,
modifier = Modifier.align(Alignment.BottomEnd),
onActionClick = { index -> /* handle action */},
actions = { index ->
StylishFab(
imageVector = actionsIcons[index],
contentDescription = "アクション $index",
onClick = { onActionClick(index) },
size = 40.dp,
)
},
)
}Testing
The root carries the default test tag stylish_speeddial for UI tests. Callers can override it by passing their own Modifier.testTag(...) in modifier.
Parameters
Whether the actions are currently visible.
Called with the new expanded state when the main button is tapped.
Modifier applied to the root container (Column for SpeedDialDirection.Up/SpeedDialDirection.Down, Row otherwise). Anchor this in a Box with align(Alignment.BottomEnd) for the standard floating pattern.
Content of the main button. Defaults to a plus Icon without label — provide labeled content (or an icon that rotates while expanded) as needed.
The direction the actions fan out in (see SpeedDialDirection).
The number of actions to compose. actions is invoked once per index 0 until actionCount.
The gap between the main button and the actions, and between adjacent actions. Defaults to StylishTheme.dimensions.itemSpacing.
The diameter of the main button. Defaults to DefaultStylishDimensions.fabSize.
Background color override for the main button. When null, StylishFab's default applies.
Content color override for the main button. When null, StylishFab's default applies.
Convenience callback for action taps; invoke it from within actions with the item's index.
Slot composing one action per index. Render a small button here (see the usage pattern above).