@ghostly-ui/core 0.2.1 → 0.2.2
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/dist/ghostly.css +119 -97
- package/package.json +1 -1
package/dist/ghostly.css
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
GHOSTLY — Zero-config skeleton loaders
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Philosophy: NEVER override layout properties. Only hide content
|
|
5
|
+
and add skeleton background. The component's own CSS defines
|
|
6
|
+
all sizing, spacing, and border-radius.
|
|
6
7
|
============================================================ */
|
|
7
8
|
|
|
8
9
|
/* --- Custom properties (override these to customize) --- */
|
|
@@ -31,25 +32,7 @@
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/* ============================================================
|
|
34
|
-
1.
|
|
35
|
-
============================================================ */
|
|
36
|
-
|
|
37
|
-
/* All targetable elements inside a ghostly container */
|
|
38
|
-
[data-ghostly] :where(
|
|
39
|
-
h1, h2, h3, h4, h5, h6,
|
|
40
|
-
p, span, a, li, td, th, dt, dd,
|
|
41
|
-
label, legend, figcaption, caption, summary,
|
|
42
|
-
blockquote, cite, q, em, strong, small, mark, code, pre,
|
|
43
|
-
button, input, textarea, select, option,
|
|
44
|
-
fieldset, dialog, details, address,
|
|
45
|
-
time, abbr, sub, sup, del, ins,
|
|
46
|
-
img, svg, video, canvas, picture, iframe
|
|
47
|
-
) {
|
|
48
|
-
--_ghostly-target: 1;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/* ============================================================
|
|
52
|
-
2. CONTAINER — Blocks interaction while loading
|
|
35
|
+
1. CONTAINER — Blocks interaction while loading
|
|
53
36
|
============================================================ */
|
|
54
37
|
|
|
55
38
|
[data-ghostly] {
|
|
@@ -59,7 +42,8 @@
|
|
|
59
42
|
}
|
|
60
43
|
|
|
61
44
|
/* ============================================================
|
|
62
|
-
|
|
45
|
+
2. TEXT ELEMENTS — Hide text, show skeleton background
|
|
46
|
+
Only override visual properties. NEVER touch layout.
|
|
63
47
|
============================================================ */
|
|
64
48
|
|
|
65
49
|
[data-ghostly] :where(
|
|
@@ -74,81 +58,137 @@
|
|
|
74
58
|
color: transparent !important;
|
|
75
59
|
background-color: var(--ghostly-color) !important;
|
|
76
60
|
background-image: none !important;
|
|
77
|
-
border-radius: var(--ghostly-radius) !important;
|
|
78
61
|
border-color: transparent !important;
|
|
79
62
|
box-shadow: none !important;
|
|
80
63
|
text-decoration: none !important;
|
|
64
|
+
text-shadow: none !important;
|
|
81
65
|
outline: none !important;
|
|
66
|
+
/* Prevent empty elements from collapsing vertically */
|
|
82
67
|
min-height: 1em;
|
|
83
|
-
min-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/* Headings get proportional min-height */
|
|
87
|
-
[data-ghostly] :where(h1) { min-height: 1.75em; min-width: 40%; }
|
|
88
|
-
[data-ghostly] :where(h2) { min-height: 1.5em; min-width: 50%; }
|
|
89
|
-
[data-ghostly] :where(h3) { min-height: 1.3em; min-width: 55%; }
|
|
90
|
-
[data-ghostly] :where(h4, h5, h6) { min-height: 1.15em; min-width: 45%; }
|
|
91
|
-
|
|
92
|
-
/* Paragraphs simulate multi-line text */
|
|
93
|
-
[data-ghostly] :where(p) { min-height: 3em; min-width: 80%; }
|
|
94
|
-
|
|
95
|
-
/* Code blocks need more height */
|
|
96
|
-
[data-ghostly] :where(pre) { min-height: 5em; min-width: 100%; }
|
|
97
|
-
|
|
98
|
-
/* Inputs keep their shape */
|
|
99
|
-
[data-ghostly] :where(input, textarea, select) {
|
|
100
|
-
min-height: 2.5rem;
|
|
101
|
-
min-width: 6rem;
|
|
68
|
+
/* Inline elements need display block/inline-block to respect min-height */
|
|
69
|
+
display: var(--_ghostly-display, revert);
|
|
102
70
|
}
|
|
103
71
|
|
|
104
|
-
/*
|
|
105
|
-
[data-ghostly] :where(
|
|
106
|
-
|
|
107
|
-
|
|
72
|
+
/* Make inline elements (span, a, em, etc.) respect min-height/width */
|
|
73
|
+
[data-ghostly] :where(
|
|
74
|
+
span, a, em, strong, small, mark, code, abbr,
|
|
75
|
+
cite, q, sub, sup, del, ins, time, label
|
|
76
|
+
) {
|
|
77
|
+
--_ghostly-display: inline-block;
|
|
108
78
|
}
|
|
109
79
|
|
|
110
|
-
/*
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
[data-ghostly] :where(
|
|
116
|
-
[data-ghostly] :where(
|
|
117
|
-
[data-ghostly] :where(
|
|
118
|
-
[data-ghostly] :where(
|
|
119
|
-
[data-ghostly] :where(
|
|
120
|
-
[data-ghostly] :where(
|
|
121
|
-
[data-ghostly] :where(
|
|
80
|
+
/* ── Prevent text elements from collapsing horizontally ──
|
|
81
|
+
Since text is transparent, the element's width comes from the text
|
|
82
|
+
content. When content is empty ('') the element collapses to 0 width.
|
|
83
|
+
We use min-width to prevent this. When real (visible) content is loaded,
|
|
84
|
+
the content width will naturally exceed the min-width. */
|
|
85
|
+
[data-ghostly] :where(h1) { min-width: 60%; }
|
|
86
|
+
[data-ghostly] :where(h2) { min-width: 50%; }
|
|
87
|
+
[data-ghostly] :where(h3) { min-width: 45%; }
|
|
88
|
+
[data-ghostly] :where(h4, h5, h6) { min-width: 40%; }
|
|
89
|
+
[data-ghostly] :where(p) { min-width: 80%; }
|
|
90
|
+
[data-ghostly] :where(span, a, em, strong, small, label, time, code) { min-width: 3rem; }
|
|
91
|
+
[data-ghostly] :where(button) { min-width: 5rem; }
|
|
92
|
+
[data-ghostly] :where(input, textarea, select) { min-width: 6rem; }
|
|
93
|
+
|
|
94
|
+
/* Headings: proportional min-height */
|
|
95
|
+
[data-ghostly] :where(h1) { min-height: 1.75em; }
|
|
96
|
+
[data-ghostly] :where(h2) { min-height: 1.5em; }
|
|
97
|
+
[data-ghostly] :where(h3) { min-height: 1.3em; }
|
|
98
|
+
[data-ghostly] :where(h4, h5, h6) { min-height: 1.15em; }
|
|
99
|
+
|
|
100
|
+
/* Paragraphs: taller to simulate multi-line text */
|
|
101
|
+
[data-ghostly] :where(p) { min-height: 3em; }
|
|
102
|
+
|
|
103
|
+
/* Code blocks: taller */
|
|
104
|
+
[data-ghostly] :where(pre) { min-height: 5em; }
|
|
105
|
+
|
|
106
|
+
/* Interactive elements: reasonable minimums */
|
|
107
|
+
[data-ghostly] :where(input, textarea, select) { min-height: 2.5rem; }
|
|
108
|
+
[data-ghostly] :where(button) { min-height: 2.25rem; }
|
|
122
109
|
|
|
123
110
|
/* ============================================================
|
|
124
|
-
|
|
111
|
+
3. MEDIA ELEMENTS — Hide content, show skeleton block
|
|
112
|
+
Preserves ALL existing dimensions and border-radius.
|
|
125
113
|
============================================================ */
|
|
126
114
|
|
|
127
115
|
[data-ghostly] :where(img, svg, video, canvas, picture, iframe) {
|
|
128
|
-
color: transparent !important;
|
|
129
116
|
background-color: var(--ghostly-color) !important;
|
|
130
|
-
border-radius: var(--ghostly-radius) !important;
|
|
131
117
|
border-color: transparent !important;
|
|
132
118
|
box-shadow: none !important;
|
|
133
119
|
}
|
|
134
120
|
|
|
135
|
-
/* Hide
|
|
121
|
+
/* Hide image content without changing dimensions */
|
|
136
122
|
[data-ghostly] :where(img) {
|
|
137
|
-
|
|
123
|
+
color: transparent !important;
|
|
124
|
+
object-position: -9999px !important;
|
|
138
125
|
}
|
|
139
126
|
|
|
140
127
|
[data-ghostly] :where(video, iframe) {
|
|
141
128
|
opacity: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* SVG: hide strokes/fills but keep size */
|
|
132
|
+
[data-ghostly] :where(svg) {
|
|
133
|
+
color: transparent !important;
|
|
134
|
+
fill: transparent !important;
|
|
135
|
+
stroke: transparent !important;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Only add min-size for SVG icons that might be empty */
|
|
139
|
+
[data-ghostly] :where(svg:empty) {
|
|
140
|
+
min-height: 1.5rem;
|
|
141
|
+
min-width: 1.5rem;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ============================================================
|
|
145
|
+
4. EMPTY CONTAINERS — Style divs that act as placeholders
|
|
146
|
+
When a component renders an empty div instead of an img
|
|
147
|
+
(e.g. avatar placeholder), it should still show skeleton.
|
|
148
|
+
============================================================ */
|
|
149
|
+
|
|
150
|
+
[data-ghostly] :where(div:empty) {
|
|
142
151
|
background-color: var(--ghostly-color) !important;
|
|
143
152
|
}
|
|
144
153
|
|
|
145
|
-
/*
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
154
|
+
/* ============================================================
|
|
155
|
+
5. BORDER RADIUS — Use computed value, fallback to default
|
|
156
|
+
Never override existing border-radius from the component.
|
|
157
|
+
============================================================ */
|
|
158
|
+
|
|
159
|
+
/* Apply default radius ONLY to elements that don't have one set.
|
|
160
|
+
We use a very low specificity so any component CSS wins. */
|
|
161
|
+
@layer ghostly-defaults {
|
|
162
|
+
[data-ghostly] h1, [data-ghostly] h2, [data-ghostly] h3,
|
|
163
|
+
[data-ghostly] h4, [data-ghostly] h5, [data-ghostly] h6,
|
|
164
|
+
[data-ghostly] p, [data-ghostly] span, [data-ghostly] a,
|
|
165
|
+
[data-ghostly] li, [data-ghostly] td, [data-ghostly] th,
|
|
166
|
+
[data-ghostly] button, [data-ghostly] input,
|
|
167
|
+
[data-ghostly] textarea, [data-ghostly] select,
|
|
168
|
+
[data-ghostly] code, [data-ghostly] pre,
|
|
169
|
+
[data-ghostly] img, [data-ghostly] svg,
|
|
170
|
+
[data-ghostly] video, [data-ghostly] canvas {
|
|
171
|
+
border-radius: var(--ghostly-radius);
|
|
172
|
+
}
|
|
149
173
|
}
|
|
150
174
|
|
|
151
|
-
/*
|
|
175
|
+
/* ============================================================
|
|
176
|
+
6. CUSTOM LINE COUNT — data-ghostly-lines="N"
|
|
177
|
+
============================================================ */
|
|
178
|
+
|
|
179
|
+
[data-ghostly] :where([data-ghostly-lines="1"]) { min-height: 1em; }
|
|
180
|
+
[data-ghostly] :where([data-ghostly-lines="2"]) { min-height: 2em; }
|
|
181
|
+
[data-ghostly] :where([data-ghostly-lines="3"]) { min-height: 3em; }
|
|
182
|
+
[data-ghostly] :where([data-ghostly-lines="4"]) { min-height: 4em; }
|
|
183
|
+
[data-ghostly] :where([data-ghostly-lines="5"]) { min-height: 5em; }
|
|
184
|
+
[data-ghostly] :where([data-ghostly-lines="6"]) { min-height: 6em; }
|
|
185
|
+
[data-ghostly] :where([data-ghostly-lines="7"]) { min-height: 7em; }
|
|
186
|
+
[data-ghostly] :where([data-ghostly-lines="8"]) { min-height: 8em; }
|
|
187
|
+
|
|
188
|
+
/* ============================================================
|
|
189
|
+
7. CUSTOM ASPECT RATIO — data-ghostly-ratio
|
|
190
|
+
============================================================ */
|
|
191
|
+
|
|
152
192
|
[data-ghostly] :where([data-ghostly-ratio="1/1"]) { aspect-ratio: 1/1 !important; }
|
|
153
193
|
[data-ghostly] :where([data-ghostly-ratio="4/3"]) { aspect-ratio: 4/3 !important; }
|
|
154
194
|
[data-ghostly] :where([data-ghostly-ratio="16/9"]) { aspect-ratio: 16/9 !important; }
|
|
@@ -156,35 +196,16 @@
|
|
|
156
196
|
[data-ghostly] :where([data-ghostly-ratio="3/4"]) { aspect-ratio: 3/4 !important; }
|
|
157
197
|
[data-ghostly] :where([data-ghostly-ratio="9/16"]) { aspect-ratio: 9/16 !important; }
|
|
158
198
|
|
|
159
|
-
/* SVG icons (typically small) */
|
|
160
|
-
[data-ghostly] :where(svg) {
|
|
161
|
-
min-height: 1.5rem;
|
|
162
|
-
min-width: 1.5rem;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
199
|
/* ============================================================
|
|
166
|
-
|
|
200
|
+
8. DECORATIVE — Strip visual noise
|
|
167
201
|
============================================================ */
|
|
168
202
|
|
|
169
203
|
[data-ghostly] :where(hr) {
|
|
170
204
|
border-color: var(--ghostly-color) !important;
|
|
171
205
|
}
|
|
172
206
|
|
|
173
|
-
[data-ghostly] :where(
|
|
174
|
-
[class*="badge"],
|
|
175
|
-
[class*="chip"],
|
|
176
|
-
[class*="tag"],
|
|
177
|
-
[class*="avatar"]
|
|
178
|
-
) {
|
|
179
|
-
color: transparent !important;
|
|
180
|
-
background-color: var(--ghostly-color) !important;
|
|
181
|
-
background-image: none !important;
|
|
182
|
-
border-color: transparent !important;
|
|
183
|
-
box-shadow: none !important;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
207
|
/* ============================================================
|
|
187
|
-
|
|
208
|
+
9. EXCLUSIONS — data-ghostly-ignore restores original styles
|
|
188
209
|
============================================================ */
|
|
189
210
|
|
|
190
211
|
[data-ghostly] [data-ghostly-ignore],
|
|
@@ -198,17 +219,15 @@
|
|
|
198
219
|
pointer-events: auto;
|
|
199
220
|
user-select: auto;
|
|
200
221
|
min-height: initial;
|
|
201
|
-
min-width: initial;
|
|
202
222
|
animation: none !important;
|
|
203
223
|
}
|
|
204
224
|
|
|
205
225
|
/* ============================================================
|
|
206
|
-
|
|
226
|
+
10. ANIMATIONS
|
|
207
227
|
============================================================ */
|
|
208
228
|
|
|
209
229
|
/* --- Shimmer — gradient sweep left to right --- */
|
|
210
230
|
|
|
211
|
-
[data-ghostly='shimmer'] :where([style*="--_ghostly-target"]),
|
|
212
231
|
[data-ghostly='shimmer'] :where(
|
|
213
232
|
h1, h2, h3, h4, h5, h6,
|
|
214
233
|
p, span, a, li, td, th, dt, dd,
|
|
@@ -217,7 +236,8 @@
|
|
|
217
236
|
button, input, textarea, select, option,
|
|
218
237
|
fieldset, dialog, details, address,
|
|
219
238
|
time, abbr, sub, sup, del, ins,
|
|
220
|
-
img, svg, video, canvas, picture, iframe
|
|
239
|
+
img, svg, video, canvas, picture, iframe,
|
|
240
|
+
div:empty
|
|
221
241
|
) {
|
|
222
242
|
background: linear-gradient(
|
|
223
243
|
90deg,
|
|
@@ -246,7 +266,8 @@
|
|
|
246
266
|
button, input, textarea, select, option,
|
|
247
267
|
fieldset, dialog, details, address,
|
|
248
268
|
time, abbr, sub, sup, del, ins,
|
|
249
|
-
img, svg, video, canvas, picture, iframe
|
|
269
|
+
img, svg, video, canvas, picture, iframe,
|
|
270
|
+
div:empty
|
|
250
271
|
) {
|
|
251
272
|
animation: ghostly-pulse var(--ghostly-speed) ease-in-out infinite !important;
|
|
252
273
|
}
|
|
@@ -266,7 +287,8 @@
|
|
|
266
287
|
button, input, textarea, select, option,
|
|
267
288
|
fieldset, dialog, details, address,
|
|
268
289
|
time, abbr, sub, sup, del, ins,
|
|
269
|
-
img, svg, video, canvas, picture, iframe
|
|
290
|
+
img, svg, video, canvas, picture, iframe,
|
|
291
|
+
div:empty
|
|
270
292
|
) {
|
|
271
293
|
animation: ghostly-wave var(--ghostly-speed) ease-in-out infinite !important;
|
|
272
294
|
}
|
|
@@ -295,7 +317,7 @@
|
|
|
295
317
|
[data-ghostly='wave'] > :nth-child(n+13) { animation-delay: 960ms !important; }
|
|
296
318
|
|
|
297
319
|
/* ============================================================
|
|
298
|
-
|
|
320
|
+
11. SMOOTH TRANSITION — fade out when loading ends
|
|
299
321
|
============================================================ */
|
|
300
322
|
|
|
301
323
|
[data-ghostly-smooth] :where(
|
|
@@ -316,7 +338,7 @@
|
|
|
316
338
|
}
|
|
317
339
|
|
|
318
340
|
/* ============================================================
|
|
319
|
-
|
|
341
|
+
12. ACCESSIBILITY
|
|
320
342
|
============================================================ */
|
|
321
343
|
|
|
322
344
|
@media (prefers-reduced-motion: reduce) {
|