Project: Improve Headings

type: #Project
status: Ready to review
owner: @horacio

Problem

Hypermedia have a very strict proposal on how headings should work on a structured document. The issue is that our strict proposal is not very well implemented in the current editor and we are not helping users benefit from it.
This project aims to solve the implementation of the strict proposal, make a better UX to interact with headings and make it all look visually great.

Solution

Before we get into any solution, let's define what is our Strict proposal. (If you already know how the Hypermedia document structure is, you can jump to the next section)

Hierarchical document structure

In order for people to collaborate around content, they need a robust structure. This is why we bet for a hierarchical structure.
// documents.proto - https://github.com/MintterHypermedia/mintter/blob/main/proto/documents/v1alpha/documents.proto

Document {
  string id = 1;
  string title = 2;
  string author = 4;
  repeated string editors = 11;
  repeated BlockNode children = 9;
  google.protobuf.Timestamp create_time = 6;
  google.protobuf.Timestamp update_time = 7;
  google.protobuf.Timestamp publish_time = 8;
}

BlockNode {
  Block block = 1;
  repeated BlockNode children = 2;
}

Block {
  string id = 1;
  string type = 2;
  string text = 3;
  string ref = 7;
  map<string, string> attributes = 4;
  repeated Annotation annotations = 5;
  string revision = 6;
}
Let's define each element in the above definitions
    Document is the main entity that package all the content authors publish in Hypermedia
    BlockNode is a section of the document. This is how we separate content by its semantics and meaning. It requires a block, and have an optional Children list of BlockNodes
    Block is the struct that defines the content of each BlockNode. Block defines the type of content it contains; currently it could be paragraph, heading, image, file, video and embed.
As you can see, with this structure we have the flexibility of adding any piece of content on a block and also add an implicit relationship between them thanks to the hierarchy.

Headings and the content above the heading should be related

In HTML, Markdown or other popular document formants on the web is not easy to have an implicit relationship between headings and the content that follows. also there's no way to enforce the level of heading elements to keep semantics in order and correct.
We believe that with hierarchy we can help writers to create this implicit and important relationships between blocks of content. Basically, every content below a heading should be a child of the heading.
Another Implicit data we can derive from hierarchy in headings is its level. This removes the need of letting the writer decide which level of heading is needed to be used. Authors only need to define when a heading needs to be defined and the level is derived from the level in which is defined.
BlocNode
  Block heading // will be H2
  children
    BlockNode
      Block paragraph
    BlockNode
      Block heading // will be H3
Like I described before, Hierarchy is a tool writers can use to make implicit relationships between the content in a document.

Hierarchy is not easy to visually represent

After some exploration, we decided to "remove" the visual nesting for all the blocks that are children of headings. This means that we are only leaving the visual indentation to any other nested block of anything other than headings.
In order to make this "non-indentable" behavior to work, we need a "visual queue" to help writers know where they are editing. I believe the visual queue we can add to the UI is to show a line on the group children of a heading when a block is selected. This will show writers inside which heading is the current block in.
Here's an example of why this visual queue CAN'T be persisted all the time
Heading examples with a line on the left

Apply Hierarchy by default

We also need to consider the fact that we can "suggest" the structure we believe by applying the correct hierarchy to blocks by default. This is not the same to "enforcing" hierarchy as what we do with listItems for example:
One example is when we press ENTER when the cursor is in a heading. Currently what we do is the normal behavior, which creates a new block BELOW the heading as a sibling. What we can do is to create a nested block below a heading in this case. This will visually look the same as the default behavior but it will have "the correct" structure.

Scope

1.5 weeks. Hopefully we will catch 80-90% of all edge cases!

Rabbit Holes

TBD

No-Goes

TBD