Tiptap: How to toggle styles/classes on existing Node

Created on 25 Oct 2018  ·  6Comments  ·  Source: ueberdosis/tiptap

Hi all and many thanks for tiptap! I've starting playing around with it yesterday and love it so far.

I'm still struggling with the concept of Nodes and Marks and when to use which. Most probably because all the prosemirror ideas are new to me, too. So, this is more about asking for guidance on how to approach this. Many, many thanks in advance!

1) My goal is to add a style "text-align" (left/middle/right) to various HTML elements including paragraphs and headings. Based on your existing example for a paragraph "Node", I've managed to implement the same for Heading. But, it feels wrong to me to create new nodes every time I want to "text-align" them. Additionally, checking if a "heading" is active (for the menubar) is more complicated because the "node.heading.active()" method now needs checks all combinations of heading level (1, 2 or 3) and text-align (left, center, right), for example: "node.heading.active({level: 1, textAlign: "left"})".

2) Another feature I'd like to implement is setting the foreground/background color. I've managed to implement a "mark" for the color like this:

export default class ColorMark extends Mark {
  get name() {
    return "color";
  }

  get schema() {
    return {
      attrs: {
        color: {
          default: ""
        }
      },
      parseDOM: [
        {
          style: "color",
          getAttrs(value) {
            return { color: value };
          }
        }
      ],
      toDOM: mark => {
        return ["span", { style: `color: ${mark.attrs.color}` }, 0];
      }
    };
  }

  command({ type, attrs }) {
    if (attrs.color) {
      return updateMark(type, attrs);
    }

    return removeMark(type);
  }
}

This code will wrap selected text with a <span> tag and set the style attribute.

Now, what I would ideally like to do is just add multiple style attributes to an existing element. For example, I would end up with a completely styled <h1> tag with the style attributes for "color", "background-color" and "text-align" set, instead of nested <span> elements.

3) I haven't figured out how to add/toggle a CSS class on a node. Is this possible?

Many thanks in advance!
-Frederik

Most helpful comment

@philippkuehn In reference to:

BTW: I'm currently working on version 1.0 and there are some changes to commands. Until now you could register only one command per node. That was very limiting in some cases. In version 1.0 you can register multiple commands per node/mark/extension. So it's possible to build a new command which checks all of your nodes in your text selection and try to set your text alignment attributes.

Were you able to ship support for multiple commands in 1.0? If so, would you please provide an example of what that may look like?

I'm trying to use multiple commands in the context of applying an alignment attribute to various node types.

All 6 comments

Hey @fdietz! Thanks for testing tiptap.

  1. Prosemirror is strict. I mean very strict. And basically, that's a great thing because whatever you paste to prosemirror – it can't destroy your editor. Everything has to pass the rules of your schema settings. Working with alignment is quite special though. I see no other solution than accepting an alignment attribute for each of your nodes. Maybe it's useful to create an abstraction layer for all of your nodes attributes. And you're right – the active() method should be improved for this use case.

  2. You have to choose between marks and node attributes. Marks are stackable. That means you can select a single word within an h1 and make it bold, italic and red at the same time. If your color should be applied to the whole h1 it must be an attribute. But then you couldn't apply this color to single words. It's not possible to merge marks unless you create one mark that with all these options as attributes. But I wouldn't recommend that.

  3. Of course you can add a class option as an attribute for all of your nodes. That should work.

BTW: I'm currently working on version 1.0 and there are some changes to commands. Until now you could register only one command per node. That was very limiting in some cases. In version 1.0 you can register multiple commands per node/mark/extension. So it's possible to build a new command which checks all of your nodes in your text selection and try to set your text alignment attributes.

Thank you so much for your detailed response! Helps me a lot to confidently move forward with my design 👍

Searching for editors. Stumbled on TipTap. Yay! Saw tables in examples. OMG YES! Reminded me of Atlassian table editing (backtracked to learn of relatedness). Wondered if possible to right justify table cells so numbers and currency look sane. Got here. @philippkuehn -- ms-word-style-alignment link applicable for that case too? Thx!

@philippkuehn In reference to:

BTW: I'm currently working on version 1.0 and there are some changes to commands. Until now you could register only one command per node. That was very limiting in some cases. In version 1.0 you can register multiple commands per node/mark/extension. So it's possible to build a new command which checks all of your nodes in your text selection and try to set your text alignment attributes.

Were you able to ship support for multiple commands in 1.0? If so, would you please provide an example of what that may look like?

I'm trying to use multiple commands in the context of applying an alignment attribute to various node types.

@austinstarin here you can find the multiple commands implementation https://github.com/scrumpy/tiptap/issues/44#issuecomment-434500844

Was this page helpful?
0 / 5 - 0 ratings

Related issues

winterdedavid picture winterdedavid  ·  3Comments

ageeye-cn picture ageeye-cn  ·  3Comments

agentq15 picture agentq15  ·  3Comments

connecteev picture connecteev  ·  3Comments

jameswragg picture jameswragg  ·  3Comments