I have been using the format() function to make very useful distillations of data. Its a great way to have one column to represent 10+ columns and condense the information. Using rectangle() is a powerful way to reduce cognitive load on the user. However, if you want to line up text and rectangle on the same line it is very difficult to get them to line up in one cell. Perhaps this could be ‘hacked’ by using length() and splice(), but I am wondering if there is another way to set up alignments in a cell. Below is an example - ideally all of the bars would be lined up next to each other so you could compare ‘apples to apples’ instead of trying to interpolate which is longer than the other:
@Bill_French Yes! That is the concept. Tell me you aren’t splicing string lengths ad nauseam?
Ha ha! No… string lengths factor into this solution but they are poor reflections of spacing distance. You need to employ tabs, and even then, I am not certain the algorithm will hold for all instances.
format([side-by-side].body,
thisRow.Name + Repeat(" ", 3 - Length(thisRow.Name)/4),
Rectangle(thisRow.Age * 3,5,"#00FF00"),
thisRow.Job + Repeat(" ", 3 - Length(thisRow.Job)/4),
Rectangle(thisRow.Income/1000,5,"#0000FF")
)
IMPORTANT - the Repeat() function contains a single tab between those quotes.
You may also have an issue with the relative length of the rectangle for age - multiplying by “3” is not going to provide accurate visuals.
EDIT: I’m in error, I think your rectangle algorithm should be accurate in terms of the relative data visual.
EDIT 2: And another odd thing - notice in the formula the use of the tab character in two places, but Discourse didn’t render both tabs. Below is a screenshot of the formula pasted here - and it contains yet another oddity - perhaps the way Coda interprets tabs inside of formulas. One is longer than the other (between the quotes), but be assured, each are a single tab character pasted there from the same copy buffer.
As you can see in the screenshot I am playing with other values to see how the name patterns react.
To be clear - I’m now absolutely certain this algorithm won’t behave perfectly in every case because it assumes that four tabs (roughly 22 characters) will accommodate the length of any name used. This is not a certainty by any stretch, but it probably works in most cases.
Dear @Bill_French,
Thanks sharing great valuable feedback with eye for detail in a understandable manner.
Thanks for the kind comments @Jean_Pierre_Traets.
This issue underscores a key tenet of Coda - it is an ideal platform for presenting information. But it should also serve to nudge engineering to consider the need for occasional use of CSS inside cells, or perhaps a formula method to Markdownify a cell maybe?
Another approach is to set the template to use the code formatting attribute and then experiment with tab characters to separate names from values.
In so doing, you can achieve a similar formatted outcome without all the tab computations in the formula itself. This approach is equally brittle in that the length of the name/value pairs on a given line could create issues.
But, to make this work really well (and reliably) Markdown (and/or CSS) is needed. I would love to see this supported in Format() templates.
| Label | Graph |
| -------------|:------:|
| {1} | {2} |
| {3} | {4} |
@Bill_French OK thank you for the great solutions. So I think this turns on how the ‘tab’ works. It seems that it will create a specified amount of space (the tab length) but allows itself to be ‘devoured’ by characters to the left up until the point at which they would ‘touch’ the tab itself and then its pushed another tab length forward? This is what induces the brittleness?
And if I’ve got it right, your second solution is exactly the same as the first, but just ‘hard codes’ the tabs in instead of creating the formulaically and would be superior due to its simplicity?
I believe so, yes. If you experiment with different name lengths you can break it. Perhaps the formula could be improved to avoid this, but it’s an issue worthy of disclosure.
Yes - well-stated. Certainly simpler to implement the code-formatting approach and I suspect this demonstrates a capability that could be handy at times. However, I’m reluctant to say that any of this is “superior”; it’s just a way to format two columns inside one cell with caveats.
If the name values were more predictable in terms of length, one might feel like this is a solid approach. And I suspect there are cases where the labels next to the graph bars are more predictable, thus making this tab approach quite useful. One more arrow in the quiver, right?
OK got it. THANK YOU!
Yes, for a dashboard where the field labels are known this is a great solution. If you are using it for something like user names where string length isn’t bound then yes you could get bugs. Got it. Great temp solution until the Codans update the format potential.
Just wanted to chime in here and say that the requirement you have is very uncommon. I mean, how much sense does it make to have multiple lines of text along with rectangles within a single cell? And if this kind of layout is needed, why not have the labels and the rectangles in two separate columns then? Would make much more sense to me tbh.
Besides, having two bars for two different metrics (age and income) don’t make much sense to me either. It looks like you’re comparing the value of Joe to the value of Plumber
Also, this is not something I’d imagine to be a valid feature request for the Format
function.
P.S. Indeed, if you totally must have this kind of layout in a cell, it’s best to experiment with code (monospace) formatting, then calculate required whitespace length as maximum string length - current string length + 1
@Paul_Danyliuk The requirement I don’t think is very uncommon when you expand your thinking about the potential for the app. When I first started using it I would have multiple columns for all of the information for a row/object. But I realized that by using format() I could collapse all of this info into a ‘badge’ cell that represented it, making it more concise and thinner. Next insight was that rectangles further reduce cognitive load and allow the user to quickly scan the canvas to see trends and insights.
For example I have built an ERP system that tracks inventory (the main use case, the example I gave above was a gross simplification). By being able to quickly scroll through the badge column and see the rectangles, the user can very quickly distill which objects are outliers and allows for a ‘manage by exception’ approach.
If we didn’t align the bars, it would be much more difficult for the user to quickly grok the trends:
Well, sure - that’s valid - these are certainly metrics that don’t belong together. But what if the metrics were sensible?
This post - like almost every post in this community - uses example data to make a point, not necessarily a real solution.
I think it’s a valid idea - cells can contain lists, right? Why not other types of collections and why not formatted in ways that improve understanding by users?
Because, the ability to convey answers and knowledge concisely and all without expanding the width of the data presentation (which forces users to endlessly scroll right or left), results in a poor user experience.
Everything about Coda is uncommon; that’s why we’re all here on a Saturday morning!
Coda’s ability to handle uncommon requirements is not because the developers have systematically created features for uncommon use cases. Rather, they are able to support these departures from the norm because of clear architectural foundations that embrace ideas that have never been possible and in many cases, have never been tried.
“The ability to hug it out on the whackiest of notions is what makes Coda truly great.” – bf
A lot, actually.
Coda’s data rendering philosophy is clearly intentional regarding the definition of a “cell” and what it might display. They have shown a great deal of interest in exploring the nature of the grid to expose new ways to enhance understanding of data. As such, I think this approach makes a lot of sense especially given that “docs” are typically best presented with some degree of constrained widths. Indeed, wide sheets and vast numbers of fields are one reason sheets are not ideal for instant understanding and awareness. This is one of the key propositions I recognized when I landed on Coda.
@Johg_Ananda is simply attempting to create a unified two-dimension spark chart in a single cell. This is both common and well understood in the data visualization community.
The days of one cell == one value have ended. The future of “cells” should embrace arbitrary collections of data however any particular developer believes it will help their users achieve their objectives.
@Johg_Ananda @Bill_French fair enough, with the real-world example this makes much more sense.
Although in this very case, I believe two columns instead of one could work just about as well, and ensure proper alignment. Or yeah, go with the monospaced font approach.
Bingo!
(that’s all I wanted to say, but Discourse forces me to type all this other distractive text)
That’s the point - it’s not 1 vs 2 columns; it’s 1 vs 8 columns.
Usability Nuance: Even if you separated the labels from the rectangles in side-by-side columns, an unsuspecting user could inadvertently hide one but not the other column. Now you have a little UX issue in the making.
It’s all about trade-offs anyway, always.
Right now the trade-off is that if the text value is longer or shorter than expected, the bars won’t be aligned anymore. Just using N tabs is not anywhere near reliable for column formatting.
Correct. This has been documented with warnings and disclosures in this thread. No one wants a brittle solution; me included. However, the actual use case he published employs fairly predictable labels, so it’s likely to work in the context presented.
And with a Markdownify() method, imagine all the possible use cases we could come up with for enhancing content in cells. Who votes against a structured table in a cell? I want to see a show of hands on this one.
Perhaps @Johg_Ananda will write this up as an official feature request. After all, this is his idea - I’m just a passenger and the ride has been wonderful. I have three clients who need this approach.
@Bill_French gets it.
I can think of a lot of ways to make this SUPER useful. Basically think of it like this, if you could embed a table within a table, what could you do?
You could create incredibly rich “books” by having a Table.Chapters and then one cell contains the “content” : a rich canvas that includes all types of other info and tables along with longform prose. The other chapters can contain metadata, references, etc. By using a table you would be able to present the information dynamically - in a book in one context or a custom learning module in another (rows/chapters presented/hidden based on the user’s condition).
You can create dashboards where each row is an object, lets say a worker, and then different cells summarize different their performance. For example I have a table with three columns ‘Work Start’, ‘Work End’, ‘Work Task’. Each of them is an array and if I could present all of them in one cell next to each other (as opposed to independent columns) in some kind of formatted narrative, the information can be much better understood than as separate columns (when I write up the feature request I’ll elaborate on this once since it would be my first implementation).
It’s a new insight to me too @Paul_Danyliuk. Its been born of moving past using Coda just for myself, but beginning to create dashboards and interfaces for non technical people who don’t have any ‘default’ understanding of their needing to be columns, but want to see the information presented in a way that intuitively and immediately makes sense. As you think on it you may come to understand how the grid + canvas can be combined to create incredibly complex and rich applications that, wouldn’t be recognizable to the user as a table yet using it as the foundation to present information. I think coda is winking to us about this by being baking in the ability to the title, column headers and gridlines.