@kubex/zinc 1.0.25 → 1.0.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/.claude/project.md +556 -0
- package/.github/workflows/js_build_and_deploy.yaml +9 -10
- package/dist/custom-elements.json +13575 -8856
- package/dist/vscode.html-custom-data.json +583 -48
- package/dist/web-types.json +1441 -181
- package/dist/zn.d.ts +1645 -660
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +1412 -893
- package/docs/_utilities/code-previews.cjs +10 -1
- package/docs/assets/scripts/docs.js +42 -18
- package/docs/data/data-table.json +229 -66
- package/docs/data/empty.json +6 -0
- package/docs/data/products-table.json +41 -193
- package/docs/pages/components/action-bar.md +121 -6
- package/docs/pages/components/alert.md +118 -15
- package/docs/pages/components/animated-button.md +299 -0
- package/docs/pages/components/audio-select.md +534 -0
- package/docs/pages/components/bulk-actions.md +79 -5
- package/docs/pages/components/button-group.md +235 -27
- package/docs/pages/components/button.md +139 -1
- package/docs/pages/components/chart.md +365 -9
- package/docs/pages/components/checkbox.md +387 -58
- package/docs/pages/components/chip.md +253 -33
- package/docs/pages/components/collapsible.md +393 -46
- package/docs/pages/components/cols.md +152 -30
- package/docs/pages/components/confirm.md +182 -16
- package/docs/pages/components/copy-button.md +169 -6
- package/docs/pages/components/data-select.md +194 -15
- package/docs/pages/components/data-table-filter.md +96 -5
- package/docs/pages/components/data-table-search.md +451 -0
- package/docs/pages/components/data-table-sort.md +66 -5
- package/docs/pages/components/data-table.md +727 -66
- package/docs/pages/components/datepicker.md +402 -7
- package/docs/pages/components/defined-label.md +120 -5
- package/docs/pages/components/dialog.md +339 -59
- package/docs/pages/components/dropdown.md +366 -11
- package/docs/pages/components/editor.md +604 -7
- package/docs/pages/components/empty-state.md +315 -16
- package/docs/pages/components/expanding-action.md +212 -28
- package/docs/pages/components/file.md +421 -12
- package/docs/pages/components/filter-container.md +158 -5
- package/docs/pages/components/filter-wrapper.md +167 -6
- package/docs/pages/components/form-group.md +383 -6
- package/docs/pages/components/hover-container.md +237 -6
- package/docs/pages/components/icon-picker.md +121 -0
- package/docs/pages/components/icon.md +454 -48
- package/docs/pages/components/inline-edit.md +787 -19
- package/docs/pages/components/input-group.md +207 -13
- package/docs/pages/components/input.md +194 -0
- package/docs/pages/components/item.md +18 -0
- package/docs/pages/components/key-container.md +115 -0
- package/docs/pages/components/key.md +101 -0
- package/docs/pages/components/menu.md +512 -6
- package/docs/pages/components/note.md +239 -36
- package/docs/pages/components/opt-group.md +107 -0
- package/docs/pages/components/pagination.md +332 -6
- package/docs/pages/components/pane.md +222 -6
- package/docs/pages/components/panel.md +213 -26
- package/docs/pages/components/popup.md +1354 -6
- package/docs/pages/components/priority-list.md +233 -0
- package/docs/pages/components/progress-bar.md +387 -6
- package/docs/pages/components/radio-group.md +242 -5
- package/docs/pages/components/radio.md +474 -6
- package/docs/pages/components/rating.md +331 -7
- package/docs/pages/components/reveal.md +524 -6
- package/docs/pages/components/scroll-container.md +552 -6
- package/docs/pages/components/select.md +762 -160
- package/docs/pages/components/skeleton.md +473 -30
- package/docs/pages/components/slideout.md +261 -5
- package/docs/pages/components/sp.md +99 -41
- package/docs/pages/components/split-button.md +347 -9
- package/docs/pages/components/split-pane.md +445 -6
- package/docs/pages/components/stat.md +549 -9
- package/docs/pages/components/status-indicator.md +230 -1
- package/docs/pages/components/stepper.md +563 -6
- package/docs/pages/components/tabs.md +439 -13
- package/docs/pages/components/textarea.md +415 -17
- package/docs/pages/components/tile.md +385 -26
- package/docs/pages/components/toggle.md +424 -6
- package/docs/pages/components/tooltip.md +367 -0
- package/docs/pages/components/translation-group.md +210 -0
- package/docs/pages/components/translations.md +319 -19
- package/docs/pages/components/vertical-stepper.md +401 -8
- package/docs/pages/components/well.md +300 -3
- package/docs/pages/getting-started/form-controls.md +162 -0
- package/docs/pages/index.md +116 -15
- package/package.json +5 -6
- package/scss/_global-spacing.scss +4 -0
- package/scss/_root.scss +2 -2
- package/scss/boot.scss +19 -0
- package/scss/shared/layout.scss +5 -0
- package/scss/themes/_light.scss +3 -3
- package/src/components/alert/alert.scss +1 -0
- package/src/components/animated-button/README.md +306 -0
- package/src/components/animated-button/animated-button.component.ts +229 -0
- package/src/components/animated-button/animated-button.scss +228 -0
- package/src/components/animated-button/animated-button.test.ts +143 -0
- package/src/components/animated-button/index.ts +12 -0
- package/src/components/button/button.component.ts +5 -0
- package/src/components/button-group/button-group.component.ts +25 -13
- package/src/components/button-group/button-group.scss +6 -0
- package/src/components/checkbox/checkbox.component.ts +4 -0
- package/src/components/checkbox/checkbox.scss +7 -4
- package/src/components/checkbox-group/checkbox-group.scss +7 -0
- package/src/components/chip/chip.component.ts +7 -2
- package/src/components/chip/chip.scss +16 -2
- package/src/components/collapsible/collapsible.component.ts +27 -20
- package/src/components/cols/cols.component.ts +14 -2
- package/src/components/cols/cols.scss +6 -12
- package/src/components/confirm/confirm.component.ts +7 -0
- package/src/components/copy-button/copy-button.component.ts +12 -11
- package/src/components/data-select/data-select.component.ts +215 -44
- package/src/components/data-select/data-select.scss +66 -6
- package/src/components/data-select/providers/currency-data-provider.ts +20 -6
- package/src/components/data-select/providers/provider.ts +1 -0
- package/src/components/data-select/providers/us-state-data-provider.ts +68 -0
- package/src/components/data-table/data-table.component.ts +81 -22
- package/src/components/data-table-search/data-table-search.component.ts +184 -0
- package/src/components/data-table-search/data-table-search.scss +17 -0
- package/src/components/data-table-search/data-table-search.test.ts +11 -0
- package/src/components/data-table-search/index.ts +12 -0
- package/src/components/datepicker/datepicker.component.ts +347 -13
- package/src/components/dialog/dialog.component.ts +1 -1
- package/src/components/empty-state/empty-state.scss +6 -1
- package/src/components/header/header.scss +3 -3
- package/src/components/icon/icon.component.ts +23 -1
- package/src/components/icon/icon.scss +23 -0
- package/src/components/icon-picker/brand-icons.ts +24 -0
- package/src/components/icon-picker/icon-picker.component.ts +407 -0
- package/src/components/icon-picker/icon-picker.scss +205 -0
- package/src/components/icon-picker/index.ts +12 -0
- package/src/components/icon-picker/line-icons.ts +612 -0
- package/src/components/icon-picker/material-icons.ts +14543 -0
- package/src/components/inline-edit/inline-edit.component.ts +190 -46
- package/src/components/inline-edit/inline-edit.scss +29 -0
- package/src/components/inline-edit/inline-edit.test.ts +314 -1
- package/src/components/input/input.component.ts +324 -5
- package/src/components/input/input.scss +87 -0
- package/src/components/input-group/input-group.component.ts +28 -7
- package/src/components/input-group/input-group.scss +48 -10
- package/src/components/item/item.component.ts +24 -3
- package/src/components/item/item.scss +18 -0
- package/src/components/key/index.ts +12 -0
- package/src/components/key/key.component.ts +47 -0
- package/src/components/key/key.scss +38 -0
- package/src/components/key-container/index.ts +12 -0
- package/src/components/key-container/key-container.component.ts +142 -0
- package/src/components/key-container/key-container.scss +33 -0
- package/src/components/menu-item/menu-item.component.ts +20 -0
- package/src/components/menu-item/menu-item.scss +69 -2
- package/src/components/navbar/navbar.component.ts +103 -11
- package/src/components/navbar/navbar.scss +6 -1
- package/src/components/opt-group/index.ts +12 -0
- package/src/components/opt-group/opt-group.component.ts +74 -0
- package/src/components/opt-group/opt-group.scss +37 -0
- package/src/components/opt-group/opt-group.test.ts +27 -0
- package/src/components/option/option.component.ts +1 -16
- package/src/components/option/option.scss +4 -0
- package/src/components/panel/panel.component.ts +10 -8
- package/src/components/panel/panel.scss +20 -0
- package/src/components/priority-list/index.ts +12 -0
- package/src/components/priority-list/priority-list.component.ts +611 -0
- package/src/components/priority-list/priority-list.scss +185 -0
- package/src/components/priority-list/priority-list.test.ts +139 -0
- package/src/components/progress-bar/progress-bar.component.ts +22 -16
- package/src/components/radio/radio.scss +10 -3
- package/src/components/select/select.component.ts +812 -72
- package/src/components/select/select.scss +108 -2
- package/src/components/select/select.test.ts +147 -2
- package/src/components/settings-container/settings-container.component.ts +44 -19
- package/src/components/settings-container/settings-container.scss +1 -1
- package/src/components/skeleton/skeleton.component.ts +6 -1
- package/src/components/slideout/slideout.scss +8 -3
- package/src/components/sp/sp.component.ts +3 -1
- package/src/components/sp/sp.scss +19 -0
- package/src/components/stepper/stepper.component.ts +16 -10
- package/src/components/textarea/textarea.scss +0 -4
- package/src/components/tile/tile.component.ts +12 -3
- package/src/components/tile/tile.scss +1 -1
- package/src/components/timer/timer.component.ts +15 -2
- package/src/components/toggle/toggle.component.ts +29 -26
- package/src/components/toggle/toggle.scss +13 -1
- package/src/components/translation-group/index.ts +12 -0
- package/src/components/translation-group/translation-group.component.ts +207 -0
- package/src/components/translation-group/translation-group.scss +8 -0
- package/src/components/translations/translations.component.ts +90 -44
- package/src/components/translations/translations.scss +4 -0
- package/src/components/vertical-stepper/vertical-stepper.component.ts +14 -9
- package/src/events/events.ts +12 -7
- package/src/events/zn-language-change.ts +7 -0
- package/src/events/zn-purchase.ts +11 -0
- package/src/events/zn-redirect.ts +7 -0
- package/src/events/zn-reorder.ts +7 -0
- package/src/events/zn-search-change.ts +11 -0
- package/src/events/zn-submit.ts +1 -1
- package/src/form-control.scss +4 -0
- package/src/internal/form-navigation.ts +510 -0
- package/src/internal/form.ts +6 -0
- package/src/zinc.ts +91 -83
|
@@ -1,70 +1,513 @@
|
|
|
1
1
|
---
|
|
2
2
|
meta:
|
|
3
3
|
title: Skeleton
|
|
4
|
-
description:
|
|
4
|
+
description: Skeletons are placeholder elements that indicate content is loading, improving perceived performance and user experience.
|
|
5
5
|
layout: component
|
|
6
6
|
fullWidth: true
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
```html:preview
|
|
10
|
-
|
|
11
10
|
<zn-skeleton></zn-skeleton>
|
|
12
11
|
```
|
|
13
12
|
|
|
13
|
+
Skeleton loaders provide visual placeholders while content is being loaded, helping users understand that something is happening and reducing perceived wait time. They create a better user experience by showing the approximate shape and layout of content before it arrives.
|
|
14
|
+
|
|
14
15
|
## Examples
|
|
15
16
|
|
|
16
|
-
###
|
|
17
|
+
### Basic Skeleton
|
|
18
|
+
|
|
19
|
+
A basic skeleton with default dimensions provides a simple loading placeholder.
|
|
17
20
|
|
|
18
21
|
```html:preview
|
|
22
|
+
<zn-skeleton></zn-skeleton>
|
|
23
|
+
```
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<div
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
<zn-skeleton
|
|
29
|
-
</div>
|
|
30
|
-
<div
|
|
31
|
-
style="display: grid; grid-template-columns: 75px 1fr; justify-content: center; align-items: center; gap: 10px; width: 450px;">
|
|
32
|
-
<p style="place-self: end;"><b>Slow:</b></p>
|
|
33
|
-
<zn-skeleton speed="5s"></zn-skeleton>
|
|
25
|
+
### Custom Dimensions
|
|
26
|
+
|
|
27
|
+
Use the `width` and `height` attributes to match the skeleton to your content's dimensions.
|
|
28
|
+
|
|
29
|
+
```html:preview
|
|
30
|
+
<div style="display: grid; gap: 10px;">
|
|
31
|
+
<zn-skeleton width="200px" height="20px"></zn-skeleton>
|
|
32
|
+
<zn-skeleton width="300px" height="20px"></zn-skeleton>
|
|
33
|
+
<zn-skeleton width="250px" height="20px"></zn-skeleton>
|
|
34
34
|
</div>
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
### Height
|
|
37
|
+
### Height Variations
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Use the `height` attribute to create skeletons of different heights for various content types.
|
|
40
40
|
|
|
41
|
+
```html:preview
|
|
41
42
|
<div style="display: grid; gap: 10px;">
|
|
42
|
-
<zn-skeleton height="
|
|
43
|
-
<zn-skeleton height="
|
|
44
|
-
<zn-skeleton height="
|
|
43
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
44
|
+
<zn-skeleton height="40px"></zn-skeleton>
|
|
45
|
+
<zn-skeleton height="60px"></zn-skeleton>
|
|
45
46
|
<zn-skeleton height="100px"></zn-skeleton>
|
|
46
47
|
</div>
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
### Width
|
|
50
|
+
### Width Variations
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
Use the `width` attribute to control skeleton width. Percentages and fixed values are both supported.
|
|
52
53
|
|
|
54
|
+
```html:preview
|
|
53
55
|
<div style="display: grid; gap: 10px;">
|
|
54
|
-
<zn-skeleton width="
|
|
55
|
-
<zn-skeleton width="
|
|
56
|
-
<zn-skeleton width="
|
|
57
|
-
<zn-skeleton width="
|
|
56
|
+
<zn-skeleton width="25%"></zn-skeleton>
|
|
57
|
+
<zn-skeleton width="50%"></zn-skeleton>
|
|
58
|
+
<zn-skeleton width="75%"></zn-skeleton>
|
|
59
|
+
<zn-skeleton width="100%"></zn-skeleton>
|
|
58
60
|
</div>
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
### Border Radius
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
Use the `radius` attribute to match your content's border radius and create different shapes.
|
|
64
66
|
|
|
67
|
+
```html:preview
|
|
65
68
|
<div style="display: grid; gap: 10px;">
|
|
66
69
|
<zn-skeleton radius="0"></zn-skeleton>
|
|
67
70
|
<zn-skeleton radius="4px"></zn-skeleton>
|
|
71
|
+
<zn-skeleton radius="8px"></zn-skeleton>
|
|
72
|
+
<zn-skeleton radius="16px"></zn-skeleton>
|
|
68
73
|
<zn-skeleton radius="50px"></zn-skeleton>
|
|
69
74
|
</div>
|
|
70
|
-
```
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Animation Speed
|
|
78
|
+
|
|
79
|
+
Use the `speed` attribute to control the animation speed. Slower animations can feel more polished, while faster animations suggest quicker loading.
|
|
80
|
+
|
|
81
|
+
```html:preview
|
|
82
|
+
<div style="display: grid; grid-template-columns: 100px 1fr; gap: 10px; align-items: center;">
|
|
83
|
+
<strong>Fast (1.5s):</strong>
|
|
84
|
+
<zn-skeleton speed="1.5s"></zn-skeleton>
|
|
85
|
+
|
|
86
|
+
<strong>Default (3s):</strong>
|
|
87
|
+
<zn-skeleton speed="3s"></zn-skeleton>
|
|
88
|
+
|
|
89
|
+
<strong>Slow (5s):</strong>
|
|
90
|
+
<zn-skeleton speed="5s"></zn-skeleton>
|
|
91
|
+
</div>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Circular Skeletons
|
|
95
|
+
|
|
96
|
+
Create circular skeleton loaders perfect for avatars by using equal width and height with a large border radius.
|
|
97
|
+
|
|
98
|
+
```html:preview
|
|
99
|
+
<div style="display: flex; gap: 16px; align-items: center;">
|
|
100
|
+
<zn-skeleton width="40px" height="40px" radius="50%"></zn-skeleton>
|
|
101
|
+
<zn-skeleton width="60px" height="60px" radius="50%"></zn-skeleton>
|
|
102
|
+
<zn-skeleton width="80px" height="80px" radius="50%"></zn-skeleton>
|
|
103
|
+
<zn-skeleton width="100px" height="100px" radius="50%"></zn-skeleton>
|
|
104
|
+
</div>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Text Line Skeletons
|
|
108
|
+
|
|
109
|
+
Create text-like loading patterns with varying widths to simulate paragraphs.
|
|
110
|
+
|
|
111
|
+
```html:preview
|
|
112
|
+
<div style="display: grid; gap: 8px; max-width: 600px;">
|
|
113
|
+
<zn-skeleton width="100%" height="16px"></zn-skeleton>
|
|
114
|
+
<zn-skeleton width="95%" height="16px"></zn-skeleton>
|
|
115
|
+
<zn-skeleton width="98%" height="16px"></zn-skeleton>
|
|
116
|
+
<zn-skeleton width="85%" height="16px"></zn-skeleton>
|
|
117
|
+
<zn-skeleton width="92%" height="16px"></zn-skeleton>
|
|
118
|
+
<zn-skeleton width="60%" height="16px"></zn-skeleton>
|
|
119
|
+
</div>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Card Skeleton
|
|
123
|
+
|
|
124
|
+
Combine multiple skeleton elements to create a complete card loading state.
|
|
125
|
+
|
|
126
|
+
```html:preview
|
|
127
|
+
<div style="max-width: 400px; padding: 20px; border: 1px solid #e0e0e0; border-radius: 8px;">
|
|
128
|
+
<zn-skeleton width="100%" height="200px" radius="8px"></zn-skeleton>
|
|
129
|
+
<div style="margin-top: 16px;">
|
|
130
|
+
<zn-skeleton width="70%" height="24px" radius="4px"></zn-skeleton>
|
|
131
|
+
<div style="margin-top: 12px;">
|
|
132
|
+
<zn-skeleton width="100%" height="16px" radius="4px"></zn-skeleton>
|
|
133
|
+
<div style="margin-top: 8px;">
|
|
134
|
+
<zn-skeleton width="100%" height="16px" radius="4px"></zn-skeleton>
|
|
135
|
+
</div>
|
|
136
|
+
<div style="margin-top: 8px;">
|
|
137
|
+
<zn-skeleton width="80%" height="16px" radius="4px"></zn-skeleton>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
<div style="margin-top: 16px; display: flex; gap: 8px;">
|
|
141
|
+
<zn-skeleton width="100px" height="36px" radius="4px"></zn-skeleton>
|
|
142
|
+
<zn-skeleton width="100px" height="36px" radius="4px"></zn-skeleton>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### User Profile Skeleton
|
|
149
|
+
|
|
150
|
+
Create a user profile loading state with avatar and text lines.
|
|
151
|
+
|
|
152
|
+
```html:preview
|
|
153
|
+
<div style="display: flex; gap: 16px; align-items: start; max-width: 500px;">
|
|
154
|
+
<zn-skeleton width="64px" height="64px" radius="50%"></zn-skeleton>
|
|
155
|
+
<div style="flex: 1; display: grid; gap: 10px;">
|
|
156
|
+
<zn-skeleton width="60%" height="20px" radius="4px"></zn-skeleton>
|
|
157
|
+
<zn-skeleton width="40%" height="16px" radius="4px"></zn-skeleton>
|
|
158
|
+
<zn-skeleton width="90%" height="14px" radius="4px"></zn-skeleton>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### List Item Skeletons
|
|
164
|
+
|
|
165
|
+
Create loading states for list items with consistent patterns.
|
|
166
|
+
|
|
167
|
+
```html:preview
|
|
168
|
+
<div style="display: grid; gap: 16px; max-width: 600px;">
|
|
169
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
170
|
+
<zn-skeleton width="48px" height="48px" radius="8px"></zn-skeleton>
|
|
171
|
+
<div style="flex: 1; display: grid; gap: 8px;">
|
|
172
|
+
<zn-skeleton width="70%" height="18px"></zn-skeleton>
|
|
173
|
+
<zn-skeleton width="50%" height="14px"></zn-skeleton>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
177
|
+
<zn-skeleton width="48px" height="48px" radius="8px"></zn-skeleton>
|
|
178
|
+
<div style="flex: 1; display: grid; gap: 8px;">
|
|
179
|
+
<zn-skeleton width="65%" height="18px"></zn-skeleton>
|
|
180
|
+
<zn-skeleton width="45%" height="14px"></zn-skeleton>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
184
|
+
<zn-skeleton width="48px" height="48px" radius="8px"></zn-skeleton>
|
|
185
|
+
<div style="flex: 1; display: grid; gap: 8px;">
|
|
186
|
+
<zn-skeleton width="75%" height="18px"></zn-skeleton>
|
|
187
|
+
<zn-skeleton width="55%" height="14px"></zn-skeleton>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Table Row Skeletons
|
|
194
|
+
|
|
195
|
+
Create loading states for table rows.
|
|
196
|
+
|
|
197
|
+
```html:preview
|
|
198
|
+
<div style="max-width: 800px;">
|
|
199
|
+
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 100px; gap: 16px; padding: 12px; border-bottom: 1px solid #e0e0e0;">
|
|
200
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
201
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
202
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
203
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
204
|
+
</div>
|
|
205
|
+
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 100px; gap: 16px; padding: 12px; border-bottom: 1px solid #e0e0e0;">
|
|
206
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
207
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
208
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
209
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
210
|
+
</div>
|
|
211
|
+
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 100px; gap: 16px; padding: 12px; border-bottom: 1px solid #e0e0e0;">
|
|
212
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
213
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
214
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
215
|
+
<zn-skeleton height="20px"></zn-skeleton>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Form Skeletons
|
|
221
|
+
|
|
222
|
+
Create loading states for form fields.
|
|
223
|
+
|
|
224
|
+
```html:preview
|
|
225
|
+
<div style="max-width: 500px; display: grid; gap: 20px;">
|
|
226
|
+
<div>
|
|
227
|
+
<zn-skeleton width="120px" height="16px" radius="4px"></zn-skeleton>
|
|
228
|
+
<div style="margin-top: 8px;">
|
|
229
|
+
<zn-skeleton width="100%" height="40px" radius="4px"></zn-skeleton>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
<div>
|
|
233
|
+
<zn-skeleton width="150px" height="16px" radius="4px"></zn-skeleton>
|
|
234
|
+
<div style="margin-top: 8px;">
|
|
235
|
+
<zn-skeleton width="100%" height="40px" radius="4px"></zn-skeleton>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
<div>
|
|
239
|
+
<zn-skeleton width="100px" height="16px" radius="4px"></zn-skeleton>
|
|
240
|
+
<div style="margin-top: 8px;">
|
|
241
|
+
<zn-skeleton width="100%" height="80px" radius="4px"></zn-skeleton>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
<zn-skeleton width="120px" height="42px" radius="4px"></zn-skeleton>
|
|
245
|
+
</div>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Dynamic Loading Simulation
|
|
249
|
+
|
|
250
|
+
A practical example showing how to toggle between loading and loaded states.
|
|
251
|
+
|
|
252
|
+
```html:preview
|
|
253
|
+
<div id="skeleton-demo">
|
|
254
|
+
<div id="content-container"></div>
|
|
255
|
+
<br />
|
|
256
|
+
<zn-button id="toggle-loading">Toggle Loading State</zn-button>
|
|
257
|
+
</div>
|
|
258
|
+
|
|
259
|
+
<script type="module">
|
|
260
|
+
const container = document.getElementById('content-container');
|
|
261
|
+
const button = document.getElementById('toggle-loading');
|
|
262
|
+
let isLoading = true;
|
|
263
|
+
|
|
264
|
+
function renderSkeleton() {
|
|
265
|
+
container.innerHTML = `
|
|
266
|
+
<div style="display: flex; gap: 16px; align-items: start; max-width: 500px;">
|
|
267
|
+
<zn-skeleton width="64px" height="64px" radius="50%"></zn-skeleton>
|
|
268
|
+
<div style="flex: 1; display: grid; gap: 10px;">
|
|
269
|
+
<zn-skeleton width="60%" height="20px"></zn-skeleton>
|
|
270
|
+
<zn-skeleton width="40%" height="16px"></zn-skeleton>
|
|
271
|
+
<zn-skeleton width="90%" height="14px"></zn-skeleton>
|
|
272
|
+
<zn-skeleton width="85%" height="14px"></zn-skeleton>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function renderContent() {
|
|
279
|
+
container.innerHTML = `
|
|
280
|
+
<div style="display: flex; gap: 16px; align-items: start; max-width: 500px;">
|
|
281
|
+
<div style="width: 64px; height: 64px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);"></div>
|
|
282
|
+
<div style="flex: 1;">
|
|
283
|
+
<h3 style="margin: 0 0 8px 0;">Jane Doe</h3>
|
|
284
|
+
<p style="margin: 0 0 8px 0; color: #666; font-size: 14px;">Senior Software Engineer</p>
|
|
285
|
+
<p style="margin: 0; font-size: 14px; line-height: 1.5;">
|
|
286
|
+
Passionate about building great user experiences and writing clean, maintainable code.
|
|
287
|
+
Loves working with modern web technologies.
|
|
288
|
+
</p>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
`;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Initial render
|
|
295
|
+
renderSkeleton();
|
|
296
|
+
|
|
297
|
+
button.addEventListener('click', () => {
|
|
298
|
+
isLoading = !isLoading;
|
|
299
|
+
if (isLoading) {
|
|
300
|
+
renderSkeleton();
|
|
301
|
+
} else {
|
|
302
|
+
renderContent();
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
</script>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Data Grid Skeleton
|
|
309
|
+
|
|
310
|
+
Create a complete data grid loading state.
|
|
311
|
+
|
|
312
|
+
```html:preview
|
|
313
|
+
<div style="max-width: 900px;">
|
|
314
|
+
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
|
|
315
|
+
<div style="border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px;">
|
|
316
|
+
<zn-skeleton width="100%" height="140px" radius="6px"></zn-skeleton>
|
|
317
|
+
<div style="margin-top: 12px;">
|
|
318
|
+
<zn-skeleton width="80%" height="18px"></zn-skeleton>
|
|
319
|
+
<div style="margin-top: 8px;">
|
|
320
|
+
<zn-skeleton width="60%" height="14px"></zn-skeleton>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
<div style="border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px;">
|
|
325
|
+
<zn-skeleton width="100%" height="140px" radius="6px"></zn-skeleton>
|
|
326
|
+
<div style="margin-top: 12px;">
|
|
327
|
+
<zn-skeleton width="75%" height="18px"></zn-skeleton>
|
|
328
|
+
<div style="margin-top: 8px;">
|
|
329
|
+
<zn-skeleton width="55%" height="14px"></zn-skeleton>
|
|
330
|
+
</div>
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
<div style="border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px;">
|
|
334
|
+
<zn-skeleton width="100%" height="140px" radius="6px"></zn-skeleton>
|
|
335
|
+
<div style="margin-top: 12px;">
|
|
336
|
+
<zn-skeleton width="85%" height="18px"></zn-skeleton>
|
|
337
|
+
<div style="margin-top: 8px;">
|
|
338
|
+
<zn-skeleton width="65%" height="14px"></zn-skeleton>
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Properties
|
|
347
|
+
|
|
348
|
+
The skeleton component exposes the following attributes and properties:
|
|
349
|
+
|
|
350
|
+
| Property | Attribute | Type | Default | Description |
|
|
351
|
+
|----------|-----------|------|---------|-------------|
|
|
352
|
+
| `speed` | `speed` | `string` | `"3s"` | Animation speed for the shimmer effect. Accepts any valid CSS time value (e.g., "1.5s", "2000ms"). |
|
|
353
|
+
| `width` | `width` | `string` | `"100%"` | Width of the skeleton element. Accepts any valid CSS width value (e.g., "200px", "50%", "10rem"). |
|
|
354
|
+
| `height` | `height` | `string` | `"20px"` | Height of the skeleton element. Accepts any valid CSS height value (e.g., "40px", "3rem", "10vh"). |
|
|
355
|
+
| `radius` | `radius` | `string` | `"4px"` | Border radius of the skeleton element. Accepts any valid CSS border-radius value (e.g., "0", "8px", "50%"). |
|
|
356
|
+
|
|
357
|
+
## Behavior
|
|
358
|
+
|
|
359
|
+
### Animation
|
|
360
|
+
|
|
361
|
+
The skeleton component uses a CSS-based shimmer animation that moves a lighter gradient across the skeleton surface. This animation:
|
|
362
|
+
|
|
363
|
+
- Runs continuously in a loop
|
|
364
|
+
- Moves from right to left across the element
|
|
365
|
+
- Uses a semi-transparent white overlay on a light gray background
|
|
366
|
+
- Respects user's motion preferences (see Accessibility section)
|
|
367
|
+
|
|
368
|
+
### Responsive Design
|
|
369
|
+
|
|
370
|
+
All dimension properties (`width`, `height`) accept any valid CSS units, making skeletons fully responsive:
|
|
371
|
+
|
|
372
|
+
- Use percentages for fluid layouts: `width="50%"`
|
|
373
|
+
- Use viewport units for screen-relative sizing: `height="10vh"`
|
|
374
|
+
- Use fixed units for precise control: `width="200px"`
|
|
375
|
+
- Combine with container queries for advanced responsiveness
|
|
376
|
+
|
|
377
|
+
### Stacking and Layout
|
|
378
|
+
|
|
379
|
+
Skeletons are block-level elements by default and can be easily arranged using standard CSS layout techniques:
|
|
380
|
+
|
|
381
|
+
- Use flexbox for horizontal arrangements
|
|
382
|
+
- Use grid for complex layouts
|
|
383
|
+
- Use standard spacing (margin/padding) for gaps
|
|
384
|
+
- Nest within containers to match your actual content structure
|
|
385
|
+
|
|
386
|
+
## Accessibility
|
|
387
|
+
|
|
388
|
+
The skeleton component is designed with accessibility in mind:
|
|
389
|
+
|
|
390
|
+
### Motion Preferences
|
|
391
|
+
|
|
392
|
+
The component respects the `prefers-reduced-motion` media query:
|
|
393
|
+
- When users prefer reduced motion, the shimmer animation is disabled
|
|
394
|
+
- The skeleton displays as a static gray block without movement
|
|
395
|
+
- This prevents motion sickness and respects user preferences
|
|
396
|
+
|
|
397
|
+
### Screen Readers
|
|
398
|
+
|
|
399
|
+
When implementing skeleton loaders:
|
|
400
|
+
- Consider adding `aria-busy="true"` to the parent container while loading
|
|
401
|
+
- Add `aria-live="polite"` to announce when content has loaded
|
|
402
|
+
- Include visually hidden text indicating loading state if needed
|
|
403
|
+
|
|
404
|
+
### Loading State Communication
|
|
405
|
+
|
|
406
|
+
Best practices for communicating loading states:
|
|
407
|
+
- Provide visual indication of approximate content shape
|
|
408
|
+
- Ensure loading states don't trap keyboard focus
|
|
409
|
+
- Announce completion of loading to screen reader users
|
|
410
|
+
- Consider a loading timeout with error handling
|
|
411
|
+
|
|
412
|
+
## Styling
|
|
413
|
+
|
|
414
|
+
The skeleton component uses CSS custom properties for styling:
|
|
415
|
+
|
|
416
|
+
### CSS Variables
|
|
417
|
+
|
|
418
|
+
| Variable | Default | Description |
|
|
419
|
+
|----------|---------|-------------|
|
|
420
|
+
| `--skeleton-speed` | `3s` | Duration of the shimmer animation |
|
|
421
|
+
| `--skeleton-width` | `100%` | Width of the skeleton element |
|
|
422
|
+
| `--skeleton-height` | `20px` | Height of the skeleton element |
|
|
423
|
+
| `--skeleton-border-radius` | `4px` | Border radius of the skeleton element |
|
|
424
|
+
|
|
425
|
+
### Customization
|
|
426
|
+
|
|
427
|
+
You can customize skeletons using CSS:
|
|
428
|
+
|
|
429
|
+
```css
|
|
430
|
+
zn-skeleton {
|
|
431
|
+
--skeleton-speed: 2s;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/* Target specific skeletons */
|
|
435
|
+
.fast-skeleton {
|
|
436
|
+
--skeleton-speed: 1s;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/* Adjust colors using CSS */
|
|
440
|
+
zn-skeleton::part(skeleton) {
|
|
441
|
+
background-color: #e0e0e0;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Best Practices
|
|
446
|
+
|
|
447
|
+
### When to Use Skeletons
|
|
448
|
+
|
|
449
|
+
- Use skeletons for content that takes more than 300ms to load
|
|
450
|
+
- Ideal for list views, cards, tables, and form layouts
|
|
451
|
+
- Best for structured content with predictable layouts
|
|
452
|
+
- Great for improving perceived performance
|
|
453
|
+
|
|
454
|
+
### Design Guidelines
|
|
455
|
+
|
|
456
|
+
- Match skeleton shapes to your actual content as closely as possible
|
|
457
|
+
- Use consistent animation speeds across your application
|
|
458
|
+
- Keep skeletons simple and avoid over-complicating the loading state
|
|
459
|
+
- Ensure skeletons have similar visual weight to the actual content
|
|
460
|
+
|
|
461
|
+
### Performance Considerations
|
|
462
|
+
|
|
463
|
+
- Skeletons are lightweight and use CSS animations (GPU-accelerated)
|
|
464
|
+
- Avoid rendering hundreds of skeleton elements simultaneously
|
|
465
|
+
- Consider progressive loading for very long lists
|
|
466
|
+
- Use skeletons in combination with proper data fetching strategies
|
|
467
|
+
|
|
468
|
+
### Layout Shift Prevention
|
|
469
|
+
|
|
470
|
+
To prevent cumulative layout shift (CLS):
|
|
471
|
+
- Ensure skeleton dimensions match loaded content exactly
|
|
472
|
+
- Reserve space for all content that will appear
|
|
473
|
+
- Don't change layout structure between skeleton and content
|
|
474
|
+
- Test with real data to verify layout stability
|
|
475
|
+
|
|
476
|
+
### Common Patterns
|
|
477
|
+
|
|
478
|
+
**Card Grids**: Use consistent skeleton patterns across grid items
|
|
479
|
+
```html
|
|
480
|
+
<!-- Each card has the same skeleton structure -->
|
|
481
|
+
<div class="card">
|
|
482
|
+
<zn-skeleton width="100%" height="200px"></zn-skeleton>
|
|
483
|
+
<zn-skeleton width="80%" height="24px"></zn-skeleton>
|
|
484
|
+
<zn-skeleton width="60%" height="16px"></zn-skeleton>
|
|
485
|
+
</div>
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**Progressive Loading**: Show skeletons first, then progressively load content
|
|
489
|
+
```javascript
|
|
490
|
+
// Show skeleton
|
|
491
|
+
showSkeleton();
|
|
492
|
+
// Fetch data
|
|
493
|
+
const data = await fetchData();
|
|
494
|
+
// Replace skeleton with content
|
|
495
|
+
renderContent(data);
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Partial Updates**: Keep loaded content visible while updating portions
|
|
499
|
+
```html
|
|
500
|
+
<!-- Keep header loaded, show skeleton for body -->
|
|
501
|
+
<div class="content">
|
|
502
|
+
<div class="header">Loaded Content</div>
|
|
503
|
+
<zn-skeleton width="100%" height="200px"></zn-skeleton>
|
|
504
|
+
</div>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### What to Avoid
|
|
508
|
+
|
|
509
|
+
- Don't use skeletons for instant content (< 300ms load time)
|
|
510
|
+
- Avoid overly detailed or complex skeleton patterns
|
|
511
|
+
- Don't use different skeleton patterns for the same content type
|
|
512
|
+
- Avoid using skeletons indefinitely (implement timeouts/error states)
|
|
513
|
+
- Don't make skeletons look exactly like content (maintain distinction)
|