Skip to content

Commit 2d036c7

Browse files
committed
docs improvements
1 parent 0ba8952 commit 2d036c7

12 files changed

Lines changed: 40 additions & 45 deletions

www/docs/components.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ They are installed onto an element with `install`:
293293
</div>
294294
~~~
295295

296-
For a more substantial example, see the [Draggable behavior](/patterns/#75-draggable-behavior) pattern.
296+
For a more substantial example, see the [Drag to Reorder](/patterns/lists-forms/drag-to-reorder/) pattern.
297297

298298
#### Behaviors vs. Components
299299

www/patterns/components/linked-scroll.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ behavior ScrollLock
101101
end
102102
~~~
103103

104-
The feature-level `set @data-locked-scroll to 'true'` marks each element
105-
on install so the `tell` query can find its peers without IDs or classes.
104+
The feature-level [`set`](/commands/set) `@data-locked-scroll to 'true'` marks each element
105+
on [`install`](/features/install) so the `tell` query can find its peers without IDs or classes.
106106

107107
There's no re-entry guard because assigning `scrollTop` to its current
108108
value is a no-op and **doesn't fire a scroll event** - so the cascade

www/patterns/dialogs/click-outside-dropdown.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ and using hyperscript's `elsewhere` modifier for the click-outside behavior.
4242
Three pieces of hyperscript do all the work:
4343

4444
- **`on click show the next <dialog/> then halt`** on the trigger
45-
button. `show` calls `dialog.show()` (non-modal), which leaves the dialog
45+
button. [`show`](/commands/show) calls `dialog.show()` (non-modal), which leaves the dialog
4646
in the document flow so `position: absolute` anchors it to its parent. `halt` stops
4747
the click from bubbling up to `document` to prevent the `on click from elsewhere` handler
4848
on the dialog from firing.

www/patterns/dom/tabs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ on click
9797

9898
Four lines, in order:
9999

100-
1. **`set tab to the closest <[role=tab]/> to the target`** - find the tab the user clicked. `the target` is the click event's `event.target`, and `closest` walks up to find the nearest ancestor (or self) matching the selector. If they clicked outside any tab, `tab` is `null`.
100+
1. **`set tab to the closest <[role=tab]/> to the target`** - find the tab the user clicked. `the target` is the click event's `event.target`, and [`closest`](/expressions/closest) walks up to find the nearest ancestor (or self) matching the selector. If they clicked outside any tab, `tab` is `null`.
101101

102102
2. **`if no tab exit end`** - bail out cleanly when the click wasn't on a tab.
103103

@@ -109,7 +109,7 @@ Four lines, in order:
109109

110110
Net effect: every tab in this component gets `aria-selected="false"`, then the clicked tab gets `aria-selected="true"`. The browser styles it via `[aria-selected="true"]` in CSS - no `.active` class needed.
111111

112-
4. **`add @hidden to <[role=tabpanel]/> in me when its @id is not (tab's @aria-controls)`** - for each tabpanel, add `@hidden` if its id doesn't match the active tab's `aria-controls`, and remove it if it does. `add ... when` toggles in both directions, so one statement handles all panels at once.
112+
4. **`add @hidden to <[role=tabpanel]/> in me when its @id is not (tab's @aria-controls)`** - for each tabpanel, [`add`](/commands/add) `@hidden` if its id doesn't match the active tab's `aria-controls`, and [`remove`](/commands/remove) it if it does. `add ... when` toggles in both directions, so one statement handles all panels at once.
113113

114114
## Why ARIA, not `.active`
115115

www/patterns/lists-forms/character-counter.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ bind .over to $msg.length > 280
8282
bind @disabled to $msg.length > 280 or $msg is empty -- on the button
8383
~~~
8484

85-
`bind $msg to me` two-way-binds the textarea's value to a global reactive
85+
[`bind`](/features/bind) `$msg to me` two-way-binds the textarea's value to a global reactive
8686
variable `$msg`. Type into the textarea, `$msg` updates. Set `$msg` from
8787
anywhere, the textarea updates. Now the counter and the button can both
8888
subscribe to it without ever touching the textarea directly.
8989

9090
The counter combines one `live` and two `bind`s:
9191

92-
- **`live put $msg.length + ' / 280' into me`** - auto-tracks `$msg.length`
92+
- **[`live`](/features/live) `put $msg.length + ' / 280' into me`** - auto-tracks `$msg.length`
9393
as a dependency and re-runs the `put` whenever it changes, so the text
9494
always reflects the current count.
9595
- **`bind .warn to $msg.length > 240`** - reactively binds the `.warn`

www/patterns/lists-forms/dependent-range.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ and pulls the *other* field's value into one of its constraint attributes.
7373
Open either picker after typing a value into the other and you'll see the
7474
out-of-range dates greyed out in the calendar UI.
7575

76-
The fourth row of the [`bind`](/patterns/lists-forms/character-counter/)
76+
The fourth row of the [`bind`](/features/bind)
7777
table is the one in play here:
7878

7979
| Form | Effect |
@@ -109,6 +109,6 @@ On first load, `$start` and `$end` haven't been written yet, so the bindings
109109
that pull from them set `@min`/`@max` to `undefined` - which the browser
110110
treats as "no constraint." Once the user types into either field, the
111111
constraint kicks in. If you want a constraint from the very first render,
112-
either initialize the variables in an `init` block or set the attributes
112+
either initialize the variables in an [`init`](/features/init) block or set the attributes
113113
in the markup as a default.
114114
{% endnote %}

www/patterns/lists-forms/drag-to-reorder.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ reorder list:
9898
- **`dragstart`** fires on the source when the user starts dragging. We
9999
stash the dragged element in `:dragged` (element-scoped on the `<ul>`,
100100
not a global, so multiple lists on the same page don't collide). Also
101-
add an `.is-dragging` class for visual feedback.
101+
[`add`](/commands/add) an `.is-dragging` class for visual feedback.
102102

103103
- **`dragend`** fires on the source after the drag ends, regardless of
104104
whether the drop succeeded. We use it to clear the visual state.
@@ -118,7 +118,7 @@ reorder list:
118118

119119
## A few subtleties
120120

121-
- **`closest <li/> to event.target`** is the right way to find the source
121+
- **[`closest`](/expressions/closest) `<li/> to event.target`** is the right way to find the source
122122
and target items. The drag event's `target` may be a child of the `<li>`
123123
(a span, a text node, etc.) - `closest` walks up to find the actual
124124
list item. Without it, dragging over an emoji or text would miss.

www/patterns/lists-forms/filterable-table.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ on input
8080
## How this works
8181

8282
Each line is a single declarative assertion about the DOM after the input
83-
fires. The magic is that `add ... when` doesn't just *add* the attribute when
83+
fires. The magic is that [`add`](/commands/add) `... when` doesn't just *add* the attribute when
8484
the predicate is true: it also *removes* it when false. So one line covers
8585
both directions of the toggle, every time the input fires.
8686

www/patterns/lists-forms/password-match.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ bind $confirm to me -- on the confirm input
8484
bind .mismatch to $confirm is not '' and $confirm is not $pw
8585
~~~
8686

87-
`bind .mismatch to <boolean>` adds the class when the expression is true and
87+
[`bind`](/features/bind) `.mismatch to <boolean>` adds the class when the expression is true and
8888
removes it when false. The runtime tracks both `$pw` and `$confirm` as
8989
dependencies, so the class re-evaluates whenever either field changes - even
9090
if the user goes back and edits the first field after typing the second.
@@ -172,7 +172,7 @@ live if $confirm is not '' and $confirm is not $pw
172172
end
173173
~~~
174174

175-
`live` re-runs every time `$pw` or `$confirm` changes, calling
175+
[`live`](/features/live) re-runs every time `$pw` or `$confirm` changes, calling
176176
`setCustomValidity` with either the error message or an empty string. An
177177
input with a non-empty validity message participates in form submission as
178178
"invalid" - the browser refuses to submit, focuses the field, and shows the

www/patterns/lists-forms/reactive-todo-list.md

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
layout: pattern.njk
33
title: Reactive Todo List
4-
description: A reactive todo list with add, done, and remove -- using live templates, object arrays, and the new `remove` command for index-based splicing.
4+
description: A reactive todo list with add, done, and remove
55
tags: [reactivity, list, remove, live-template]
66
difficulty: intermediate
77
---
88

99
A complete todo list: add items, mark them done, remove them, filter by
1010
text. State is a plain array of `{text, done}` objects, rendered by a
11-
`<script type="text/hyperscript-template" live>` that re-renders whenever the array changes.
11+
`<script type="text/hyperscript-template" live>` template that re-renders whenever the array changes.
1212

1313
{% example "Todo List" %}
1414
<div class="todo-app"
@@ -93,71 +93,66 @@ text. State is a plain array of `{text, done}` objects, rendered by a
9393
9494
All state lives in two global variables initialized on the wrapper div:
9595
96-
```
96+
~~~ hyperscript
9797
init set $todos to [{text:'Learn hyperscript', done:true},
9898
{text:'Build something cool', done:false},
9999
{text:'Ship it', done:false}]
100100
set $search to ''
101-
```
101+
~~~
102102
103103
`$todos` is a plain array of `{text, done}` objects. `$search` is the
104-
current filter string, two-way bound to the search input via `bind`.
104+
current filter string, two-way bound to the search input via [`bind`](/features/bind).
105105
106106
### Adding items
107107
108108
The text input listens for Enter and has a named `add` event that the
109109
button can trigger:
110110
111-
```
111+
~~~ hyperscript
112112
on keyup[key is 'Enter'] trigger add
113113
on add
114114
halt unless my value is not empty
115115
append {text: my value, done: false} to $todos
116116
clear me
117-
```
117+
~~~
118118
119119
`append` pushes a new object onto `$todos`. The live template sees the
120120
mutation and re-renders.
121121
122122
### Rendering
123123
124-
The `<script type="text/hyperscript-template" live>` block renders the list. `#for` iterates `$todos`
125-
with a `where` filter and an `index i` binding:
124+
The `<script type="text/hyperscript-template" live>` block renders the
125+
list. `#for` iterates `$todos` with a `where` filter:
126126
127-
```
128-
#for todo in $todos where its text contains $search ignoring case index i
129-
<li class="${'done' if todo.done else ''}">
127+
~~~ html
128+
#for todo in $todos where the todo's text contains $search ignoring case
129+
<li class="${'done' if todo is done}">
130130
...
131131
</li>
132132
#else
133133
<li class="empty">Nothing here.</li>
134134
#end
135-
```
136-
137-
The `index i` gives us the position of each item in the original
138-
(unfiltered) array, which we need for the checkbox and remove button.
135+
~~~
139136
140137
### Toggling done
141138
142-
Each checkbox writes back to the source array by index:
139+
Each checkbox writes back to the todo object directly:
143140
144141
```html
145-
<input type="checkbox" _="on click set $todos[${i}].done to my checked" />
142+
<input type="checkbox" _="on click set the todo's done to my checked" />
146143
```
147144
148-
`${i}` is interpolated at render time, so each checkbox targets its own
149-
item. Setting the property triggers re-render, which updates the
150-
`class="done"` and the strikethrough.
145+
Note that here we have inner hyperscript on the generated input, and it is able to reference `todo` as a normal variable.
146+
This is because hyperscript captures scopes/closures associated with looping in templates and makes the loop variables
147+
available in generated scripts, making scripting with hyperscript templates natural.
151148
152149
### Removing items
153150
154-
The remove button uses `remove` with an index expression:
151+
The remove button uses [`remove`](/commands/remove) with the captured object reference:
155152
156153
```html
157-
<button _="on click remove $todos[${i}]">x</button>
154+
<button _="on click remove todo from $todos">x</button>
158155
```
159156
160-
`remove $todos[${i}]` splices element `i` out of the array (a new feature
161-
in 0.9.90). Because the value at that index is a plain object, not a DOM
162-
node, `remove` dispatches to the array splice path instead of the DOM
163-
detach path. The live template re-renders after the splice.
157+
`remove todo from $todos` finds the object by reference in the array and
158+
splices it out. The live template reactively re-renders after the splice.

0 commit comments

Comments
 (0)