Closed rishson closed 7 years ago
Some possible approaches:
layout.css
or similar, that has flexbox classes, e.g. .fit {
flex: 1;
}
.full-width {
flex: 0 0 100%;
}
.half-width {
flex: 0 0 50%;
}
and then provide a layout
mixin for widgets
that would convert layout props to classes, e.g.
[treat below as pseudocode]
getChildrenNodes: function (this: List): DNode[] {
const layoutClasses = layout.get(this.properties);
const classes = ['some-class'];
return [ v('div', classes.concat(layoutClasses)) ];
}
where the layout
would do something like:
get: function (props: WidgetProperties) {
const classes = [];
if(props.layout.fullWidth) {
classes.push(LAYOUT_CLASSES.full-width);
}
if(props.layout.halfWidth) {
classes.push(LAYOUT_CLASSES.full-width)
}
...
//you could even make it more intelligent, by inspecting parent to make sure it had the correct enclosing classes, e.g. parent of `x-width` needs to have `fit`...
}
The above is similar to what angular material does for layout, e.g. component attributes are parsed by a directive and layout classes applied to the component root node.
Other musings:
At the moment, I think providing widgets to do layout is overkill, but I've not really thought about this much - just getting down my thoughts. The only layout widget that I could see us having to provide would be a splitter
widget.
Layout css would need to provide sensible device breakpoints with @media
queries, out of the box.
@bitpshr @matt-gadd just adding you in a comment, in case you thought I'd just closed the previous issue for no reason 😄
I think that the best approach to this is to create a layout css-module that can be required into dojo widgets and custom widgets to apply layout rules. I don't believe there would be any need for a layout.ts
mixin or similar. The layout classes can be mixed into the theme classes to provide the appropriate layout. Utilising the current css-module
and postcss
pipeline will provide browser prefix support and seamless css-properties integration by default.
// layout.css
.flex-container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.flex-grow-item {
flex-grow: 1;
}
// tabpanel.ts
import * as layout from 'path/to/layout.css';
getChildrenNodes(this) {
return [
v(`ul`, { classes: { [ layout.flexContainer ]: true, ...this.theme.tabPanelTabs } }, [
v('li', { classes: { [ layout.flexItem ]: true, ...this.theme.tabPanelTab } }, [ 'tab1' ]),
// ....
])
]
}
In a situation where it is desirable to mix these styles into the tabPanel css such that they can be changed via a theme or overrideClass, rather than applying separate classes, css-module
compose
function could be used instead. ie.
// tabpanel.css
.tabPanelTabs {
composes: flex-container from 'path/to/layout.css';
}
.tabPanelTab {
composes: flex-item from 'path/to/layout.css';
}
@Tomdye but how do you pass the layout to the widget
? Layout is something that happens to your top level widget node (usually), as in something higher in the tree, tells you how you should be layed out. I can see your solution can layout children by importing the classes and applying, but most often, you will have to reference a property passed to you, at least for getNode
in your widget, and possibly when applying layout classes to children.
So for the outer class, ie. laying out the widget rather than laying out it's children, the parent of the widget would require in the layout.css
module and apply the correct classes at creation time.
This would apply to any classes the widget user wishes to apply to the widgets outer class.
// main.ts
import * as layout from 'path/to/layout.css';
import createTabPanel from 'path/to/tabpanel';
// ...
w(createTabPanel, { classes: {
[ layout.flexItem ]: true,
[ layout.pull-right ]: true
} });
This outstanding issue blocks the above: https://github.com/dojo/widgets/issues/221
I'd much rather not have to use props for layout. I guess the use case in my head when I thought you needed them was something like:
you have a grid of items, where at the last render cycle, there were 3 items per row. the user deletes one of the items the remaining 2 items should now take up the remaining width, e.g. the items width goes from 33.3333% to 50% between render cycles.
But you are right, you could just inspect how many items there are in getChildrenNodes
of the parent and apply the correct layout class.
Its almost too easy 🤔
Ok but I think that kind of scenario is an edge case and would be addressed by a flex layout anyway which would not need to know about how many items there were etc... If not, it would likely be handled by inline styles within the widget logic itself.
OK, I've changed to title. We should implement @tomdye 's solution and provide a simple layout.css
file that can be imported and used with the themeing system.
Throwing this back because it looks like this is getting in the way,
How about http://typestyle.io/#/ ?
What I liked the most in dojo1 was the Semantic theme which can be found here: http://websemantics.github.io/semantic-dojo/
I already recommended semantic ui and now I am working on semantic ui components for dojo2 similar to https://react.semantic-ui.com/introduction
Issue moved to dojo/widgets #337 via ZenHub
@rishson commented on Mon Jan 16 2017
We need to consider what layout mechanisms we want to support in Dojo 2. We should consider
css-grid
support,flexbox
support etc. We need to decide if we recommend 3rd party grid solutions, write our own, provide advice only...@matt-gadd commented on Wed Jan 18 2017
@rishson I think this issue should be moved to
dojo/meta
.@bitpshr commented on Fri Jan 20 2017
Thinking out loud, all our widgets are still rendered as DOM. Users can always write their own CSS to lay widgets out however they want. What would Dojo 2 provide as a framework to facilitate this? We should probably avoid anything resembling
dojo/layout
.