useMuiFabAdapter
Returns props for an MUI Fab that reacts to React Hook Form state, with form-state-driven disabling, styles and reset.
useMuiFabAdapter returns props you spread onto MUI's Fab so it can submit or reset a React Hook Form form and react to its state. It's what MuiFabElement uses internally.
The hook behaves exactly like useMuiButtonAdapter: same props, same disabling rules, same reset handling. Use it instead of the element when you want classes that follow the form state (the element turns class composition off), when the Fab's content should change with the returned disabled or error, or when you wrap the Fab in your own component.
Import
import { useMuiFabAdapter } from "@piplup/rhf-adapters/mui-material";Usage
SendFab stays clickable while the message is empty, so submitting shows the required error, but its style function dims it until the form is valid. It's disabled only while the (simulated) request runs.
"use client";import SendIcon from "@mui/icons-material/Send";import Fab from "@mui/material/Fab";import Stack from "@mui/material/Stack";import { MuiTextFieldElement, useMuiFabAdapter,} from "@piplup/rhf-adapters/mui-material";import { type Control, useForm } from "react-hook-form";type FormValues = { message: string };// Stays clickable while the form is invalid, so submitting shows the// validation errors, but `style` dims it to hint that something is missing.// It is disabled only while the submit handler runs.function SendFab({ control }: { control: Control<FormValues> }) { // Fab has no error or helperText props, so keep them off the DOM. const { error: _error, helperText: _helperText, ...adapter } = useMuiFabAdapter<FormValues, HTMLButtonElement>({ control, type: "submit", disableOnIsSubmitting: true, style: ({ error }) => ({ opacity: error ? 0.6 : 1 }), }); return ( <Fab variant="extended" color="primary" {...adapter}> <SendIcon sx={{ mr: 1 }} /> Send </Fab> );}export default function Page() { const { control, handleSubmit } = useForm<FormValues>({ defaultValues: { message: "" }, }); return ( <form noValidate onSubmit={handleSubmit(async (values) => { // Simulate a slow request so the disabled state is visible. await new Promise((resolve) => setTimeout(resolve, 1500)); alert(JSON.stringify(values, null, 2)); })} > <Stack direction="column" spacing={2} sx={{ alignItems: "flex-start" }}> <MuiTextFieldElement control={control} name="message" label="Message" required multiline minRows={3} fullWidth /> <SendFab control={control} /> </Stack> </form> );}How it works
For the full behavior (form state subscription, the disabling table, reset on type="reset", helper text) see How it works on the button hook page. What's worth knowing for a Fab:
Styling from form state. style can be an object or a function. A function receives { disabled, error } and its result becomes the returned style. MuiFabElement accepts the same function. error is your error prop if you pass one, and otherwise true whenever the form's isValid is false, which includes fields the user hasn't touched yet. That's why the demo's Fab starts dimmed.
Dim instead of disable. disableOnError disables the Fab for the same condition, which means the user can't click it to find out what's missing. A style (or a class through classes.error) gives the same hint and still lets submission run validation and show the errors.
classes. With class composition on (the default for the hook), classes.root is always applied, and classes.disabled and classes.error are added while those states are active. The hook also returns classes unchanged, so the same object reaches Fab's own classes prop.
Fab has no error or helperText props. Remove them from the returned object before spreading it, as the demo and the element do.
Props
Prop
Type
Return value
Prop
Type