ExamplesCustom SchemasAlert Block with Full UX

Alert Block with Full UX

In this example, we create a custom Alert block which is used to emphasize text, same as in the minimal Alert block example. However, in this example, we also add a command to insert the block via the Slash Menu, and an entry in the Formatting Toolbar's Block Type Select to change the current block to an Alert.

Try it out: Press the "/" key to open the Slash Menu and insert an Alert block! Or highlight text in a paragraph, then change the block type to an Alert using the Block Type Select in the Formatting Toolbar!

Relevant Docs:

import { defaultProps } from "@blocknote/core";import { createReactBlockSpec } from "@blocknote/react";import { Menu } from "@mantine/core";import { MdCancel, MdCheckCircle, MdError, MdInfo } from "react-icons/md";import "./styles.css";// The types of alerts that users can choose from.export const alertTypes = [  {    title: "Warning",    value: "warning",    icon: MdError,    color: "#e69819",    backgroundColor: {      light: "#fff6e6",      dark: "#805d20",    },  },  {    title: "Error",    value: "error",    icon: MdCancel,    color: "#d80d0d",    backgroundColor: {      light: "#ffe6e6",      dark: "#802020",    },  },  {    title: "Info",    value: "info",    icon: MdInfo,    color: "#507aff",    backgroundColor: {      light: "#e6ebff",      dark: "#203380",    },  },  {    title: "Success",    value: "success",    icon: MdCheckCircle,    color: "#0bc10b",    backgroundColor: {      light: "#e6ffe6",      dark: "#208020",    },  },] as const;// The Alert block.export const createAlert = createReactBlockSpec(  {    type: "alert",    propSchema: {      textAlignment: defaultProps.textAlignment,      textColor: defaultProps.textColor,      type: {        default: "warning",        values: ["warning", "error", "info", "success"],      },    },    content: "inline",  },  {    render: (props) => {      const alertType = alertTypes.find(        (a) => a.value === props.block.props.type,      )!;      const Icon = alertType.icon;      return (        <div className={"alert"} data-alert-type={props.block.props.type}>          {/*Icon which opens a menu to choose the Alert type*/}          <Menu withinPortal={false}>            <Menu.Target>              <div className={"alert-icon-wrapper"} contentEditable={false}>                <Icon                  className={"alert-icon"}                  data-alert-icon-type={props.block.props.type}                  size={32}                />              </div>            </Menu.Target>            {/*Dropdown to change the Alert type*/}            <Menu.Dropdown>              <Menu.Label>Alert Type</Menu.Label>              <Menu.Divider />              {alertTypes.map((type) => {                const ItemIcon = type.icon;                return (                  <Menu.Item                    key={type.value}                    leftSection={                      <ItemIcon                        className={"alert-icon"}                        data-alert-icon-type={type.value}                      />                    }                    onClick={() =>                      props.editor.updateBlock(props.block, {                        type: "alert",                        props: { type: type.value },                      })                    }                  >                    {type.title}                  </Menu.Item>                );              })}            </Menu.Dropdown>          </Menu>          {/*Rich text field for user to type in*/}          <div className={"inline-content"} ref={props.contentRef} />        </div>      );    },  },);