Skip to content

Commit 4f654b4

Browse files
authored
inputs edits (#792)
* inputs edits * tweak inline example * trim inputs overview * button input * checkbox edits * color input * date input * file edits * form edits * radio edits * range edits * search edits * select edits * table edits * text edits * textarea edits * toggle edits
1 parent 1b7e1f2 commit 4f654b4

22 files changed

+497
-619
lines changed

docs/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ index: false
9898
margin-left: 0.25rem;
9999
}
100100

101+
@media (prefers-color-scheme: light) {
102+
h1 {
103+
--theme-red: #d75c48;
104+
}
105+
}
106+
101107
</style>
102108

103109
<div class="hero">

docs/inputs/button.md

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,34 @@
11
# Button input
22

3-
[API Reference ›](https://github.com/observablehq/inputs/blob/main/README.md#button)
3+
<a href="https://github.com/observablehq/inputs/blob/main/README.md#button" target="_blank">API</a> · <a href="https://github.com/observablehq/inputs/blob/main/src/button.js" target="_blank">Source</a> · The button input emits an *input* event when you click it. Buttons may be used to trigger the evaluation of cells, say to restart an animation. For example, below is an animation that progressively hides a bar. Clicking the button will restart the animation.
44

5-
The button input emits an *input* event when you click it. Buttons may be used to trigger the evaluation of cells, say to restart an animation.
6-
7-
For example, below is an animation (using [yield](../javascript/generators)) that progressively hides a bar.
8-
9-
```js echo
10-
import * as Inputs from "npm:@observablehq/inputs";
11-
```
5+
<canvas id="canvas" width="360" height="20" style="max-width: 100%; color: var(--theme-foreground-focus); border: solid 1px var(--theme-foreground);">
126

137
```js echo
14-
const width = 360;
15-
const height = 20;
16-
const style = "max-width: 100%; border: solid 1px black;";
8+
const replay = view(Inputs.button("Replay"));
179
```
1810

19-
```html
20-
<canvas id="canvas" width="${width}" height="${height}" style="${style}">
21-
```
11+
The code block below references <code>replay</code>, so it will run automatically whenever the replay button is clicked.
2212

23-
```js echo
24-
const replay = view(Inputs.button("Replay"));
13+
```js
2514
const canvas = document.querySelector("#canvas");
2615
const context = canvas.getContext("2d");
16+
context.fillStyle = getComputedStyle(canvas).color;
2717
```
2818

29-
The code block below references <code>replay</code>, so it will run automatically whenever the replay button is clicked. If you click the button while the animation is still running, the animation will be interrupted and restart from the beginning.
30-
3119
```js echo
32-
replay;
20+
replay; // run this block when the button is clicked
3321
const progress = (function* () {
34-
for (let i = width; i >= 0; --i) {
35-
context.clearRect(0, 0, width, height);
36-
context.fillRect(0, 0, i, height);
37-
yield context.canvas;
22+
for (let i = canvas.width; i >= 0; --i) {
23+
context.clearRect(0, 0, canvas.width, canvas.height);
24+
context.fillRect(0, 0, i, canvas.height);
25+
yield canvas;
3826
}
3927
})();
4028
```
4129

30+
<div class="note">The <code>progress</code> top-level variable is declared as a <a href="../javascript/generators">generator</a>. This causes the Observable runtime to automatically advance the generator on each animation frame. If you prefer, you could write this animation using a standard <code>requestAnimationFrame</code> loop, but generators are nice because the animation will automatically be interrupted when the code is <a href="../javascript/reactivity#invalidation">invalidated</a>.</div>
31+
4232
You can also use buttons to count clicks. While the value of a button is often not needed, it defaults to zero and is incremented each time the button is clicked.
4333

4434
```js echo
@@ -49,15 +39,13 @@ const clicks = view(Inputs.button("Click me"));
4939
clicks
5040
```
5141

52-
Interpolate input values into Markdown using [inline expressions](../javascript#inline-expressions):
53-
54-
You have clicked ${clicks} times.
42+
You have clicked ${clicks} times.
5543

5644
```md
5745
You have clicked ${clicks} times.
5846
```
5947

60-
You can change this behavior by specifying the *value* and *reduce* options: *value* is the initial value, and *reduce* is called whenever the button is clicked, being passed the current value and returning the new value. The value of the button below is the last time the button was clicked, or null if the button has not been clicked.
48+
While buttons count clicks by default, you can change the behavior by specifying the *value* and *reduce* options: *value* is the initial value, and *reduce* is called whenever the button is clicked, being passed the current value and returning the new value. The value of the button below is the last time the button was clicked, or null if the button has not been clicked.
6149

6250
```js echo
6351
const time = view(Inputs.button("Update", {value: null, reduce: () => new Date}));
@@ -83,7 +71,7 @@ const counter = view(Inputs.button([
8371
counter
8472
```
8573

86-
The first argument to `Inputs.button()` is the contents of the button. It’s not required, but it’s strongly encouraged.
74+
The first argument to `Inputs.button()` is the contents of the button. It’s not required, but is strongly encouraged.
8775

8876
```js echo
8977
const x = view(Inputs.button());
@@ -121,9 +109,9 @@ Inputs.button("Copy to clipboard", {value: null, reduce: () => navigator.clipboa
121109

122110
The available button input options are:
123111

124-
* *label* - a label; either a string or an HTML element.
112+
* *label* - a label; either a string or an HTML element
125113
* *required* - if true, the initial value defaults to undefined.
126-
* *value* - the initial value; defaults to 0 or null if *required* is false.
127-
* *reduce* - a function to update the value on click; by default returns *value* + 1.
128-
* *width* - the width of the input (not including the label).
129-
* *disabled* - whether input is disabled; defaults to false.
114+
* *value* - the initial value; defaults to 0 or null if *required* is false
115+
* *reduce* - a function to update the value on click; by default returns *value* + 1
116+
* *width* - the width of the input (not including the label)
117+
* *disabled* - whether input is disabled; defaults to false

docs/inputs/checkbox.md

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# Checkbox input
22

3-
[API Reference ›](https://github.com/observablehq/inputs/blob/main/README.md#checkbox)
4-
5-
The checkbox input allows the user to choose any of a given set of values. (See the [radio](./radio) input for single-choice.) A checkbox is recommended over a [select](./select) input when the number of values to choose from is small — say, seven or fewer — because all choices will be visible up-front, improving usability. For zero or one choice, see the [toggle](./toggle) input.
3+
<a href="https://github.com/observablehq/inputs/blob/main/README.md#checkbox" target="_blank">API</a> · <a href="https://github.com/observablehq/inputs/blob/main/src/checkbox.js" target="_blank">Source</a> · The checkbox input allows the user to choose any of a given set of values. (See the [radio](./radio) input for single-choice.) A checkbox is recommended over a [select](./select) input when the number of values to choose from is small — say, seven or fewer — because all choices will be visible up-front, improving usability. For zero or one choice, see the [toggle](./toggle) input.
64

75
The initial value of a checkbox defaults to an empty array. You can override this by specifying the *value* option, which should also be an array (or iterable).
86

@@ -11,11 +9,7 @@ const colors = view(Inputs.checkbox(["red", "green", "blue"], {label: "color"}))
119
```
1210

1311
```js echo
14-
colors
15-
```
16-
17-
```html echo
18-
<div style="display: flex;">${colors.map(color => html`<div style="background-color: ${color}; width: 25px; height: 25px;">`)}
12+
colors
1913
```
2014

2115
A checkbox’s values need not be strings: they can be anything. Specify a *format* function to control how these values are presented to the reader.
@@ -31,7 +25,7 @@ const teams = [
3125
```
3226

3327
```js echo
34-
const watching = view(Inputs.checkbox(teams, {label: "Watching", format: x => x.name}));
28+
const watching = view(Inputs.checkbox(teams, {label: "Watching", format: (x) => x.name}));
3529
```
3630

3731
```js echo
@@ -51,17 +45,38 @@ vowels
5145
The *format* function, like the *label*, can return either a text string or an HTML element. This allows extensive control over the appearance of the checkbox, if desired.
5246

5347
```js echo
54-
const colors2 = view(Inputs.checkbox(["red", "green", "blue"], {value: ["red"], label: html`<b>Colors</b>`, format: x => html`<span style="text-transform: capitalize; border-bottom: solid 2px ${x}; margin-bottom: -2px;">${x}`}));
48+
const colors2 = view(
49+
Inputs.checkbox(["red", "green", "blue"], {
50+
value: ["red"],
51+
label: html`<b>Colors</b>`,
52+
format: (x) =>
53+
html`<span style="
54+
text-transform: capitalize;
55+
border-bottom: solid 2px ${x};
56+
margin-bottom: -2px;
57+
">${x}</span>`
58+
})
59+
);
5560
```
5661

5762
```js echo
5863
colors2
5964
```
6065

61-
If the checkbox’s data are specified as a Map, the values will be the map’s values while the keys will be the displayed options. (This behavior can be customized by passing *keyof* and *valueof* function options.) Below, the displayed sizes are named, but the value is the corresponding number of fluid ounces.
66+
If the checkbox’s data are specified as a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), the values will be the map’s values while the keys will be the displayed options. (This behavior can be customized by passing *keyof* and *valueof* function options.) Below, the displayed sizes are named, but the value is the corresponding number of fluid ounces.
6267

6368
```js echo
64-
const sizes = view(Inputs.checkbox(new Map([["Short", 8], ["Tall", 12], ["Grande", 16], ["Venti", 20]]), {value: [12], label: "Size"}));
69+
const sizes = view(
70+
Inputs.checkbox(
71+
new Map([
72+
["Short", 8],
73+
["Tall", 12],
74+
["Grande", 16],
75+
["Venti", 20]
76+
]),
77+
{value: [12], label: "Size"}
78+
)
79+
);
6580
```
6681

6782
```js echo
@@ -71,10 +86,17 @@ sizes
7186
Since the *format* function is passed elements from the data, it can access both the key and value from the corresponding Map entry.
7287

7388
```js echo
74-
const size2 = view(Inputs.checkbox(
75-
new Map([["Short", 8], ["Tall", 12], ["Grande", 16], ["Venti", 20]]),
76-
{value: [12], label: "Size", format: ([name, value]) => `${name} (${value} oz)`}
77-
));
89+
const size2 = view(
90+
Inputs.checkbox(
91+
new Map([
92+
["Short", 8],
93+
["Tall", 12],
94+
["Grande", 16],
95+
["Venti", 20]
96+
]),
97+
{value: [12], label: "Size", format: ([name, value]) => `${name} (${value} oz)`}
98+
)
99+
);
78100
```
79101

80102
```js echo
@@ -84,14 +106,19 @@ size2
84106
Passing a Map to checkbox is especially useful in conjunction with [d3.group](https://d3js.org/d3-array/group). For example, given a the sample `olympians` dataset of Olympic athletes, we can use d3.group to group them by gold medal count, and then checkbox to select the athletes for the chosen count. Note that the value of the checkbox will be an array of arrays, since d3.group returns a Map from key to array; use [*array*.flat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) to merge these arrays if desired.
85107

86108
```js echo
87-
const goldAthletes = view(Inputs.checkbox(d3.group(olympians, d => d.gold), {label: "Gold medal count", sort: "descending", key: [4, 5]}));
109+
const goldAthletes = view(
110+
Inputs.checkbox(
111+
d3.group(olympians, (d) => d.gold),
112+
{label: "Gold medal count", sort: "descending", key: [4, 5]}
113+
)
114+
);
88115
```
89116

90117
```js echo
91118
goldAthletes.flat()
92119
```
93120

94-
If the *sort* and *unique* options are specified, the checkbox’s keys will be sorted and duplicate keys will be discarded, respectively.
121+
If the *sort* and *unique* options are specified, the checkbox’s keys will be sorted and duplicate keys will be discarded, respectively.
95122

96123
```js echo
97124
const bases = view(Inputs.checkbox("GATTACA", {sort: true, unique: true}));
@@ -107,14 +134,12 @@ bases
107134

108135
The available checkbox input options are:
109136

110-
* *label* - a label; either a string or an HTML element.
111-
* *sort* - true, “ascending”, “descending”, or a comparator function to sort keys; defaults to false.
112-
* *unique* - true to only show unique keys; defaults to false.
113-
* *locale* - the current locale; defaults to English.
114-
* *format* - a format function; defaults to [formatLocaleAuto](https://github.com/observablehq/inputs/blob/main/README.md#inputsformatlocaleautolocale) composed with *keyof*.
115-
* *keyof* - a function to return the key for the given element in *data*.
116-
* *valueof* - a function to return the value of the given element in *data*.
117-
* *value* - the initial value, an array; defaults to an empty array (no selection).
118-
* *disabled* - whether input is disabled, or the disabled values; defaults to false.
119-
120-
<!-- TODO check formatLocaleAuto link-->
137+
* *label* - a label; either a string or an HTML element
138+
* *sort* - true, *ascending*, *descending*, or a comparator to sort keys; defaults to false
139+
* *unique* - true to only show unique keys; defaults to false
140+
* *locale* - the current locale; defaults to English
141+
* *format* - a format function; defaults to [formatLocaleAuto](https://github.com/observablehq/inputs/blob/main/README.md#inputsformatlocaleautolocale) composed with *keyof*
142+
* *keyof* - a function to return the key for the given element in *data*
143+
* *valueof* - a function to return the value of the given element in *data*
144+
* *value* - the initial value, an array; defaults to an empty array (no selection)
145+
* *disabled* - whether input is disabled, or the disabled values; defaults to false

docs/inputs/color.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# Color input
22

3-
[API Reference ›](https://github.com/observablehq/inputs/blob/main/README.md#inputscoloroptions)
4-
5-
The color input specifies an RGB color as a hexadecimal string `#rrggbb`. The initial value defaults to black (`#000000`) and can be specified with the *value* option.
3+
<a href="https://github.com/observablehq/inputs/blob/main/README.md#inputscoloroptions" target="_blank">API</a> · <a href="https://github.com/observablehq/inputs/blob/main/src/color.js" target="_blank">Source</a> · The color input specifies an RGB color as a hexadecimal string `#rrggbb`. The initial value defaults to black (`#000000`) and can be specified with the *value* option.
64

75
```js echo
86
const color = view(Inputs.color({label: "Favorite color", value: "#4682b4"}));
@@ -44,4 +42,4 @@ disabled
4442

4543
**Inputs.color(*options*)**
4644

47-
Like [Inputs.text](./text), but where *type* is color. The color value is represented as an RGB hexadecimal string such as #ff00ff. This type of input does not support the following options: *placeholder*, *pattern*, *spellcheck*, *autocomplete*, *autocapitalize*, *min*, *max*, *minlength*, *maxlength*.
45+
Like [Inputs.text](./text), but where *type* is color. The color value is represented as an RGB hexadecimal string such as #ff00ff. This type of input does not support the following options: *placeholder*, *pattern*, *spellcheck*, *autocomplete*, *autocapitalize*, *min*, *max*, *minlength*, *maxlength*.

docs/inputs/date.md

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# Date input
22

3-
[API Reference ›](https://github.com/observablehq/inputs/blob/main/README.md#date)
4-
5-
The date input specifies a date.
3+
<a href="https://github.com/observablehq/inputs/blob/main/README.md#date" target="_blank">API</a> · <a href="https://github.com/observablehq/inputs/blob/main/src/date.js" target="_blank">Source</a> · The date input specifies a date.
64

75
```js echo
86
const date = view(Inputs.date());
@@ -86,15 +84,15 @@ readonly
8684

8785
The available date input options are:
8886

89-
* *label* - a label; either a string or an HTML element.
90-
* *value* - the initial value, as a JavaScript Date or formatted as an ISO string (yyyy-mm-dd); defaults to null.
91-
* *min* - [minimum value](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/min) attribute.
92-
* *max* - [maximum value](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/max) attribute.
93-
* *required* - if true, the input must be a valid date.
94-
* *validate* - a function to check whether the text input is valid.
95-
* *width* - the width of the input (not including the label).
96-
* *submit* - whether to require explicit submission before updating; defaults to false.
97-
* *readonly* - whether input is readonly; defaults to false.
98-
* *disabled* - whether input is disabled; defaults to false.
87+
* *label* - a label; either a string or an HTML element
88+
* *value* - the initial value as a [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) or `YYYY-MM-DD` string; defaults to null
89+
* *min* - [minimum value](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/min) attribute
90+
* *max* - [maximum value](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/max) attribute
91+
* *required* - if true, the input must be a valid date
92+
* *validate* - a function to check whether the text input is valid
93+
* *width* - the width of the input (not including the label)
94+
* *submit* - whether to require explicit submission; defaults to false
95+
* *readonly* - whether input is readonly; defaults to false
96+
* *disabled* - whether input is disabled; defaults to false
9997

10098
The value of the input is a Date instance at UTC midnight of the specified date, or null if no (valid) value has been specified. Note that the displayed date format is [based on the browser’s locale](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date).

0 commit comments

Comments
 (0)