Canvas

From SocialStack

Canvas is SocialStack's main mechanism for representing configurable structured content - that's mainly things like pages of your site and emails. It is stored as a JSON format and the JSON is passed to the React <Canvas> element usually as a child. The JSON usually originates from the Canvas Editor.


import Canvas from 'UI/Canvas';

..

<Canvas>{"t":"UI/Header"}</Canvas>

Canvas Json[edit | edit source]

{
    "t": "UI/HelloWorld",
    "d": {
        "customProp": "This is a prop value passed to UI/HelloWorld"
    },
    "c": [
        {
            "t": "b",
            "c": "This is bold text as a child of UI/HelloWorld."
        }
    ]
}


The JSON that Canvas uses is a very thin system for representing a tree of elements. A json object with these fields we'll refer to as a "canvas node" here. It has 4 main fields:

  • t (type): The type of this element. It is either an absolute component path or the name of a HTML element usually in lowercase.
  • d (data): Any custom data for the element. In React these are passed to your element as props as-is. Importantly though, HTML elements are not expected to support data (but where they do, the values are as-is attributes). This is such that canvas JSON is safe for use by frontend users to create and is not overly tied to HTML itself. I.e. "t": "b" indicates bold.
  • c (children): Any child nodes of the element. These are processed as canvas nodes then passed as the children prop in React. It can be an array of canvas nodes/ strings, a single canvas node or a single string. Strings are treated as raw text.
  • g (graph): A set of canvas graph nodes from the graph editor which is used to define dynamic content flows without having to hardcode it, such as a page which displays user profiles on the site. The user is loaded in the graph and then the fields are connected to components with a graph.

There are some additional fields which can be used for diffing canvas JSON amongst other things:

  • s (string): An object containing "s": "some text" works the same way as just a text string in children, but with the advantage of being able to have additional fields on it such as an id.
  • i (id): A unique number for this particular node. Particularly useful for comparing changes in canvases. Editors must not reuse a removed id; it must only ever increase.
  • ti (template ID): If a canvas node was imported from another canvas, it can be given both an ID and a template ID to identify where it originated from. This allows these remote nodes to have custom overrideable data values but are still easily diffable with the source canvas that they came from.
  • r (roots): Sometimes you may want your props to be canvas formatted. You could pass a JSON string via data and then have your component internally render it but that is not particularly friendly for editors - it's nice if a canvas editor is aware that your prop is something it can edit too, potentially even inline. This is what roots are for - they are canvas root nodes which are then passed to your component as a prop after it has been rendered. I.e. in React, the value of the prop that you receive is a React node. A canvas root node has the restriction that it must be an object, not a string, but it can still contain strings as its child nodes.