or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

built-in-directives.mdcore-templates.mdcustom-directives.mdindex.mdstatic-templates.md
tile.json

built-in-directives.mddocs/

0

# Built-in Directives

1

2

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

3

4

## Capabilities

5

6

### Conditional Rendering Directives

7

8

#### when Directive

9

10

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

11

12

```typescript { .api }

13

/**

14

* When `condition` is true, returns the result of calling `trueCase()`, else

15

* returns the result of calling `falseCase()` if `falseCase` is defined.

16

* @param condition - Condition to evaluate (any value)

17

* @param trueCase - Function called when condition is truthy

18

* @param falseCase - Optional function called when condition is falsy

19

* @returns Result of the appropriate template function

20

*/

21

function when<C, T, F = undefined>(

22

condition: C,

23

trueCase: (c: Exclude<C, Falsy>) => T,

24

falseCase?: (c: Extract<C, Falsy>) => F

25

): C extends Falsy ? F : T;

26

27

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

28

```

29

30

**Usage Examples:**

31

32

```typescript

33

import { html } from 'lit-html';

34

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

35

36

const userStatus = (isLoggedIn: boolean, username?: string) => html`

37

<div>

38

${when(

39

isLoggedIn,

40

() => html`<span>Welcome, ${username}!</span>`,

41

() => html`<a href="/login">Please log in</a>`

42

)}

43

</div>

44

`;

45

```

46

47

#### choose Directive

48

49

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

50

51

```typescript { .api }

52

/**

53

* Chooses and renders one of many template functions based on a given value.

54

* @param value - The value to switch on

55

* @param cases - Array of [key, template] pairs to choose from

56

* @param defaultCase - Optional default template function

57

* @returns Result of the matching template function

58

*/

59

function choose<T, V>(

60

value: T,

61

cases: Array<[T, () => V]>,

62

defaultCase?: () => V

63

): V | typeof nothing;

64

```

65

66

**Usage Examples:**

67

68

```typescript

69

import { html } from 'lit-html';

70

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

71

72

// Switch on string values

73

const statusDisplay = (status: string) => html`

74

<div class="status">

75

${choose(status, [

76

['loading', () => html`<span class="spinner">Loading...</span>`],

77

['success', () => html`<span class="check">✓ Complete</span>`],

78

['error', () => html`<span class="error">✗ Failed</span>`],

79

], () => html`<span>Unknown status</span>`)}

80

</div>

81

`;

82

83

// Switch on number values

84

const priorityBadge = (priority: number) => html`

85

${choose(priority, [

86

[1, () => html`<span class="badge high">High</span>`],

87

[2, () => html`<span class="badge medium">Medium</span>`],

88

[3, () => html`<span class="badge low">Low</span>`],

89

])}

90

`;

91

92

// Without default case

93

const iconTemplate = (iconType: 'home' | 'user' | 'settings') => html`

94

${choose(iconType, [

95

['home', () => html`<svg><!-- home icon --></svg>`],

96

['user', () => html`<svg><!-- user icon --></svg>`],

97

['settings', () => html`<svg><!-- settings icon --></svg>`],

98

])}

99

`;

100

```

101

102

#### ifDefined Directive

103

104

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

105

106

```typescript { .api }

107

/**

108

* For AttributeParts, sets the attribute if the value is defined and removes

109

* the attribute if the value is undefined.

110

* @param value - Value to check and potentially set

111

* @returns The value or nothing if undefined

112

*/

113

function ifDefined(value: unknown): unknown;

114

```

115

116

**Usage Examples:**

117

118

```typescript

119

import { html } from 'lit-html';

120

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

121

122

const link = (href?: string, title?: string) => html`

123

<a href="${ifDefined(href)}" title="${ifDefined(title)}">

124

Link text

125

</a>

126

`;

127

```

128

129

#### until Directive

130

131

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

132

133

```typescript { .api }

134

/**

135

* Renders one of a series of values, including Promises, to a Part.

136

* Values are rendered in priority order, with the first argument having the

137

* highest priority and the last argument having the lowest priority.

138

* @param values - Values to render in priority order

139

* @returns DirectiveResult for rendering

140

*/

141

function until(...values: unknown[]): DirectiveResult;

142

```

143

144

**Usage Examples:**

145

146

```typescript

147

import { html } from 'lit-html';

148

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

149

150

const asyncContent = html`

151

<div>

152

${until(

153

fetch('/api/data').then(r => r.json()).then(data => html`<pre>${JSON.stringify(data, null, 2)}</pre>`),

154

html`<div class="spinner">Loading...</div>`

155

)}

156

</div>

157

`;

158

```

159

160

### List Rendering Directives

161

162

#### repeat Directive

163

164

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

165

166

```typescript { .api }

167

/**

168

* A directive that repeats a series of values (usually templates) generated

169

* from an iterable, and updates those items efficiently when the iterable changes.

170

* @param items - The iterable to iterate over

171

* @param keyFnOrTemplate - Either a key function or the template function

172

* @param template - The template function (if keyFnOrTemplate is a key function)

173

* @returns DirectiveResult for rendering the list

174

*/

175

function repeat<T>(

176

items: Iterable<T>,

177

keyFnOrTemplate: KeyFn<T> | ItemTemplate<T>,

178

template?: ItemTemplate<T>

179

): DirectiveResult;

180

181

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

182

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

183

```

184

185

**Usage Examples:**

186

187

```typescript

188

import { html } from 'lit-html';

189

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

190

191

// Simple list without keys

192

const simpleList = (items: string[]) => html`

193

<ul>

194

${repeat(items, (item) => html`<li>${item}</li>`)}

195

</ul>

196

`;

197

198

// List with keys for efficient updates

199

const userList = (users: User[]) => html`

200

<ul>

201

${repeat(

202

users,

203

(user) => user.id, // Key function

204

(user, index) => html`

205

<li class="user">

206

<span>${user.name}</span>

207

<span>#${index + 1}</span>

208

</li>

209

`

210

)}

211

</ul>

212

`;

213

```

214

215

#### map Directive

216

217

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

218

219

```typescript { .api }

220

/**

221

* Maps an iterable using a template function.

222

* @param items - The iterable to map over

223

* @param template - Function that returns a template for each item

224

* @returns DirectiveResult for rendering the mapped items

225

*/

226

function map<T>(

227

items: Iterable<T>,

228

template: (item: T, index: number) => unknown

229

): DirectiveResult;

230

```

231

232

#### join Directive

233

234

Joins rendered items with a separator template.

235

236

```typescript { .api }

237

/**

238

* Joins an array of templates with a separator template.

239

* @param items - Array of templates to join

240

* @param joiner - Separator template to insert between items

241

* @returns DirectiveResult for rendering the joined content

242

*/

243

function join<I, J>(

244

items: Iterable<I>,

245

joiner: (index: number) => J

246

): DirectiveResult;

247

```

248

249

#### range Directive

250

251

Renders a range of numbers using a template function.

252

253

```typescript { .api }

254

/**

255

* Renders a range of integers from startAt to endAt (exclusive).

256

* @param startAt - Starting number (inclusive)

257

* @param endAt - Ending number (exclusive)

258

* @param template - Function to render each number

259

* @returns DirectiveResult for rendering the range

260

*/

261

function range<T>(

262

startAt: number,

263

endAt: number,

264

template: (item: number, index: number) => T

265

): DirectiveResult;

266

```

267

268

### Styling Directives

269

270

#### classMap Directive

271

272

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

273

274

```typescript { .api }

275

/**

276

* A directive that applies dynamic CSS classes.

277

* @param classInfo - Object mapping class names to boolean values

278

* @returns DirectiveResult for applying classes

279

*/

280

function classMap(classInfo: ClassInfo): DirectiveResult;

281

282

interface ClassInfo {

283

readonly [name: string]: string | boolean | number;

284

}

285

```

286

287

**Usage Examples:**

288

289

```typescript

290

import { html } from 'lit-html';

291

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

292

293

const button = (isPrimary: boolean, isDisabled: boolean) => html`

294

<button class=${classMap({

295

'btn': true,

296

'btn-primary': isPrimary,

297

'btn-secondary': !isPrimary,

298

'disabled': isDisabled

299

})}>

300

Click me

301

</button>

302

`;

303

```

304

305

#### styleMap Directive

306

307

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

308

309

```typescript { .api }

310

/**

311

* A directive that applies CSS properties to an element.

312

* @param styleInfo - Object mapping CSS properties to values

313

* @returns DirectiveResult for applying styles

314

*/

315

function styleMap(styleInfo: StyleInfo): DirectiveResult;

316

317

interface StyleInfo {

318

readonly [name: string]: string | number | undefined | null;

319

}

320

```

321

322

**Usage Examples:**

323

324

```typescript

325

import { html } from 'lit-html';

326

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

327

328

const coloredBox = (color: string, size: number) => html`

329

<div style=${styleMap({

330

backgroundColor: color,

331

width: `${size}px`,

332

height: `${size}px`,

333

borderRadius: '4px'

334

})}>

335

Colored box

336

</div>

337

`;

338

```

339

340

### Performance and Caching Directives

341

342

#### cache Directive

343

344

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

345

346

```typescript { .api }

347

/**

348

* Enables fast switching between multiple templates by caching the DOM they render.

349

* @param value - Key to cache the template by

350

* @returns DirectiveResult for caching

351

*/

352

function cache(value: unknown): DirectiveResult;

353

```

354

355

#### guard Directive

356

357

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

358

359

```typescript { .api }

360

/**

361

* Prevents re-evaluation of a template function until one or more of its dependencies changes.

362

* @param dependencies - Values to check for changes

363

* @param valueFn - Function that returns the template when dependencies change

364

* @returns Result of valueFn or cached result

365

*/

366

function guard(dependencies: unknown[], valueFn: () => unknown): unknown;

367

```

368

369

#### keyed Directive

370

371

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

372

373

```typescript { .api }

374

/**

375

* Associates a renderable value with a unique key. When the key changes, the

376

* previous DOM is removed and a new DOM is rendered in its place.

377

* @param key - Unique key for the template

378

* @param value - Value to render

379

* @returns DirectiveResult for keyed rendering

380

*/

381

function keyed(key: unknown, value: unknown): DirectiveResult;

382

```

383

384

#### live Directive

385

386

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

387

388

```typescript { .api }

389

/**

390

* Checks binding values against live DOM values, instead of previously bound

391

* values, when determining whether to update the value.

392

* @param value - Value to bind

393

* @returns DirectiveResult for live binding

394

*/

395

function live(value: unknown): DirectiveResult;

396

```

397

398

### Async Rendering Directives

399

400

#### asyncAppend Directive

401

402

Appends values from an async iterable as they become available.

403

404

```typescript { .api }

405

/**

406

* Renders values from an async iterable, appending each new value after the previous.

407

* @param asyncIterable - The async iterable to render from

408

* @param mapper - Optional function to transform each value

409

* @returns DirectiveResult for async appending

410

*/

411

function asyncAppend<T>(

412

asyncIterable: AsyncIterable<T>,

413

mapper?: (value: T, index: number) => unknown

414

): DirectiveResult;

415

```

416

417

#### asyncReplace Directive

418

419

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

420

421

```typescript { .api }

422

/**

423

* Renders values from an async iterable, replacing the previous value with each new value.

424

* @param asyncIterable - The async iterable to render from

425

* @param mapper - Optional function to transform each value

426

* @returns DirectiveResult for async replacement

427

*/

428

function asyncReplace<T>(

429

asyncIterable: AsyncIterable<T>,

430

mapper?: (value: T, index: number) => unknown

431

): DirectiveResult;

432

```

433

434

### DOM Manipulation Directives

435

436

#### ref Directive

437

438

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

439

440

```typescript { .api }

441

/**

442

* Sets the value of a Ref object or calls a ref callback with the element it's bound to.

443

* @param refOrCallback - Ref object or callback function

444

* @returns DirectiveResult for ref binding

445

*/

446

function ref(refOrCallback: Ref | RefCallback): DirectiveResult;

447

448

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

449

450

interface Ref<T = Element> {

451

readonly value: T | undefined;

452

}

453

454

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

455

```

456

457

**Usage Examples:**

458

459

```typescript

460

import { html, render } from 'lit-html';

461

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

462

463

const myRef = createRef<HTMLInputElement>();

464

465

const template = html`

466

<input ${ref(myRef)} type="text" />

467

<button @click=${() => myRef.value?.focus()}>Focus Input</button>

468

`;

469

```

470

471

#### templateContent Directive

472

473

Renders the content of a template element.

474

475

```typescript { .api }

476

/**

477

* Renders the content of a template element as HTML.

478

* @param templateElement - The template element to render

479

* @returns DirectiveResult for rendering template content

480

*/

481

function templateContent(templateElement: HTMLTemplateElement): DirectiveResult;

482

```

483

484

### Unsafe Content Directives

485

486

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

487

488

#### unsafeHTML Directive

489

490

Renders raw HTML content without escaping.

491

492

```typescript { .api }

493

/**

494

* Renders the result as HTML, rather than text.

495

* @param value - HTML string to render (must be trusted)

496

* @returns DirectiveResult for rendering HTML

497

*/

498

function unsafeHTML(value: string | typeof nothing | typeof noChange): DirectiveResult;

499

```

500

501

#### unsafeSVG Directive

502

503

Renders raw SVG content without escaping.

504

505

```typescript { .api }

506

/**

507

* Renders the result as SVG, rather than text.

508

* @param value - SVG string to render (must be trusted)

509

* @returns DirectiveResult for rendering SVG

510

*/

511

function unsafeSVG(value: string | typeof nothing | typeof noChange): DirectiveResult;

512

```

513

514

#### unsafeMathML Directive

515

516

Renders raw MathML content without escaping.

517

518

```typescript { .api }

519

/**

520

* Renders the result as MathML, rather than text.

521

* @param value - MathML string to render (must be trusted)

522

* @returns DirectiveResult for rendering MathML

523

*/

524

function unsafeMathML(value: string | typeof nothing | typeof noChange): DirectiveResult;

525

```

526

527

## Import Patterns

528

529

All directives are imported from individual modules:

530

531

```typescript

532

// Individual directive imports

533

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

534

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

535

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

536

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

537

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

538

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

539

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

540

541

// Use in templates

542

const template = html`

543

<div class=${classMap(classes)} style=${styleMap(styles)}>

544

${repeat(items, (item) => item.id, (item) => html`<span>${item.name}</span>`)}

545

</div>

546

`;

547

```