Open flochtililoch opened 2 years ago
One other approach we could consider is to allow <styles>
elements anywhere within the XML. This could make it easier for one-off styling sometimes needed for a specific component.
Another question: should <styles>
elements override global settings, or only apply to the scope (fragment or doc)? I can see benefits of using localized-styles rather than merging the global styles. RN makes this easy to implement by passing multiple stylesheets as the prop.
One other approach we could consider is to allow
<styles>
elements anywhere within the XML. This could make it easier for one-off styling sometimes needed for a specific component.
I thought about this a bit, I think part of one-off styling is really bound to how the system that generates your markup is organized. With the solution we're currently exploring for our backend, we'll have the ability to collocate styles with components, so that'll fill the need here. It's true that when writing the XML manually, it's not the easiest right now to associate a style with an element, but is this a use case you think is worth optimizing for?
Also, as of right now, not every Hyperview components are rendering children elements, so that might also make it unpredictable when this would work - or would be at the expanse of a larger refactor.
should
<styles>
elements override global settings, or only apply to the scope (fragment or doc)
By global settings, you meant the document, right? As of right now, styles are already scoped to the doc. Could you list some of the benefits you have in mind for scoping the styles to the fragment only?
I thought about this a bit, I think part of one-off styling is really bound to how the system that generates your markup is organized. With the solution we're currently exploring for our backend, we'll have the ability to collocate styles with components, so that'll fill the need here. It's true that when writing the XML manually, it's not the easiest right now to associate a style with an element, but is this a use case you think is worth optimizing for?
The use case is when we sometimes have a one-off need, for example if a specific element needs a custom width. I'm noticing our design system styles are getting littered with some of these one-off styles, which is bloating the payload for all screens.
Also worth keeping in mind that when adding features to Hyperview core, the open-source users won't have the benefit of our internal system for rolling up all styles. So I could see some users relying on co-located styles with their components, even if we're not doing that ourselves.
I agree it may not be something we need to add immediately, but I want to at least keep the door open for this sort of design in the future.
should
<styles>
elements override global settings, or only apply to the scope (fragment or doc)By global settings, you meant the document, right? As of right now, styles are already scoped to the doc. Could you list some of the benefits you have in mind for scoping the styles to the fragment only?
This is probably best shown with an example. I believe <styles>
are scoped to a <screen>
right now, right?
<doc xmlns="https://hyperview.org/hyperview" >
<screen>
<styles><style id="main" flex="1" backgroundColor="red" /></styles>
<body>
<view style="main" / > <!-- this will be red -->
</body>
</screen>
<screen>
<styles><style id="main" flex="1" backgroundColor="blue" /></styles>
<body>
<view style="main" / > <!-- this will be blue -->
</body>
</screen>
</doc>
So there's a precedent that the styles apply only to the context where they are defined, in this case the <screen>
.
For consistency, it seems like <fragment>
should follow the same logic. The example below shows the state of the XML after we append a fragment to the main view:
<doc xmlns="https://hyperview.org/hyperview" >
<screen>
<styles>
<style id="main" flex="1" backgroundColor="red" />
</styles>
<body>
<view style="main"> <!-- this will be red -->
<fragment>
<styles>
<style id="secondary" color="green" />
</styles>
<body>
<text style="secondary">World!</text> <!-- this will be green -->
<view style="main" /> <!-- this will be red, using style from parent screen -->
</body>
</fragment>
<text style="secondary">Hello</text> <!-- this will not be green -->
</view>
</body>
</screen>
</doc>
Now that I've written out this example, I do see some potential issues, which means maybe we don't want to do this.
<body>
elements.One other idea to explore: since the desired effect is to add styles at the screen-level, perhaps this could be done with a behavior. Something like this:
<view>
<behavior trigger="load" once="true" action="add-styles">
<styles>
<style id="secondary" color="green" />
</styles>
</behavior>
<text style="secondary">World!</text>
</view>
Some alternatives:
Inlined styles style attributes are only applied to their parent element.
<view href="#">
<style backgroundColor="red">
<modifier pressed="true">
<style backgroundColor="blue" />
</modifier>
</style>
<text>
<style color="yellow">
<modifier pressed="true">
<style backgroundColor="green" />
</modifier>
</style>
Hello world
</text>
<style>
anywhere
styles are combined in a single stylesheet and collisions are removed. cons: can be undeterministic depending on XML parsing.
<doc xmlns="https://hyperview.org/hyperview">
<screen>
<styles>
<style id="primary" color="blue" />
</styles>
<body>
<text style="primary">Hello</text>
<style id="primary" color="red" />
<view>
<style id="primary" color="green" />
</view>
</body>
</screen>
</doc>
namespaced style attributes similar to inlined styles but less verbose syntax (but more XML namespaces)
<doc xmlns="https://hyperview.org/hyperview" hv-style="https://hyperview.org/hyperview/styles" hv-style-pressed="https://hyperview.org/hyperview/styles/pressed">
<screen>
<body>
<text style:color="red" style:fontSize="12">
Hello
<text hv-style:backgroundColor="blue" hv-style-pressed:backroundColor="red">world</text>
</text>
</body>
</screen>
</doc>
Amongst the alternatives listed, I think option 1 for inlined styles is the most straight-forward.
<style>
anywhere, we could have some issues especially when styles are loaded through fragments on an existing screen. But this is similar to CSS, so maybe people are used to it?It may help to introduce a <inline-style>
tag for option 1, to help distinguish inline styles from those with global references.
Like you said, with
Right now, the styles definition is represented under the
element.<styles>
element, which by spec requires to be an immediate children of the<screen>
element. Hyperview fragments by spec only return elements that can be appended to aProposal: define a new
<fragment>
element, modeled after the<screen>
element, that will serve the purpose of nesting content and styles in two separate elements. For example:We would need for this to update the existing parsing code to change the validation logic while preserving support for the old format, then extract the stylesheet here (like it's done here) and merge it in the existing stylesheet (stored on the React state).