CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lit-html

HTML templates literals in JavaScript that enable efficient, expressive HTML templating with incremental DOM updates

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

built-in-directives.mddocs/

Built-in Directives

Comprehensive collection of directives for common templating patterns including conditional rendering, lists, styling, and performance optimization.

Capabilities

Conditional Rendering Directives

when Directive

Conditionally renders content based on a boolean condition with lazy evaluation.

/**
 * When `condition` is true, returns the result of calling `trueCase()`, else
 * returns the result of calling `falseCase()` if `falseCase` is defined.
 * @param condition - Condition to evaluate (any value)
 * @param trueCase - Function called when condition is truthy
 * @param falseCase - Optional function called when condition is falsy
 * @returns Result of the appropriate template function
 */
function when<C, T, F = undefined>(
  condition: C,
  trueCase: (c: Exclude<C, Falsy>) => T,
  falseCase?: (c: Extract<C, Falsy>) => F
): C extends Falsy ? F : T;

type Falsy = null | undefined | false | 0 | -0 | 0n | '';

Usage Examples:

import { html } from 'lit-html';
import { when } from 'lit-html/directives/when.js';

const userStatus = (isLoggedIn: boolean, username?: string) => html`
  <div>
    ${when(
      isLoggedIn,
      () => html`<span>Welcome, ${username}!</span>`,
      () => html`<a href="/login">Please log in</a>`
    )}
  </div>
`;

choose Directive

Selects and renders one template from multiple options based on a key value.

/**
 * Chooses and renders one of many template functions based on a given value.
 * @param value - The value to switch on
 * @param cases - Array of [key, template] pairs to choose from
 * @param defaultCase - Optional default template function
 * @returns Result of the matching template function
 */
function choose<T, V>(
  value: T,
  cases: Array<[T, () => V]>,
  defaultCase?: () => V
): V | typeof nothing;

Usage Examples:

import { html } from 'lit-html';
import { choose } from 'lit-html/directives/choose.js';

// Switch on string values
const statusDisplay = (status: string) => html`
  <div class="status">
    ${choose(status, [
      ['loading', () => html`<span class="spinner">Loading...</span>`],
      ['success', () => html`<span class="check">✓ Complete</span>`],
      ['error', () => html`<span class="error">✗ Failed</span>`],
    ], () => html`<span>Unknown status</span>`)}
  </div>
`;

// Switch on number values
const priorityBadge = (priority: number) => html`
  ${choose(priority, [
    [1, () => html`<span class="badge high">High</span>`],
    [2, () => html`<span class="badge medium">Medium</span>`],
    [3, () => html`<span class="badge low">Low</span>`],
  ])}
`;

// Without default case
const iconTemplate = (iconType: 'home' | 'user' | 'settings') => html`
  ${choose(iconType, [
    ['home', () => html`<svg><!-- home icon --></svg>`],
    ['user', () => html`<svg><!-- user icon --></svg>`],
    ['settings', () => html`<svg><!-- settings icon --></svg>`],
  ])}
`;

ifDefined Directive

Only renders an attribute if the value is not null or undefined.

/**
 * For AttributeParts, sets the attribute if the value is defined and removes
 * the attribute if the value is undefined.
 * @param value - Value to check and potentially set
 * @returns The value or nothing if undefined
 */
function ifDefined(value: unknown): unknown;

Usage Examples:

import { html } from 'lit-html';
import { ifDefined } from 'lit-html/directives/if-defined.js';

const link = (href?: string, title?: string) => html`
  <a href="${ifDefined(href)}" title="${ifDefined(title)}">
    Link text
  </a>
`;

until Directive

Renders placeholder content until a promise resolves, then renders the resolved value.

/**
 * Renders one of a series of values, including Promises, to a Part.
 * Values are rendered in priority order, with the first argument having the
 * highest priority and the last argument having the lowest priority.
 * @param values - Values to render in priority order
 * @returns DirectiveResult for rendering
 */
function until(...values: unknown[]): DirectiveResult;

Usage Examples:

import { html } from 'lit-html';
import { until } from 'lit-html/directives/until.js';

const asyncContent = html`
  <div>
    ${until(
      fetch('/api/data').then(r => r.json()).then(data => html`<pre>${JSON.stringify(data, null, 2)}</pre>`),
      html`<div class="spinner">Loading...</div>`
    )}
  </div>
`;

List Rendering Directives

repeat Directive

Efficiently renders lists with identity-based updates for optimal performance.

/**
 * A directive that repeats a series of values (usually templates) generated
 * from an iterable, and updates those items efficiently when the iterable changes.
 * @param items - The iterable to iterate over
 * @param keyFnOrTemplate - Either a key function or the template function
 * @param template - The template function (if keyFnOrTemplate is a key function)
 * @returns DirectiveResult for rendering the list
 */
function repeat<T>(
  items: Iterable<T>,
  keyFnOrTemplate: KeyFn<T> | ItemTemplate<T>,
  template?: ItemTemplate<T>
): DirectiveResult;

type KeyFn<T> = (item: T, index: number) => unknown;
type ItemTemplate<T> = (item: T, index: number) => unknown;

Usage Examples:

import { html } from 'lit-html';
import { repeat } from 'lit-html/directives/repeat.js';

// Simple list without keys
const simpleList = (items: string[]) => html`
  <ul>
    ${repeat(items, (item) => html`<li>${item}</li>`)}
  </ul>
`;

// List with keys for efficient updates
const userList = (users: User[]) => html`
  <ul>
    ${repeat(
      users,
      (user) => user.id, // Key function
      (user, index) => html`
        <li class="user">
          <span>${user.name}</span>
          <span>#${index + 1}</span>
        </li>
      `
    )}
  </ul>
`;

map Directive

Transforms an iterable using a template function, similar to Array.map().

/**
 * Maps an iterable using a template function.
 * @param items - The iterable to map over
 * @param template - Function that returns a template for each item
 * @returns DirectiveResult for rendering the mapped items
 */
function map<T>(
  items: Iterable<T>,
  template: (item: T, index: number) => unknown
): DirectiveResult;

join Directive

Joins rendered items with a separator template.

/**
 * Joins an array of templates with a separator template.
 * @param items - Array of templates to join
 * @param joiner - Separator template to insert between items
 * @returns DirectiveResult for rendering the joined content
 */
function join<I, J>(
  items: Iterable<I>,
  joiner: (index: number) => J
): DirectiveResult;

range Directive

Renders a range of numbers using a template function.

/**
 * Renders a range of integers from startAt to endAt (exclusive).
 * @param startAt - Starting number (inclusive)
 * @param endAt - Ending number (exclusive)
 * @param template - Function to render each number
 * @returns DirectiveResult for rendering the range
 */
function range<T>(
  startAt: number,
  endAt: number,
  template: (item: number, index: number) => T
): DirectiveResult;

Styling Directives

classMap Directive

Applies dynamic CSS classes based on an object of class names and boolean values.

/**
 * A directive that applies dynamic CSS classes.
 * @param classInfo - Object mapping class names to boolean values
 * @returns DirectiveResult for applying classes
 */
function classMap(classInfo: ClassInfo): DirectiveResult;

interface ClassInfo {
  readonly [name: string]: string | boolean | number;
}

Usage Examples:

import { html } from 'lit-html';
import { classMap } from 'lit-html/directives/class-map.js';

const button = (isPrimary: boolean, isDisabled: boolean) => html`
  <button class=${classMap({
    'btn': true,
    'btn-primary': isPrimary,
    'btn-secondary': !isPrimary,
    'disabled': isDisabled
  })}>
    Click me
  </button>
`;

styleMap Directive

Applies dynamic inline styles based on an object of CSS properties and values.

/**
 * A directive that applies CSS properties to an element.
 * @param styleInfo - Object mapping CSS properties to values
 * @returns DirectiveResult for applying styles
 */
function styleMap(styleInfo: StyleInfo): DirectiveResult;

interface StyleInfo {
  readonly [name: string]: string | number | undefined | null;
}

Usage Examples:

import { html } from 'lit-html';
import { styleMap } from 'lit-html/directives/style-map.js';

const coloredBox = (color: string, size: number) => html`
  <div style=${styleMap({
    backgroundColor: color,
    width: `${size}px`,
    height: `${size}px`,
    borderRadius: '4px'
  })}>
    Colored box
  </div>
`;

Performance and Caching Directives

cache Directive

Caches rendered templates by key for efficient switching between different templates.

/**
 * Enables fast switching between multiple templates by caching the DOM they render.
 * @param value - Key to cache the template by
 * @returns DirectiveResult for caching
 */
function cache(value: unknown): DirectiveResult;

guard Directive

Only re-renders when dependencies change, providing performance optimization.

/**
 * Prevents re-evaluation of a template function until one or more of its dependencies changes.
 * @param dependencies - Values to check for changes
 * @param valueFn - Function that returns the template when dependencies change
 * @returns Result of valueFn or cached result
 */
function guard(dependencies: unknown[], valueFn: () => unknown): unknown;

keyed Directive

Associates a template with a key for efficient updates when the key changes.

/**
 * Associates a renderable value with a unique key. When the key changes, the
 * previous DOM is removed and a new DOM is rendered in its place.
 * @param key - Unique key for the template
 * @param value - Value to render
 * @returns DirectiveResult for keyed rendering
 */
function keyed(key: unknown, value: unknown): DirectiveResult;

live Directive

Sets properties or attributes only when they differ from the live DOM value.

/**
 * Checks binding values against live DOM values, instead of previously bound
 * values, when determining whether to update the value.
 * @param value - Value to bind
 * @returns DirectiveResult for live binding
 */
function live(value: unknown): DirectiveResult;

Async Rendering Directives

asyncAppend Directive

Appends values from an async iterable as they become available.

/**
 * Renders values from an async iterable, appending each new value after the previous.
 * @param asyncIterable - The async iterable to render from
 * @param mapper - Optional function to transform each value
 * @returns DirectiveResult for async appending
 */
function asyncAppend<T>(
  asyncIterable: AsyncIterable<T>,
  mapper?: (value: T, index: number) => unknown
): DirectiveResult;

asyncReplace Directive

Replaces content with values from an async iterable as they become available.

/**
 * Renders values from an async iterable, replacing the previous value with each new value.
 * @param asyncIterable - The async iterable to render from
 * @param mapper - Optional function to transform each value
 * @returns DirectiveResult for async replacement
 */
function asyncReplace<T>(
  asyncIterable: AsyncIterable<T>,
  mapper?: (value: T, index: number) => unknown
): DirectiveResult;

DOM Manipulation Directives

ref Directive

Provides a reference to a rendered element for direct DOM manipulation.

/**
 * Sets the value of a Ref object or calls a ref callback with the element it's bound to.
 * @param refOrCallback - Ref object or callback function
 * @returns DirectiveResult for ref binding
 */
function ref(refOrCallback: Ref | RefCallback): DirectiveResult;

type RefCallback = (el: Element | undefined) => void;

interface Ref<T = Element> {
  readonly value: T | undefined;
}

function createRef<T = Element>(): Ref<T>;

Usage Examples:

import { html, render } from 'lit-html';
import { ref, createRef } from 'lit-html/directives/ref.js';

const myRef = createRef<HTMLInputElement>();

const template = html`
  <input ${ref(myRef)} type="text" />
  <button @click=${() => myRef.value?.focus()}>Focus Input</button>
`;

templateContent Directive

Renders the content of a template element.

/**
 * Renders the content of a template element as HTML.
 * @param templateElement - The template element to render
 * @returns DirectiveResult for rendering template content
 */
function templateContent(templateElement: HTMLTemplateElement): DirectiveResult;

Unsafe Content Directives

Security Warning: These directives render raw content and can introduce XSS vulnerabilities if used with untrusted input.

unsafeHTML Directive

Renders raw HTML content without escaping.

/**
 * Renders the result as HTML, rather than text.
 * @param value - HTML string to render (must be trusted)
 * @returns DirectiveResult for rendering HTML
 */
function unsafeHTML(value: string | typeof nothing | typeof noChange): DirectiveResult;

unsafeSVG Directive

Renders raw SVG content without escaping.

/**
 * Renders the result as SVG, rather than text.
 * @param value - SVG string to render (must be trusted)
 * @returns DirectiveResult for rendering SVG
 */
function unsafeSVG(value: string | typeof nothing | typeof noChange): DirectiveResult;

unsafeMathML Directive

Renders raw MathML content without escaping.

/**
 * Renders the result as MathML, rather than text.
 * @param value - MathML string to render (must be trusted)
 * @returns DirectiveResult for rendering MathML
 */
function unsafeMathML(value: string | typeof nothing | typeof noChange): DirectiveResult;

Import Patterns

All directives are imported from individual modules:

// Individual directive imports
import { repeat } from 'lit-html/directives/repeat.js';
import { classMap } from 'lit-html/directives/class-map.js';
import { styleMap } from 'lit-html/directives/style-map.js';
import { when } from 'lit-html/directives/when.js';
import { until } from 'lit-html/directives/until.js';
import { guard } from 'lit-html/directives/guard.js';
import { ref, createRef } from 'lit-html/directives/ref.js';

// Use in templates
const template = html`
  <div class=${classMap(classes)} style=${styleMap(styles)}>
    ${repeat(items, (item) => item.id, (item) => html`<span>${item.name}</span>`)}
  </div>
`;

docs

built-in-directives.md

core-templates.md

custom-directives.md

index.md

static-templates.md

tile.json