Skip to content

Commit 717793e

Browse files
authored
refactor: Split preact-custom-element docs from general CEs (#1297)
1 parent 4e0dbb2 commit 717793e

3 files changed

Lines changed: 129 additions & 110 deletions

File tree

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
---
2+
title: preact-custom-element
3+
description: Wrap your Preact component up as a custom element
4+
---
5+
6+
# preact-custom-element
7+
8+
Preact's tiny size and standards-first approach make it a great choice for building web components.
9+
10+
Preact is designed to render both full applications and individual parts of a page, making it a natural fit for building Web Components. Many companies use this approach to build component or design systems that are then wrapped up into a set of Web Components, enabling re-use across multiple projects and within other frameworks whilst continuing to offer the familiar Preact APIs.
11+
12+
---
13+
14+
<toc></toc>
15+
16+
---
17+
18+
## Creating a Web Component
19+
20+
Any Preact component can be turned into a web component with [preact-custom-element](https://github.com/preactjs/preact-custom-element), a very thin wrapper that adheres to the Custom Elements v1 spec.
21+
22+
```jsx
23+
import register from 'preact-custom-element';
24+
25+
const Greeting = ({ name = 'World' }) => <p>Hello, {name}!</p>;
26+
27+
register(Greeting, 'x-greeting', ['name'], { shadow: false });
28+
// ^ ^ ^ ^
29+
// | HTML tag name | use shadow-dom
30+
// Component definition Observed attributes
31+
```
32+
33+
> Note: As per the [Custom Element Specification](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname), the tag name must contain a hyphen (`-`).
34+
35+
Use the new tag name in HTML, attribute keys and values will be passed in as props:
36+
37+
```html
38+
<x-greeting name="Billy Jo"></x-greeting>
39+
```
40+
41+
Output:
42+
43+
```html
44+
<p>Hello, Billy Jo!</p>
45+
```
46+
47+
### Observed Attributes
48+
49+
Web Components require explicitly listing the names of attributes you want to observe in order to respond when their values are changed. These can be specified via the third parameter that's passed to the `register()` function:
50+
51+
```jsx
52+
// Listen to changes to the `name` attribute
53+
register(Greeting, 'x-greeting', ['name']);
54+
```
55+
56+
If you omit the third parameter to `register()`, the list of attributes to observe can be specified using a static `observedAttributes` property on your Component. This also works for the Custom Element's name, which can be specified using a `tagName` static property:
57+
58+
```jsx
59+
import register from 'preact-custom-element';
60+
61+
// <x-greeting name="Bo"></x-greeting>
62+
class Greeting extends Component {
63+
// Register as <x-greeting>:
64+
static tagName = 'x-greeting';
65+
66+
// Track these attributes:
67+
static observedAttributes = ['name'];
68+
69+
render({ name }) {
70+
return <p>Hello, {name}!</p>;
71+
}
72+
}
73+
register(Greeting);
74+
```
75+
76+
If no `observedAttributes` are specified, they will be inferred from the keys of `propTypes` if present on the Component:
77+
78+
```jsx
79+
// Other option: use PropTypes:
80+
function FullName({ first, last }) {
81+
return (
82+
<span>
83+
{first} {last}
84+
</span>
85+
);
86+
}
87+
88+
FullName.propTypes = {
89+
first: Object, // you can use PropTypes, or this
90+
last: Object // trick to define un-typed props.
91+
};
92+
93+
register(FullName, 'full-name');
94+
```
95+
96+
### Passing slots as props
97+
98+
The `register()` function has a fourth parameter to pass options; currently, only the `shadow` option is supported, which attaches a shadow DOM tree to the specified element. When enabled, this allows the use of named `<slot>` elements to forward the Custom Element's children to specific places in the shadow tree.
99+
100+
```jsx
101+
function TextSection({ heading, content }) {
102+
return (
103+
<div>
104+
<h1>{heading}</h1>
105+
<p>{content}</p>
106+
</div>
107+
);
108+
}
109+
110+
register(TextSection, 'text-section', [], { shadow: true });
111+
```
112+
113+
Usage:
114+
115+
```html
116+
<text-section>
117+
<span slot="heading">Nice heading</span>
118+
<span slot="content">Great content</span>
119+
</text-section>
120+
```

content/en/guide/v10/web-components.md

Lines changed: 3 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@ description: How to use web components with Preact
55

66
# Web Components
77

8-
Preact's tiny size and standards-first approach make it a great choice for building web components.
8+
Web Components are a set of different technologies that allow you to create reusable, encapsulated custom HTML elements that are entirely framework-agnostic. Examples of Web Components include elements like `<material-card>` or `<tab-bar>`.
99

10-
Web Components are a set of standards that make it possible to build new HTML element types - Custom Elements like `<material-card>` or `<tab-bar>`.
11-
Preact [fully supports these standards](https://custom-elements-everywhere.com/#preact), allowing seamless use of Custom Element lifecycles, properties and events.
12-
13-
Preact is designed to render both full applications and individual parts of a page, making it a natural fit for building Web Components. Many companies use it to build component or design systems that are then wrapped up into a set of Web Components, enabling re-use across multiple projects and within other frameworks.
10+
As a platform primitive, Preact [fully supports Web Components](https://custom-elements-everywhere.com/#preact), allowing seamless use of Custom Element lifecycles, properties, and events in your Preact apps.
1411

1512
Preact and Web Components are complementary technologies: Web Components provide a set of low-level primitives for extending the browser, and Preact provides a high-level component model that can sit atop those primitives.
1613

@@ -56,7 +53,7 @@ function Foo() {
5653
}
5754
```
5855

59-
> **Note:** Preact makes no assumptions over naming schemes and will not attempt to coerce names, in JSX or otherwise, to DOM properties. If a custom element has a property name `someProperty`, it will need to be set using `someProperty=...` rather than `some-property=...`.
56+
> **Note:** Preact makes no assumptions over naming schemes and will not attempt to coerce names, in JSX or otherwise, to DOM properties. If a custom element has a property name `someProperty`, then it will need to be set using that exact same capitalization and spelling (`someProperty=...`). `someproperty=...` or `some-property=...` will not work.
6057
6158
When rendering static HTML using `preact-render-to-string` ("SSR"), complex property values like the object above are not automatically serialized. They are applied once the static HTML is hydrated on the client.
6259

@@ -92,107 +89,3 @@ Preact normalizes the casing of standard built-in DOM Events, which are normally
9289
// Corrected: listens for "tabchange" event (lower-case)
9390
<tab-bar ontabchange={() => console.log('tab change')} />
9491
```
95-
96-
## Creating a Web Component
97-
98-
Any Preact component can be turned into a web component with [preact-custom-element](https://github.com/preactjs/preact-custom-element), a very thin wrapper that adheres to the Custom Elements v1 spec.
99-
100-
```jsx
101-
import register from 'preact-custom-element';
102-
103-
const Greeting = ({ name = 'World' }) => <p>Hello, {name}!</p>;
104-
105-
register(Greeting, 'x-greeting', ['name'], { shadow: false });
106-
// ^ ^ ^ ^
107-
// | HTML tag name | use shadow-dom
108-
// Component definition Observed attributes
109-
```
110-
111-
> Note: As per the [Custom Element Specification](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname), the tag name must contain a hyphen (`-`).
112-
113-
Use the new tag name in HTML, attribute keys and values will be passed in as props:
114-
115-
```html
116-
<x-greeting name="Billy Jo"></x-greeting>
117-
```
118-
119-
Output:
120-
121-
```html
122-
<p>Hello, Billy Jo!</p>
123-
```
124-
125-
### Observed Attributes
126-
127-
Web Components require explicitly listing the names of attributes you want to observe in order to respond when their values are changed. These can be specified via the third parameter that's passed to the `register()` function:
128-
129-
```jsx
130-
// Listen to changes to the `name` attribute
131-
register(Greeting, 'x-greeting', ['name']);
132-
```
133-
134-
If you omit the third parameter to `register()`, the list of attributes to observe can be specified using a static `observedAttributes` property on your Component. This also works for the Custom Element's name, which can be specified using a `tagName` static property:
135-
136-
```jsx
137-
import register from 'preact-custom-element';
138-
139-
// <x-greeting name="Bo"></x-greeting>
140-
class Greeting extends Component {
141-
// Register as <x-greeting>:
142-
static tagName = 'x-greeting';
143-
144-
// Track these attributes:
145-
static observedAttributes = ['name'];
146-
147-
render({ name }) {
148-
return <p>Hello, {name}!</p>;
149-
}
150-
}
151-
register(Greeting);
152-
```
153-
154-
If no `observedAttributes` are specified, they will be inferred from the keys of `propTypes` if present on the Component:
155-
156-
```jsx
157-
// Other option: use PropTypes:
158-
function FullName({ first, last }) {
159-
return (
160-
<span>
161-
{first} {last}
162-
</span>
163-
);
164-
}
165-
166-
FullName.propTypes = {
167-
first: Object, // you can use PropTypes, or this
168-
last: Object // trick to define un-typed props.
169-
};
170-
171-
register(FullName, 'full-name');
172-
```
173-
174-
### Passing slots as props
175-
176-
The `register()` function has a fourth parameter to pass options; currently, only the `shadow` option is supported, which attaches a shadow DOM tree to the specified element. When enabled, this allows the use of named `<slot>` elements to forward the Custom Element's children to specific places in the shadow tree.
177-
178-
```jsx
179-
function TextSection({ heading, content }) {
180-
return (
181-
<div>
182-
<h1>{heading}</h1>
183-
<p>{content}</p>
184-
</div>
185-
);
186-
}
187-
188-
register(TextSection, 'text-section', [], { shadow: true });
189-
```
190-
191-
Usage:
192-
193-
```html
194-
<text-section>
195-
<span slot="heading">Nice heading</span>
196-
<span slot="content">Great content</span>
197-
</text-section>
198-
```

src/config.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,12 @@
517517
"name": {
518518
"en": "preact-iso"
519519
}
520+
},
521+
{
522+
"path": "/preact-custom-element",
523+
"name": {
524+
"en": "preact-custom-element"
525+
}
520526
}
521527
]
522528
}

0 commit comments

Comments
 (0)