Skip to content

Commit

Permalink
Mediaquery in grid card.
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasloven committed Mar 14, 2021
1 parent 7c775a1 commit 14bcca0
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 16 deletions.
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ All column based layouts accept the following options:
|`max_cols` | number | Maximum number of columns to show | 4 if sidebar is hidden <br> 3 if sidebar is shown |
|`rtl`| `true`/`false` | Place columns in right-to-left order | `false`|

> NOTE: If you're migrating from layout-card "1.0" (v16 - sorry about the version number confusion), this is significantly fewer options than you are used to. \
> The reason for this is twofold. \
> First: Maintainability. As Home Assistant and Lovelace evolves, it grows increasingly more difficult to keep up the more options you want to keep alive. \
> Second: Usability. I want to focus on fewer options and doing the right thing out of the box instead. And the three remaining options actually have much more impact than you'd think.
>
> If you want more fine-grained controll (e.g. variable sized columns), please take a look at the Grid layout.

### Masonry layout

The masonry layout immitates the default layout of lovelace.
Expand Down Expand Up @@ -161,22 +168,33 @@ The vertical layout accepts the following **card** layout options:
The grid layout will give you full controll of your cards by leveraging [CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/).

The grid layout accepts any option starting with `grid-` that works for a Grid Container.
The grid layout also accepts any card layout option starting with `grid-` that works for a Grid Item.

![Grid Layout](https://user-images.githubusercontent.com/1299821/111069100-cac3f700-84cb-11eb-904f-cb5661c5734b.png)
Furthermore, the special option `mediaquery` can be used to set grid options depending on currently matched [@media rules](https://www.w3schools.com/cssref/css3_pr_mediaquery.asp). This helps immensely in creating fully responsive layouts. \
Please see the example code accompanying the screen recording below.

For the card layout options. the grid layout accepts any css grid property starting with `grid-` that works for a Grid Item.

![Grid Layout](https://user-images.githubusercontent.com/1299821/111082577-4d1edc00-8509-11eb-80d1-2ecbdea7a085.gif)
<details>
<summary>Screenshot source code</summary>
<summary>Yaml code</summary>

```yaml
title: Grid layout
type: custom:grid-layout
layout:
grid-template-columns: 25% 25% 25% 25%
grid-template-columns: 25% 1fr 50px 25%
grid-template-rows: auto
grid-template-areas: |
"header header header header"
"main main . sidebar"
"footer footer footer footer"
mediaquery:
"(max-width: 600px)":
grid-template-columns: 50% 50%
grid-template-areas: |
"header sidebar"
"main main"
"footer footer"
cards:
- type: entities
entities:
Expand Down
15 changes: 8 additions & 7 deletions layout-card.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "layout-card",
"version": "2.0.0",
"version": "2.1.0",
"description": "",
"private": true,
"scripts": {
Expand Down
37 changes: 33 additions & 4 deletions src/layouts/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import {
CardConfig,
CardConfigGroup,
LovelaceCard,
ViewConfig,
GridViewConfig,
} from "../types";
import { BaseLayout } from "./base-layout";

class GridLayout extends BaseLayout {
_mediaQueries: Array<MediaQueryList | null> = [];
_layoutMQs: Array<MediaQueryList | null> = [];
_config: GridViewConfig;

async setConfig(config: ViewConfig) {
async setConfig(config: GridViewConfig) {
await super.setConfig(config);

for (const card of this._config.cards) {
Expand All @@ -25,6 +27,16 @@ class GridLayout extends BaseLayout {
this._mediaQueries.push(null);
}
}

if (this._config.layout.mediaquery) {
for (const [query, layout] of Object.entries(
this._config.layout?.mediaquery
)) {
const mq = window.matchMedia(query);
this._layoutMQs.push(mq);
mq.addEventListener("change", () => this._setGridStyles());
}
}
}

async updated(changedProperties) {
Expand All @@ -35,12 +47,28 @@ class GridLayout extends BaseLayout {
}

async firstUpdated() {
this._setGridStyles();
}

_setGridStyles() {
const root = this.shadowRoot.querySelector("#root") as HTMLElement;
if (this._config.layout)
for (const [key, value] of Object.entries(this._config.layout)) {
const addStyles = (layout) => {
for (const [key, value] of Object.entries(layout)) {
if (key.startsWith("grid"))
root.style.setProperty(key, (value as any) as string);
}
};

root.style.cssText = "";

if (this._config.layout) addStyles(this._config.layout);

for (const q of this._layoutMQs) {
if (q.matches) {
addStyles(this._config.layout.mediaquery[q.media]);
break;
}
}
}

_shouldShow(card: LovelaceCard, config: CardConfig, index: number) {
Expand Down Expand Up @@ -91,6 +119,7 @@ class GridLayout extends BaseLayout {
display: grid;
margin-left: 4px;
margin-right: 4px;
justify-content: center;
}
#root > * {
margin: var(--masonry-view-card-margin, 4px 4px 8px);
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ export interface ColumnViewConfig extends ViewConfig {
};
}

export interface GridViewConfig extends ViewConfig {
layout?: {
mediaquery?: Array<Record<string, any>>;
};
}

export interface LayoutCardConfig {
cards?: Array<CardConfig>;
entities?: Array<CardConfig>;
Expand Down

0 comments on commit 14bcca0

Please sign in to comment.