When pressed, a floating action button can display three to six related actions in the form of a Speed Dial.
If more than six actions are needed, something other than a FAB should be used to present them.
The floating action button can display related actions.
import * as React from 'react';
import Box from '@mui/material/Box';
import SpeedDial from '@mui/material/SpeedDial';
import SpeedDialIcon from '@mui/material/SpeedDialIcon';
import SpeedDialAction from '@mui/material/SpeedDialAction';
import FileCopyIcon from '@mui/icons-material/FileCopyOutlined';
import SaveIcon from '@mui/icons-material/Save';
import PrintIcon from '@mui/icons-material/Print';
import ShareIcon from '@mui/icons-material/Share';
const actions = [
{ icon: <FileCopyIcon />, name: 'Copy' },
{ icon: <SaveIcon />, name: 'Save' },
{ icon: <PrintIcon />, name: 'Print' },
{ icon: <ShareIcon />, name: 'Share' },
];
export default function BasicSpeedDial() {
return (
<Box sx={{ height: 320, transform: 'translateZ(0px)', flexGrow: 1 }}>
<SpeedDial
ariaLabel="SpeedDial basic example"
sx={{ position: 'absolute', bottom: 16, right: 16 }}
icon={<SpeedDialIcon />}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
/>
))}
</SpeedDial>
</Box>
);
}
import * as React from 'react';
import { styled } from '@mui/material/styles';
import Box from '@mui/material/Box';
import FormControl from '@mui/material/FormControl';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormLabel from '@mui/material/FormLabel';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import Switch from '@mui/material/Switch';
import SpeedDial, { SpeedDialProps } from '@mui/material/SpeedDial';
import SpeedDialIcon from '@mui/material/SpeedDialIcon';
import SpeedDialAction from '@mui/material/SpeedDialAction';
import FileCopyIcon from '@mui/icons-material/FileCopyOutlined';
import SaveIcon from '@mui/icons-material/Save';
import PrintIcon from '@mui/icons-material/Print';
import ShareIcon from '@mui/icons-material/Share';
const StyledSpeedDial = styled(SpeedDial)(({ theme }) => ({
position: 'absolute',
'&.MuiSpeedDial-directionUp, &.MuiSpeedDial-directionLeft': {
bottom: theme.spacing(2),
right: theme.spacing(2),
},
'&.MuiSpeedDial-directionDown, &.MuiSpeedDial-directionRight': {
top: theme.spacing(2),
left: theme.spacing(2),
},
}));
const actions = [
{ icon: <FileCopyIcon />, name: 'Copy' },
{ icon: <SaveIcon />, name: 'Save' },
{ icon: <PrintIcon />, name: 'Print' },
{ icon: <ShareIcon />, name: 'Share' },
];
export default function PlaygroundSpeedDial() {
const [direction, setDirection] =
React.useState<SpeedDialProps['direction']>('up');
const [hidden, setHidden] = React.useState(false);
const handleDirectionChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDirection(
(event.target as HTMLInputElement).value as SpeedDialProps['direction'],
);
};
const handleHiddenChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setHidden(event.target.checked);
};
return (
<Box sx={{ transform: 'translateZ(0px)', flexGrow: 1 }}>
<FormControlLabel
control={
<Switch checked={hidden} onChange={handleHiddenChange} color="primary" />
}
label="Hidden"
/>
<FormControl component="fieldset" sx={{ mt: 1, display: 'flex' }}>
<FormLabel component="legend">Direction</FormLabel>
<RadioGroup
aria-label="direction"
name="direction"
value={direction}
onChange={handleDirectionChange}
row
>
<FormControlLabel value="up" control={<Radio />} label="Up" />
<FormControlLabel value="right" control={<Radio />} label="Right" />
<FormControlLabel value="down" control={<Radio />} label="Down" />
<FormControlLabel value="left" control={<Radio />} label="Left" />
</RadioGroup>
</FormControl>
<Box sx={{ position: 'relative', mt: 3, height: 320 }}>
<StyledSpeedDial
ariaLabel="SpeedDial playground example"
hidden={hidden}
icon={<SpeedDialIcon />}
direction={direction}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
/>
))}
</StyledSpeedDial>
</Box>
</Box>
);
}
The open state of the component can be controlled with the open
/onOpen
/onClose
props.
import * as React from 'react';
import Box from '@mui/material/Box';
import SpeedDial from '@mui/material/SpeedDial';
import SpeedDialIcon from '@mui/material/SpeedDialIcon';
import SpeedDialAction from '@mui/material/SpeedDialAction';
import FileCopyIcon from '@mui/icons-material/FileCopyOutlined';
import SaveIcon from '@mui/icons-material/Save';
import PrintIcon from '@mui/icons-material/Print';
import ShareIcon from '@mui/icons-material/Share';
const actions = [
{ icon: <FileCopyIcon />, name: 'Copy' },
{ icon: <SaveIcon />, name: 'Save' },
{ icon: <PrintIcon />, name: 'Print' },
{ icon: <ShareIcon />, name: 'Share' },
];
export default function ControlledOpenSpeedDial() {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
return (
<Box sx={{ height: 320, transform: 'translateZ(0px)', flexGrow: 1 }}>
<SpeedDial
ariaLabel="SpeedDial controlled open example"
sx={{ position: 'absolute', bottom: 16, right: 16 }}
icon={<SpeedDialIcon />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
onClick={handleClose}
/>
))}
</SpeedDial>
</Box>
);
}
You can provide an alternate icon for the closed and open states using the icon
and openIcon
props
of the SpeedDialIcon
component.
import * as React from 'react';
import Box from '@mui/material/Box';
import SpeedDial from '@mui/material/SpeedDial';
import SpeedDialIcon from '@mui/material/SpeedDialIcon';
import SpeedDialAction from '@mui/material/SpeedDialAction';
import FileCopyIcon from '@mui/icons-material/FileCopyOutlined';
import SaveIcon from '@mui/icons-material/Save';
import PrintIcon from '@mui/icons-material/Print';
import ShareIcon from '@mui/icons-material/Share';
import EditIcon from '@mui/icons-material/Edit';
const actions = [
{ icon: <FileCopyIcon />, name: 'Copy' },
{ icon: <SaveIcon />, name: 'Save' },
{ icon: <PrintIcon />, name: 'Print' },
{ icon: <ShareIcon />, name: 'Share' },
];
export default function OpenIconSpeedDial() {
return (
<Box sx={{ height: 320, transform: 'translateZ(0px)', flexGrow: 1 }}>
<SpeedDial
ariaLabel="SpeedDial openIcon example"
sx={{ position: 'absolute', bottom: 16, right: 16 }}
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
/>
))}
</SpeedDial>
</Box>
);
}
The SpeedDialActions tooltips can be displayed persistently so that users don’t have to long-press to see the tooltip on touch devices.
It is enabled here across all devices for demo purposes, but in production it could use the isTouch
logic to conditionally set the prop.
import * as React from 'react';
import Box from '@mui/material/Box';
import Backdrop from '@mui/material/Backdrop';
import SpeedDial from '@mui/material/SpeedDial';
import SpeedDialIcon from '@mui/material/SpeedDialIcon';
import SpeedDialAction from '@mui/material/SpeedDialAction';
import FileCopyIcon from '@mui/icons-material/FileCopyOutlined';
import SaveIcon from '@mui/icons-material/Save';
import PrintIcon from '@mui/icons-material/Print';
import ShareIcon from '@mui/icons-material/Share';
const actions = [
{ icon: <FileCopyIcon />, name: 'Copy' },
{ icon: <SaveIcon />, name: 'Save' },
{ icon: <PrintIcon />, name: 'Print' },
{ icon: <ShareIcon />, name: 'Share' },
];
export default function SpeedDialTooltipOpen() {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
return (
<Box sx={{ height: 330, transform: 'translateZ(0px)', flexGrow: 1 }}>
<Backdrop open={open} />
<SpeedDial
ariaLabel="SpeedDial tooltip example"
sx={{ position: 'absolute', bottom: 16, right: 16 }}
icon={<SpeedDialIcon />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
tooltipOpen
onClick={handleClose}
/>
))}
</SpeedDial>
</Box>
);
}
ariaLabel
for the speed dial component.tooltipTitle
for each speed dial action.aria-haspopup
, aria-expanded
and aria-controls
attributes.role="menu"
and aria-orientation
set according to the direction.role="menuitem"
, and an aria-describedby
attribute that references the associated tooltip.