Code Style - Elements
Consult the library guides for general rules
This document is a supplement, not a replacement, for the basic usage guides:
Don't name the classes
Rather, use a _
as a placeholder:
@customElement('circle-button')
export class _ extends LitElement {
//...
}
The exception to this is when defining a base class for the sake of inheritance (discussed below in Global styles)
Be explicit with variants
Example - a property "color" should not be defined as a string, rather it should be defined as an enum or string variants:
export type Color = "red" | "blue" | "green";
@property()
color: Color = "red";
No null values
In the example above, it could have instead be written as:
@property()
color: "red" | "blue" | "green" | null = null;
This is bad. There should always be a sane non-null value.
Favor a declarative code style
Some tips:
- There is almost never a need for a
var
orlet
, everything should beconst
. - Instead of switch+return, use conditionals (a.k.a. ternaries) or a predefined lookup
- Create pure functions instead of class methods (i.e. in
render()
, callrenderFooter(args)
instead ofthis.renderFooter()
) - Split things out into small functions as needed
When conditionals get long, use the following style:
cond1 ? option1
: cond2 ? option2
: cond3 ? option3
: default
Use nothing
When interpolating the template literals, it's often required to render "nothing". Instead of null
or ""
, lit-html exports a special nothing
object for this use case. Use that instead, since it will also prevent other bugs.
See lit-html docs for details.
Don't hardcode data in the render function
Static data should be moved out of the render function and defined as a const
with an all-caps variable name.
For displayable strings, we will eventually have a more complex localization solution, but for now - use the STR_
prefix in order to facilitate string replacement / localization later
Example:
const STR_HOWDY = "hello world";
@customElement('my-element')
export class _ extends LitElement {
render() {
return html`<div>${STR_HOWDY}</div>`;
}
}
Dynamic styles
lit-element and lit-html provide some helpers like classMap
and styleMap
to make some of the code around dynamic styling cleaner.
At the end of the day, you're just returning html. Both classes and inline styles can be changed at runtime based on properties.
Reusable styles
There are a few approaches to reusable static styles: css vars, inheritance, interpolation, and mixins.
Reusable styles - CSS Vars
CSS Vars pierce down through the shadow dom, and can be used by any nested child anywhere.
It's a great way to define global themes, or, more generally, for a child element to declare which of its styles can be overridden by an ancestor
Reusable styles - Inheritance
This approach is handy when there's a clear hierarchy of global styles for particular kinds of elements, but not others.
Example:
_in styles/text.ts
export class BaseText extends LitElement {
static get styles() {
//Note that it's an array even with only one entry
//This is required to keep the consistent ...super.styles in the subclass
return [css`
.bold{
font-weight: 600;
}
`]
}
}
anywhere
import {BaseText} from "@elements/_styles/text";
@customElement('my-element')
export class _ extends BaseText {
static get styles() {
return [...super.styles, css`
:host {
width: 100px;
}
`]
}
render() {
//...
}
}
Reusable styles - Mixins
Mixins are more flexible than inheritance, but can also be harder to reason about and decide what should/should not be included.
Example:
_in styles/colors.ts
import { css} from 'lit-element';
export const colorTheme = css`
.red { rgba(161,168,173,255) }
.blue { rgba(85,144,252,255) }
`;
anywhere
import {colorTheme} from "@elements/_styles/colors";
@customElement('circle-button')
export class _ extends LitElement {
static get styles() {
return [colorTheme, css`
.foo {
border-style: solid;
border-width: 1px;
border-color: ${colorValues.grey};
}
`]
}
render() {
//...
}
}
Of course, they are just JS objects, so they can be grouped into their own arrays and mixed in like:
//cssThemes is an array of css objects
static get styles() {
return [...cssThemes, css`
.foo {
border-style: solid;
border-width: 1px;
border-color: ${colorValues.grey};
}
`]
}
Reusable styles - Interpolation
The static CSS getter cannot be interpolated at runtime with dynamic values, but it can be interpolated with static css
literals
Example:
_in styles/colors.ts
import { css} from 'lit-element';
export const colorValues = {
grey: css`rgba(161,168,173,255)`,
blue: css`rgba(85,144,252,255)`
}
anywhere
import {colorValues} from "@elements/_styles/colors";
@customElement('circle-button')
export class _ extends LitElement {
static get styles() {
return [css`
.foo {
border-style: solid;
border-width: 1px;
border-color: ${colorValues.grey};
}
`]
}
render() {
//...
}
}