appreciated/grid-layout

Allow setting multiple values (f.e. for grid-template-areas) by using media queries

jflamy opened this issue · 5 comments

In order to create responsive grids, it would be nice to be able to set responsive steps as is possible with form layouts (https://vaadin.com/components/vaadin-form-layout/java-examples)
Since it is not possible to add @media selectors inline (directly on the element), a possible workaround would be to create a separate DOM style object and use it to hold the various css and variants for the grid as suggested in the second answer to https://stackoverflow.com/questions/9808233/is-it-possible-to-put-css-media-rules-inline
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style

@jflamy can you give a more graphical example of what you are trying to archive?

Have you tried the demo?. Since there already are responsive grids. What is it you need that is different from the repeat(AUTO_FIT / AUTO_FILL ...)

Example: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Realizing_common_layouts_using_CSS_Grid_Layout

I understand that these things are probably easier done using a Polymer or Lit-Html template. But until a few weeks ago, I was "Java-only" and would have been able to use your extension, but not able to create a web component comfortably.

Vaadin Flow itself does not allow setting media queries from the server-side. But there would be the possibility to add this feature by using this addon.

The API of this Addon should support this out of the box.

I added an code example that solves your issue. But I think this Addon should provide an even better support than that since it is very verbose.

Component header = getDiv();
Component left = getDiv();
Component right = getDiv();
Component content = getDiv();

FluentGridLayout mediaGridLayout = new FluentGridLayout()
        .withTemplateAreas(new TemplateAreas[]{
                new TemplateAreas("header", "header", "header", "header", "header"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right")
        })
        .withItem(header).withArea(header, new TemplateArea("header"))
        .withItem(left).withArea(left, new TemplateArea("left"))
        .withItem(right).withArea(right, new TemplateArea("right"))
        .withItem(content).withArea(content, new TemplateArea("content"));
mediaGridLayout.setWidth("100%");
mediaGridLayout.setHeight("600px");

CustomMediaQuery customMediaQuery800 = new CustomMediaQuery(visible -> {
    if (visible) {
        mediaGridLayout.setTemplateAreas(new TemplateAreas[]{
                new TemplateAreas("header", "header", "header", "header", "header"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right")
        });
    }
}, "(min-width: 800px)");
CustomMediaQuery customMediaQuerySmaller = new CustomMediaQuery(visible -> {
    if (visible) {
        mediaGridLayout.setTemplateAreas(new TemplateAreas[]{
                new TemplateAreas("header"),
                new TemplateAreas("left"),
                new TemplateAreas("content"),
                new TemplateAreas("right")
        });
    }
}, "(max-width: 800px)");

I though of an API extension with the following declaration GridLayout::setTemplateAreas(TemplateAreas[] templateAreas, String query) would be quite convenient. Which would allow to write something as this:

Component header = getDiv();
Component left = getDiv();
Component right = getDiv();
Component content = getDiv();

FluentGridLayout mediaGridLayout = new FluentGridLayout()
        .withTemplateAreas(new TemplateAreas[]{
                new TemplateAreas("header"),
                new TemplateAreas("left"),
                new TemplateAreas("content"),
                new TemplateAreas("right")
        }, "(max-width: 800px)")
        .withTemplateAreas(new TemplateAreas[]{
                new TemplateAreas("header", "header", "header", "header", "header"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right")
        },"(min-width: 800px)")
        .withItem(header).withArea(header, new TemplateArea("header"))
        .withItem(left).withArea(left, new TemplateArea("left"))
        .withItem(right).withArea(right, new TemplateArea("right"))
        .withItem(content).withArea(content, new TemplateArea("content"));
mediaGridLayout.setWidth("100%");
mediaGridLayout.setHeight("600px");

Note: Instead of writing "(max-width: 800px)" I would provide a proper API.

@jflamy What do you think about this?

Component header = getDiv();
Component left = getDiv();
Component right = getDiv();
Component content = getDiv();

FluentGridLayout mediaGridLayout = new FluentGridLayout()
        .withTemplateAreas(new MediaQuery(new MaxWidth("800px")),
                new TemplateAreas("header"),
                new TemplateAreas("left"),
                new TemplateAreas("content"),
                new TemplateAreas("right"))
        .withTemplateAreas(new MediaQuery(new MinWidth("800px")),
                new TemplateAreas("header", "header", "header", "header", "header"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right"),
                new TemplateAreas("left", "content", "content", "content", "right"))
        .withItem(header).withArea(header, new TemplateArea("header"))
        .withItem(left).withArea(left, new TemplateArea("left"))
        .withItem(right).withArea(right, new TemplateArea("right"))
        .withItem(content).withArea(content, new TemplateArea("content"));
mediaGridLayout.setWidth("100%");
mediaGridLayout.setHeight("600px");