Next.js Conf 2024: Your app should be Live by Default – Watch Keynote

Document Actions API

Add custom operations to documents.

You can use the Document Actions API for Sanity Studio to customize and control operations that can be done to documents. When you create a custom action, it will be available in the actions menu in the document editor. You create custom actions by adding a Document action component to the document.actions array of your workspace configuration.

Learn how to create custom workflows with the Document Actions API.

Use Document actions to build custom workflows

document.actions accepts either a static array of document action components or a callback function returning the same. When supplied with a static array, Sanity Studio will append your actions to the list of already existing actions.

Protip

Sanity Studio comes with a set of predefined document actions enabled that are helpful for manipulating documents. These are:

    You are free to swap any or all of these out with your own custom actions, or conditionally disable or enable them in your studio configuration.

    import {CustomAction} from './actions'
    
    export default defineConfig({
      // ...rest of config
      document: {
        actions: [CustomAction],
      },
    })

    In contrast, when using the callback method, you will need to make sure you return the exact set of actions you want to register. Helpfully, the callback function receives the current array of registered action components as its first argument and a context object as its second and final argument.

    import {HelloWorldAction} from './actions'
    
    export default defineConfig({
      // ... rest of config
      document: {
        actions: (prev, context) => {
          // Only add the action for documents of type "movie"
          // for other types return the current array of actions as is
          return context.schemaType === 'movie' ? [HelloWorldAction, ...prev] : prev;
        },
      },
    })

    Callback context properties

    • currentUserobject | CurrentUser

      An object containing information about the currently logged in user

    • schemaTypestring

      Schema type of the current document

    • datasetstring

      Name of the dataset

    • projectIdstring

      Unique ID of the project

    • getClientfunction

      Returns a configured SanityClient

    • documentIdstring

      ID of the document

    • schemaobject | Schema

      The schema registry of your project. Use `schema.get("schemaTypeName") to retrieve any schema by name.

    Example

    document: {
        actions: function (prev, context) {
          console.log('context: ', context);
          return prev.map((originalAction) => (originalAction.action === 'publish' ? HelloWorldAction : originalAction));
        }
      },

    Document Action components

    This table describes the values a document action component receives as properties:

    Properties

    • idstring

      The current document’s id.

    • typestring

      The schema type of the current document.


    • draftSanityDocument

      The draft document (e.g. unpublished changes) if any.

      Returns null if there are no unpublished changes.

    • publishedSanityDocument

      The version of the document that is currently published (if any).

      Returns null if the document isn't published.

    • onCompletefunction

      A callback function that the action components must call to signal that the action has completed

    • liveEditboolean

      Whether the document is published continuously (live) or not.

    Document Action description

    Every Document Action component must return either null or an action description object. An action description describes the action state that can be used to render action components in different render contexts (e.g. in a toolbar, as a menu item, etc.). This table describes the different properties of an action description object.

    • REQUIREDlabelstring

      This is the action label. If the action is displayed as a button, this is typically what becomes the button label.

    • REQUIREDonHandlevoid

      This allows the action component to specify a function that gets called when the user wants the action to happen (e.g. the user clicked the button or pressed the keyboard shortcut combination). The implementation of the onHandle must either make sure to start the dialog flow or to execute the operation immediately.

    • iconReact Element

      In render contexts where it makes sense to display an icon, this will appear as the icon for the action. Default is null

    • disabledboolean

      This tells the render context whether to disable this action. Default is false.

    • shortcutstring

      A keyboard shortcut that should trigger the action. The keyboard shortcut must be compatible with the format supported by the is-hotkey-package.

    • titlestring

      A title for the action. Depending on the render context this will be used as tooltip title (e.g. for buttons it may be passed as the title attribute). Default is null.

    • dialogConfirmDialog | PopOverDialog | ModalDialog

      If this is returned, its value will be turned into a dialog by the render context. More about dialog types below. Default is null.

    • groupArray<'default' | 'paneActions'>

      Allow users to specify whether a specific document action should appear in the footer ("default") or in the document's context menu ("paneActions").

    • toneButtonTone

      Allows changing the tone of the action when displayed.

    Document Action dialog types

    Dialogs can notify and inform users about the outcome of an action, or they can collect confirmation before executing the action. You can define the following dialog types:

    Examples of the different dialog types

    confirm

    This tells the render context to display a confirm dialog.

    Properties

    • typestring

      Must be confirm.

    • colorstring

      Support the following values warning, success, danger, info.

    • messagestring | React.ReactNode

      The message that will be shown in the dialog.

    • onConfirmfunction

      A function to execute when the the user confirms the dialog.

    • onCancelfunction

      A function to execute when the user cancels the dialog.

    Example

    export function ConfirmDialogAction({onComplete}) {
      const [dialogOpen, setDialogOpen] = React.useState(false)
      return {
        label: 'Show confirm',
        onHandle: () => {
          setDialogOpen(true)
        },
        dialog: dialogOpen && {
          type: 'confirm',
          onCancel: onComplete,
          onConfirm: () => {
            alert('You confirmed!')
            onComplete()
          },
          message: 'Please confirm!'
        }
      }
    }

    popover

    This will display the value specified by the content property in a popover dialog. The onClose property is required, and will normally be triggered by click outside or closing the popover.

    • REQUIREDonClosefunction

      A function to execute when the dialog is closed.

    • typestring

      Must be popover.

    • contentstring | React.ReactNode

      The content to be shown in the popover dialog.

    Example

    export function PopoverDialogAction({onComplete}) {
      const [dialogOpen, setDialogOpen] = React.useState(false)
      return {
        label: 'Show popover',
        onHandle: () => {
          setDialogOpen(true)
        },
        dialog: dialogOpen && {
          type: 'popover',
          onClose: onComplete,
          content: "👋 I'm a popover!"
        }
      }
    }

    dialog

    This will display the value specified by the content property in a dialog window. The onClose property is required.

    • REQUIREDonClosefunction

      A function to execute when the user closes the dialog.

    • typestring

      Must be dialog.

    • headerstring

      Text to show in the header field of the dialog.

    • contentstring | React.ReactNode

      The content to show in the dialog.

    • footerstring

      Text to show in the footer field of the dialog.

    Example

    export function ConfirmDialogAction({onComplete}) {
      const [dialogOpen, setDialogOpen] = React.useState(false)
      return {
        label: 'Show confirm',
        onHandle: () => {
          setDialogOpen(true)
        },
        dialog: dialogOpen && {
          type: 'dialog',
          onClose: onComplete,
          content: <div>
            <h3>👋 ... and I'm a dialog</h3>
            <img src="https://source.unsplash.com/1600x900/?cat" style={{width: '100%'}}/>
            <p>
              I'm suitable for longer and more diverse forms of content.
            </p>
          </div>
        }
      }
    }

    custom

    This will display the value specified by the component property in a custom dialog window. The onClose property is required.

    • REQUIREDonClosefunction

      A function to execute when the user closes the dialog.

    • typestring

      Must be custom.

    • componentstring | React.ReactNode

      The content to show in the dialog. Pass a React component with the custom properties you want to render in the custom modal.

    Example

    import {Button, Card, Dialog, Stack, Text} from '@sanity/ui'
    
    export function CustomDialogAction({onComplete}) {
      const [dialogOpen, setDialogOpen] = React.useState(false)
      return {
        label: 'Custom modal',
        tone: 'primary',
        onHandle: toggleOpen,
        dialog: {
          type: 'custom',
          component: open && (
            <Dialog
              header="Custom action component"
              id="custom-modal"
              onClickOutside={toggleOpen}
              onClose={toggleOpen}
              width={1}
              footer={
                <Stack padding={2}>
                  <Button onClick={toggleOpen} text="Close" />
                </Stack>
              }
            >
              <Card padding={5}>
                <Text>This dialog is rendered using a custom dialog component.
                </Text>
              </Card>
            </Dialog>
          ),
        }
      }
    }

    Was this article helpful?