Book-Like Navigation/Search

Use Cases

Observations

  • There is a distinction between use cases where either structure is very important (a book) or not necessary at all (Help/FAQs)

  • For a book, it’s all about narrative and therefore structure and flow must be controllable via the ToC and page next/prev controls

  • For Help/FAQs search is likely much more important. You might arrive with a specific problem and just search for a solution. For FAQs there might be no narrative at all.

  • A guide is something in between those two, it might have a narrative that builds up but you might also want to just search for some specific keyword/solution.

UI-Driven Approach

Questions & Semantics

  • Following the use cases, what should this structured/searchable entity that spans over multiple notebooks be called? Collection is already reserved and does not imply order. Neither can we use group for it.

  • Nesting implies structure so we could call it a Nested Notebook. How notebooks are nested defines the structure of the ToC.

  • Creating a nested notebook does not require a setting. The act of nesting itself creates the nested notebook (see Notion’s way of nesting notebooks).

Limitations

  • With nesting notebooks one cannot create a book that consists of notebooks of different accounts.

  • Is this something we want? Likely a collection is better suited for this.

UI

Nesting

Notion’s UI seems very much suited for all of these use cases. You start by clicking the Plus next to the title ToC item. In our case this would show something like "Add a sub-notebook" or "Add a notebook inside". Notion does not have page prev/next controls at the bottom of the page but we could easily provide these as a setting under a ••• menu next to the title ToC item once it has nested pages ("Show previous/next controls at the bottom of each page").

Notion does not have section groups (e.g. ala GitBook):

Instead, since structure entirely emerges from how content is nested, chapter pages show what pages they have nested inside them:

I think Notion’s approach here is only flawed in that they only show the first level of descendants but not the entire tree of descendants. Showing the tree would "automatically" show a ToC for each chapter at the bottom of each page and make chapter pages without other content less awkward. This would also make the root page more useful as it would feature the entire (untruncated) ToC in there.

Searching

Again, I think Notion’s approach would suit as well here too. Their search interface is entirely keyboard-navigable and would integrate well with our command palette. You could either trigger it through the command palette or by clicking a similar "Quick Find" link in the sidebar (that in turn shows the command palette with the search being already active).

Their search interface shows the most recent pages by default and also acts as a tool to quickly navigate between pages (think a "jump to page" feature).

Search in Show mode

While the general search interface could be the same, we don’t have the sidebar in show mode as prominently and therefore don’t have the Quick Find link exposed. This could be remedied by having a search bar much more prominent in the top bar:

Conclusion

  • Nested notebooks are well-suited to build structure that results in a multi-page ToC. Because nesting depth is arbitrary you can create book-like notebooks (nesting depth is high) and FAQ-like things (nesting depth is low/1).

  • I propose copying Notion’s approach for nested notebooks with the addition of adding a setting for showing page prev/next controls at the bottom of each page.

  • The search interface could be integrated well with our command palette and could also act as a tool to quickly navigate between pages.

  • Caveats are that you can’t create nested notebooks over multiple accounts and can’t have ToC items without content whose entire purpose it to add more structure (GitBook-style "groups").

Examples

Executable Book Project

See https://jupyterbook.org/intro.html as example.

  • Book ToC on the left, Page ToC on the right

  • Search shows results in content area

  • shows prev/next at bottom of page

Quantum Country

  • Shows Chapter and section ToC in one (sections show only for currently active chapter)

  • no search

  • no prev/next at bottom of page

Crafting Interpreters Book

  • divides book into Parts, Chapters, Sections

  • chapter & sections are together in sidebar but only for current section

  • collapses ToC sidebar by default, dismisses its state after navigating to next chapter

  • provides next/prev chapter in sidebar and top control to go to current part (doesn’t show what current part is)

  • provides only next chapter control at bottom of page

  • no search

Preview (macOS)

  • shows chapters and sections as tree view in sidebar (sections are collapsed by default)

  • sidebar toggle has multiple options (could be interesting for us too, e.g. show chapters + sections, show only this notebooks’s sections)

  • search takes over the sidebar with results (also showing a bit of context), the first search result is being displayed in the main content area with the search term highlighted

  • no prev/next at bottom of page

GitBook

  • Content is structured in Initial Page (always at root level), Pages (can be nested) and Groups (acting as separator between pages).

  • shows section ToC as icon next to page title, shows a popover when clicked

  • shows prev/next at bottom of screen

  • search field expands into its own sidebar, results show up as you type and show with a bit of surrounding context and the search term highlighted

Notion

  • Page ToC in sidebar, no section ToC

  • Searchable from sidebar, opens search interface in modal, shows results with a bit of surrounding context and highlighted search term

  • no prev/next at bottom of page

Programmatic Approach

Another entirely different approach would be to provide as minimal UI as possible but let the author handle the rendering of a ToC spanning multiple notebooks using code cells and transclusions. Transclusions would also allow that the ToC could span over notebooks of different accounts.

So far we have been mostly UI-driven but looking at e.g. Roam, allowing users to "hack" the UI could show possibilities that we now don’t necessarily think of now. It would also shift the conversation from "What is the best UI for x?" to "What is the best way to allow implementing UIs for x, y and z?".

Requirements

  • Let users run code in the Editor worker.

  • Implement notebook transclusions.

    • It might be nice to allow to select how a transcluded notebook presents itself, e.g. as a multi-line preview, the full notebook or just as a link that shows the title. For the ToC use case a link would be enough.

    • For the ToC use case, the root notebook might have a nested bullet list of transclusion links to other notebooks which defines the structure of the ToC.

  • Provide, e.g. the ToC renderer as multi method that can be overwritten. This means once a code cell with a "toc" multi method is available, the editor (and show) will display it.

    • The multi method needs access to the notebook data structure and could walk over the ToC list of transcluded notebooks and generate the sidebar ToC from that.

    • Another way would be to, instead of the bullet list, having the transclusions right in the code cell and define the structure via a EDN.

    • The ToC acts as navigation between notebooks so we might need to provide a way to check which notebook is currently being displayed.

  • To aid discoverability we can add a "Custom Table of Contents" item to the insert menu that comes pre-filled with an example, link to docs and with the correct runtime settings set.

Limitations

  • This is not very discoverable. Good documentation and examples are paramount.

Examples

Jekyll

  • retrieves page data from a YAML source or from all pages frontmatter

  • provides page data to Liquid templates

  • provides a page object to liquid that contains the current URL so an active class can be applied to the current nav item

{% for item in site.data.samplelist.docs %}
    <li class="{% if item.url == page.url %}active{% endif %}">
      <a href="{{ item.url }}">{{ item.title }}</a>
    </li>
{% endfor %}
HTML

Roam

  • has transclusion-like block references

  • building a ToC is making a nested list of block references