notions task list view and build details deep dive

Notion has a task list view. Similar to Trellos Board (Trellos drag'n'drop animation is still cool). Here's an example of Notions Task List.


Users can add and remove new columns (aka groups) and can add/remove items in each group including moving between groups.

Notion styles the columns with Flexbox but you could also style it with Grid.

I see two main options for the GET api to structure the return data (or as response to POST success)

  1. api returns the data already organized into lists corresponding to columns (groups) in the UI; i.e. each group has it's list of tasks already organized
  2. api returns flat list of tasks (a map is useful for faster lookup) and separate list for group (column) information; FE needs to do some filtering and organizing
Notion takes the 2nd approach and structured like below (simplified). It has 4 main entities: 
  • groups; organized various ways, including a list of every taskId in a group (see "board_columns")
  • tasks; organized in a json map called "recordMap"
  • the collection they belong to ("collection")
  • the overall "space" it all belongs to i.e. a space has collections and a collection has tasks which are organized into groups

{
  board_columns: {
    groups: [
      { type: "select", value: "To Do" }, 
      { type: "select", value: "Doing" }, 
    ],
    results: counts in each group,

    "results:select:To Do": {
       blockIds: [ 
         "idForTask1", "idForTask2", "idForTask3" 
       ]
    },    
    "results:select:Doing": {
       blockIds: [ 
         "idForTask4"
       ]
    }
  },
  
  recordMap: {
    block: {
      "idForTask1": {
        id: "idForTask1",
        title: "yoga",
        parentId: "idOfCollection"
        created: 1647802320000,
        last_edited: 1647802320000,
      },
      "idForTask2": {
        id: "idForTask2",
        title: "get breakfast",
        parentId: "idOfCollection"
        created: 1647802320000,
        last_edited: 1647802320000,
      },
      "idForTask3": {
        id: "idForTask3",
        title: "cook breakfast",
        parentId: "idOfCollection"
        created: 1647802320000,
        last_edited: 1647802320000,
      },
       "idForTask4": {
        id: "idForTask4",
        title: "sleep well",
        parentId: "idOfCollection"
        created: 1647812460000,
        last_edited: 1647812460000,
      },
    }
  },
  collection: {
    "idOfCollection": {
      name: "Task List",
      description: "This is my cool task list for home chores",
    }
  },
  space: "this is the who notion app for this user"
}
  


Trello returns a list of card (task) objects and a list of list objects (columns). Each card has the id of the list it belongs in (as well as lots more info including properties for votes, comments, badges, limits and more). 

Unlike Notion, Trellos list of cards is not a map keyed by id. So I assume the frontend needs to go through the list of all cards and create sublists for each list of cards (versus map lookup).
Trellos api also includes other data such as user preferences (e.g. showSidebar or not), background styling etc.

Trello also styles the columns with flexbox. Each card in is an anchor tag with some divs and nested spans (Notion the same). Likewise the list "+ Add" is a link (unlike Notions which is a div with role="button"). 
  • for Notion, wouldn't an anchor be more semantically correct? or a real button not a div?

It's a credit to Trellos design how well it's held up over time, and Notions design is quite similar.

I built a simple Task List similar to Notions. I built 2 lists one styled using grid (1st) and another using flexbox (2nd). Here's a screenshot (notice the columns).
For the flexbox version I created a container for the list of columns and made that flex (defaults to row, no wrap) with a small column-gap.
Then each column is a flex container, flex-direction column, small row gap and I set a width of 260px. Setting height 100% makes height as long vertically as the content.

These are sophisticated, complex UIs with lots of controls and states and I've just scratched the surface, the devil truly is in the details.
Notions Filter/Sort/Search links are implemented a divs with role="button". Why not actually button?   Same for Board view and Table view, both divs.
Also tabbing does not work for me in Notions task list (tabbing does work for my implementation ;-) )




     

Comments

Popular posts from this blog

deep dive into Material UI TextField built by mui

angular js protractor e2e cheatsheet

react-router v6.4+ loaders, actions, forms and more