SaveButton

Submits the parent SimpleForm / react-hook-form context.

Installation

pnpm dlx shadcn@latest add @shadmin/save-button

Usage

import { SimpleForm, SaveButton } from "@/components/admin";
 
const PostEdit = () => (
  <Edit>
    <SimpleForm toolbar={<SaveButton />}>{/* inputs */}</SimpleForm>
  </Edit>
);

By default, the SaveButton is always enabled. This follows UX best practices to avoid confusing users about why a button is disabled (see Nielsen Norman Group guidelines).

To disable the button when the form is pristine, use the disabled prop with useFormState():

import { SaveButton, useFormState } from "@/components/admin";
 
const CustomToolbar = () => {
  const { isDirty, dirtyFields } = useFormState();
  // Use both for robustness across React Hook Form versions
  const isFormDirty = isDirty || Object.keys(dirtyFields).length > 0;
  return <SaveButton disabled={!isFormDirty} />;
};

Important: When using useFormState(), you MUST destructure the properties you want to subscribe to (e.g., isDirty, dirtyFields). This is required for React Hook Form's Proxy-based subscription system to work correctly.

On click, it triggers the handleSubmit callback from the form context.

Props

PropRequiredTypeDefaultDescription
classNameOptionalstring-Extra classes
disabledOptionalboolean-Force disabled
iconOptionalReactNodeSave iconCustom icon
labelOptionalstringra.action.savei18n key
mutationOptionsOptionalobject-Options for the dataProvider.create() or dataProvider.update() call
transformOptional(data: any) => any-Modify data before submit
typeOptional"button"|"submit"|"reset"submitHTML button type
variantOptional"default"|"outline"|"destructive"|"secondary"|"ghost"|"link"defaultshadcn button variant

icon

Replaces the default <Save /> shown alongside the label. Pass any lucide-react icon to convey a different action.

import { Send } from "lucide-react";
import { SaveButton } from "@/components/admin";
 
<SaveButton icon={<Send />} />;