or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-configuration.mdcompiler-api.mdcomponent-development.mddevelopment-server.mdindex.mdruntime-utilities.mdtesting-utilities.md

component-development.mddocs/

0

# Component Development

1

2

Core decorators and utilities for creating web components with TypeScript and JSX. Stencil provides a comprehensive decorator-based component authoring system with full TypeScript support.

3

4

## Capabilities

5

6

### Component Decorator

7

8

The main decorator for defining a web component class with configuration options.

9

10

```typescript { .api }

11

/**

12

* The @Component() decorator is used to provide metadata about the component class

13

* @param opts - Component configuration options

14

* @returns Class decorator

15

*/

16

function Component(opts: ComponentOptions): ClassDecorator;

17

18

interface ComponentOptions {

19

/** Tag name of the web component. Must contain a '-' */

20

tag: string;

21

/** Relative URL to external stylesheet file */

22

styleUrl?: string;

23

/** Array of stylesheets or mode-specific stylesheets */

24

styleUrls?: string[] | ModeStyles;

25

/** Inline CSS styles */

26

styles?: string | { [modeName: string]: any };

27

/** Use native shadow DOM encapsulation */

28

shadow?: boolean | ShadowRootOptions;

29

/** Use scoped stylesheets without native shadow DOM */

30

scoped?: boolean;

31

/** Array of relative paths to asset directories */

32

assetsDirs?: string[];

33

/** Enable form-associated component behavior */

34

formAssociated?: boolean;

35

}

36

37

interface ShadowRootOptions {

38

/** Mitigate custom element focusability issues */

39

delegatesFocus?: boolean;

40

}

41

42

interface ModeStyles {

43

[modeName: string]: string | string[];

44

}

45

```

46

47

**Usage Example:**

48

49

```typescript

50

@Component({

51

tag: 'my-button',

52

styleUrl: 'my-button.css',

53

shadow: true,

54

})

55

export class MyButton {

56

// Component implementation

57

}

58

```

59

60

### Property Decorators

61

62

Decorators for defining component properties, state, and element references.

63

64

```typescript { .api }

65

/**

66

* The @Prop() decorator defines component properties/attributes

67

* @param opts - Property configuration options

68

* @returns Property decorator

69

*/

70

function Prop(opts?: PropOptions): PropertyDecorator;

71

72

interface PropOptions {

73

/** Custom attribute name override */

74

attribute?: string | null;

75

/** Allow internal mutation of the prop */

76

mutable?: boolean;

77

/** Reflect property changes to attribute */

78

reflect?: boolean;

79

}

80

81

/**

82

* The @State() decorator manages internal component state

83

* @returns Property decorator

84

*/

85

function State(): PropertyDecorator;

86

87

/**

88

* The @Element() decorator provides reference to the host element

89

* @returns Property decorator

90

*/

91

function Element(): PropertyDecorator;

92

93

/**

94

* The @AttachInternals() decorator provides access to ElementInternals

95

* for form-associated components

96

* @returns Property decorator

97

*/

98

function AttachInternals(): PropertyDecorator;

99

```

100

101

**Usage Examples:**

102

103

```typescript

104

export class MyComponent {

105

@Prop() name: string;

106

@Prop({ reflect: true }) active: boolean;

107

@State() private count: number = 0;

108

@Element() el: HTMLElement;

109

@AttachInternals() internals: ElementInternals;

110

}

111

```

112

113

### Method Decorators

114

115

Decorators for exposing public methods and watching property changes.

116

117

```typescript { .api }

118

/**

119

* The @Method() decorator exposes methods on the public API

120

* @param opts - Method configuration options

121

* @returns Method decorator

122

*/

123

function Method(opts?: MethodOptions): MethodDecorator;

124

125

interface MethodOptions {}

126

127

/**

128

* The @Watch() decorator watches for property changes

129

* @param propName - Name of the property to watch

130

* @returns Method decorator

131

*/

132

function Watch(propName: string): MethodDecorator;

133

```

134

135

**Usage Examples:**

136

137

```typescript

138

export class MyComponent {

139

@Prop() value: string;

140

141

@Method()

142

async reset(): Promise<void> {

143

this.value = '';

144

}

145

146

@Watch('value')

147

valueChanged(newValue: string, oldValue: string) {

148

console.log('Value changed:', oldValue, '->', newValue);

149

}

150

}

151

```

152

153

### Event System

154

155

Decorators and utilities for creating and listening to custom events.

156

157

```typescript { .api }

158

/**

159

* The @Event() decorator creates custom DOM events

160

* @param opts - Event configuration options

161

* @returns Property decorator

162

*/

163

function Event(opts?: EventOptions): PropertyDecorator;

164

165

interface EventOptions {

166

/** Custom event name override */

167

eventName?: string;

168

/** Whether the event bubbles up through the DOM */

169

bubbles?: boolean;

170

/** Whether the event is cancelable */

171

cancelable?: boolean;

172

/** Whether the event can bubble across shadow DOM boundary */

173

composed?: boolean;

174

}

175

176

/**

177

* The @Listen() decorator listens to DOM events

178

* @param eventName - Name of the event to listen to

179

* @param opts - Listener configuration options

180

* @returns Method decorator

181

*/

182

function Listen(eventName: string, opts?: ListenOptions): MethodDecorator;

183

184

interface ListenOptions {

185

/** Where to attach the event listener */

186

target?: ListenTargetOptions;

187

/** Use capturing phase */

188

capture?: boolean;

189

/** Use passive event listener */

190

passive?: boolean;

191

}

192

193

type ListenTargetOptions = 'body' | 'document' | 'window';

194

195

interface EventEmitter<T = any> {

196

emit: (data?: T) => CustomEvent<T>;

197

}

198

```

199

200

**Usage Examples:**

201

202

```typescript

203

export class MyComponent {

204

@Event() myCustomEvent: EventEmitter<string>;

205

@Event({ bubbles: false }) myPrivateEvent: EventEmitter<number>;

206

207

@Listen('click')

208

handleClick(event: MouseEvent) {

209

this.myCustomEvent.emit('Button clicked!');

210

}

211

212

@Listen('resize', { target: 'window' })

213

handleResize(event: Event) {

214

console.log('Window resized');

215

}

216

}

217

```

218

219

### JSX and Rendering

220

221

Functions and utilities for JSX templating and virtual DOM creation.

222

223

```typescript { .api }

224

/**

225

* JSX pragma function for creating virtual DOM nodes

226

* @param sel - Element selector or component

227

* @param data - Element attributes and properties

228

* @param children - Child elements

229

* @returns Virtual DOM node

230

*/

231

function h(sel: any): VNode;

232

function h(sel: Node, data: VNodeData | null): VNode;

233

function h(sel: any, data: VNodeData | null): VNode;

234

function h(sel: any, text: string): VNode;

235

function h(sel: any, children: Array<VNode | undefined | null>): VNode;

236

function h(sel: any, data: VNodeData | null, text: string): VNode;

237

function h(sel: any, data: VNodeData | null, children: Array<VNode | undefined | null>): VNode;

238

function h(sel: any, data: VNodeData | null, children: VNode): VNode;

239

240

/**

241

* Host functional component for setting attributes on the host element

242

*/

243

declare const Host: FunctionalComponent<HostAttributes>;

244

245

interface HostAttributes {

246

class?: string | { [className: string]: boolean };

247

style?: { [key: string]: string | undefined };

248

ref?: (el: HTMLElement | null) => void;

249

[prop: string]: any;

250

}

251

252

/**

253

* Fragment functional component for multiple children without wrapper

254

*/

255

declare const Fragment: FunctionalComponent<{}>;

256

257

/**

258

* Render virtual DOM tree to a container element

259

* @param vnode - Virtual DOM tree to render

260

* @param container - Container element to render into

261

*/

262

function render(vnode: VNode, container: Element): void;

263

```

264

265

**Usage Examples:**

266

267

```typescript

268

export class MyComponent {

269

@Prop() items: string[];

270

271

render() {

272

return (

273

<Host class="my-component">

274

<div class="header">

275

<h1>My Component</h1>

276

</div>

277

<div class="content">

278

{this.items.map(item => (

279

<div class="item" key={item}>

280

{item}

281

</div>

282

))}

283

</div>

284

</Host>

285

);

286

}

287

}

288

289

// Using Fragment

290

render() {

291

return (

292

<Fragment>

293

<div>First child</div>

294

<div>Second child</div>

295

</Fragment>

296

);

297

}

298

```

299

300

### Lifecycle Hooks

301

302

Component lifecycle interfaces for handling component state changes.

303

304

```typescript { .api }

305

interface ComponentWillLoad {

306

/**

307

* Called once before the component's first render

308

*/

309

componentWillLoad(): Promise<void> | void;

310

}

311

312

interface ComponentDidLoad {

313

/**

314

* Called once after the component's first render

315

*/

316

componentDidLoad(): void;

317

}

318

319

interface ComponentWillUpdate {

320

/**

321

* Called before each render (except the first)

322

*/

323

componentWillUpdate(): Promise<void> | void;

324

}

325

326

interface ComponentDidUpdate {

327

/**

328

* Called after each render (except the first)

329

*/

330

componentDidUpdate(): void;

331

}

332

333

interface ComponentInterface {

334

connectedCallback?(): void;

335

disconnectedCallback?(): void;

336

componentWillLoad?(): Promise<void> | void;

337

componentDidLoad?(): void;

338

componentWillUpdate?(): Promise<void> | void;

339

componentDidUpdate?(): void;

340

componentWillRender?(): Promise<void> | void;

341

componentDidRender?(): void;

342

componentShouldUpdate?(newVal: any, oldVal: any, propName: string): boolean | void;

343

render?(): any;

344

}

345

```

346

347

**Usage Example:**

348

349

```typescript

350

export class MyComponent implements ComponentInterface {

351

@State() private data: any[] = [];

352

353

async componentWillLoad() {

354

// Load data before first render

355

this.data = await fetchData();

356

}

357

358

componentDidLoad() {

359

// Component is ready, set up event listeners

360

console.log('Component loaded');

361

}

362

363

componentShouldUpdate(newVal: any, oldVal: any, propName: string): boolean {

364

// Control when component should update

365

return newVal !== oldVal;

366

}

367

368

render() {

369

return <div>{this.data.length} items loaded</div>;

370

}

371

}

372

```

373

374

### Functional Components

375

376

Support for functional components with utilities for working with children.

377

378

```typescript { .api }

379

interface FunctionalComponent<T = {}> {

380

(props: T, children: VNode[], utils: FunctionalUtilities): VNode | VNode[];

381

}

382

383

interface FunctionalUtilities {

384

/**

385

* Iterate over children with a callback

386

*/

387

forEach: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => void) => void;

388

/**

389

* Transform children and return new array

390

*/

391

map: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => ChildNode) => VNode[];

392

}

393

394

interface ChildNode {

395

vtag?: string | number | Function;

396

vkey?: string | number;

397

vtext?: string;

398

vchildren?: VNode[];

399

vattrs?: any;

400

vname?: string;

401

}

402

```

403

404

**Usage Example:**

405

406

```typescript

407

export const AddClass: FunctionalComponent = (_, children, utils) => (

408

utils.map(children, child => ({

409

...child,

410

vattrs: {

411

...child.vattrs,

412

class: `${child.vattrs.class} add-class`

413

}

414

}))

415

);

416

417

// Usage in JSX

418

render() {

419

return (

420

<AddClass>

421

<div>This will have 'add-class' added</div>

422

</AddClass>

423

);

424

}

425

```