Navbar Architecture

Albert • 2023-01-02

A deeper dive into our current Navbar system and how it can be improved.

background

Old Design

Let's dive deeper into how navbar work currently and see what the problems are.

Supported Navbar Types

We support:

  • NavbarBrandLogo → This is the left part of the navbar.
  • NavbarLink → A text-style navbar link
  • NavbarWeb3Button → we might want to deprecate this as nobody's using this. You can't actually create this kind of button on the editor yet.
  • NavbarButton → A button-style navbar item
  • NavbarDropdown → A dropdown style navbar.

There's some other styling that you might want to know. For example: position , style and isBlur . You can see this in the Navbar inside its core type packages/core/src/types/navbar.ts

How data are stored and modified

Data is stored inside ISpace (you can see this in apps/editor/types.ts). The data type is already defined there as NavbarContent .

Currently there are 2 context that help modify data in the server:

  • NavbarEditorDispatchContext to make changes on the navbar. Please note that this is only modifying local state, not updating the data in the database.
  • NavbarEditorContext to see navbar's content.

As you can see we're using React's basic context to store navbar data locally. We usually use NavbarEditorProvider and then wrap them around basic TextEditorProvider

Taken from apps/editor/data/editor/provider.tsx

We can then get the data from context inside BaseTextEditorProvider by calling useContext(NavbarEditorContext); and then save those values to the database accordingly. You can see this in action in apps/editor/data/editor/provider.tsx

Current Design Limitation

The first problem: Unable to create multiple kinds of navbar in a single website

You should see that the Navbar information is stored on the ISpace level. Each IPage have 1 ISpace which means that 1 page can only have 1 kind of Navbar.

We're starting to see user asking for different navbar style on different pages. The current design does not allow us to do this since only 1 navbar is attached to a site ( ISpace ).

The second problem: Undo's and Redo's doesn't work

You can't do undo and redo in navbar, once you delete a single menu, or make some changes to the text. It's not possible to undo them because it's not connected/governed by Slate which handles text editor's undo and redo.

The third problem: Non-RTC friendly

Since we want to move towards multiplayer editor (being able to real-time collab). we want the data to be inside Slate's domain. We're most likely going to use slate-yjs binding for RTC which nicely handles all the conflict resolution for us.

Yjs requires us to use standardize data structure for them to know how to resolve conflicts. Those data structures are in the form of Slate operations which is already implemented by the bindings.

We want to leverage these tools, but we need to make our navbar editor part of it. This is why it's important to push the data of Navbar content into slate's JSON.

If we don't do this, we risk having non-collaborative navbar and collaborative page content editor, which in UX perspective is disastrous.

New Design

We want to make minimal changes to the core type of navbar. We don't want to change this because it will cause more backward compatibility issue (old navbar won't work).

I think there are a couple of things that should be done:

We should prioritize making the navbar part of the page content.

There's a couple of action items here:

  1. We must move the rendering of Navbar into Serializer in @typedream/components
  2. We must ensure backward compatibility, if there's navbar inside ISpace's Navbar props.
  3. In the editor and renderer we have to make sure that the navbar positioning is maintained correctly (on the top of the page, as navbar should be), either by specifying that navbar should only exist in the beginning of the document and/or by normalizing it (moving any instance of navbar to the top of the page).

Implementation details

We need to take existing navbar content, and try to make Serializer able to render navbar. Then we want to make sure that we add the storybook case on it.

Cases that we should consider:

  1. If there's old navbar (in space.customization) AND in page's content, make sure to render the one in page content (newer version)
  2. If there's only old navbar, then render the old navbar.
  3. If there's only new navbar, then render the new navbar.

How to maintain the navbar positioning?

All we need to do is make sure that navbar element is the first element in the page.published_content (or page.content). You can do this by making sure every time user try to insert navbar:

  1. Check whether navbar already exist. if so, then just focus on the navbar
  2. If not, create the navbar element in the [0,0] path.


See More Posts


Cardy

Copyright © 2021 Govest, Inc. All rights reserved.