asyncapi-react
asyncapi-react copied to clipboard
DocsUI: Messages Object output
Description
This issue is for the design progress and proposal of the UX/UI updates to the Messages Object documentation output.
Scope
- [ ] Design
- [ ] Implementation
See comments below for design progress.
RFC: Proposal for new UX for Payload documentation output
https://www.loom.com/share/dba7481f296046629b30995628b924e3
Here is a new idea I have that could improve the experience of the Payload component. My inspiration came from browser developer tools where you can toggle all levels of an object with ease and see everything you need in one line.
Some more features that we should add: Need a way to collapse and expand all. Should there be one button to expand and collapse the whole payload? Or should a button like this be available at all Object levels? I guess it depends on the complexity of the payload structure. Let me know what you think!
@mcturco
Here is a new idea I have that could improve the experience of the Payload component. My inspiration came from browser developer tools where you can toggle all levels of an object with ease and see everything you need in one line.
Yeah, it looks very good, however have in mind that metadata of single property can be very complex. At the moment you render type, name, format and description. We can have also constraints like minLength
, maxLength
etc, examples for given field, metadata like read-only
, write-only
, external documentation link (in future also tags). So as you see, render in single line can be very problematic and by this we render in current react-component each metadata under each other.
Need a way to collapse and expand all. Should there be one button to expand and collapse the whole payload? Or should a button like this be available at all Object levels? I guess it depends on the complexity of the payload structure. Let me know what you think!
Yeah, we should have that implemented, button to collapse only one level and all levels. I added suggestion to current design in this PR https://github.com/asyncapi/asyncapi-react/pull/620
@magicmatatjahu Thanks for that feedback! @fmvilas explained the problems with showing the constraints of each property to me during our 1:1 call and how that could become confusing on one line. He also mentioned that we should think about the fact that description
in the spec supports markdown, so we need a way to show that as well.
Going to take that information and come up with some other solutions that might work. Thanks! 😄
Updated Payload Output Design
Hi here is a video explaining the new design iteration for the payload
object, would appreciate any feedback you have!
https://www.loom.com/share/7c5b1e5ca14c4b4691eda0080ebe3849
I love the idea for long descriptions ❤️
Hey all! 👋
I have been working on an update for this issue, and wanted to first offer it in video form if that suits you:
https://www.loom.com/share/6d24178eb4fc43b49c30f4696f2761ae
Went back to the drawing board
After presenting the previous idea during the community meeting livestream, I received some great feedback that led me to the conclusion that we needed to head back to the drawing board and address some concerns that were mentioned:
- There is not enough space to present various metadatas within schema properties
- How are we going to show validations such as if/then/else?
Well, before I felt like I could dive headfirst into ideation on these two issues, I felt like I had to do some background research to better understand JSON schema and the different complexities within.
Along this journey, I started brainstorming in a FigJam file and jotted down some of the "bread and butter" components that is needed for your JSON schema. Click here to open the FigJam -> https://www.figma.com/file/j6UgI3CC6bmzv6NRpaNEtF/JSON-Schema-Brainstorm?node-id=0%3A1
After defining the 🍞 & 🧈, I felt like I could once again start coming up with a layout that would make sense to build off of.
From this idea, I began to craft wireframes at a bit higher of a level but not focused so much on UI to see if I can start hammering out an established experience.

And here is this experience put to the test by using some example schemas from the JSON Schema website:

Link to Figma File -> https://www.figma.com/file/wJHfdNxBeXg4O3jxcqcL9X/JSON-Schema-Wireframes?node-id=7%3A355
What do you think? Am I on the right track?
Would appreciate some feedback so I can decide how to proceed!
cc: @derberg @magicmatatjahu @jonaslagoni @fmvilas
Thanks so much for taking the time to record a video 🙏🏼 It helped to check it out quickly 🚀
Only positive feedback, sorry 😄
- good decision to not take up all the use cases at the same time, but gradually extend design on the way 👏🏼
- I like a lot the new position of the information about the
type
. I did not catch it during the video, will they be colored differently depending on the type? - I like your approach for more human-readable approach when representing
Rules
, so you do not just display what is in the schema, for example>0
but actually put a property name next to itage > 0
, so readers do not need to exercise brain to visualize that, but it is basically there in the UI. I kinda reminded me of the project I stumbled upon some time ago, maybe will help you in your journey 😄 -> https://coveooss.github.io/json-schema-for-humans/#/Examples (especially interesting is why they are adding a kind of "breadcrumbs" info about the property location inside schema)
IMHO it is going a very good direction 🚀
@derberg
Thanks so much for taking the time to record a video 🙏🏼 It helped to check it out quickly 🚀
Yay! Super glad you thought the video presentation was helpful 😄
I like a lot the new position of the information about the type. I did not catch it during the video, will they be colored differently depending on the type?
Yeah at this stage I was more focused on the interactions and layout of how we might present the information, but I definitely was thinking as I was designing this that we could color-code the property types!
I like your approach for more human-readable approach when representing Rules, so you do not just display what is in the schema, for example >0 but actually put a property name next to it age > 0, so readers do not need to exercise brain to visualize that, but it is basically there in the UI.
Yes! Glad you found that helpful and easier to read. I was stuck at this for a while trying to figure out the best human approach, and really was just thinking how people are used to seeing rules in math with variables. Interested to see other opinions on this as well!
I kinda reminded me of the project I stumbled upon some time ago, maybe will help you in your journey 😄 -> https://coveooss.github.io/json-schema-for-humans/#/Examples (especially interesting is why they are adding a kind of "breadcrumbs" info about the property location inside schema)
Bless you for this reference 🙏 As I was working on this, I couldn't help but think that someone must have already done this same kind of thing before but I couldn't find any specific projects similar. I definitely think adding an element like breadcrumbs might be super helpful to keep track of where you are viewing the schema.
IMHO it is going a very good direction 🚀
I SUPER appreciate your quick and thoughtful feedback, Lukasz! Thank you! 😄
Update! Ideation on if/then/else implementation
Video:
https://www.loom.com/share/65c5b8fd731d4674bd466b4231b16d52
Transcript:
Hey guys, happy Monday. I wanted to just start presenting some more things that I've been coming up with as far as this messages object item in Github.
I have a few ideas for if then, else that I would like to present and get some feedback on if possible.
TL;DW too long didn't watch: basically these are the three options that I have.
This is one where I list the conditions at the bottom outside of the property's object.
The next one, where I list the conditions on the left side, where you can toggle between them.
And then the last one where I list on the top, where we can toggle between them as well.
(For a detailed explanation of these options, view the video on loom which also contains a longer transcript)
Love it! Have you thought about having tabs inside the property box instead? I mean, when age >= 21
, only beverage
changes so why not put the tab there? I know multiple properties can be affected by the same condition so what we can do in this case is that if you click on the age >= 21
tab inside beverage
it will also switch to the age >= 21
tab in the other fields affected by the condition. Am I making myself understood? I find it hard to explain it 😄
I know multiple properties can be affected by the same condition so what we can do in this case is that if you click on the age >= 21 tab inside beverage it will also switch to the age >= 21 tab in the other fields affected by the condition.
Hey @fmvilas thanks for leaving feedback 😄
Yes, I understand exactly what you are saying. However, say that the payload consists of more than just two properties, maybe something like 8 properties. My fear is that if someone clicks on the condition tab under beverage
they will fail to notice the changes that occur in every other property. This is a potential problem that I noticed with the ReDoc example.
Having the tabs on top or to to the side of the whole payload might be a clearer experience. Here is the user journey that I was thinking would happen:
Developer wants to see payload under specific condition --> Developer selects a condition tab --> Developer can view entire payload under that condition
Whereas the other journey might look like:
Developer wants to see payload under specific condition --> Searches through properties for different conditions --> Selects a condition at the property level --> Scrolls back up to see changes reflected based on that condition selection (Potentially misses out on noticing what has changed)
@mcturco Awesome designs as usual ❤️ However I have some doubts looking on examples. I know that it's on early stage and you experiment with some cases, but I see some problems that you sooner or later will catch and you will end up with redesign everything 😅 Trust me, the amount of curses I have uttered over JSON Schema and its flexibility is large enough that I consider myself an expert 🤣 Ok, so:
-
you put
type
of given field on the left. It's nice, however sooner or later you will notice that JSON Schema can be defined as union, so given field can be string or number. I think that it will be problem, how to render that union types? I think that tabs (for particular field) should be better - user will choose between string and number and we will render rules for particular type (e.g. for string, min length of string, for number min, max value etc). That left rendered type is good, but only for "simple" schemas, so please consider to render that type next to the name of field (as ReDoc does it). We can discuss it of course :)Union can be defined in two ways, by defining
type
as array or usingoneOf
, so below examples are same (in sense of validation) but described in two ways:{ type: ['string', 'number'] } { oneOf: [ { type: string } { type: number } ] }
-
now you focus only on objects as root schema and message's payload (I guess) in 99% cases is described as object so it's fine, however people can also define given payload as normal string or number, or even array, so we should have some idea to render that standalone simple schema.
-
about conditions: I like that idea with tabs, but you need to understand that some conditions will be better to render in "root" tabs but some only in given place. If a given field of type number is greater than 10 then it must be a multiple of 5, but if smaller then it must be a multiple of 2. I know silly example but it shows that you can define this in JSON Schema, very complex example but it is possible. In that case it is better to render such conditions as tabs for the field level, not at global tabs.
Let me know if you understand everything I wrote about or if I should describe something more, These problems and edge cases with JSON Schema are a lot. I don't want to scare you but to show that it is a difficult task to make designs for it. Other places like servers etc will be much, much easier, trust me :)
Wouldn't they also struggle to find what has changed if the tab is on top? I mean, if we have 8 properties and say 4 change. How do you spot them anyway?
Two more suggestions/questions:
- What if the condition is on the
age
property instead? - What if we briefly highlight the properties that have changed? Can be done with a subtle drop shadow animation that runs for 2 or 3 seconds and fades away slowly.
Oh, BTW, the term you're looking for in the video is discriminator
😄
SOOO thankful for everyone's feedback, I feel like we are really starting to get somewhere promising!
I recorded a video feedback if that is okay with you guys.
https://www.loom.com/share/540e392a2c9e4235ae1afd7c5048f458
@magicmatatjahu, I addressed your concerns in the video 😄
What if the condition is on the age property instead?
@fmvilas so we would add the conditions/rules under age
and not on beverage
at all?
What if we briefly highlight the properties that have changed? Can be done with a subtle drop shadow animation that runs for 2 or 3 seconds and fades away slowly.
Great idea, I have built upon that idea in the video 😄
Oh, BTW, the term you're looking for in the video is discriminator 😄
THANK YOU! I forgot what the word was hahaha
Yeah, my suggestion is that if it's a condition in age
it might make sense to have a dropdown in age
that lets you choose that condition. Once it's selected, the rest of the fields can change with the visual feedback. My only concern about this approach is that some of the conditions may involve multiple properties so we probably gotta make it clear somehow.
Also, with the current approach of putting a dropdown, what if a property is only present when a specific condition is met? You can't select the condition because the property will not be present, right? Maybe the best way to do it after all is to put conditions at a global level 😄
Yeah, my suggestion is that if it's a condition in age it might make sense to have a dropdown in age that lets you choose that condition. Once it's selected, the rest of the fields can change with the visual feedback. My only concern about this approach is that some of the conditions may involve multiple properties so we probably gotta make it clear somehow.
Yeah I had the same concern when you were showing me offline how the conditions work in ReDoc. It's cool, but I think it still has some problems that we would need to address.
Also, with the current approach of putting a dropdown, what if a property is only present when a specific condition is met? You can't select the condition because the property will not be present, right? Maybe the best way to do it after all is to put conditions at a global level 😄
Yeah that's what I was thinking before when I had the tabs at the global level. I was thinking that it might be easier to discover the "new payload" when that condition is met if we just switched the whole payload based on a tab. However, is there a possibility to have conditions within an object property within payload? It seems like you can, so maybe we have to keep these tabs available at each object level... but that could get confusing. Hmmmmm 🤔
@fmvilas
Also, with the current approach of putting a dropdown, what if a property is only present when a specific condition is met? You can't select the condition because the property will not be present, right? Maybe the best way to do it after all is to put conditions at a global level 😄
In JSON Schema you can't influence the "shape" of JSON Schema from the child's point of view, the parent can it, so I don't think it's problematic.
For example, you can influence what is required because of some condition:
type: object
properties:
a: ...
b: ...
if:
properties:
a:
const: 'something'
then:
required: [b]
so it means that if a
property is equal to something
, then b
property is required - you have condition on the root of some object, but you cannot influence on b
from a
point of view like there:
type: object
properties:
a:
if:
const: 'something'
then:
# how to "see" b property from parent schema?
b: ...
I think that approach of Redoc maybe isn't perfect but it renders correctly conditions, in the schema level where conditions are.
@mcturco Sorry for making you crying at the beginning of video 😆 Sorry also for delay.
For first part of union type: I don't know how often people write union as type: [string, number]
, because as I know people usually use oneOf
for unions (like in my examples), but JSON Schema also supports that array of type
.
I very like that idea with string or number
- as I know Stoplight render union in similar way, but I have one suggestion. Could we render union type with tabs? I mean something like that, if you have string or number (or even more types in the union) we can render one tab for string and one tab for number. For example (I will show my idea in markdown 😆 ), take schema:
type: [string, number]
minLength: 1 # related to the string type
format: email
maxValue: 5 # related to the number type
When string
is active
age [string] [number]
{desription of age field}
Rules
The string must have a minimum of 1 character.
Format: email
When number
is active:
age [string] [number]
{desription of age field}
Rules
Value can have a maximum value of 5.
For second part about standalone simple schema:
yeah, it's make sense to indicate in some way that you have object, string etc. Maybe we should have option to "hide" the property name and only render the type of schema? By this we can reuse the component for objects rendering and render only one property, but you know, with hack that we don't render property of object but simple schema. WDYT? if I am difficult to understand here then let me know.
Third part about conditions:
Yeah 😆 It was a stupid example, but I answered to Fran's comment about conditions and JSON Schema has big restriction here https://github.com/asyncapi/asyncapi-react/issues/618#issuecomment-1228396976 In general, it is not possible to change the condition of a "parent" schema in a sub schemas, as I wrote in the example, and so the conditions should be rendered where they are defined - these conditions can affect deeper schemas but no longer on higher ones (their parents). Let me know if this is clear, we can meet and I'll explain it to you with a dozen examples.
Or... as you show at the end of video with that conditional
tab. I like it, really. It's fine, easy to understand (for me) and we only show what should change with certain condition, not everything.
Conditions are very difficult to render but we are getting better and better.
BTW. I wonder if we should write some library that would simplify given schema to simplifier form, for example removing if/then/else
and create based on condition some union available of schemas. WDYT? Missy would have an easier work with designs and the implementation itself in the future of the Schema React component would be easier. However, I don't know if such logic is possible, but we can try. cc @fmvilas
Great work Missy! 🚀
@magicmatatjahu Thank you for your thoughtful and detailed feedback!!! Left some comments below:
@mcturco Sorry for making you crying at the beginning of video 😆 Sorry also for delay.
🤣
I very like that idea with string or number - as I know Stoplight render union in similar way, but I have one suggestion. Could we render union type with tabs? I mean something like that, if you have string or number (or even more types in the union) we can render one tab for string and one tab for number.
So I originally thought about designing it like this with tabs, but then I was thinking: let's say the property has type: [number, integer]
and every other rule is the same (like there is no differing validation between number
and integer
.) Would it then be weird to have tabs for this case? Maybe we can render tabs if the validation is different depending on type
but if the validation is the same for each type
then we just render the types like number or integer
. What do you think?
For second part about standalone simple schema:
yeah, it's make sense to indicate in some way that you have object, string etc. Maybe we should have option to "hide" the property name and only render the type of schema? By this we can reuse the component for objects rendering and render only one property, but you know, with hack that we don't render property of object but simple schema. WDYT? if I am difficult to understand here then let me know.
Not sure that I fully understand what you mean here 😅 I know what you mean by showing simple schemas, but wouldn't the property name still have to exist? Unless the payload ends up being something like:
messages:
OrderReceived:
payload:
type: string
description: Message sent when the order has been received
Then in that case, yeah, maybe we just simply hide the property name. I can definitely think about this more too and see what other ways we can render this!
Third part about conditions:
In general, it is not possible to change the condition of a "parent" schema in a sub schemas, as I wrote in the example, and so the conditions should be rendered where they are defined - these conditions can affect deeper schemas but no longer on higher ones (their parents)
Yep, I understand what you are saying here. I think the more challenging problem is the fact that a condition on one property can affect a sibling property, and that could be above or below the property with the condition depending on how someone writes their schema. Which you would hope that someone would be aware that they should probably keep properties with conditions closer to the top, but that might not always be the case. That's why I was thinking having a tab at the global level might make sense, but we can play with some more options. Maybe it would be good just to start with something initially and then see how it works in the application, then iterate on different solutions.
BTW. I wonder if we should write some library that would simplify given schema to simplifier form, for example removing if/then/else and create based on condition some union available of schemas. WDYT? Missy would have an easier work with designs and the implementation itself in the future of the Schema React component would be easier. However, I don't know if such logic is possible, but we can try. cc @fmvilas
I don't think I understand what you mean here. Do you mean separating the conditions from the normal schema shape?
Great work Missy! 🚀
Thank you so much 😄 Having fun with this problem!
Just filmed an update video! Would love your thoughts/feedback! We are getting super close to solving this problem 🙏
https://www.loom.com/share/5713a828b5ad478794ce5647f53e34ce
cc: @fmvilas @magicmatatjahu @derberg
First of all, I love how the discussion is going 👏 I feel that we're really thinking about the problem right now, and that's awesome.
So, following your examples with age
and beverage
, I also like the version that has the "Conditional logic" tab on beverage
instead of age
. However, a potential limitation came to my mind: say, for instance, beverage
doesn't exist by default and it can only be specified when age
is >= 21. How do you overcome this limitation? The beverage
property will not be there so the Conditional Logic tab would not be rendered either 🤔 Should we maybe aim for a Conditional Logic tab at payload level instead?
First of all, I love how the discussion is going 👏 I feel that we're really thinking about the problem right now, and that's awesome.
I agree!! And I am so appreciative that we are having this conversation as it keeps me from being blocked in my design process!
So, following your examples with age and beverage, I also like the version that has the "Conditional logic" tab on beverage instead of age.
Cool, so we are all in agreement that this is a good solution for conditions on properties that affect themselves? (not even sure if that statement makes sense haha)
However, a potential limitation came to my mind: say, for instance, beverage doesn't exist by default and it can only be specified when age is >= 21. How do you overcome this limitation? The beverage property will not be there so the Conditional Logic tab would not be rendered either 🤔 Should we maybe aim for a Conditional Logic tab at payload level instead?
Good point. Here's what I am thinking: On a left-hand sticky sidebar, we list all the rules and allow the user to click on each rule and view how it affects the entire payload. Changes might be highlighted briefly in the UI for visibility.
Demo: https://www.loom.com/share/a8a320510987480ca7c06cb413474b8c
I love the concept but I'm afraid we may not have enough horizontal space to have sticky conditions, payload, and examples. And also, potentially, sidebar navigation (when downloaded). What if we render a sticky button near the payload and when you click on it, it displays the conditions panel? Like a sticky menu maybe? Or maybe the whole payload can be contained inside a panel with a toolbar on top. This toolbar would have Conditions
button and also a button to display the raw JSON Schema that's being rendered. What do you think?
I love the concept but I'm afraid we may not have enough horizontal space to have sticky conditions, payload, and examples. And also, potentially, sidebar navigation (when downloaded).
Good point!
What if we render a sticky button near the payload and when you click on it, it displays the conditions panel? Like a sticky menu maybe? Or maybe the whole payload can be contained inside a panel with a toolbar on top. This toolbar would have Conditions button and also a button to display the raw JSON Schema that's being rendered. What do you think?
LOVE this idea. Going to explore this in the wireframes this week and then I will touch back!
Okay so I started crafting a layout for the sticky tabs idea that @fmvilas mentioned above, and I think it is starting to come together! The only thing I am unsure of just yet is how to present the conditions at the payload level. Will think through some possible solutions for this, but if you guys have any input here that would be great!
Here is a quick demo: https://www.loom.com/share/2931451036e0434ea8e54a4724a4d5f5
And here is the figma prototype link if you want to check it out there: https://www.figma.com/proto/wJHfdNxBeXg4O3jxcqcL9X/JSON-Schema-Wireframes?node-id=105%3A1529&scaling=scale-down&page-id=2%3A29&starting-point-node-id=105%3A1529&show-proto-sidebar=1
This issue has been automatically marked as stale because it has not had recent activity :sleeping:
It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation.
There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model.
Let us figure out together how to push this issue forward. Connect with us through one of many communication channels we established here.
Thank you for your patience :heart:
Keep it open, dear bot.
This issue has been automatically marked as stale because it has not had recent activity :sleeping:
It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation.
There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model.
Let us figure out together how to push this issue forward. Connect with us through one of many communication channels we established here.
Thank you for your patience :heart:
Querido GitHub Actions, I hope this message finds you well. Please, kindly wait a bit more for this issue to be solved. Yours faithfully, Fran.
Hey @mcturco
I'm interested to work on this issue!