[lion-button] How to apply class names when extending #1158
-
Assuming there will be users migrating to Lion from a (React/Vue/Angular) design system, it's likely that users will already have CSS and a class name convention. E.g. .acme-button {}
.acme-button--primary { background: blue; }
.acme-button--secondary { background: white; } So when creating a new Most examples of styling I've seen suggest using the I'm looking specifically at the As suggested here it's beneficial to extend the base class rather than render a In effect I want to merge my custom CSS class names with other attributes from export default class AcmeButton extends LionButton {
constructor() {
super();
this.type = "primary";
}
static get properties() {
return {
type: { type: String },
};
}
static get styles() {
return [
super.styles,
css`
.acme-button {
...
}
.acme-button--primary {
...
}
`,
];
}
// how to render with custom class names, is something like this possible?
_buttonTemplate() {
return html`<button class=${classMap({ 'acme-button': true, [`acme-button--${this.type}`]: true })}></button>`
}
}
customElements.define("acme-button", AcmeButton); Update: Noticed this potential solution from Material Design Web Components which might actually work for a number of scenarios like this. A protected method on the base class which returns classes to be applied to the element. Anything extending can then override or merge with the base classes. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
With LionButton and also other Lion fields that wrap native fields, it is a little bit special indeed. This is because we spawn the native The usual way would be to just override the styles: static get styles() {
return [
super.styles,
css`
:host {
background-color: blue;
}
`,
];
} But as you mentioned, it requires you to pull the CSS rules out of your CSS blocks and paste them into :host selector in your extension. The other option is indeed to adjust the template to have the classes applied to them, so you can just copy the ready-made CSS entirely. static get styles() {
return [
super.styles,
css`
.acme-button--primary {
background: blue;
}
/** etc. */
`,
];
} render() {
return html`
${this._beforeTemplate()}
<div class="button-content acme-button--primary" id="${this._buttonId}"><slot></slot></div>
${this._afterTemplate()}
<slot name="_button"></slot>
`;
} Although for your use case I suppose it will be a little different, since the styling applies to the host element, so you need the class added on the host: constructor() {
super();
this.classList.add('acme-button--primary');
} Which in some ways is simpler.. and you could potentially do something like that to your rendered content as well in the The example from MWC is pretty neat, because it allows you to easily add in your own classes without overriding the template, because you have this class map hook in your component. The problem is that you need such a method for every DOM element in your templates if you want this approach usable everywhere, and you'd also still face the problem that you can't apply this to the host element itself. So I think extending & overriding is still unavoidable. I get the concerns about breaking changes. If Lion changes something fundamental about the Extending and overriding may seem scary but it is the main use case for Lion. Methods, props, templates, that are not prefixed with a double |
Beta Was this translation helpful? Give feedback.
With LionButton and also other Lion fields that wrap native fields, it is a little bit special indeed. This is because we spawn the native
<button>
or native<input>
in case of LionInput for example, inside the LightDOM. This is for accessibility reasons, because the field has to be in the same DOM as the label. For button, it's mostly for supporting (native) form submission.The usual way would be to just override the styles:
But as you mentioned, it requires you to pull the CSS rules out of your CSS blocks and paste them into :host selector in your extension.
T…