An important part of that is custom content - in Rabbit terms these are content "blocks"; one of a few basic components that makes up a Rabbit app (data, layout, content).
The story here is what I'd like to think about as "unlimited re-usability" - i.e. you can import any part of any app (kit) into any other and use it (a fork essentially).
I'm making a small Airflow UI as a demo ("Hareflow" trololol) and as part of that effort I assembled a compound component that consists of 2 heatmaps and 1 calendar type visualization (content blocks) all assembled into a "screen" to keep them all laid out together, with all the formatting and data needed.
It works for my use case, looks nice (imho), and serves the purpose (an easy to understand heatmap for calendar time, in months, days, and weeks) and will be used for click filter actions to guide the lower components.
The neat thing here is that I can import this "screen" into another project/kit and all it dependencies will come with it - everything it needs to render and then the new user can begin modifying it as they see fit to their use-case.
I hate the expression "it just works", but that's the idea. If we can re-use all previous efforts in a seamless way (regardless of what they are: viz, data, layouts, screens, actions, parameters, colors, or a combo of all of them), I feel that this is a huge boon to productivity and makes it feel good to put time into something small, since you know that it can be a persistent part of your toolbox moving forward (more on that later).
“Curiouser and curiouser!” Cried Alice (she was so much surprised, that for the moment she quite forgot how to speak good English).”
Every lib (and sometimes every different graph within one) has it's own configuration settings that often need to be set up in very particular ways to get particular outcomes. They aren't always straightforward, can contain strange nesting, JSON boilerplate, and there is little consistency across the board (talking about declarative viz libs here).
Now I'm not currently focused on making UIs for all of these - so I need to use a common pattern... and the common pattern (duh) is just text editing of the prop maps.
But this can lead to all kinds of issues:
- many configs are not terse and intuitive
- users don't know what keys are needed or even available
- editing a huge obtuse map is NOT ergonomic
- keys that need to be there but rarely change clutter the map
- no help for the user
- sending users to 3rd party sites to look up config values is terrible
Basically, it works - but it's kind of a mess.
How can I make this experience easier (and scalably so) - WITHOUT building a UI for each one (which would be foolish anyways, given that creative users don't like being boxed in to pre-set options)?
The start of "editing the editor"
If anyone is a fan of video game development - especially the more old-school type before pre-baked "Game Engines" became so ubiquitous - it was fairly common for games to build in their own makeshift editor to change things on the fly and help speed up the creation of content.
I'm shooting for something similar here on a smaller scale.
When editing a content block - the user can also edit the blocks meta-data, which is ALSO the data the system uses to present the editor screen to the user...
So instead of a single dumb code box, the user can now do the following:
- break the props map up into individual code trees that make sense
- hide other ones that are less important / optional
- list the keys required for a particular prop(s)
- list the keys possible for a particular prop(s)
- add in-line documentation blocks
- add a Material design icon to differentiate this block in the UI
- add tooltips to individual prop blocks
- add category, sub-category and type (for searching and filtering)
So, we are still "just editing" some configuration in a window - but we've moved the experience much closer to something that makes sense visually as opposed to a JSON/EDN dump.
Now - combine that with my import story from above - I can create a custom component (or a bundled set of them) and not only pre-configure what they look like / behave like - but I can configure how they are even modified in the editor...
So think about that - an imported component contains not only everything needed for it to work (render) out of the box, but it also contains the info needed to modify itself cleanly and be somewhat self-documented.
"user space text-editor extending"
One last thought... hypothetically, what happens when I have a editor block that only, let's say, chooses a color.... and let's say that I ALSO have a content block I made that chooses colors... who is to say that they won't be able to just say...
For this prop, use this UI block instead of text...
"user space editor UI extending"
...and all that custom logic is shippable as a unit to other kits/apps...