@taprootio/espalier 5.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/css/image/banner-static.css +237 -0
- package/custom-elements.json +3842 -3637
- package/dist/image/esp-image.d.ts +70 -3
- package/dist/image/esp-image.js +171 -12
- package/dist/pickers/esp-pick-one.d.ts +4 -0
- package/dist/pickers/esp-pick-one.js +10 -12
- package/dist/pickers/esp-pick-some.js +7 -7
- package/dist/pickers/esp-picker-base.js +5 -5
- package/dist/pickers/esp-picker-item.js +5 -5
- package/dist/pickers/esp-picker-menu.js +4 -3
- package/dist/pickers/typeahead-controller.js +1 -1
- package/dist/shared/events.d.ts +1 -1
- package/dist/shared/virtualizer/internal/virtualize.js +1 -1
- package/dist/video/esp-video.d.ts +18 -53
- package/dist/video/esp-video.js +25 -25
- package/espalier.css-data.json +16 -0
- package/espalier.token-manifest.json +24 -0
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
# 6.1.0
|
|
2
|
+
|
|
3
|
+
Banner overlays gain a copy-stack layout contract (supporting copy, one action, middle positions, a compact band, and a static first-paint layout), and pickers no longer pick the option a finger lands on when it starts scrolling.
|
|
4
|
+
|
|
5
|
+
- **New: middle content positions.** `esp-image`'s `content-position` takes `middle-start` and `middle-end`, centering the copy against the inline start or end edge and mirroring in right-to-left text. An `auto` scrim follows the copy to that edge.
|
|
6
|
+
- **New: a banner copy stack.** Beside `slot="overlay"` (the headline), banners take `slot="overlay-supporting"` for one supporting sentence and `slot="overlay-action"` for one native link or button. Together they lay out as one stack: grouped spacing (`--esp-image-overlay-gap`), the supporting sentence on the lead type role, a line length bounded by `--esp-image-overlay-measure` (`36rem` by default), and an action with a comfortable target and a two-tone focus ring that reads over any photograph. The scrim now covers every piece of overlay copy, not just the headline. A headline on its own lays out exactly as before.
|
|
7
|
+
- **New: `compact-placement="below"`.** Below the compact width the copy moves into a band under the image, on the banner scheme's own surface and ink, for crops that lose their quiet region at narrow widths. The default, `overlay`, keeps today's behavior.
|
|
8
|
+
- **New: `@taprootio/espalier/image/banner-static.css`.** A stylesheet that lays server-rendered banners out before `esp-image` upgrades, from the same attributes plus `--esp-image-static-ratio` and `--esp-image-static-compact-ratio`, so nothing shifts at hydration. The Image banners guide lists its inputs and limits.
|
|
9
|
+
- **Fixed: banner copy could be clipped.** Copy taller than the ratio's frame (text enlarged to 200%, long localized labels, a narrow column) was cut off; the banner now grows to fit it, the image covers the grown frame, and words too long for a line wrap. A banner whose copy fits keeps exactly its current geometry, and an explicit, capped, or stretched block size still wins.
|
|
10
|
+
- **Banner copy never moves with the image.** A transform or animation on a banner's projected image or `::part(image)` stays inside the image box, and under `prefers-reduced-motion` those animations and transitions stop.
|
|
11
|
+
- **Fixed: swiping a picker's option list picked the first option touched.** Pickers picked on the press, before the browser could tell a tap from a scroll, so on a phone every swipe chose an option and closed the menu; `esp-pick-one` also picked a hidden option behind its input when the input was tapped after scrolling. Options are now picked by the tap that ends on them, a press keeps focus (and a typeahead query) in the input, and a tap on the input only focuses it. This applies to `esp-pick-one`, `esp-pick-some`, and `esp-font-picker`, with or without typeahead.
|
|
12
|
+
- **Fixed: typing a typeahead filter after scrolling a long picker list could throw** while the list shrank.
|
|
13
|
+
|
|
14
|
+
# 6.0.0
|
|
15
|
+
|
|
16
|
+
Espalier 6 removes `esp-video`'s unused streaming adapter, and pickers now show an item's new label when its text changes after it was selected.
|
|
17
|
+
|
|
18
|
+
- **Breaking: `esp-video` no longer takes a streaming adapter.** The `adapter` property, `EspalierVideo.defaultAdapter`, and the `VideoAdapter` type are gone, along with the `"adapter"` value of `VideoSourceMode` (the `mode` in event details) and of `VideoErrorReason`. The element plays `src` where the browser can play `type`, and `fallback-src` otherwise; for a source every browser plays, set `type="video/mp4"`. Nothing else about the element changes: `type` still defaults to HLS, which Safari, iOS, and current Chrome play natively.
|
|
19
|
+
- **Fixed: a picker kept showing an item's old label after its text changed.** A picker copies its `esp-picker-item` children and removes them from the page, so a template that rewrote an item in place (Lit's `map` reusing elements by position, for example, when a placeholder entry is replaced by loaded data) changed nothing the picker saw, and `esp-pick-one` kept showing the placeholder. An item's `text`, `icon`, and `styles` changes now reach its picker: `esp-pick-one` re-renders the selected label, and `esp-pick-some` the selected chip. The selection follows the item's `value` and no `esp-value-changed` fires. `esp-pick-some` chips now also follow the new item when the items are replaced outright. An item element the picker no longer lists, whose `value` was rewritten, or whose items the host has since replaced from code, is ignored.
|
|
20
|
+
- **Fixed: a typeahead picker with `fetchItems` replaced the server's results when its items changed.** Picking in `esp-pick-some`, or any change to `pickerItems`, re-ran the local filter over the canonical items and swapped the remote results shown in the menu for them. The menu now keeps the server's results, with their selected marks updated, and a chip keeps the label of the remote result the visitor picked until the item with that value changes or first arrives. Clearing `fetchItems` while a query is typed shows the local matches at once, and a request still in flight from the cleared source no longer brings its results back, or empties the menu if it fails.
|
|
21
|
+
|
|
1
22
|
# 5.0.0
|
|
2
23
|
|
|
3
24
|
Espalier 5 removes the compatibility paths kept for older consumers, adds a native video player, `esp-video`, and makes form errors perceivable to assistive technology: form-item errors now mark, describe, and announce the field, `esp-input` accepts `step="any"`, and choice groups take their name from the form item. The "Migrating To Espalier 5" guide lists each replacement and the form behavior to check.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Espalier esp-image banner: static layout before the component upgrades.
|
|
3
|
+
*
|
|
4
|
+
* Server-rendered `<esp-image banner>` markup paints with page styles alone
|
|
5
|
+
* until Espalier's module defines the element. This sheet lays the same
|
|
6
|
+
* markup out from its attributes in that window, matching the upgraded
|
|
7
|
+
* banner's geometry so nothing shifts at hydration: the frame ratio, focal
|
|
8
|
+
* cropping, every `content-position`, the copy stack and its measure, growth
|
|
9
|
+
* for long or enlarged copy, and `compact-placement="below"`.
|
|
10
|
+
*
|
|
11
|
+
* Every rule is scoped to `esp-image[banner]:not(:defined)`, so it stops
|
|
12
|
+
* applying the moment the element upgrades.
|
|
13
|
+
*
|
|
14
|
+
* Inputs the server sets inline (CSS cannot read a ratio from an attribute):
|
|
15
|
+
* --esp-image-static-ratio the `ratio` value, e.g. `3 / 1`
|
|
16
|
+
* --esp-image-static-compact-ratio the `compact-ratio` value, if any
|
|
17
|
+
* --esp-image-object-position the focal point, e.g. `65% 40%`
|
|
18
|
+
*
|
|
19
|
+
* Limits, all documented in the image banners guide: the compact switch uses
|
|
20
|
+
* the default 40rem width (a custom `--esp-image-compact-width` cannot apply
|
|
21
|
+
* before upgrade); no scrim or texture paints until upgrade; copy must be
|
|
22
|
+
* emitted in stack order (headline, supporting, action); and a custom
|
|
23
|
+
* `--esp-image-overlay-padding` must be a single length for the compact band.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
esp-image[banner]:not(:defined) {
|
|
27
|
+
--_esp-image-static-pad: var(--esp-image-overlay-padding, var(--esp-size-padding-page, 1rem));
|
|
28
|
+
--_esp-image-static-gap: var(--esp-image-overlay-gap, var(--esp-size-small, 0.75rem));
|
|
29
|
+
--_esp-image-static-before: 1fr;
|
|
30
|
+
--_esp-image-static-after: 0fr;
|
|
31
|
+
display: grid;
|
|
32
|
+
grid-template-columns: minmax(0, 1fr);
|
|
33
|
+
/* media | space before | headline | supporting | action | space after */
|
|
34
|
+
grid-template-rows:
|
|
35
|
+
auto minmax(0, var(--_esp-image-static-before)) auto auto auto
|
|
36
|
+
minmax(0, var(--_esp-image-static-after));
|
|
37
|
+
justify-items: start;
|
|
38
|
+
text-align: start;
|
|
39
|
+
overflow: clip;
|
|
40
|
+
overflow-wrap: anywhere;
|
|
41
|
+
container-type: inline-size;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* The image spans every row at the banner ratio, so the banner is as tall as
|
|
45
|
+
the ratio or the copy, whichever is taller, and the image covers it all. */
|
|
46
|
+
esp-image[banner]:not(:defined) > picture,
|
|
47
|
+
esp-image[banner]:not(:defined) > img {
|
|
48
|
+
display: block;
|
|
49
|
+
grid-row: 1 / -1;
|
|
50
|
+
grid-column: 1;
|
|
51
|
+
align-self: stretch;
|
|
52
|
+
justify-self: stretch;
|
|
53
|
+
inline-size: 100%;
|
|
54
|
+
block-size: auto;
|
|
55
|
+
aspect-ratio: var(--esp-image-static-ratio, auto);
|
|
56
|
+
object-fit: cover;
|
|
57
|
+
object-position: var(--esp-image-object-position, center);
|
|
58
|
+
}
|
|
59
|
+
esp-image[banner]:not(:defined) > picture > img {
|
|
60
|
+
display: block;
|
|
61
|
+
inline-size: 100%;
|
|
62
|
+
block-size: 100%;
|
|
63
|
+
object-fit: cover;
|
|
64
|
+
object-position: var(--esp-image-object-position, center);
|
|
65
|
+
}
|
|
66
|
+
esp-image[banner]:not(:defined) > esp-image-option {
|
|
67
|
+
display: none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Vertical placement: which side of the copy takes the free space. */
|
|
71
|
+
esp-image[banner]:not(:defined):is(
|
|
72
|
+
[content-position="top-start"],
|
|
73
|
+
[content-position="top"],
|
|
74
|
+
[content-position="top-end"]
|
|
75
|
+
) {
|
|
76
|
+
--_esp-image-static-before: 0fr;
|
|
77
|
+
--_esp-image-static-after: 1fr;
|
|
78
|
+
}
|
|
79
|
+
esp-image[banner]:not(:defined):is(
|
|
80
|
+
[content-position="middle-start"],
|
|
81
|
+
[content-position="center"],
|
|
82
|
+
[content-position="middle-end"]
|
|
83
|
+
) {
|
|
84
|
+
--_esp-image-static-before: 1fr;
|
|
85
|
+
--_esp-image-static-after: 1fr;
|
|
86
|
+
}
|
|
87
|
+
/* Inline placement, logical so right-to-left mirrors. */
|
|
88
|
+
esp-image[banner]:not(:defined):is(
|
|
89
|
+
[content-position="top"],
|
|
90
|
+
[content-position="center"],
|
|
91
|
+
[content-position="bottom"]
|
|
92
|
+
) {
|
|
93
|
+
justify-items: center;
|
|
94
|
+
text-align: center;
|
|
95
|
+
}
|
|
96
|
+
esp-image[banner]:not(:defined):is(
|
|
97
|
+
[content-position="top-end"],
|
|
98
|
+
[content-position="middle-end"],
|
|
99
|
+
[content-position="bottom-end"]
|
|
100
|
+
) {
|
|
101
|
+
justify-items: end;
|
|
102
|
+
text-align: end;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* The copy. The upgraded overlay pads the copy as a block; here each piece of
|
|
106
|
+
copy carries that padding itself, as a margin, so the image stays
|
|
107
|
+
full-bleed. A headline on its own keeps its own margins, as it does once
|
|
108
|
+
upgraded, by taking the padding as padding instead. */
|
|
109
|
+
esp-image[banner]:not(:defined) > :is([slot="overlay"], [slot="overlay-supporting"], [slot="overlay-action"]) {
|
|
110
|
+
grid-column: 1;
|
|
111
|
+
min-inline-size: 0;
|
|
112
|
+
}
|
|
113
|
+
esp-image[banner]:not(:defined) > [slot="overlay"] {
|
|
114
|
+
grid-row: 3;
|
|
115
|
+
max-inline-size: var(--esp-image-overlay-measure, none);
|
|
116
|
+
padding: var(--_esp-image-static-pad);
|
|
117
|
+
}
|
|
118
|
+
/* A lone headline carries the overlay padding here; content-box keeps a
|
|
119
|
+
measure bounding its text, as after upgrade, where that padding belongs to
|
|
120
|
+
the overlay rather than the headline. */
|
|
121
|
+
esp-image[banner]:not(:defined):not(:has(> [slot="overlay-supporting"], > [slot="overlay-action"]))
|
|
122
|
+
> [slot="overlay"] {
|
|
123
|
+
box-sizing: content-box;
|
|
124
|
+
}
|
|
125
|
+
esp-image[banner]:not(:defined) > [slot="overlay-supporting"] {
|
|
126
|
+
grid-row: 4;
|
|
127
|
+
}
|
|
128
|
+
esp-image[banner]:not(:defined) > [slot="overlay-action"] {
|
|
129
|
+
grid-row: 5;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* A copy stack: supporting copy or an action is present. */
|
|
133
|
+
esp-image[banner]:not(:defined):has(> [slot="overlay-supporting"], > [slot="overlay-action"])
|
|
134
|
+
> :is([slot="overlay"], [slot="overlay-supporting"], [slot="overlay-action"]) {
|
|
135
|
+
max-inline-size: var(--esp-image-overlay-measure, 36rem);
|
|
136
|
+
margin: var(--_esp-image-static-pad) !important;
|
|
137
|
+
}
|
|
138
|
+
esp-image[banner]:not(:defined):has(> [slot="overlay-supporting"], > [slot="overlay-action"])
|
|
139
|
+
> [slot="overlay"] {
|
|
140
|
+
padding: 0;
|
|
141
|
+
}
|
|
142
|
+
esp-image[banner]:not(:defined):has(> [slot="overlay-supporting"], > [slot="overlay-action"])
|
|
143
|
+
> [slot="overlay"]:has(~ [slot="overlay-supporting"], ~ [slot="overlay-action"]) {
|
|
144
|
+
margin-block-end: 0 !important;
|
|
145
|
+
}
|
|
146
|
+
esp-image[banner]:not(:defined) > [slot="overlay"] ~ [slot="overlay-supporting"] {
|
|
147
|
+
margin-block-start: var(--_esp-image-static-gap) !important;
|
|
148
|
+
}
|
|
149
|
+
esp-image[banner]:not(:defined) > [slot="overlay-supporting"]:has(~ [slot="overlay-action"]) {
|
|
150
|
+
margin-block-end: 0 !important;
|
|
151
|
+
}
|
|
152
|
+
esp-image[banner]:not(:defined)
|
|
153
|
+
> :is([slot="overlay"], [slot="overlay-supporting"])
|
|
154
|
+
~ [slot="overlay-action"] {
|
|
155
|
+
margin-block-start: calc(2 * var(--_esp-image-static-gap)) !important;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Defaults the upgraded overlay gives its supporting copy and action. They
|
|
159
|
+
carry no specificity, so page styles win here exactly as they do after
|
|
160
|
+
upgrade. */
|
|
161
|
+
:where(esp-image[banner]:not(:defined)) > :where([slot="overlay-supporting"]) {
|
|
162
|
+
font-family: var(--esp-font-body, inherit);
|
|
163
|
+
font-weight: var(--esp-type-lead-font-weight, var(--esp-font-weight-body, 400));
|
|
164
|
+
font-size: var(--esp-type-lead-font-size, 1.25rem);
|
|
165
|
+
line-height: 1.4;
|
|
166
|
+
}
|
|
167
|
+
:where(esp-image[banner]:not(:defined)) > :where(a[slot="overlay-action"], button[slot="overlay-action"]) {
|
|
168
|
+
display: inline-flex;
|
|
169
|
+
align-items: center;
|
|
170
|
+
justify-content: center;
|
|
171
|
+
box-sizing: border-box;
|
|
172
|
+
min-block-size: 2.75rem;
|
|
173
|
+
padding: 0.5em 1.25em;
|
|
174
|
+
border: 2px solid currentColor;
|
|
175
|
+
border-radius: var(--esp-size-border-radius, 0.375rem);
|
|
176
|
+
background: transparent;
|
|
177
|
+
font-family: var(--esp-font-body, inherit);
|
|
178
|
+
font-size: var(--esp-type-normal, 1rem);
|
|
179
|
+
font-weight: 600;
|
|
180
|
+
line-height: 1.2;
|
|
181
|
+
text-align: center;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Compact band: below the default compact width the image keeps the compact
|
|
185
|
+
ratio in its own row and the copy follows on the banner scheme's surface. */
|
|
186
|
+
esp-image[banner][compact-placement="below"]:not(:defined) {
|
|
187
|
+
background-color: var(--esp-image-scrim-color, var(--esp-color-background, oklch(0.98 0 0)));
|
|
188
|
+
}
|
|
189
|
+
esp-image[banner][compact-placement="below"][banner-scheme="light"]:not(:defined) {
|
|
190
|
+
background-color: var(
|
|
191
|
+
--esp-image-scrim-color,
|
|
192
|
+
oklch(from var(--esp-color-background, oklch(0.98 0 0)) 0.97 c h)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
esp-image[banner][compact-placement="below"][banner-scheme="dark"]:not(:defined) {
|
|
196
|
+
background-color: var(
|
|
197
|
+
--esp-image-scrim-color,
|
|
198
|
+
oklch(from var(--esp-color-background, oklch(0.98 0 0)) 0.13 c h)
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
@container (width < 40rem) {
|
|
202
|
+
esp-image[banner]:not(:defined) > :is(picture, img) {
|
|
203
|
+
aspect-ratio: var(--esp-image-static-compact-ratio, var(--esp-image-static-ratio, auto));
|
|
204
|
+
}
|
|
205
|
+
esp-image[banner][compact-placement="below"]:not(:defined) > :is(picture, img) {
|
|
206
|
+
grid-row: 1;
|
|
207
|
+
}
|
|
208
|
+
esp-image[banner][compact-placement="below"]:not(:defined)
|
|
209
|
+
> :is([slot="overlay"], [slot="overlay-supporting"], [slot="overlay-action"]) {
|
|
210
|
+
color: var(--esp-image-overlay-color, var(--esp-color-headings, oklch(0.2 0 0)));
|
|
211
|
+
text-shadow: none;
|
|
212
|
+
}
|
|
213
|
+
esp-image[banner][compact-placement="below"][banner-scheme="light"]:not(:defined)
|
|
214
|
+
> :is([slot="overlay"], [slot="overlay-supporting"], [slot="overlay-action"]) {
|
|
215
|
+
color: var(
|
|
216
|
+
--esp-image-overlay-color,
|
|
217
|
+
oklch(from var(--esp-color-headings, oklch(0.2 0 0)) 0.2 c h)
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
esp-image[banner][compact-placement="below"][banner-scheme="dark"]:not(:defined)
|
|
221
|
+
> :is([slot="overlay"], [slot="overlay-supporting"], [slot="overlay-action"]) {
|
|
222
|
+
color: var(
|
|
223
|
+
--esp-image-overlay-color,
|
|
224
|
+
oklch(from var(--esp-color-headings, oklch(0.2 0 0)) 0.97 c h)
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* The image never moves under reduced motion, before upgrade as after. */
|
|
230
|
+
@media (prefers-reduced-motion: reduce) {
|
|
231
|
+
esp-image[banner]:not(:defined) > picture,
|
|
232
|
+
esp-image[banner]:not(:defined) > picture > img,
|
|
233
|
+
esp-image[banner]:not(:defined) > img {
|
|
234
|
+
animation: none !important;
|
|
235
|
+
transition: none !important;
|
|
236
|
+
}
|
|
237
|
+
}
|