vigetlabs / colonel-kurtz

A Block Editor
MIT License
319 stars 33 forks source link

Use JSON Schemas to define the content field for block types #109

Open nhunzaker opened 9 years ago

nhunzaker commented 9 years ago

This relates to #28.

In the future, I would love for block types to be defined with something like this:

{
    "title": "Hero",
    "type": "object",
    "properties": {
        "title": {
            "type": "string"
        },
        "subtitle": {
            "type": "string"
        },
        "image": {
            "type": "photo"
        }
    },
    "required": ["title", "image"]
}

With this structure, we can auto-generate a block type for the user by default. They hit success immediately, and can break down into React if they need anything else.

efatsi commented 8 years ago

I'm confused a bit by this approach. I have two questions for this Hero example:

Question 1. What's the mechanism for opening up the Hero component in React? You mentioned this in Slack:

The editing experience for a block is handled by associating a React component with the type field.

But I see "type": "object" here. Seems like it would be hard to hook up a Component to this data.

Question 2. (clarification) If I had a custom field type (like photo or WYSIWYG for instance), is the thinking that I would create that React component and associate it with a specific type, and then to use that field would simply be by defining "type": "wysiwyg" on a property in this JSON?

nhunzaker commented 8 years ago

Sorry to get back to you so late....

What's the mechanism for opening up the Hero component in React? You mentioned this in Slack:

By default, we would provide a standard React component for rendering the object type. In the hero example, this would look like a form with a text field for the title and subtitle, with a photo picker for the image (screenshot below).

If I had a custom field type (like photo or WYSIWYG for instance), is the thinking that I would create that React component and associate it with a specific type, and then to use that field would simply be by defining "type": "wysiwyg" on a property in this JSON?

Precisely. As an additional note, this also allows each unique block type that utilized this "wysiwyg" block to have their own custom validation, if need be.


I had a chance to get back to my initial proof of concept:

let editor = new Colonel({
  el: document.getElementById('app'),

  schema: [{
    "id": "hero",
    "title": "Hero",
    "type": "object", // Right now, this is assumed to be the default type

    "properties": {
      "title": {
        "type": "string",
        "description": "The main heading."
      },
      "subtitle": {
        "type": "string",
        "description": "Secondary text below the heading."
      },
      "image": {
        "description": "A background image behind the text",
        "type": "image"
      }
    }
  }]
})

Which looks like:

screen shot 2016-06-16 at 7 09 46 am

There's a couple of things I like here.

  1. The data structure is explicit. I never liked how it was split across multiple React components before
  2. We have a very clear strategy for validating blocks and sending errors down to individual blocks. We can also either lean on existing JSON Schema validation libraries, or at the very least, the schema is in one place, and we can provide hooks to recursively validate the component tree in a straight-forward way.
  3. We avoid situations where we share React components to keep a consistent editing experience. I've watched our BlockType components slowly pile on more and more conditionals as they have to accommodate more use cases. Ideally, most React components can focus on managing a single field, with occasional custom React components for compound types (like a hero image, or photo carousel) where warranted. Hopefully this can help to mitigate a lot of that complexity.
  4. I think, technically, we might even be able to version these schemas. I don't expect to do that right away, but it's something I'm curious about.

It's on the nh-json-schema branch if you want to hack on it too:

https://github.com/vigetlabs/colonel-kurtz/compare/nh-json-schema?expand=1