Unlock seamless workflows and faster delivery with our latest releases- get the details

Create different block styles for the dropdown and editor

By Geoff Ball

Your block styles will normally look the same in the editor and the styles dropdown. For the times you don't want that, this workaround lets you configure them differently.

post.tsx

import { defineField, defineType } from "sanity";
import { Text } from "@sanity/ui";

const HeadingStyle = {
  marginTop: "-1.5rem",
  borderBottom: "1px dashed #000",
  paddingBottom: "50px",
  paddingTop: "50px",
  paddingLeft: "70px",
};

const HeadingListStyle = {
  margin: "0",
  borderBottom: "1px dashed #000",
  paddingBottom: "5px",
  paddingTop: "5px",
  paddingLeft: "7px",
};

const TextStyle = {
  fontSize: "28px",
  fontWeight: 600,
};

export const post = defineType({
  name: "post",
  title: "Post",
  type: "document",
  fields: [
    defineField({
      name: "title",
      title: "Title",
      type: "string",
    }),
    defineField({
      name: "body",
      title: "Body",
      type: "array",
      of: [
        {
          type: "block",
          styles: [
            { title: "Normal", value: "normal" },
            {
              title: "Normal Heading",
              value: "normalHeading",
              component: (props) => {
                return (
                  <div style={HeadingStyle}>
                    <Text style={TextStyle}>{props.children}</Text>
                  </div>
                );
              },
            },
            {
              title: "Conditional Heading",
              value: "conditionalHeading",
              component: (props) => {
                return (
                  <div style={Array.isArray(props.children) ? HeadingStyle : HeadingListStyle}>
                    <Text style={TextStyle}>{props.children}</Text>
                  </div>
                );
              },
            },
          ],
        },
      ],
    }),
  ],
});

At the time of writing (Studio v3.64.3), block styles in the Portable Text Editor will be rendered in the dropdown the same as they will in the editor. Normally, this will be what you want, as it should help editors apply a style and know what it will look like in the editor.

In some cases, such as when a style has been customized with large padding or margin, you may wish to override the style in the dropdown. There is not currently a way to do this via a prop (like component) that can be added to your style, but we can take advantage of how props are handled differently in the dropdown and the editor to apply different styles. Namely, in the styles dropdown props.children is a string, while in the editor it is an array. With that in mind, we can conditionally render a class or style. [Note: This is a workaround and is subject to change in the future. I would recommend keeping your two styles as similar as possible in the event this behaviour breaks.]

If you were to implement the example above (with exaggerated CSS styles to make a point), you would see that the shared style looks okay in the editor but not the styles dropdown, where the padding is too dominant and is pushing the text off to the right. The conditionally-styled heading displays the same in the editor, but has its CSS styles tempered in the dropdown to fit more comfortably into the flow while still suggesting how it will be rendered.

Most of the time, you shouldn't need to use this, but it could come in handy when using more unconventional or extreme block styles.

Contributor

Other schemas by author

Matching the end of a string in GROQ

GROQ doesn't yet include a function to match the end of a string, but we can simulate it by splitting our string on our term.

Geoff Ball
Go to Matching the end of a string in GROQ