You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For every distinct type of frame (XYFrame, NetworkFrame, OrdinalFrame) there is Responsive* and Spark* variants which main goal is to define particular space allocation behavior while the original frame assumes strict size being defined by the author. The need for explicit size definition doesn't exist without a reason: both SVG and Canvas require the size to be defined before they render the content within. Physical size being a type of visual values directly affects how exactly the content within should be rendered.
(following rationale is based on my experience and expectations in developing web UIs)
A piece of data visualization is often not a single unit of content on the web page: one might need a column or two of text content, or the viz is a part of application UI, which has plenty of controls, other sources of information and quite possibly a couple of more pieces of data viz. Before a developer steps into adding a data visualization piece there already plenty of work that is done. Given the variety of the devices used for browsing the internet one can never assume a single since of a viewport the app should work within. When you get to adding SVG or Canvas that start requiring to specify very explicit sizes, this is where you can get stuck figuring out all the possible scenarios and outcomes of choosing the wrong size.
This type of consideration never exists when you work with typical text or illustrations content and use flexbox or grid layout. Either the content fluidly defines the behavior of container, or the containers (based on its context) defines how children suppose to allocate space within. Spark* and Responsive* frames seem to be fitting this sort of inversion of control scenarios: despite having a content within (e.g. XYFrame) that was initially working only with predefined size, Responsive frame expects parent container in user space to define how the content should behave thus delegating the control over to the user.
Having this sort of control outside of any library or framework means the user has all the potential and flexibility of existing tools and their experience. This means no artificial limitation to how the library or framework can be integrated in an existing UI.
I still need to learn more about Spark* frames but I'd make a wild guess that the same reasoning is applicable to them as well.
Generalized behavior
Basically, the question is: what if we assume responsive behavior as a default space allocation behavior?size prop can still exist if the strict size is needed. The main reason for this is that it would mean top level Semiotic components are easily integrate-able into whatever UI users already have: notebooks, applications, web documents. It means no additional handling or size control needed within Semiotic components, as well as special API: the implementation of necessary space allocation behavior happens in the most basic way of how things behave on the web page. The users don't need to learn about additional semantics since they just use the basics of the environment they're working with. This also means that the documentation can be simplified to describe the common way of doing things.
It might be too verbose, so here is another look on this problem: if we assume responsive behavior as a default, we still can define a visualization frame that has static size, just because this is how the platform works and we don't even need a special top level API for this.
There plenty of small implementation details that go into this idea, I'll be trying to define them here:
useElementSize() is moved to a separate module so it can be shared between frames
Frames use their wrappers to compute size if the prop is not provided
Frames inline prop to to apply inline block behavior
Implementation
A lot of small implementation details that need to considered and some that I may not be familiar with, but in my mind the described behavior comes down to the following:
functionXYFrame(props){letref=useRef();letsize=useElementSize(ref);// as an option we can pass down some more styles applied to the wrapper// however it might be advised to just to keep those on the user sideletstyle={display: props.inline ? "inline-block" : "block", ...props.style};// in the same way as it happens now, computing all props that Frame needs// and the size is already available on this level, regardless of frame typeletcomputedProps={/* whatever <Frame /> needs */}return(<divstyle={style}ref={ref}>{/* to ensure we don't render Frame with [0, 0] as it would be just waste of time */}{size!=null ? <Framesize={size}{...computedProps}/> : null}</div>)}
Quite possibly we can get rid of the notion of SpanOrDiv as a result of these changes.
Benefits
Smaller API surface area
on its own, it means users won't need to return to docs once they realize they need fluid version of a frame
no ambiguity and questioning "what is the difference"
no "Spark" frame that assumes understanding of a term "sparklines" in data viz context (or am I the only one?)
Users getting all the flexibility of their grid solution and practices (no more workarounds)
It is worth discussing the rationale behind suggested behavior. One might say that generalization can go even further and Semiotic could just export Frame as the only piece of API needed. Yet, it is about the amount of concepts necessary to get the task done.
Drawbacks
Things like SparkNetworkFrame may include very specific defaults for its original frame implementation which means there are plenty of cases where things can't really "just work".
More testing for Spark frames needed before considering generalizing this behavior
How do we teach it
I believe the suggested behavior streamlines the teaching aspect of Semiotic. Frames become no different from other flexible/static containers (e.g. images) and the same rules apply: you either set an explicit size, or assume the fluid container to define available space. If an inline frame behavior needed, one simply set the style to "display: inline-block" and the rest of expected rules apply. I guess it still sounds as over simplification, so having a quick guide with visual examples should definitely help.
A guide exists explaining fluid layout and showing examples of responsive frame and inline frames usage
Breaking changes
The suggested behavior means not only some parts of API being removed but also the fact that frames no longer have default size. While I don't expect much of users to be relying on the default size, it is still reasonable to mention this change in changelog and migration guide. The basic suggestion can be something like "if you Semiotic v1 frame doesn't have size prop, it means it uses the default value, so set it to [500, 500] when migrating to avoid layout issues". More testing possibly required.
Changelog mentions removed top level components
Changelog mentions removed default size value
Migration guide explains that size should be defined if it wasn't to avoid breaking existing visualizations
(the issue includes definitions of done that we can use to track related pull requests and the whole initiative progress)
@emeeks, @willingc, looking forward to your feedback and questions. I'm thinking about opening a draft PR with some preliminary implementation changes, to see how far we can actually go.
The text was updated successfully, but these errors were encountered:
For every distinct type of frame (
XYFrame
,NetworkFrame
,OrdinalFrame
) there isResponsive*
andSpark*
variants which main goal is to define particular space allocation behavior while the original frame assumes strict size being defined by the author. The need for explicit size definition doesn't exist without a reason: both SVG and Canvas require the size to be defined before they render the content within. Physical size being a type of visual values directly affects how exactly the content within should be rendered.(following rationale is based on my experience and expectations in developing web UIs)
A piece of data visualization is often not a single unit of content on the web page: one might need a column or two of text content, or the viz is a part of application UI, which has plenty of controls, other sources of information and quite possibly a couple of more pieces of data viz. Before a developer steps into adding a data visualization piece there already plenty of work that is done. Given the variety of the devices used for browsing the internet one can never assume a single since of a viewport the app should work within. When you get to adding SVG or Canvas that start requiring to specify very explicit sizes, this is where you can get stuck figuring out all the possible scenarios and outcomes of choosing the wrong size.
This type of consideration never exists when you work with typical text or illustrations content and use flexbox or grid layout. Either the content fluidly defines the behavior of container, or the containers (based on its context) defines how children suppose to allocate space within.
Spark*
andResponsive*
frames seem to be fitting this sort of inversion of control scenarios: despite having a content within (e.g.XYFrame
) that was initially working only with predefined size, Responsive frame expects parent container in user space to define how the content should behave thus delegating the control over to the user.Having this sort of control outside of any library or framework means the user has all the potential and flexibility of existing tools and their experience. This means no artificial limitation to how the library or framework can be integrated in an existing UI.
I still need to learn more about
Spark*
frames but I'd make a wild guess that the same reasoning is applicable to them as well.Generalized behavior
Basically, the question is: what if we assume responsive behavior as a default space allocation behavior?
size
prop can still exist if the strict size is needed. The main reason for this is that it would mean top level Semiotic components are easily integrate-able into whatever UI users already have: notebooks, applications, web documents. It means no additional handling or size control needed within Semiotic components, as well as special API: the implementation of necessary space allocation behavior happens in the most basic way of how things behave on the web page. The users don't need to learn about additional semantics since they just use the basics of the environment they're working with. This also means that the documentation can be simplified to describe the common way of doing things.It might be too verbose, so here is another look on this problem: if we assume responsive behavior as a default, we still can define a visualization frame that has static size, just because this is how the platform works and we don't even need a special top level API for this.
There plenty of small implementation details that go into this idea, I'll be trying to define them here:
useElementSize()
is moved to a separate module so it can be shared between framessize
if the prop is not providedinline
prop to to apply inline block behaviorImplementation
A lot of small implementation details that need to considered and some that I may not be familiar with, but in my mind the described behavior comes down to the following:
Quite possibly we can get rid of the notion of
SpanOrDiv
as a result of these changes.Benefits
It is worth discussing the rationale behind suggested behavior. One might say that generalization can go even further and Semiotic could just export
Frame
as the only piece of API needed. Yet, it is about the amount of concepts necessary to get the task done.Drawbacks
Things like
SparkNetworkFrame
may include very specific defaults for its original frame implementation which means there are plenty of cases where things can't really "just work".How do we teach it
I believe the suggested behavior streamlines the teaching aspect of Semiotic. Frames become no different from other flexible/static containers (e.g. images) and the same rules apply: you either set an explicit size, or assume the fluid container to define available space. If an inline frame behavior needed, one simply set the style to "display: inline-block" and the rest of expected rules apply. I guess it still sounds as over simplification, so having a quick guide with visual examples should definitely help.
Breaking changes
The suggested behavior means not only some parts of API being removed but also the fact that frames no longer have default
size
. While I don't expect much of users to be relying on the default size, it is still reasonable to mention this change in changelog and migration guide. The basic suggestion can be something like "if you Semiotic v1 frame doesn't havesize
prop, it means it uses the default value, so set it to[500, 500]
when migrating to avoid layout issues". More testing possibly required.size
valuesize
should be defined if it wasn't to avoid breaking existing visualizations(the issue includes definitions of done that we can use to track related pull requests and the whole initiative progress)
@emeeks, @willingc, looking forward to your feedback and questions. I'm thinking about opening a draft PR with some preliminary implementation changes, to see how far we can actually go.
The text was updated successfully, but these errors were encountered: