WIP: Table Layout

A first step towards Table / spreadsheet functionality.

For me personally this would be enough as far as tables go. Databases like Notion or speadsheets like Excel are certainly powerful, but there is a reason those apps have hundreds of developers implementing only this. Data aggregation can (and should?) be done with queries. You could even argue that this is how it should be: Each cell is a single rem which can be referenced separately (as opposed to having the whole table in one rem).

The only thing missing for RemNote (AFAIK this is the same power level as roam tables?) is more powerful flash card generation. This could be done with more powerful flashcard generation (similar to #Extra Card Detail) or using Queue Plugins in the future.

How it looks at the moment

Rendered Table and corresponding rem:

Generated flash cards for a cell

CSS

See What is Custom CSS and how do I use it?

This is not yet polished enough to put on the Library but since many people asking for table visuals I’ll put the CSS here anyway. Maybe someone else can even improve the code :smiley:

.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container {
  border: 1px solid black;
}

/* fix collapsing borders */
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-child(n+2) {
  border-left: unset;
  margin-left: -1px;
}

/* remove indentation marker */
.tree-node-container[data-rem-container-tags~=column-table] .TreeNode {
  border-left: unset !important;
}

.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container > div:first-child {
  border-bottom: 1px solid black;
  font-weight: bold;
  background-color: rgba(0,0,0,0.05);
}

.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container > .TreeNode > .tree-node-container > div:first-child:not(:focus-within) .descriptor_rem_type,
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container > .TreeNode > .tree-node-container > div:first-child:not(:focus-within) .separator-symbol {
  display: none;
}

#hierarchy-editor .tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container > .TreeNode {
  margin-left: 0;
  padding-left: 0;
}

.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode:not(:hover) .rem-bullet__container {
  visibility: hidden;
}


.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode {
  display: grid;
  /* auto jumps when toggling/writing rems */ 
  /* grid-template-columns: auto auto auto; */
  grid-auto-columns: 1fr;
}

.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-of-type(1) {
  grid-column: 1;
}
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-of-type(2) {
  grid-column: 2;
}
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-of-type(3) {
  grid-column: 3;
}
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-of-type(4) {
  grid-column: 4;
}
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-of-type(5) {
  grid-column: 5;
}
.tree-node-container[data-rem-container-tags~=column-table] > .TreeNode > .tree-node-container:nth-of-type(6) {
  grid-column: 6;
}

Content to generate the table

- Column Table   
    - Thing template
        - Property 1
        - Property 2
    - First
        - Property 1:: value 1
        - Property 2:: value 2
    - Second
        - Property 1:: value 3
        - Property 2:: value 4

Property 1 and Property 2 should/could be slots.

TODO

These things are unfinished in particular:

  • I did not explore all flashcard possibilities yet. E.g. it might be nice when practicing to have multilines as columns to practice a whole column in one go somehow.
  • Only multiple lines in a cell break the layout. This could be solved with row tables (fixed column width).
  • Maybe use flexbox instead of grid. (I had experimented with this when making the original demos and it is sometimes more better.)
  • (Option to) hide tags.
  • Style first column if it is the template (maybe use extra tag).
  • Make it easier to follow lines, e.g. alternate colors or borders.
  • Compatibility with bullet point changing CSS (tskn theme) and Rem Type and Practice Direction icons.
6 Likes

Thanks for working on this, as always!

Couple comments:

  1. At least to me, it’s much more common to need each row to be a Thing (ex. Countries), with columns being the attributes/properties (ex. Capital, Population, Area…). Would it be possible to invert if needed? Of course, I’d still want each Thing to be readable without the table tag, as an individual Rem with subRems (ie., the main Rem “UK”, with subRems “Capital: London”, “Population: 66M”, “Area: 242k”…).
  2. What happens if I change the order of subRems within a Thing (ex. move Property 1 under Property 2), or insert arbitrary subRems in random positions (ex. if I insert a normal text Rem between Property 1 and Property 2)? Does this mess up the table, or is the table grabbing only the Property X slots? This was my main concern with your first demo for the table - as useful as it is, the table doesn’t actually reflect the inherent structure of the data (I don’t think Rem ordering by itself is reliable for that, since it’s so easy to insert, remove and move them about), so it’s easy to make a mistake and everything becomes unaligned…
2 Likes

Yes. You might remember the grocery example in the original Table FR.

This is just CSS. Think of it as the column layout with borders. But this is just the same with a markdown table.

For the column table you can give the rows a fixed row height though, or a fixed column width for the row tables.
Or you assign different colors to each row (when editing) to make making mistakes harder.

2 Likes

Another way I was thinking, to partially avoid the issues I mentioned (ie., keeping things aligned) would be to add the Automatically Sort powerup to each Thing (alongside the Thing template). That way at least the order of the Property slots would be the same always (since the sorting is based on the slot names, rather than the content).

Of course, this is assuming that all Things have the same properties… And that no other sibling ends up mixed into them. So this solution might still be too unreliable for longer tables, at least for someone absent-minded like me… (in fact, the reason I want true tables in the first place is to help me make sure things stay structured :slight_smile: )

(By the way, I just realized that if you change a property name, the Automatically Sort powerup doesn’t act right away on the Rems that contains it. You need to click on the Rem to make it “wake up” and be re-sorted.).

PS: Sorry if this is a stupid question, but could you elaborate what this is in reference to?:

1 Like

Column table means children of the table rem are columns and their grandchildren are cells of the column (row table means they are rows …).
A cell has a width and a height. If you have too much text it gets expanded and pushes other cells away.
For column layouts you can set a fixed width but then longer text will result in heigher cells pushing all following cells down in that column only.
For row layouts this is more natural (since you need a somewhat fixed width anyway or else your text is always just one long line): An increased height affects all other cells on that row but none of the other rows (since they are contained in other rows).

2 Likes

I hope some developers gather around and make this thing as a finalized feature. I believe this is a very powerful feature and will take some time.

and thanks to @hannesfrank a lot to show the possibility in a workable and visual way :slight_smile:

2 Likes