import { css, html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { tailwind } from '../styles/tailwind.js';
/**
* A counter button — small on purpose, but it demonstrates the four things
* almost every Lit component needs: a reactive property, scoped styles, a
* custom event, and a slot.
*
* @fires count-changed - Dispatched when the count changes. `detail.count`
* carries the new value.
* @slot - Label rendered inside the button.
* @csspart button - The underlying button element, styleable from outside.
*/
@customElement('counter-button')
export class CounterButton extends LitElement {
/**
* Tailwind first, then the rules utilities cannot express. Later sheets win,
* so the handwritten block stays last.
*/
static override styles = [
tailwind,
css`
/* The host element itself, which no utility class can target. */
:host {
display: inline-block;
}
button {
/*
* Form controls do not inherit the page font. Tailwind's preflight
* normally fixes that, but preflight is document-level and is not
* adopted into shadow roots, so components repeat the one line here.
*/
font: inherit;
}
`,
];
/**
* Current count. Declared with `@property` (not `@state`) so it is part of
* the public API and can be set from markup as `count="3"`.
*/
@property({ type: Number, reflect: true })
count = 0;
/** How much each click adds. */
@property({ type: Number, attribute: 'step-by' })
stepBy = 1;
override render() {
return html`
`;
}
// Private class field syntax keeps the method off the public API surface.
#increment = (): void => {
this.count += this.stepBy;
// `composed: true` is required for the event to escape the shadow root.
this.dispatchEvent(
new CustomEvent<{ count: number }>('count-changed', {
detail: { count: this.count },
bubbles: true,
composed: true,
}),
);
};
}
declare global {
interface HTMLElementTagNameMap {
'counter-button': CounterButton;
}
}