Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request: more control over child divs created by node views #1527

Closed
thatsjonsense opened this issue Jun 30, 2021 · 8 comments
Closed

Request: more control over child divs created by node views #1527

thatsjonsense opened this issue Jun 30, 2021 · 8 comments
Labels
sponsor 💖 This issue or pull request was created by a Tiptap sponsor Type: Feature The issue or pullrequest is a new feature

Comments

@thatsjonsense
Copy link
Contributor

The problem I am facing
When working with Node Views in React, Tiptap creates two wrapping divs around both the node view itself and the content. Visually:

<div class="react-renderer">
  <div data-node-view-wrapper>
    <my node view HTML>
      <div data-node-view-content>
        <div>
           <the node view content>

This is fine for many blocks but can lead to non-semantic HTML and messed up rendering. In my case, I created a TableRow node view and so I end up with DIVs between the TR and TD tags.

The solution I would like
Ideally, my content could be rendered without any intermediate divs. I don't know enough about Prosemirror to see why these are needed in the first place. Alternatively, I wish there was a single wrapping div and I could control the tag used for it.

Alternatives I have considered
For now, I'm getting around this by applying the display: contents CSS property to the intermediate divs to prevent them from actually rendering. This is messy but seems to work alright. It makes me wonder if the divs are actually providing any value, since they aren't being displayed.

@thatsjonsense thatsjonsense added Type: Feature The issue or pullrequest is a new feature v2 labels Jun 30, 2021
@hanspagel
Copy link
Contributor

hanspagel commented Jul 11, 2021

Does that help?

The NodeViewWrapper and NodeViewContent components render a <div> HTML tag (<span> for inline nodes), but you can change that. For example <NodeViewContent as="p"> should render a paragraph. One limitation though: That tag must not change during runtime.

https://www.tiptap.dev/guide/node-views/react#adding-a-content-editable

@hanspagel hanspagel added the sponsor 💖 This issue or pull request was created by a Tiptap sponsor label Jul 11, 2021
@thatsjonsense
Copy link
Contributor Author

thatsjonsense commented Jul 11, 2021

Hi @hanspagel , thanks for the suggestion but no it doesn't. When you set as="p" it only changes how the outer node renders. I believe it still renders a div inside of that, so instead of <div><div> you get <p><div>

@tmm
Copy link

tmm commented Jul 26, 2021

This is an issue for me as well.

I'm trying to add an editable caption to an image and need to set up onKeyDown to prevent Enter from splitting the node (this also happens in the demo in the docs):

<NodeViewWrapper as="figure" className="react-component-with-content">
  <img alt={attrs.alt} src={attrs.src} />
  <NodeViewContent
    as="figcaption"
    role="textbox"
    tabIndex={-1}
    onKeyDown={onKeyDown}
  />
</NodeViewWrapper>

Unfortunately, this doesn't get passed down to the div inside figcaption (NodeViewContent).

Would be great to either remove the inner div inside node view content or be able to pass props down to the inner div.

@philippkuehn
Copy link
Contributor

Unfortunately we can’t remove any of these divs. It’s because node views (dom and contentDOM) have to be synchronous. React can only render asynchronous. In Vue.js we don’t have to render these wrapper nodes.

@jorchg
Copy link

jorchg commented Aug 12, 2021

For me the problem is that I am trying to use a component from an external library, but this component accepts only String children, so when I try to create a new node and pass down the content to the component, always get (as normal) the error Warning: Failed prop type: Invalid prop 'children' of type 'object' supplied to 'CodeSnippet', expected 'string'.

I am passing ReactNodeViewRenderer this component:

const CustomCode = (props) => {
  return (
    <NodeViewWrapper as="span" className="carbon-code">
      <CodeSnippet type="inline">
        <NodeViewContent as="span" />
      </CodeSnippet>
    </NodeViewWrapper>
  );
}

Is there anything I can do to just pass a textNode down to my CodeSnippet component? Thank you :)

@hanspagel hanspagel removed the v2 label Sep 28, 2021
@philippkuehn
Copy link
Contributor

Fixed by #2213

@anton-liubushkin
Copy link
Contributor

anton-liubushkin commented Apr 4, 2022

@philippkuehn I'm sorry, but I don't understand how #2213 fixes the problem with the extra inner div of NodeViewContent?

@seleckis
Copy link

seleckis commented Feb 23, 2024

This issue is still actual, cannot add extra table cell to table row without breaking the table structure with extra div. Please reopen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sponsor 💖 This issue or pull request was created by a Tiptap sponsor Type: Feature The issue or pullrequest is a new feature
Projects
None yet
Development

No branches or pull requests

7 participants