Skip to content

Commit 1c3e027

Browse files
authored
Merge pull request #27 from github/more-docs
More docs
2 parents 7fb65e6 + 153c08e commit 1c3e027

5 files changed

Lines changed: 191 additions & 17 deletions

File tree

docs/_guide/actions.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,23 @@ chapter: 6
33
subtitle: Binding Events
44
---
55

6-
Catalyst Components, upon creation, will search for any children with the `data-action` attribute, and bind events based on the value of this attribute. Any _public method_ on a Controller can be bound to via `data-action`.
6+
Catalyst Components automatically bind actions upon instantiation. Automatically as part of the `connectedCallback`, a component will search for any children with the `data-action` attribute, and bind events based on the value of this attribute. Any _public method_ on a Controller can be bound to via `data-action`.
7+
8+
<div class="d-flex border rounded-1 my-3 box-shadow-medium">
9+
<span class="d-flex bg-blue text-white rounded-left-1 p-3">
10+
<svg width="24" viewBox="0 0 14 16" class="octicon octicon-info" aria-hidden="true">
11+
<path
12+
fill-rule="evenodd"
13+
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
14+
/>
15+
</svg>
16+
</span>
17+
<div class="p-3">
18+
19+
Remember! Actions are _automatically_ bound using the `@controller` decorator. There's no extra JavaScript code needed.
20+
21+
</div>
22+
</div>
723

824
### Example
925

@@ -120,8 +136,7 @@ class HelloController extends HTMLElement {
120136
}
121137
```
122138

123-
124-
### How are actions registered?
139+
### What about without Decorators?
125140

126141
If you're using decorators, then the `@controller` decorator automatically handles binding of actions to a Controller.
127142

docs/_guide/decorators.md

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,74 @@ chapter: 3
33
subtitle: Using TypeScript for ergonomics
44
---
55

6-
This is decorators
6+
Decorators are used heavily in Catalyst, because they provide really clean ergonomics and makes using the library a lot easier. Decorators are a special, (currently) non standard, feature of TypeScript. You'll need to turn the `experimentalDecorators` option on inside of your TypeScript project to use them.
7+
8+
You can read more about [decorators in the TypeScript handbook](https://www.typescriptlang.org/docs/handbook/decorators.html), but here's quick guide:
9+
10+
Decorators can be used three ways:
11+
12+
### Class Decorators
13+
14+
Catalyst comes with the `@controller` decorator. This gets put on top of the class, like so:
15+
16+
```js
17+
@controller
18+
class MyController extends HTMLElement {}
19+
```
20+
21+
### Class Field Decorators
22+
23+
Catalyst comes with the `@target` and `@targets` decorators for more [read about Targets](/guide/targets). These get added on top or to the left of the field name, like so:
24+
25+
```js
26+
class MyController extends HTMLElement {
27+
28+
@target something
29+
30+
// Alternative style
31+
@targets
32+
others
33+
34+
}
35+
```
36+
<br>
37+
38+
Class Field decorators get given the class and the field name so they can add custom functionality to the field. Because they operate on the fields, they must be put on top of or to the left of the field.
39+
40+
### Method Decorators
41+
42+
Catalyst doesn't currently ship with any method decorators, but you might see them in code. They work just like Field Decorators (in fact they're the same thing). Put them on top or on the left of the method, like so:
43+
44+
45+
```js
46+
class MyController extends HTMLElement {
47+
48+
@log
49+
submit() {
50+
// ...
51+
}
52+
53+
// Alternative style
54+
55+
@log load() {
56+
// ...
57+
}
58+
59+
}
60+
```
61+
62+
### Function Call Decorators
63+
64+
Some decorators are customisable - they get called with additional arguments, just like a function call. An example of this is the `@debounce` decorator in the [`@github/mini-throttle`](https://github.com/github/mini-throttle) package:
65+
66+
```js
67+
class MyController extends HTMLElement {
68+
69+
@debounce(100)
70+
handleInput() {
71+
// ...
72+
}
73+
74+
}
75+
```
76+
<br>

docs/_guide/introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The Web Systems team at GitHub explored other tools that adopt these set of patt
1919

2020
Catalyst takes these three core concepts and delivers them in the lightest possible way they can be delivered.
2121

22-
- **Observabiliy** Catalyst solves observability by leveraging [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Custom Elements are given unique names within a system, and the browser will automatically use the Custom Element registry to observe these Elements entering and leaving the DOM. Read more about this in the Guide Section entitled [Custom Elements](/guide/custom-elements).
22+
- **Observability** Catalyst solves observability by leveraging [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Custom Elements are given unique names within a system, and the browser will automatically use the Custom Element registry to observe these Elements entering and leaving the DOM. Read more about this in the Guide Section entitled [Custom Elements](/guide/custom-elements).
2323

2424
- **Listening** Event Delegation makes a great deal of sense when observing events "high up the tree" - registering global event listeners on the Window element - but Custom Elements sit much closer to their children within the tree, and so Direct Event binding is preferred. Catalyst solves this by binding event listeners to any descendants with `data-action` attributes. Read more about this in the Guide Section entitled [Actions](/guide/actions).
2525

docs/_guide/targets.md

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ chapter: 5
33
subtitle: Querying Descendants
44
---
55

6-
Catalyst Components are just Web Components, and so you can simply use `querySelector` or `querySelectorAll` to select descendants of the element. Targets, however, provide a more consistent interface for accessing descendants.
6+
One of the three [core patterns](/guide/introduction#three-core-concepts-observe-listen-query) is Querying. In Catalyst, Targets are the preferred way to query. Target use `querySelectorAll` under the hood, but make it a lot simpler to work with.
7+
8+
Catalyst Components are really just Web Components, so you could simply use `querySelector` or `querySelectorAll` to select descendants of the element. Targets avoid some of the problems of `querySelector`; they provide a more consistent interface and handle nesting intuitively. Targets are also a little more ergonomic to reuse in a class. We'd recommend using Targets over `querySelector` wherever you can.
9+
10+
To create a Target, use the `@target` decorator on a class field, and add the matching `data-target` attribute to your HTML, like so:
711

812
### Example
913

1014
<div class="d-flex my-4">
11-
<div class="">
15+
<div>
1216

1317
```html
1418
<hello-controller>
@@ -22,10 +26,11 @@ Catalyst Components are just Web Components, and so you can simply use `querySel
2226
<div class="ml-4">
2327

2428
```js
25-
import { target } from "@github/catalyst"
29+
import { controller, target } from "@github/catalyst"
2630

31+
@controller
2732
class HelloController extends Controller {
28-
@target outputTarget: HTMLElement
33+
@target outputTarget!: HTMLElement
2934

3035
greet() {
3136
this.outputTarget.textContent = `Hello, world!`
@@ -45,28 +50,59 @@ The target syntax follows a pattern of `controller.target`.
4550

4651
### Multiple Targets
4752

53+
<div class="d-flex border rounded-1 my-3 box-shadow-medium">
54+
<span class="d-flex bg-blue text-white rounded-left-1 p-3">
55+
<svg width="24" viewBox="0 0 14 16" class="octicon octicon-info" aria-hidden="true">
56+
<path
57+
fill-rule="evenodd"
58+
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
59+
/>
60+
</svg>
61+
</span>
62+
<div class="p-3">
63+
64+
Remember! There are two decorators available, `@target` which fetches only one element, and `@targets` which fetches multiple. This is the only difference, but it's an important one.
65+
66+
</div>
67+
</div>
68+
69+
The `@target` decorator will only ever return _one_ element, just like `querySelector`. If you want to get multiple Targets, you need the `@targets` decorator which works almost identically, but it'll return an _array_ of _N_ elements.
70+
4871
Elements can be referenced as multiple targets, and targets may be referenced multiple times within the HTML:
4972

5073
```html
5174
<teammembers-controller>
5275
<userlist-controller>
5376
<user-controller data-target="userlist-controller.user">
54-
<input type="checkbox" data-target="teammembers-controller.read-checkbox">
55-
<input type="checkbox" data-target="teammembers-controller.write-checkbox">
77+
<input type="checkbox" data-target="teammembers-controller.readCheckbox">
78+
<input type="checkbox" data-target="teammembers-controller.writeCheckbox">
5679
</user-controller>
5780
<user-controller data-target="userlist-controller.user">
58-
<input type="checkbox" data-target="teammembers-controller.read-checkbox">
59-
<input type="checkbox" data-target="teammembers-controller.write-checkbox">
81+
<input type="checkbox" data-target="teammembers-controller.readCheckbox">
82+
<input type="checkbox" data-target="teammembers-controller.writeCheckbox">
6083
</user-controller>
6184
</userlist-controller>
6285
</teammembers-controller>
6386
```
6487

65-
### Single vs Plural
88+
<br>
89+
90+
```js
91+
import { controller, targets } from "@github/catalyst"
92+
93+
@controller
94+
class HelloController extends Controller {
95+
@targets readCheckbox!: HTMLElement
96+
@targets writeCheckbox!: HTMLElement
6697

67-
There are two decorators available, `@target` which fetches only one element, and `@targets` which fetches multiple. It is important to distinguish between the two.
98+
validate() {
99+
// One checkbox must be checked!
100+
return this.readCheckbox.length > 0 && this.writeCheckbox.length > 0
101+
}
102+
}
103+
```
68104

69-
### How are actions registered?
105+
### What about without Decorators?
70106

71107
If you're using decorators, then the `@target` and `@targets` decorators will turn the decorated properties into getters.
72108

docs/_guide/your-first-component.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,57 @@ subtitle: Building an HTMLElement
33
chapter: 2
44
---
55

6-
Your first component
6+
Custom Elements allow you to create reusable components that you can declare in HTML, and [progressively enhance](https://en.wikipedia.org/wiki/Progressive_enhancement) within JavaScript. Custom Elements must named with a `-` in the HTML name, and the JS class must `extend HTMLElement`. When the browser connects each element class instance to the DOM node, `connectedCallback` is fired - this is where you can change parts of the element. Here's a basic example:
7+
8+
```html
9+
<my-controller></my-controller>
10+
<script>
11+
class MyController extends HTMLElement {
12+
connectedCallback() {
13+
this.innerHTML = 'Hello World!'
14+
}
15+
}
16+
window.customElements.register('my-controller', MyController)
17+
</script>
18+
```
19+
<br>
20+
21+
22+
Here are the three key elements to remember:
23+
24+
- Custom Elements must have a dash in the name.
25+
- The JS class must `extend HTMLElement`
26+
- `connectedCallback` can be used as a life-cycle hook for when the element and class are connected.
27+
28+
### Catalyst
29+
30+
Catalyst saves you writing some of this boilerplate, by automatically calling the `customElements.register` code, and by adding ["Actions"](/guide/actions) and ["Targets"](/guide/targets) features described later. If you're using TypeScript with `decorators` support, simply add `@controller` to the top of your class:
31+
32+
```js
33+
@controller
34+
class MyController extends HTMLElement {
35+
connectedCallback() {
36+
this.innerHTML = 'Hello World!'
37+
}
38+
}
39+
// No longer need this:
40+
// window.customElements.register('my-controller', MyController)
41+
```
42+
<br>
43+
44+
Catalyst will automatically "dasherize" the class name. All capital letters get lowercased and dash separated.
45+
46+
By convention, Catalyst controllers end in `Controller`, but it's not required.
47+
48+
#### What about without Decorators?
49+
50+
If you don't want to use decorators, you can simply wrap the class in a call to `controller`:
51+
52+
```js
53+
controller(
54+
class MyController extends HTMLElement {
55+
//...
56+
}
57+
)
58+
```
59+
<br>

0 commit comments

Comments
 (0)