@kubex/zinc 1.1.97 → 1.1.99
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/AGENTS.md +5 -0
- package/CLAUDE.md +5 -0
- package/dist/chunks/zn.R2EAU6OS.js +1 -0
- package/dist/custom-elements.json +14747 -12528
- package/dist/vscode.html-custom-data.json +386 -61
- package/dist/web-types.json +1232 -481
- package/dist/zn.d.ts +529 -11
- package/dist/zn.min.js +649 -478
- package/docs/pages/components/background.md +143 -0
- package/docs/pages/components/button.md +11 -1
- package/docs/pages/components/chart.md +165 -3
- package/docs/pages/components/checkbox-group.md +13 -1
- package/docs/pages/components/checkbox.md +59 -1
- package/docs/pages/components/icon-picker.md +8 -0
- package/docs/pages/components/radio-group.md +12 -0
- package/docs/pages/components/radio.md +188 -0
- package/docs/pages/components/remarkd-editor.md +22 -0
- package/docs/pages/components/scroll-container.md +14 -15
- package/docs/pages/components/thumbnail-group.md +216 -0
- package/docs/pages/components/thumbnail.md +349 -0
- package/docs/pages/components/well.md +34 -0
- package/package.json +1 -1
- package/src/components/background/background.component.ts +111 -0
- package/src/components/background/background.scss +236 -0
- package/src/components/background/background.test.ts +120 -0
- package/src/components/background/index.ts +12 -0
- package/src/components/button/button.component.ts +8 -0
- package/src/components/chart/builders.test.ts +190 -1
- package/src/components/chart/builders.ts +246 -4
- package/src/components/chart/chart.component.ts +33 -1
- package/src/components/chart/chart.test.ts +66 -1
- package/src/components/chart/echarts-loader.ts +10 -0
- package/src/components/checkbox/checkbox.component.ts +62 -6
- package/src/components/checkbox/checkbox.scss +1 -0
- package/src/components/checkbox/checkbox.test.ts +56 -0
- package/src/components/checkbox-group/checkbox-group.component.ts +15 -0
- package/src/components/checkbox-group/checkbox-group.scss +23 -5
- package/src/components/checkbox-group/checkbox-group.test.ts +15 -0
- package/src/components/collapsible/collapsible.component.ts +49 -4
- package/src/components/collapsible/collapsible.scss +33 -14
- package/src/components/confirm/confirm.component.ts +3 -3
- package/src/components/confirm/confirm.test.ts +15 -0
- package/src/components/dialog/dialog.component.ts +3 -2
- package/src/components/editor/editor.component.ts +7 -6
- package/src/components/header/header.scss +2 -2
- package/src/components/icon-picker/icon-picker.component.ts +3 -0
- package/src/components/icon-picker/lucide-icons.ts +1756 -0
- package/src/components/navbar/navbar.scss +11 -0
- package/src/components/page/page.scss +1 -1
- package/src/components/radio/radio.component.ts +63 -7
- package/src/components/radio/radio.scss +1 -0
- package/src/components/radio/radio.test.ts +56 -0
- package/src/components/radio-group/radio-group.component.ts +16 -3
- package/src/components/radio-group/radio-group.scss +23 -4
- package/src/components/radio-group/radio-group.test.ts +15 -0
- package/src/components/remarkd-editor/remarkd-editor.component.ts +118 -5
- package/src/components/remarkd-editor/remarkd-editor.scss +8 -1
- package/src/components/remarkd-editor/remarkd-editor.test.ts +135 -0
- package/src/components/scroll-container/scroll-container.component.ts +15 -1
- package/src/components/scroll-container/scroll-container.scss +4 -2
- package/src/components/scroll-container/scroll-container.test.ts +13 -0
- package/src/components/slideout/slideout.component.ts +3 -2
- package/src/components/split-pane/split-pane.scss +21 -15
- package/src/components/thumbnail/index.ts +12 -0
- package/src/components/thumbnail/thumbnail.component.ts +460 -0
- package/src/components/thumbnail/thumbnail.scss +360 -0
- package/src/components/thumbnail/thumbnail.test.ts +379 -0
- package/src/components/thumbnail-group/index.ts +12 -0
- package/src/components/thumbnail-group/thumbnail-group.component.ts +268 -0
- package/src/components/thumbnail-group/thumbnail-group.scss +86 -0
- package/src/components/thumbnail-group/thumbnail-group.test.ts +151 -0
- package/src/components/tile/tile.scss +4 -2
- package/src/components/translation-group/translation-group.test.ts +22 -0
- package/src/components/translations/translations.component.ts +18 -3
- package/src/components/well/well.component.ts +22 -4
- package/src/components/well/well.scss +24 -0
- package/src/components/well/well.test.ts +43 -0
- package/src/form-control.scss +3 -1
- package/src/internal/conditional.ts +2 -2
- package/src/internal/form.ts +2 -1
- package/src/internal/selection-card.ts +19 -0
- package/src/selection-card.scss +187 -0
- package/src/utilities/query.test.ts +18 -1
- package/src/utilities/query.ts +8 -0
- package/src/zinc.ts +3 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
---
|
|
2
|
+
meta:
|
|
3
|
+
title: Thumbnail
|
|
4
|
+
description: A captioned image tile with a fixed aspect ratio, optional corner badges and actions, and optional link or selectable behaviour.
|
|
5
|
+
layout: component
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
A thumbnail is a single media preview with its title beneath it. Thumbnails are usually placed inside a
|
|
9
|
+
[thumbnail group](/components/thumbnail-group), which lays them out as a scrollable row that expands into a grid.
|
|
10
|
+
|
|
11
|
+
```html:preview
|
|
12
|
+
<div style="width: 200px;">
|
|
13
|
+
<zn-thumbnail
|
|
14
|
+
src="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=600&q=60"
|
|
15
|
+
caption="Tahoe Day">
|
|
16
|
+
</zn-thumbnail>
|
|
17
|
+
</div>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### Aspect Ratio
|
|
23
|
+
|
|
24
|
+
The media frame is `16 / 9` by default. Set the `aspect-ratio` attribute to any CSS aspect ratio to change it — the
|
|
25
|
+
image is cropped to fill the frame, so captions stay aligned across a row whatever the source dimensions are.
|
|
26
|
+
|
|
27
|
+
```html:preview
|
|
28
|
+
<div style="display: flex; gap: 16px;">
|
|
29
|
+
<div style="width: 160px;">
|
|
30
|
+
<zn-thumbnail
|
|
31
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&q=60"
|
|
32
|
+
caption="16 / 9">
|
|
33
|
+
</zn-thumbnail>
|
|
34
|
+
</div>
|
|
35
|
+
<div style="width: 160px;">
|
|
36
|
+
<zn-thumbnail
|
|
37
|
+
aspect-ratio="1 / 1"
|
|
38
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&q=60"
|
|
39
|
+
caption="1 / 1">
|
|
40
|
+
</zn-thumbnail>
|
|
41
|
+
</div>
|
|
42
|
+
<div style="width: 160px;">
|
|
43
|
+
<zn-thumbnail
|
|
44
|
+
aspect-ratio="3 / 4"
|
|
45
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&q=60"
|
|
46
|
+
caption="3 / 4">
|
|
47
|
+
</zn-thumbnail>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The `--zn-thumbnail-aspect-ratio` custom property does the same thing, and because it inherits you can set it once on
|
|
53
|
+
any ancestor — a wrapper, or a [thumbnail group](/components/thumbnail-group) — to reshape every thumbnail beneath it.
|
|
54
|
+
A thumbnail's own `aspect-ratio` attribute still wins over an inherited value.
|
|
55
|
+
|
|
56
|
+
```html:preview
|
|
57
|
+
<div style="display: flex; gap: 16px; --zn-thumbnail-aspect-ratio: 1 / 1;">
|
|
58
|
+
<div style="width: 160px;">
|
|
59
|
+
<zn-thumbnail
|
|
60
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&q=60"
|
|
61
|
+
caption="Inherited 1 / 1">
|
|
62
|
+
</zn-thumbnail>
|
|
63
|
+
</div>
|
|
64
|
+
<div style="width: 160px;">
|
|
65
|
+
<zn-thumbnail
|
|
66
|
+
src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=600&q=60"
|
|
67
|
+
caption="Inherited 1 / 1">
|
|
68
|
+
</zn-thumbnail>
|
|
69
|
+
</div>
|
|
70
|
+
<div style="width: 160px;">
|
|
71
|
+
<zn-thumbnail
|
|
72
|
+
aspect-ratio="16 / 9"
|
|
73
|
+
src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=600&q=60"
|
|
74
|
+
caption="Overridden">
|
|
75
|
+
</zn-thumbnail>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Badges and Actions
|
|
81
|
+
|
|
82
|
+
The `badge` slot pins content to the bottom-left of the media and the `actions` slot pins it to the bottom-right. Use
|
|
83
|
+
`icon` for the common case of a single badge icon.
|
|
84
|
+
|
|
85
|
+
Each slotted element becomes its own chip, so several actions read as separate icons dotted along the thumbnail rather
|
|
86
|
+
than a single grouped pill. `--zn-thumbnail-chip-gap` controls the spacing between them, and
|
|
87
|
+
`--zn-thumbnail-chip-background` / `--zn-thumbnail-chip-color` restyle them.
|
|
88
|
+
|
|
89
|
+
A badge describes the asset rather than doing something, so it keeps the chip's shape but is held back on opacity
|
|
90
|
+
(`--zn-thumbnail-badge-opacity`, default `0.65`) and takes no pointer events — clicks pass straight through to the
|
|
91
|
+
thumbnail. Actions keep full opacity, the pointer cursor and a hover state. `--zn-thumbnail-chip-radius` rounds both off.
|
|
92
|
+
|
|
93
|
+
The overlay sits **outside** the thumbnail's link, so anything you put in `actions` keeps its own click behaviour — a
|
|
94
|
+
download link downloads, a button's handler runs — and never selects the thumbnail or follows its `href`.
|
|
95
|
+
|
|
96
|
+
```html:preview
|
|
97
|
+
<div style="display: flex; gap: 16px;">
|
|
98
|
+
<div style="width: 180px;">
|
|
99
|
+
<zn-thumbnail
|
|
100
|
+
src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=600&q=60"
|
|
101
|
+
caption="Sequoia Sunrise"
|
|
102
|
+
icon="play_arrow">
|
|
103
|
+
</zn-thumbnail>
|
|
104
|
+
</div>
|
|
105
|
+
<div style="width: 180px;">
|
|
106
|
+
<zn-thumbnail
|
|
107
|
+
src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=600&q=60"
|
|
108
|
+
caption="One action"
|
|
109
|
+
icon="play_arrow">
|
|
110
|
+
<a slot="actions" href="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05" download>
|
|
111
|
+
<zn-icon src="download" size="14"></zn-icon>
|
|
112
|
+
</a>
|
|
113
|
+
</zn-thumbnail>
|
|
114
|
+
</div>
|
|
115
|
+
<div style="width: 180px;">
|
|
116
|
+
<zn-thumbnail
|
|
117
|
+
src="https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=600&q=60"
|
|
118
|
+
caption="Three actions"
|
|
119
|
+
icon="play_arrow">
|
|
120
|
+
<zn-icon slot="actions" src="download" size="14"></zn-icon>
|
|
121
|
+
<zn-icon slot="actions" src="share" size="14"></zn-icon>
|
|
122
|
+
<zn-icon slot="actions" src="more_horiz" size="14"></zn-icon>
|
|
123
|
+
</zn-thumbnail>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Preview
|
|
129
|
+
|
|
130
|
+
Provide `full-uri` and the thumbnail becomes previewable: activating it opens a full-screen overlay that grows out of
|
|
131
|
+
the thumbnail's position, over a backdrop, with rounded edges. Escape, the close button, or a click on the backdrop
|
|
132
|
+
shrinks it back to where it came from.
|
|
133
|
+
|
|
134
|
+
The panel takes the asset's own aspect ratio, so it wraps the image rather than letterboxing it in a fixed-shape box —
|
|
135
|
+
which also means the close button sits on the image's top-right corner, not on a surrounding container. It grows to
|
|
136
|
+
whichever of `--zn-thumbnail-preview-max-width` (70vw) or `--zn-thumbnail-preview-max-height` (70vh) it reaches first,
|
|
137
|
+
so it always leaves the page visible around it.
|
|
138
|
+
|
|
139
|
+
The ratio is measured from the thumbnail's own already-loaded image, which shares it with the full-size asset. That
|
|
140
|
+
keeps the panel's size known before the large file arrives, so the grow animation has a correct target from the first
|
|
141
|
+
frame; the thumbnail image is held behind it, blurred, in the meantime, and the panel resizes only if the full asset
|
|
142
|
+
turns out to be a genuinely different shape. Override the measurement with `--zn-thumbnail-preview-aspect-ratio` — for
|
|
143
|
+
slotted media that can't be measured, for instance — and round the corners with `--zn-thumbnail-preview-radius`.
|
|
144
|
+
|
|
145
|
+
```html:preview
|
|
146
|
+
<div style="display: flex; gap: 16px;">
|
|
147
|
+
<div style="width: 180px;">
|
|
148
|
+
<zn-thumbnail
|
|
149
|
+
src="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=400&q=50"
|
|
150
|
+
full-uri="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=2000&q=80"
|
|
151
|
+
caption="Tahoe Day">
|
|
152
|
+
</zn-thumbnail>
|
|
153
|
+
</div>
|
|
154
|
+
<div style="width: 180px;">
|
|
155
|
+
<zn-thumbnail
|
|
156
|
+
src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=400&q=50"
|
|
157
|
+
full-uri="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=2000&q=80"
|
|
158
|
+
caption="Sequoia Sunrise">
|
|
159
|
+
</zn-thumbnail>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Because the preview opens in the browser's top layer, it escapes a [thumbnail group](/components/thumbnail-group)'s
|
|
165
|
+
scrolling row rather than being clipped by it.
|
|
166
|
+
|
|
167
|
+
#### Preview Trigger
|
|
168
|
+
|
|
169
|
+
By default a plain click opens the preview. Set `preview-trigger="button"` to put a dedicated expand control on the
|
|
170
|
+
media instead, leaving clicks free for selection or for the thumbnail's `href`.
|
|
171
|
+
|
|
172
|
+
```html:preview
|
|
173
|
+
<zn-thumbnail-group caption="Pick a still" selectable>
|
|
174
|
+
<zn-thumbnail
|
|
175
|
+
value="tahoe"
|
|
176
|
+
preview-trigger="button"
|
|
177
|
+
src="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=400&q=50"
|
|
178
|
+
full-uri="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=2000&q=80"
|
|
179
|
+
caption="Tahoe Day"
|
|
180
|
+
selected>
|
|
181
|
+
</zn-thumbnail>
|
|
182
|
+
<zn-thumbnail
|
|
183
|
+
value="sequoia"
|
|
184
|
+
preview-trigger="button"
|
|
185
|
+
src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=400&q=50"
|
|
186
|
+
full-uri="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=2000&q=80"
|
|
187
|
+
caption="Sequoia Sunrise">
|
|
188
|
+
</zn-thumbnail>
|
|
189
|
+
<zn-thumbnail
|
|
190
|
+
value="sonoma"
|
|
191
|
+
preview-trigger="button"
|
|
192
|
+
src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=400&q=50"
|
|
193
|
+
full-uri="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=2000&q=80"
|
|
194
|
+
caption="Sonoma Horizon">
|
|
195
|
+
</zn-thumbnail>
|
|
196
|
+
</zn-thumbnail-group>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
When both `href` and `full-uri` are set, a plain left click previews while modifier and middle clicks still open the
|
|
200
|
+
link in a new tab. Cancelling `zn-select` suppresses the preview (and the navigation) entirely, and `showPreview()` /
|
|
201
|
+
`hidePreview()` drive the overlay from script.
|
|
202
|
+
|
|
203
|
+
#### Previewing Other Media
|
|
204
|
+
|
|
205
|
+
The `preview` slot replaces the preview's contents, so the full-size asset doesn't have to be an image. Filling the
|
|
206
|
+
slot enables the preview on its own — `full-uri` isn't needed.
|
|
207
|
+
|
|
208
|
+
```html:preview
|
|
209
|
+
<div style="width: 180px;">
|
|
210
|
+
<zn-thumbnail
|
|
211
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=400&q=50"
|
|
212
|
+
caption="Big Sur">
|
|
213
|
+
<video slot="preview" controls autoplay muted
|
|
214
|
+
poster="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1200&q=70"
|
|
215
|
+
src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"></video>
|
|
216
|
+
</zn-thumbnail>
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Links
|
|
221
|
+
|
|
222
|
+
Set `href` to render the thumbnail as an anchor. `target` is forwarded to it.
|
|
223
|
+
|
|
224
|
+
```html:preview
|
|
225
|
+
<div style="width: 180px;">
|
|
226
|
+
<zn-thumbnail
|
|
227
|
+
src="https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=600&q=60"
|
|
228
|
+
caption="Goa Beaches"
|
|
229
|
+
href="https://unsplash.com"
|
|
230
|
+
target="_blank">
|
|
231
|
+
</zn-thumbnail>
|
|
232
|
+
</div>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Selected
|
|
236
|
+
|
|
237
|
+
`selected` draws the accent ring. A [thumbnail group](/components/thumbnail-group) with `selectable` manages this for
|
|
238
|
+
you; set it by hand when you're tracking selection yourself from the `zn-select` event.
|
|
239
|
+
|
|
240
|
+
A thumbnail only enters the tab order when it's a link or when `selectable` is set — a group with `selectable` sets
|
|
241
|
+
that on its children for you. If you're handling `zn-select` yourself, set `selectable` too so the thumbnail is
|
|
242
|
+
reachable by keyboard and announced as a button.
|
|
243
|
+
|
|
244
|
+
```html:preview
|
|
245
|
+
<div style="display: flex; gap: 16px;">
|
|
246
|
+
<div style="width: 180px;">
|
|
247
|
+
<zn-thumbnail
|
|
248
|
+
src="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=600&q=60"
|
|
249
|
+
caption="Selected"
|
|
250
|
+
selected>
|
|
251
|
+
</zn-thumbnail>
|
|
252
|
+
</div>
|
|
253
|
+
<div style="width: 180px;">
|
|
254
|
+
<zn-thumbnail
|
|
255
|
+
src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=600&q=60"
|
|
256
|
+
caption="Not selected">
|
|
257
|
+
</zn-thumbnail>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Active
|
|
263
|
+
|
|
264
|
+
`active` draws a ring in a second colour, for the thumbnail currently in use — playing, open, being edited — as opposed
|
|
265
|
+
to the one the user has picked. It's independent of `selected`, and takes the ring colour when a thumbnail is both.
|
|
266
|
+
Recolour either ring with `--zn-thumbnail-active-color` and `--zn-thumbnail-selected-color`.
|
|
267
|
+
|
|
268
|
+
```html:preview
|
|
269
|
+
<div style="display: flex; gap: 16px;">
|
|
270
|
+
<div style="width: 160px;">
|
|
271
|
+
<zn-thumbnail
|
|
272
|
+
src="https://images.unsplash.com/photo-1439066615861-d1af74d74000?w=600&q=60"
|
|
273
|
+
caption="Idle">
|
|
274
|
+
</zn-thumbnail>
|
|
275
|
+
</div>
|
|
276
|
+
<div style="width: 160px;">
|
|
277
|
+
<zn-thumbnail
|
|
278
|
+
src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=600&q=60"
|
|
279
|
+
caption="Selected"
|
|
280
|
+
selected>
|
|
281
|
+
</zn-thumbnail>
|
|
282
|
+
</div>
|
|
283
|
+
<div style="width: 160px;">
|
|
284
|
+
<zn-thumbnail
|
|
285
|
+
src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=600&q=60"
|
|
286
|
+
caption="Active"
|
|
287
|
+
icon="play_arrow"
|
|
288
|
+
active>
|
|
289
|
+
</zn-thumbnail>
|
|
290
|
+
</div>
|
|
291
|
+
<div style="width: 160px;">
|
|
292
|
+
<zn-thumbnail
|
|
293
|
+
src="https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=600&q=60"
|
|
294
|
+
caption="Both"
|
|
295
|
+
selected
|
|
296
|
+
active>
|
|
297
|
+
</zn-thumbnail>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Disabled
|
|
303
|
+
|
|
304
|
+
A disabled thumbnail is dimmed, emits no `zn-select`, and renders as a plain element rather than a link.
|
|
305
|
+
|
|
306
|
+
```html:preview
|
|
307
|
+
<div style="width: 180px;">
|
|
308
|
+
<zn-thumbnail
|
|
309
|
+
src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=600&q=60"
|
|
310
|
+
caption="Processing"
|
|
311
|
+
href="/media/1"
|
|
312
|
+
disabled>
|
|
313
|
+
</zn-thumbnail>
|
|
314
|
+
</div>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Custom Media
|
|
318
|
+
|
|
319
|
+
Leave `src` unset and slot your own media into the `image` slot (or the default slot) — a `<video>`, a `<canvas>`, or
|
|
320
|
+
an icon placeholder. Slotted media is stretched to fill the frame.
|
|
321
|
+
|
|
322
|
+
```html:preview
|
|
323
|
+
<div style="display: flex; gap: 16px;">
|
|
324
|
+
<div style="width: 180px;">
|
|
325
|
+
<zn-thumbnail caption="No preview">
|
|
326
|
+
<zn-icon slot="image" src="image" size="32" color="disabled"></zn-icon>
|
|
327
|
+
</zn-thumbnail>
|
|
328
|
+
</div>
|
|
329
|
+
<div style="width: 180px;">
|
|
330
|
+
<zn-thumbnail caption="Colour block">
|
|
331
|
+
<div slot="image" style="background: linear-gradient(135deg, #8967ef, #38bdf8);"></div>
|
|
332
|
+
</zn-thumbnail>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Without a Caption
|
|
338
|
+
|
|
339
|
+
Set `hide-caption` to render just the media frame.
|
|
340
|
+
|
|
341
|
+
```html:preview
|
|
342
|
+
<div style="width: 180px;">
|
|
343
|
+
<zn-thumbnail
|
|
344
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&q=60"
|
|
345
|
+
caption="Hidden"
|
|
346
|
+
hide-caption>
|
|
347
|
+
</zn-thumbnail>
|
|
348
|
+
</div>
|
|
349
|
+
```
|
|
@@ -45,6 +45,40 @@ Use the `inline` attribute to display the well as an inline-flex element, allowi
|
|
|
45
45
|
</p>
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
### Preformatted Content
|
|
49
|
+
|
|
50
|
+
Use the `pre` attribute to render the content inside a `pre` element. Whitespace and line breaks are preserved and the content is rendered in a monospace font. Long lines scroll horizontally rather than widening the well.
|
|
51
|
+
|
|
52
|
+
```html:preview
|
|
53
|
+
<zn-well pre icon="terminal">$ zinc build --watch
|
|
54
|
+
compiling components...
|
|
55
|
+
done in 1.2s</zn-well>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Breaking Long Words
|
|
59
|
+
|
|
60
|
+
Use the `break-long` attribute to break long unbroken strings — tokens, hashes, URLs — so they wrap inside the well instead of forcing it wider than its container.
|
|
61
|
+
|
|
62
|
+
```html:preview
|
|
63
|
+
<div style="width: 320px;">
|
|
64
|
+
<p>Without <code>break-long</code>:</p>
|
|
65
|
+
<zn-well icon="key">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJVadQssw5c</zn-well>
|
|
66
|
+
|
|
67
|
+
<p>With <code>break-long</code>:</p>
|
|
68
|
+
<zn-well break-long icon="key">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJVadQssw5c</zn-well>
|
|
69
|
+
</div>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Preformatted and Broken
|
|
73
|
+
|
|
74
|
+
Combine `pre` and `break-long` to keep the monospace font and line breaks while still wrapping long lines instead of scrolling them.
|
|
75
|
+
|
|
76
|
+
```html:preview
|
|
77
|
+
<div style="width: 320px;">
|
|
78
|
+
<zn-well pre break-long icon="key">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJVadQssw5c</zn-well>
|
|
79
|
+
</div>
|
|
80
|
+
```
|
|
81
|
+
|
|
48
82
|
### Inline vs Block
|
|
49
83
|
|
|
50
84
|
Compare the difference between inline and block (default) display modes.
|
package/package.json
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
2
|
+
import {property} from 'lit/decorators.js';
|
|
3
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
4
|
+
import {styleMap} from 'lit/directives/style-map.js';
|
|
5
|
+
import ZincElement from '../../internal/zinc-element';
|
|
6
|
+
import ZnIcon from '../icon';
|
|
7
|
+
|
|
8
|
+
import styles from './background.scss';
|
|
9
|
+
|
|
10
|
+
export type BackgroundImageStrength = 'soft' | 'medium' | 'full';
|
|
11
|
+
export type BackgroundMotion = 'none' | 'drift' | 'breathe';
|
|
12
|
+
export type BackgroundOverlay = 'none' | 'soft' | 'strong';
|
|
13
|
+
export type BackgroundOverlayTone = 'light' | 'dark';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @summary Composes a colour, decorative image, image strength, optional motion and contrast overlay behind slotted content.
|
|
17
|
+
*
|
|
18
|
+
* @documentation https://zinc.style/components/background
|
|
19
|
+
* @status experimental
|
|
20
|
+
* @since 1.0
|
|
21
|
+
*
|
|
22
|
+
* @dependency zn-icon
|
|
23
|
+
*
|
|
24
|
+
* @slot - Content displayed above the background layers.
|
|
25
|
+
*
|
|
26
|
+
* @csspart base - The component's full-size background canvas.
|
|
27
|
+
* @csspart image - The decorative background image.
|
|
28
|
+
* @csspart overlay - The contrast overlay between the image and content.
|
|
29
|
+
* @csspart floating-icons - The non-interactive layer containing the floating icons.
|
|
30
|
+
* @csspart floating-icon - Each floating `zn-icon`.
|
|
31
|
+
* @csspart content - The wrapper around the default slot.
|
|
32
|
+
*
|
|
33
|
+
* @cssproperty --zn-background-color - Fallback colour when the `color` attribute is not set.
|
|
34
|
+
* @cssproperty --zn-background-image-position - Position of the background image. Defaults to `center`.
|
|
35
|
+
* @cssproperty --zn-background-overlay-angle - Direction of the overlay gradient. Defaults to `110deg`.
|
|
36
|
+
* @cssproperty --zn-background-floating-icon-color - Colour of the floating icons. Defaults to `currentColor`.
|
|
37
|
+
*/
|
|
38
|
+
export default class ZnBackground extends ZincElement {
|
|
39
|
+
static styles: CSSResultGroup = unsafeCSS(styles);
|
|
40
|
+
static dependencies = {'zn-icon': ZnIcon};
|
|
41
|
+
|
|
42
|
+
private readonly resizeObserver = new ResizeController<number>(this, {
|
|
43
|
+
callback: entries => {
|
|
44
|
+
const width = entries[0]?.contentRect.width ?? this.offsetWidth;
|
|
45
|
+
return Math.max(1, Math.min(width * 0.05, 150));
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/** URL of the decorative background image. */
|
|
50
|
+
@property() image = '';
|
|
51
|
+
|
|
52
|
+
/** CSS colour painted beneath the image. */
|
|
53
|
+
@property() color = '';
|
|
54
|
+
|
|
55
|
+
/** Visibility of the image: `soft` (30%), `medium` (62%) or `full` (100%). */
|
|
56
|
+
@property({attribute: 'image-strength', reflect: true}) imageStrength: BackgroundImageStrength = 'full';
|
|
57
|
+
|
|
58
|
+
/** Subtle animation applied to the image. Motion stops when reduced motion is requested. */
|
|
59
|
+
@property({reflect: true}) motion: BackgroundMotion = 'none';
|
|
60
|
+
|
|
61
|
+
/** Strength of the contrast gradient above the image. */
|
|
62
|
+
@property({reflect: true}) overlay: BackgroundOverlay = 'soft';
|
|
63
|
+
|
|
64
|
+
/** Whether the overlay uses a light or dark contrast treatment. */
|
|
65
|
+
@property({attribute: 'overlay-tone', reflect: true}) overlayTone: BackgroundOverlayTone = 'light';
|
|
66
|
+
|
|
67
|
+
/** Comma-separated Zinc icon names placed as ambient decoration. At most eight are rendered. */
|
|
68
|
+
@property({attribute: 'floating-icons'}) floatingIcons = '';
|
|
69
|
+
|
|
70
|
+
/** Pauses background motion without changing the selected motion treatment. */
|
|
71
|
+
@property({type: Boolean, reflect: true}) paused = false;
|
|
72
|
+
|
|
73
|
+
render() {
|
|
74
|
+
const floatingIcons = this.floatingIcons
|
|
75
|
+
.split(',')
|
|
76
|
+
.map(icon => icon.trim())
|
|
77
|
+
.filter(Boolean)
|
|
78
|
+
.slice(0, 8);
|
|
79
|
+
const floatingIconSize = this.resizeObserver.value ?? 1;
|
|
80
|
+
|
|
81
|
+
return html`
|
|
82
|
+
<div
|
|
83
|
+
part="base"
|
|
84
|
+
class="background"
|
|
85
|
+
style=${styleMap({'--_zn-background-color': this.color || undefined})}>
|
|
86
|
+
${this.image ? html`
|
|
87
|
+
<img
|
|
88
|
+
part="image"
|
|
89
|
+
class="background__image"
|
|
90
|
+
src=${this.image}
|
|
91
|
+
alt=""
|
|
92
|
+
decoding="async">
|
|
93
|
+
` : ''}
|
|
94
|
+
<div part="overlay" class="background__overlay" aria-hidden="true"></div>
|
|
95
|
+
${floatingIcons.length ? html`
|
|
96
|
+
<div part="floating-icons" class="background__floating-icons" aria-hidden="true">
|
|
97
|
+
${floatingIcons.map(icon => html`
|
|
98
|
+
<zn-icon
|
|
99
|
+
part="floating-icon"
|
|
100
|
+
class="background__floating-icon"
|
|
101
|
+
src=${icon}
|
|
102
|
+
size=${floatingIconSize}
|
|
103
|
+
aria-hidden="true"></zn-icon>
|
|
104
|
+
`)}
|
|
105
|
+
</div>
|
|
106
|
+
` : ''}
|
|
107
|
+
<div part="content" class="background__content"><slot></slot></div>
|
|
108
|
+
</div>
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
}
|