Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/components/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Once all the metadata has been collected, all the decorators are removed from th
- [@Listen()](./events.md#listen-decorator) listens for DOM events
- [@AttrDeserialize()](./serialization-deserialization.md#the-attrdeserialize-decorator-attrdeserialize) declares a hook to translate a component's attribute string to its JS property
- [@PropSerialize()](./serialization-deserialization.md#the-propserialize-decorator-propserialize) declares a hook that translates a component's JS property to its attribute string
- [@AttachInternals()](./attach-internals.md) attaches ElementInternals to a component


## Lifecycle hooks
Expand Down
68 changes: 68 additions & 0 deletions docs/components/attach-internals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: Attach Internals
sidebar_label: Attach Internals
description: attach internals decorator
slug: /attach-internals
---

# Attach Internals Decorator

The `@AttachInternals` decorator is used to attach [ElementInternals](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals) to a Stencil component.
This allows you to leverage features such as [Custom States](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet) and [Form Association](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals#form_association).

## Form Association

Read the dedicated guide on [Form Associated Components](./form-associated.md) and how to use `@AttachInternals` there.

## Custom States

You can use the `@AttachInternals` decorator to define [Custom States](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet) for your component.

```tsx
import { Component, h, AttachInternals } from '@stencil/core';
/**
* My Element component
*/
@Component({
tag: 'my-element',
styleUrl: 'my-element.css',
})
export class MyElement {
@AttachInternals({
states: {
/** A custom state for my element */
'my-custom-state': true,
/** Another custom state for my element */
'another-state': false
}
}) internals: ElementInternals;
render() {
return <div>My Element</div>;
}
}
```

In the example above, we define two custom states: `my-custom-state` and `another-state`.

The initial values of the custom states can be set via the `states` object and
later on, you can update the states dynamically using the `internals.states` property. For example:

```tsx
handleClick() {
this.internals.states.add('another-state'); // to add a state
this.internals.states.delete('my-custom-state'); // to remove a state
}
```

You or your element users can then use custom states in CSS like so:

```css
/* Use them internally... */
:host(:state(my-custom-state)) {
background-color: yellow;
}
/* ... Or use them externally */
my-element:state(another-state) {
border: 2px solid red;
}
```
17 changes: 17 additions & 0 deletions docs/components/templating-and-jsx.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,23 @@ export class AppHome {

In this example we are using `ref` to get a reference to our input `ref={(el) => this.textInput = el as HTMLInputElement}`. We can then use that ref to do things such as grab the value from the text input directly `this.textInput.value`.

## Explicitly setting attributes or properties

By default, Stencil tries to intelligently determine whether to set an attribute or (more commonly) a property on an element when using JSX.
However, in some cases you may want to explicitly set one or the other. You can do this by using the `attr:` or `prop:` prefixes. For example:

```tsx
<input attr:value="Hello" />
```

will set the `value` attribute on the input element, while:

```tsx
<input prop:value="Hello" />
```

will explicitly set the `value` property on the input element.


## Avoid Shared JSX Nodes

Expand Down
1 change: 1 addition & 0 deletions docs/documentation-generation/01-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ slug: /doc-generation

- [`docs-readme`: Documentation readme files formatted in markdown](./docs-readme.md)
- [`docs-json`: Documentation data formatted in JSON](./docs-json.md)
- [`docs-custom-elements-manifest`: Custom Elements Manifest (CEM) format](./docs-custom-elements-manifest.md)
- [`docs-custom`: Custom documentation generation](./docs-custom.md)
- [`docs-vscode`: Documentation generation for VS Code](./docs-vscode.md)
- [`stats`: Stats about the compiled files](./docs-stats.md)
Expand Down
213 changes: 213 additions & 0 deletions docs/documentation-generation/docs-custom-elements-manifest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
---
title: Docs Custom Elements Manifest Output Target
sidebar_label: CEM (docs-custom-elements-manifest)
description: Custom Elements Manifest
slug: /docs-custom-elements-manifest
---

# Generating Documentation in Custom Elements Manifest (CEM) format

Since Stencil v4.42, Stencil supports automatically generating a [Custom Elements Manifest (CEM)](https://custom-elements-manifest.open-wc.org/)
file in your project. The CEM format is a standardized JSON format for describing
custom elements and is supported by a variety of tools in the web components ecosystem.


```tsx title="stencil.config.ts"
import { Config } from '@stencil/core';

export const config: Config = {
outputTargets: [
{
type: 'docs-custom-elements-manifest',
file: 'path/to/cem.json'
}
]
};
```

The JSON file output by Stencil conforms to the [CEM Schema interface](https://github.com/webcomponents/custom-elements-manifest/blob/main/schema.d.ts).

## Properties, Methods, Events, and Attributes

The CEM output target includes information about your components' properties,
methods, events, and attributes based on the decorators you use in your Stencil
components.

## CSS Properties

Stencil can document CSS variables if you annotate them with JSDoc-style
comments in your CSS/SCSS files. If, for instance, you had a component with a
CSS file like the following:

```css title="src/components/my-button/my-button.css"
:host {
/**
* @prop --background: Background of the button
* @prop --background-activated: Background of the button when activated
* @prop --background-focused: Background of the button when focused
*/
--background: pink;
--background-activated: aqua;
--background-focused: fuchsia;
}
```

Then you'd get the following in the JSON output:

```json title="Example docs-custom-elements-manifest Output"
[
{
"cssProperties": [
{
"name": "background",
"description": "Background of the button"
},
{
"name": "background-activated",
"description": "Background of the button when activated"
},
{
"name": "background-focused",
"description": "Background of the button when focused"
}
]
}
]
```

## Slots and CSS Parts

If one of your Stencil components makes use of
[slots](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) for
rendering children or [CSS Parts](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) for styling,
you can document them by using the `@slot` and `@part` JSDoc tags in the
component's comments.

For instance, if you had a `my-button` component with a slot you might document
it like so:

```tsx title="src/components/my-button/my-button.tsx"
import { Component, h } from '@stencil/core';

/**
* @slot buttonContent - Slot for the content of the button
*
* @part button - The button element
*/
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true,
})
export class MyButton {
render() {
return <button part="button"><slot name="buttonContent"></slot></button>
}
}
```

This would show up in the generated JSON file like so:

```json
"slots": [
{
"name": "buttonContent",
"description": "Slot for the content of the button"
}
],
"cssParts": [
{
"name": "button",
"description": "The button element"
}
]
```

:::caution
Stencil does not check that the slots you document in a component's JSDoc
comment using the `@slot` tag are actually present in the JSX returned by the
component's `render` function.

It is up to you as the component author to ensure the `@slot` tags on a
component are kept up to date.
:::

## Custom States

You can document [Custom States](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet) for your components using the `@AttachInternals` decorator
and JSDoc comments.

For example:

```tsx title="src/components/my-element/my-element.tsx"
import { Component, h, AttachInternals } from '@stencil/core';
/**
* My Element component
*/
@Component({
tag: 'my-element',
styleUrl: 'my-element.css',
shadow: true,
})
export class MyElement {
@AttachInternals({
states: {
new: true,
/** If this item is older than 6 months old. Use via `:state(archived)` */
archived: false
},
}) internals!: ElementInternals;
```

This would show up in the generated JSON file like so:

```json
"customStates": [
{
"name": "new",
"description": ""
},
{
"name": "archived",
"description": "If this item is older than 6 months old. Use via `:state(archived)"
}
]
```

## Demos

You can save demos for a component in the `usage/` subdirectory within
that component's directory. The content of these files will be added to the
`demos` property of the generated JSON. This allows you to keep examples right
next to the code, making it easy to include them in a documentation site or
other downstream consumer(s) of your docs.

:::caution
Stencil doesn't check that your demos are up-to-date! If you make any
changes to your component's API you'll need to remember to update your demos
manually.
:::

If, for instance, you had a usage example like this:

````md title="src/components/my-button/usage/my-button-usage.md"
# How to use `my-button`

A button is often a great help in adding interactivity to an app!

You could use it like this:

```html
<my-button>My Button!</my-button>
```
````


You'd get the following in the JSON output under the `"usage"` key:

```json
"demos": [{
"url": "my-button-usage.md",
"description": "# How to use `my-button`\n\nA button is often a great help in adding interactivity to an app!\n\nYou could use it like this:\n\n```html\n<my-button>My Button!</my-button>\n```\n"
}]
```
4 changes: 2 additions & 2 deletions docs/documentation-generation/docs-custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ The generated docs JSON data will in the type of `JsonDocs` which consists of ma
| `events` | Array of metadata objects for each usage of the [`@Event` decorator](../components/events.md#event-decorator) on the current component. |
| `listeners` | Array of metadata objects for each usage of the [`@Listen` decorator](../components/events.md#listen-decorator) on the current component. |
| `styles` | Array of objects documenting annotated [CSS variables](./docs-json.md#css-variables) used in the current component's CSS. |
| `slots` | Array of objects documenting [slots](./docs-json.md#slots) which are tagged with `@slot` in the current component's JSDoc comment. |
| `parts` | Array of objects derived from `@part` tags in the current component's JSDoc comment. |
| `slots` | Array of objects documenting [slots](./docs-json.md#slots-and-css-parts) which are tagged with `@slot` in the current component's JSDoc comment. |
| `parts` | Array of objects documenting [CSS Parts](./docs-json.md#slots-and-css-parts) which are derived from `@part` tags in the current component's JSDoc comment. |
| `dependents` | Array of components where current component is used |
| `dependencies` | Array of components which is used in current component |
| `dependencyGraph` | Describes a tree of components coupling |
Expand Down
Loading
Loading