Skip to main content
Version: v5 (Preview)

Component Decorator

@Component() is a decorator that designates a TypeScript class as a Stencil component. Every Stencil component gets transformed into a web component at build time.

import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
// additional options
})
export class TodoList {
// implementation omitted
}

Component Options​

The @Component() decorator takes one argument, an object literal containing configuration options for the component. This allows each component to be individually configured to suit the unique needs of each project.

Each option, its type, and whether it's required is described below.

tag​

Required

Type: string

Details:
This value sets the name of the custom element that Stencil will generate. To adhere to the HTML spec, the tag name must contain a dash ('-').

Ideally, the tag name is a globally unique value. Having a globally unique value helps prevent naming collisions with the global CustomElementsRegistry, where all custom elements are defined. It's recommended to choose a unique prefix for all your components within the same collection.

Example:

import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
})
export class TodoList {
// implementation omitted
}

After compilation, the component defined in TodoList can be used in HTML or another TSX file:

<!-- Here we use the component in an HTML file -->
<todo-list></todo-list>
{/* Here we use the component in a TSX file */}
<todo-list></todo-list>

assetsDirs​

Optional

Type: string[]

Details:
assetsDirs is an array of relative paths from the component to a directory containing the static files (assets) the component requires.

Example:
Below is an example project's directory structure containing an example component and assets directory.

src/
└── components/
├── assets/
│ └── sunset.jpg
└── todo-list.tsx

Below, the todo-list component will correctly load the sunset.jpg image from the assets/ directory, using Stencil's getAssetPath().

import { Component, Prop, getAssetPath } from '@stencil/core';

@Component({
tag: 'todo-list',
// 1. assetsDirs lists the 'assets' directory as a relative (sibling)
// directory
assetsDirs: ['assets']
})
export class TodoList {
image = "sunset.jpg";

render() {
// 2. the asset path is retrieved relative to the asset base path to use in
// the <img> tag
const imageSrc = getAssetPath(`./assets/${this.image}`);
return <img src={imageSrc} />
}
}

In the example above, the following allows todo-list to display the provided asset:

  1. The TodoList's @Component() decorator has the assetsDirs property, and lists the file's sibling directory, assets/. This will copy the assets directory over to the distribution directory.
  2. Stencil's getAssetPath() is used to retrieve the path to the image to be used in the <img> tag

For more information on configuring assets, please see Stencil's Assets Guide

encapsulation​

Optional

Type:

type Encapsulation =
| {
type: 'shadow';
mode?: 'open' | 'closed';
delegatesFocus?: boolean;
slotAssignment?: 'manual' | 'named';
clonable?: boolean;
serializable?: boolean;
}
| { type: 'scoped'; patches?: ('all' | 'children' | 'clone' | 'insert')[] }
| { type: 'none'; patches?: ('all' | 'children' | 'clone' | 'insert')[] };

Default: { type: 'none' }

Details:
encapsulation controls how a component's styles and DOM are isolated from the rest of the page. Stencil supports three encapsulation types:

  • shadow: uses the browser's native Shadow DOM. Styles and internal markup are fully isolated from the rest of the page.
  • scoped: uses scoped CSS. Stencil generates a unique class for your styles so they don't leak out, but the component's DOM stays in the light DOM and light-DOM styles can still leak in.
  • none (default): no style encapsulation. The component's markup and styles behave like any other element on the page.

See Component Archetypes for when to use each.

Shadow DOM options (type: 'shadow'):

  • mode: 'open' (default) or 'closed'. A closed shadow root can't be reached from element.shadowRoot outside the component.
  • delegatesFocus: provides focus to the first focusable element inside the component when a non-focusable part is clicked.
  • slotAssignment: 'manual' enables manual slot assignment (otherwise known as imperative slot assignment); 'named' is the default DOM slotting behavior.
  • clonable: preserves the shadow root when the host is deep-cloned via Node.cloneNode(true). Without it, cloning a shadow host produces an empty shell.
  • serializable: marks the shadow root serializable, so it's included when the host is serialized via Element.getHTML({ serializableShadowRoots: true }).

Scoped/none options (type: 'scoped' or type: 'none'):

  • patches: which light-DOM slot patches Stencil applies to this component ('all', 'children', 'clone', 'insert'). Overrides the project-wide compat.lightDomPatches config setting for this component specifically.

Examples:

import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
encapsulation: { type: 'shadow' },
})
export class TodoList {
// implementation omitted
}
Closed shadow root with delegated focus
@Component({
tag: 'todo-list',
encapsulation: { type: 'shadow', mode: 'closed', delegatesFocus: true },
})
export class TodoList {
// implementation omitted
}
Scoped CSS
@Component({
tag: 'todo-list',
encapsulation: { type: 'scoped' },
})
export class TodoList {
// implementation omitted
}
note

Migrating from Stencil v4? shadow: true becomes encapsulation: { type: 'shadow' }, scoped: true becomes encapsulation: { type: 'scoped' }, and no encapsulation option becomes encapsulation: { type: 'none' } (or omit the property — 'none' is the default). formAssociated: true is gone too — see the @AttachInternals() decorator, which sets it automatically. Run stencil migrate --dry-run to preview the automatic migration.

styleUrl​

Optional

Type: string

Details:
Relative URL to an external stylesheet containing styles to apply to your component. Out of the box, Stencil will only process CSS files (files ending with .css). Support for additional CSS variants, like Sass, can be added via a plugin.

Example:
Below is an example project's directory structure containing an example component and stylesheet.

src/
└── components/
├── todo-list.css
└── todo-list.tsx

By setting styleUrl, Stencil will apply the todo-list.css stylesheet to the todo-list component:

import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
styleUrl: './todo-list.css',
})
export class TodoList {
// implementation omitted
}

styleUrls​

Optional

Type: string[] | { [modeName: string]: string | string[]; }

Details:
A list of relative URLs to external stylesheets containing styles to apply to your component.

Alternatively, an object can be provided that maps a named "mode" to one or more stylesheets.

Out of the box, Stencil will only process CSS files (ending with .css). Support for additional CSS variants, like Sass, can be added via a plugin.

Example:
Below is an example project's directory structure containing an example component and stylesheet.

src/
└── components/
├── todo-list-1.css
├── todo-list-2.css
└── todo-list.tsx

By setting styleUrls, Stencil will apply both stylesheets to the todo-list component:

Using an array of styles
import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
styleUrls: ['./todo-list-1.css', './todo-list-2.css']
})
export class TodoList {
// implementation omitted
}
Using modes
import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
styleUrls: {
ios: 'todo-list-1.ios.scss',
md: 'todo-list-2.md.scss',
}
})
export class TodoList {
// implementation omitted
}

Read more on styling modes in the Components Styling section.

styles​

Optional

Type: string | { [modeName: string]: any }

Details:
A string that contains inlined CSS instead of using an external stylesheet. The performance characteristics of this feature are the same as using an external stylesheet.

When using styles, only CSS is permitted. See styleUrl if you need more advanced features.

Example:

import { Component } from '@stencil/core';

@Component({
tag: 'todo-list',
styles: 'div { background-color: #fff }'
})
export class TodoList {
// implementation omitted
}

Embedding or Nesting Components​

Components can be composed easily by adding the HTML tag to the JSX code. Since the components are just HTML tags, nothing needs to be imported to use a Stencil component within another Stencil component.

Here's an example of using a component within another component:

import { Component, Prop } from '@stencil/core';

@Component({
tag: 'my-embedded-component'
})
export class MyEmbeddedComponent {
@Prop() color: string = 'blue';

render() {
return (
<div>My favorite color is {this.color}</div>
);
}
}
import { Component } from '@stencil/core';

@Component({
tag: 'my-parent-component'
})
export class MyParentComponent {

render() {
return (
<div>
<my-embedded-component color="red"></my-embedded-component>
</div>
);
}
}

The my-parent-component includes a reference to the my-embedded-component in the render() function.

Component Architecture Patterns​

Stencil supports advanced component architecture patterns including class inheritance and composition. Learn more about organizing component logic with controllers in the Mixins & Reactive Controllers guide.