elvish-css 1.0.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +518 -0
  3. package/dist/elvish.css +2194 -0
  4. package/dist/elvish.d.ts +78 -0
  5. package/dist/elvish.esm.js +2185 -0
  6. package/dist/elvish.iife.js +2169 -0
  7. package/dist/elvish.min.css +9 -0
  8. package/dist/elvish.umd.js +2173 -0
  9. package/elvish.css +28 -0
  10. package/elvish.js +81 -0
  11. package/global/global.css +16 -0
  12. package/global/modern.css +305 -0
  13. package/global/reset.css +507 -0
  14. package/global/tokens.css +154 -0
  15. package/global/transitions.css +288 -0
  16. package/global/transitions.js +289 -0
  17. package/global/utilities.css +151 -0
  18. package/package.json +61 -0
  19. package/primitives/adleithian/adleithian.css +16 -0
  20. package/primitives/adleithian/adleithian.js +63 -0
  21. package/primitives/bau/bau.css +86 -0
  22. package/primitives/bau/bau.js +127 -0
  23. package/primitives/enedh/enedh.css +38 -0
  24. package/primitives/enedh/enedh.js +110 -0
  25. package/primitives/esgal/esgal.css +39 -0
  26. package/primitives/esgal/esgal.js +115 -0
  27. package/primitives/fano/fano.css +28 -0
  28. package/primitives/fano/fano.js +108 -0
  29. package/primitives/gant-thala/gant-thala.css +32 -0
  30. package/primitives/gant-thala/gant-thala.js +69 -0
  31. package/primitives/glan-tholl/glan-tholl.css +71 -0
  32. package/primitives/glan-tholl/glan-tholl.js +147 -0
  33. package/primitives/glan-veleg/glan-veleg.css +45 -0
  34. package/primitives/glan-veleg/glan-veleg.js +138 -0
  35. package/primitives/gonath/gonath.css +57 -0
  36. package/primitives/gonath/gonath.js +113 -0
  37. package/primitives/gwistindor/gwistindor.css +52 -0
  38. package/primitives/gwistindor/gwistindor.js +96 -0
  39. package/primitives/hath/hath.css +39 -0
  40. package/primitives/hath/hath.js +107 -0
  41. package/primitives/him/him.css +43 -0
  42. package/primitives/him/him.js +169 -0
  43. package/primitives/miriant/miriant.css +75 -0
  44. package/primitives/miriant/miriant.js +158 -0
  45. package/primitives/thann/thann.css +57 -0
  46. package/primitives/thann/thann.js +96 -0
  47. package/primitives/tiniath/tiniath.css +16 -0
  48. package/primitives/tiniath/tiniath.js +88 -0
  49. package/primitives/vircantie/vircantie.css +24 -0
  50. package/primitives/vircantie/vircantie.js +83 -0
package/elvish.css ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Elvish - All Styles
3
+ *
4
+ * Import this file to get all layout primitive styles.
5
+ * Import global/global.css separately for design tokens, reset, and utilities.
6
+ *
7
+ * Primitives use Sindarin names from Tolkien's Elvish languages.
8
+ */
9
+
10
+ /* Core primitives */
11
+ @import './primitives/hath/hath.css'; /* Stack */
12
+ @import './primitives/bau/bau.css'; /* Box */
13
+ @import './primitives/enedh/enedh.css'; /* Center (horizontal) */
14
+ @import './primitives/tiniath/tiniath.css'; /* Cluster */
15
+ @import './primitives/glan-veleg/glan-veleg.css'; /* Sidebar */
16
+ @import './primitives/gwistindor/gwistindor.css'; /* Switcher */
17
+ @import './primitives/esgal/esgal.css'; /* Cover (vertical center) */
18
+ @import './primitives/vircantie/vircantie.css'; /* Grid */
19
+ @import './primitives/gant-thala/gant-thala.css'; /* Frame (aspect) */
20
+ @import './primitives/glan-tholl/glan-tholl.css'; /* Reel (side-scrolling) */
21
+ @import './primitives/fano/fano.css'; /* Imposter (overlay) */
22
+ @import './primitives/thann/thann.css'; /* Icon */
23
+ @import './primitives/adleithian/adleithian.css'; /* Container */
24
+
25
+ /* Extended primitives */
26
+ @import './primitives/him/him.css'; /* Sticky */
27
+ @import './primitives/miriant/miriant.css'; /* Grid-placed */
28
+ @import './primitives/gonath/gonath.css'; /* Masonry - "stone collection" */
package/elvish.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Elvish - All Primitives
3
+ *
4
+ * Import this file to register all custom elements:
5
+ *
6
+ * <script type="module" src="./elvish.js"></script>
7
+ *
8
+ * Or import specific primitives:
9
+ *
10
+ * import { HathLayout, BauLayout } from './elvish.js';
11
+ *
12
+ * Primitives use Sindarin names from Tolkien's Elvish languages.
13
+ */
14
+
15
+ // Core primitives (Sindarin names with English translations)
16
+ export { default as HathLayout } from './primitives/hath/hath.js'; // Stack
17
+ export { default as BauLayout } from './primitives/bau/bau.js'; // Box
18
+ export { default as EnedhLayout } from './primitives/enedh/enedh.js'; // Center (horizontal)
19
+ export { default as TiniathLayout } from './primitives/tiniath/tiniath.js'; // Cluster
20
+ export { default as GlanVelegLayout } from './primitives/glan-veleg/glan-veleg.js'; // Sidebar
21
+ export { default as GwistindorLayout } from './primitives/gwistindor/gwistindor.js'; // Switcher
22
+ export { default as EsgalLayout } from './primitives/esgal/esgal.js'; // Cover (vertical center)
23
+ export { default as VircantieLayout } from './primitives/vircantie/vircantie.js'; // Grid
24
+ export { default as GantThalaLayout } from './primitives/gant-thala/gant-thala.js'; // Frame (aspect)
25
+ export { default as GlanThollLayout } from './primitives/glan-tholl/glan-tholl.js'; // Reel (side-scrolling)
26
+ export { default as FanoLayout } from './primitives/fano/fano.js'; // Imposter (overlay)
27
+ export { default as ThannLayout } from './primitives/thann/thann.js'; // Icon
28
+ export { default as AdleithianLayout } from './primitives/adleithian/adleithian.js'; // Container
29
+
30
+ // Extended primitives
31
+ export { default as HimLayout } from './primitives/him/him.js'; // Sticky
32
+ export { default as MiriantLayout } from './primitives/miriant/miriant.js'; // Grid-placed
33
+ export { default as GonathLayout } from './primitives/gonath/gonath.js'; // Masonry
34
+
35
+ // Version info
36
+ export const VERSION = '2.0.0';
37
+
38
+ // Primitives reference (Sindarin → English)
39
+ export const PRIMITIVES = {
40
+ // Core
41
+ 'i-hath': 'Stack',
42
+ 'i-bau': 'Box',
43
+ 'i-enedh': 'Center (horizontal)',
44
+ 'i-tiniath': 'Cluster',
45
+ 'i-glan-veleg': 'Sidebar',
46
+ 'i-gwistindor': 'Switcher',
47
+ 'i-esgal': 'Cover (vertical center)',
48
+ 'i-vircantie': 'Grid',
49
+ 'i-gant-thala': 'Frame (aspect)',
50
+ 'i-glan-tholl': 'Reel (side-scrolling)',
51
+ 'i-fano': 'Imposter (overlay)',
52
+ 'i-thann': 'Icon',
53
+ 'i-adleithian': 'Container',
54
+ // Extended
55
+ 'i-him': 'Sticky',
56
+ 'i-miriant': 'Grid-placed',
57
+ 'i-gonath': 'Masonry',
58
+ };
59
+
60
+ // Sindarin vocabulary reference
61
+ export const SINDARIN = {
62
+ hath: 'a row, rank, series',
63
+ bau: 'box, container',
64
+ enedh: 'middle, center',
65
+ tiniath: 'small things, cluster of sparks',
66
+ 'glan-veleg': 'clear/open + mighty/great',
67
+ gwistindor: 'change-watcher',
68
+ esgal: 'screen, hiding, cover',
69
+ vircantie: 'jewel-pattern (grid)',
70
+ 'gant-thala': 'harp-foot (ratio/proportion)',
71
+ 'glan-tholl': 'clear/open + hollow (scrolling)',
72
+ fano: 'white phantom, cloud (overlay)',
73
+ thann: 'sign, token (icon)',
74
+ adleithian: 'releaser, liberator (container)',
75
+ him: 'steadfast, abiding (sticky)',
76
+ miriant: 'jewel-work (explicit placement)',
77
+ gonath: 'the stone collection (masonry)',
78
+ // Attribute names
79
+ echuiol: 'awakening (active)',
80
+ dhoren: 'hidden, secret',
81
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Elvish - Global Styles
3
+ *
4
+ * Import this file to get all global styles:
5
+ * - Design tokens (modular scale, colors, etc.)
6
+ * - Reset and axioms
7
+ * - Utility classes
8
+ * - Modern CSS features (@function, if(), sibling-index, etc.)
9
+ * - View Transitions for smooth layout changes
10
+ */
11
+
12
+ @import 'tokens.css';
13
+ @import 'reset.css';
14
+ @import 'utilities.css';
15
+ @import 'modern.css';
16
+ @import 'transitions.css';
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Elvish Modern - CSS Functions & Advanced Features
3
+ *
4
+ * Features requiring Chrome 133+ / Edge 133+ (progressive enhancement)
5
+ * Firefox and Safari fallbacks provided where possible.
6
+ *
7
+ * BROWSER SUPPORT (as of Jan 2026):
8
+ * - if() : Chrome 137+, Edge 137+
9
+ * - @function : Chrome 139+, Edge 139+
10
+ * - sibling-index/count : Chrome 138+, Edge 138+
11
+ * - typed attr() : Chrome 133+, Edge 133+
12
+ * - light-dark() : All modern browsers ✓
13
+ * - Relative colors : All modern browsers ✓
14
+ */
15
+
16
+ /* ============================================================================
17
+ * CUSTOM FUNCTIONS (@function)
18
+ * ============================================================================
19
+ * Reusable logic defined once, used everywhere.
20
+ * Chrome 139+ / Edge 139+
21
+ */
22
+
23
+ /* Negate a value */
24
+ @function --negate(--value) {
25
+ result: calc(-1 * var(--value));
26
+ }
27
+
28
+ /* Linear interpolation between two values */
29
+ @function --lerp(--a, --b, --t) {
30
+ result: calc(var(--a) + (var(--b) - var(--a)) * var(--t));
31
+ }
32
+
33
+ /* Fluid value between min and max based on viewport */
34
+ @function --fluid(--min, --max, --min-vw: 20rem, --max-vw: 75rem) {
35
+ result: clamp(
36
+ var(--min),
37
+ calc(var(--min) + (var(--max) - var(--min)) * ((100vw - var(--min-vw)) / (var(--max-vw) - var(--min-vw)))),
38
+ var(--max)
39
+ );
40
+ }
41
+
42
+ /* Add transparency to a color */
43
+ @function --alpha(--color, --opacity) {
44
+ result: oklch(from var(--color) l c h / var(--opacity));
45
+ }
46
+
47
+ /* Lighten a color */
48
+ @function --lighten(--color, --amount: 0.1) {
49
+ result: oklch(from var(--color) calc(l + var(--amount)) c h);
50
+ }
51
+
52
+ /* Darken a color */
53
+ @function --darken(--color, --amount: 0.1) {
54
+ result: oklch(from var(--color) calc(l - var(--amount)) c h);
55
+ }
56
+
57
+ /* Spacing multiplier */
58
+ @function --space(--multiplier: 1) {
59
+ result: calc(var(--s0) * var(--multiplier));
60
+ }
61
+
62
+ /* Conditional border-radius (0 when near edge, normal otherwise) */
63
+ @function --safe-radius(--radius, --threshold: 8px) {
64
+ /* Use container query units if available */
65
+ result: clamp(0px, calc((100cqi - var(--threshold)) * 999), var(--radius));
66
+ }
67
+
68
+
69
+ /* ============================================================================
70
+ * STAGGER ANIMATIONS (sibling-index)
71
+ * ============================================================================
72
+ * Automatic stagger delays without JavaScript!
73
+ * Chrome 138+ / Edge 138+
74
+ */
75
+
76
+ /* Stagger children entrance animations */
77
+ .stagger-enter > * {
78
+ animation: elvish-fade-in-up var(--duration-normal, 300ms) var(--ease-out, ease-out) both;
79
+ animation-delay: calc((sibling-index() - 1) * var(--stagger-delay, 50ms));
80
+ }
81
+
82
+ /* Stagger with @starting-style for appear animations */
83
+ .stagger-appear > * {
84
+ opacity: 1;
85
+ transform: translateY(0);
86
+ transition:
87
+ opacity var(--duration-normal, 300ms) var(--ease-out, ease-out),
88
+ transform var(--duration-normal, 300ms) var(--ease-out, ease-out);
89
+ transition-delay: calc((sibling-index() - 1) * var(--stagger-delay, 50ms));
90
+
91
+ @starting-style {
92
+ opacity: 0;
93
+ transform: translateY(20px);
94
+ }
95
+ }
96
+
97
+ /* Cascade opacity based on position */
98
+ .fade-cascade > * {
99
+ opacity: calc(1 - (sibling-index() - 1) * 0.08);
100
+ }
101
+
102
+ /* Rainbow children using sibling-index for hue */
103
+ .rainbow > * {
104
+ --hue: calc(sibling-index() * (360 / sibling-count()));
105
+ background: oklch(85% 0.2 var(--hue));
106
+ }
107
+
108
+ /* Auto-numbered list items */
109
+ .auto-number > *::before {
110
+ content: counter(sibling-index) ". ";
111
+ counter-increment: none; /* We don't need CSS counters anymore! */
112
+ }
113
+
114
+
115
+ /* ============================================================================
116
+ * CONDITIONAL STYLES (if() function)
117
+ * ============================================================================
118
+ * Inline conditionals in CSS values.
119
+ * Chrome 137+ / Edge 137+
120
+ */
121
+
122
+ /* Theme-aware component using if() */
123
+ .theme-aware {
124
+ --is-dark: false;
125
+
126
+ background: if(
127
+ style(--is-dark: true): var(--color-surface-dark, #1a1a2e);
128
+ else: var(--color-surface-light, #ffffff)
129
+ );
130
+
131
+ color: if(
132
+ style(--is-dark: true): var(--color-text-dark, #f0f0f5);
133
+ else: var(--color-text-light, #1a1a2e)
134
+ );
135
+ }
136
+
137
+ /* Responsive without media queries using if() */
138
+ .responsive-grid {
139
+ display: grid;
140
+ grid-template-columns: if(
141
+ media(width >= 900px): repeat(4, 1fr);
142
+ media(width >= 600px): repeat(3, 1fr);
143
+ media(width >= 400px): repeat(2, 1fr);
144
+ else: 1fr
145
+ );
146
+ }
147
+
148
+ /* Compact variant using style query in if() */
149
+ .adaptive-card {
150
+ --variant: default;
151
+
152
+ padding: if(
153
+ style(--variant: compact): var(--s-1);
154
+ style(--variant: spacious): var(--s2);
155
+ else: var(--s1)
156
+ );
157
+
158
+ font-size: if(
159
+ style(--variant: compact): var(--s-1);
160
+ else: var(--s0)
161
+ );
162
+ }
163
+
164
+
165
+ /* ============================================================================
166
+ * TYPED ATTR() - HTML to CSS Bridge
167
+ * ============================================================================
168
+ * Use HTML attributes as typed CSS values.
169
+ * Chrome 133+ / Edge 133+
170
+ */
171
+
172
+ /* Grid columns from data attribute */
173
+ [data-columns] {
174
+ --columns: attr(data-columns type(<number>), 1);
175
+ display: grid;
176
+ grid-template-columns: repeat(var(--columns), 1fr);
177
+ }
178
+
179
+ /* Color from data attribute */
180
+ [data-color] {
181
+ color: attr(data-color type(<color>), currentColor);
182
+ }
183
+
184
+ /* Background color from data attribute */
185
+ [data-bg] {
186
+ background-color: attr(data-bg type(<color>), transparent);
187
+ }
188
+
189
+ /* Spacing from data attribute */
190
+ [data-space] {
191
+ --space-value: attr(data-space type(<length>), var(--s1));
192
+ gap: var(--space-value);
193
+ padding: var(--space-value);
194
+ }
195
+
196
+ /* Progress bar using attr() */
197
+ [data-progress] {
198
+ --progress: attr(data-progress type(<percentage>), 0%);
199
+ background: linear-gradient(
200
+ to right,
201
+ var(--color-accent) var(--progress),
202
+ var(--color-surface-sunken) var(--progress)
203
+ );
204
+ }
205
+
206
+ /* Aspect ratio from attribute */
207
+ [data-ratio] {
208
+ aspect-ratio: attr(data-ratio type(<ratio>), 1);
209
+ }
210
+
211
+ /* Dynamic view-transition-name from id */
212
+ [data-transition] {
213
+ view-transition-name: attr(data-transition type(<custom-ident>), none);
214
+ }
215
+
216
+
217
+ /* ============================================================================
218
+ * KEYFRAMES
219
+ * ============================================================================
220
+ */
221
+
222
+ @keyframes elvish-fade-in {
223
+ from { opacity: 0; }
224
+ }
225
+
226
+ @keyframes elvish-fade-in-up {
227
+ from {
228
+ opacity: 0;
229
+ transform: translateY(var(--distance, 20px));
230
+ }
231
+ }
232
+
233
+ @keyframes elvish-fade-in-down {
234
+ from {
235
+ opacity: 0;
236
+ transform: translateY(calc(var(--distance, 20px) * -1));
237
+ }
238
+ }
239
+
240
+ @keyframes elvish-scale-in {
241
+ from {
242
+ opacity: 0;
243
+ transform: scale(0.95);
244
+ }
245
+ }
246
+
247
+ @keyframes elvish-slide-in-right {
248
+ from {
249
+ transform: translateX(100%);
250
+ }
251
+ }
252
+
253
+ @keyframes elvish-slide-in-left {
254
+ from {
255
+ transform: translateX(-100%);
256
+ }
257
+ }
258
+
259
+
260
+ /* ============================================================================
261
+ * FEATURE DETECTION
262
+ * ============================================================================
263
+ * Fallbacks for browsers without support.
264
+ */
265
+
266
+ /* Fallback for sibling-index() - requires JS to set --i custom property */
267
+ @supports not (animation-delay: calc(sibling-index() * 1ms)) {
268
+ .stagger-enter > * {
269
+ /* Fallback: use nth-child or JS-set custom property */
270
+ animation-delay: calc(var(--i, 0) * var(--stagger-delay, 50ms));
271
+ }
272
+
273
+ .stagger-enter > :nth-child(1) { --i: 0; }
274
+ .stagger-enter > :nth-child(2) { --i: 1; }
275
+ .stagger-enter > :nth-child(3) { --i: 2; }
276
+ .stagger-enter > :nth-child(4) { --i: 3; }
277
+ .stagger-enter > :nth-child(5) { --i: 4; }
278
+ .stagger-enter > :nth-child(6) { --i: 5; }
279
+ .stagger-enter > :nth-child(7) { --i: 6; }
280
+ .stagger-enter > :nth-child(8) { --i: 7; }
281
+ .stagger-enter > :nth-child(9) { --i: 8; }
282
+ .stagger-enter > :nth-child(10) { --i: 9; }
283
+ }
284
+
285
+ /* Fallback for if() - use custom properties toggled by classes */
286
+ @supports not (color: if(style(--x: y): red; else: blue)) {
287
+ .theme-aware {
288
+ background: var(--color-surface-light, #ffffff);
289
+ color: var(--color-text-light, #1a1a2e);
290
+ }
291
+
292
+ .theme-aware.is-dark {
293
+ background: var(--color-surface-dark, #1a1a2e);
294
+ color: var(--color-text-dark, #f0f0f5);
295
+ }
296
+ }
297
+
298
+ /* Fallback for typed attr() */
299
+ @supports not (color: attr(data-x type(<color>), red)) {
300
+ [data-columns="2"] { grid-template-columns: repeat(2, 1fr); }
301
+ [data-columns="3"] { grid-template-columns: repeat(3, 1fr); }
302
+ [data-columns="4"] { grid-template-columns: repeat(4, 1fr); }
303
+ [data-columns="5"] { grid-template-columns: repeat(5, 1fr); }
304
+ [data-columns="6"] { grid-template-columns: repeat(6, 1fr); }
305
+ }