new view type: grid
jonschlinkert opened this issue · comments
@doowb and I had an interesting conversation a couple of days ago, as a result we're considering adding a fourth view type: grid
, for handling grid systems.
(This is only a partially-formed idea. it's really interesting but is not yet "planned". Feedback welcome)
Synopsis
Whereas "view collections" are used for organizing and caching views, "view types" determine how the individual views in a collection will be handled during the render cycle. For example, views with the partial
view type will be merged onto the context before being passed to the template engine for rendering, but views with the layout
and renderable
types will not.
View types
This library currently supports three view types: partial
, renderable
and layout
. Passed on the viewType
option when a collection is created, collections may have one or more view types, defaulting to renderable
if no other types are defined.
partial
: allows "partial views" to be injected into other views. useful for components, document fragments, or other snippets of reusable code or content.layout
: allows views to "wrap" other views (of any type, including other layouts or partials) with common code or content.renderable
: views that have a one-to-one relationship with rendered files that will eventually be visible to a user or visitor to a website. For example: pages or blog posts.
Proposed
The grid
view type would combine concepts from the partial
and layout
types to allow users to pre-define complex page layout systems, whilst also keeping a separation of concerns between structure and content.
In practice, this means that grids themselves would be defined using a declarative configuration, the markup (rows and columns) of the grid would be entirely composed of user-defined views (templates), and the content that will eventually populate the individual "cells" of the grid can also be defined using a declarative configuration - allowing them to be modified on-the-fly during the build cycle (e.g. just as you can easily change the layout
of a view using middleware, you could also customize the cells of a grid on a page-by-page, or collection-by-collection, or task-by-task basis).
The concept
This is totally pseudo-code, but hopefully you will get the idea and be able to give feedback.
Grids will be created like any other views.
app.create('foo', {viewType: 'grid'});
Once created, you would add grid
views with app.foo()
(like other custom collections). We would add support for two special properties unique to grids (we're open to suggestions on the property names):
schema
: an object, for defining the actual grid system using columns, rows, and even other (nested) grids.structure
: an object that provides a semantic "mapping" between the grid-schema-object, and css-based grid "positions" that can be specified by other views (in other words, this would allow you to add a partial to the "banner" position on a grid, instead ofrow2.col1-col4
or whatever).
app.foo('magazine', {
// main content here, along with a "grid" tag defining where the actual grid will be injected
content: '<div>{% grid %}</div>',
// grids can also use layouts, like any other view type
layout: 'main',
// rows and columns in the schema would define the "grid positions", as well as
// the context for those individual "cells"
schema: {
row1: {
// like layouts, the templates in "cells" would be resolved before injecting content
content: '{% row %}',
col1: {
content: '{% col %}',
}
},
row2: {
col1: {
content: '{% col %}',
}
},
row3: {
// nested grid
grid: 'baz',
}
},
structure: {
nav: 'row1.col1',
banner: 'row2.col1',
main: 'row3.grid.row2.co2'
}
});
Then, renderable
views (like pages, posts etc) can specify a grid to use, along with with content to populate the cells. For example:
app.page('whatever', {
content: 'this is some content...',
layout: 'default',
grid: {
name: 'magazine',
structure: {
nav: {
data: {span: 12},
content: '<div class="nav">...</div>'
},
banner: {
data: {span: 12},
content: '<div class="banner">...</div>'
},
main: {
data: {span: 6}
content: 'some content or partials or whatever for the `main` cell on the `magazine` grid'
}
}
}
});