kedhar-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,451 @@
1
+ /* kedhar-ui v0.1.0 — https://github.com/kedharsairam/kedhar-ui */
2
+
3
+ /* ══════════════════════════════════════════════════════════════
4
+ kedhar-ui — Design Tokens
5
+ ══════════════════════════════════════════════════════════════
6
+ These tokens are consumed by base.css and components.css.
7
+ Each site imports its theme file to set the --ks-color-* values.
8
+ ══════════════════════════════════════════════════════════════ */
9
+
10
+ :root {
11
+ /* ─── Spacing Scale ──────────────────────────────────────── */
12
+ --ks-space-1: 4px;
13
+ --ks-space-2: 8px;
14
+ --ks-space-3: 12px;
15
+ --ks-space-4: 16px;
16
+ --ks-space-5: 20px;
17
+ --ks-space-6: 24px;
18
+ --ks-space-8: 32px;
19
+ --ks-space-10: 40px;
20
+ --ks-space-12: 48px;
21
+ --ks-space-16: 64px;
22
+ --ks-space-20: 80px;
23
+
24
+ /* ─── Border Radius ──────────────────────────────────────── */
25
+ --ks-radius-sm: 6px;
26
+ --ks-radius-md: 10px;
27
+ --ks-radius-lg: 16px;
28
+ --ks-radius-xl: 24px;
29
+ --ks-radius-full: 9999px;
30
+
31
+ /* ─── Typography ─────────────────────────────────────────── */
32
+ --ks-font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
33
+ --ks-font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace;
34
+
35
+ --ks-text-xs: 0.75rem;
36
+ --ks-text-sm: 0.875rem;
37
+ --ks-text-base: 1rem;
38
+ --ks-text-lg: 1.125rem;
39
+ --ks-text-xl: 1.25rem;
40
+ --ks-text-2xl: 1.5rem;
41
+ --ks-text-3xl: 1.875rem;
42
+ --ks-text-4xl: 2.25rem;
43
+
44
+ --ks-leading-tight: 1.25;
45
+ --ks-leading-normal: 1.5;
46
+ --ks-leading-relaxed: 1.625;
47
+
48
+ --ks-weight-normal: 400;
49
+ --ks-weight-medium: 500;
50
+ --ks-weight-semibold: 600;
51
+ --ks-weight-bold: 700;
52
+
53
+ /* ─── Shadows ────────────────────────────────────────────── */
54
+ --ks-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
55
+ --ks-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
56
+ --ks-shadow-lg: 0 10px 25px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.04);
57
+ --ks-shadow-xl: 0 20px 50px -8px rgba(0, 0, 0, 0.1);
58
+
59
+ /* ─── Transitions ────────────────────────────────────────── */
60
+ --ks-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
61
+ --ks-ease-in: cubic-bezier(0.4, 0, 0.68, 0.06);
62
+ --ks-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
63
+ --ks-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
64
+
65
+ --ks-duration-fast: 150ms;
66
+ --ks-duration-normal: 250ms;
67
+ --ks-duration-slow: 400ms;
68
+
69
+ /* ─── Z-Index Scale ──────────────────────────────────────── */
70
+ --ks-z-base: 1;
71
+ --ks-z-dropdown: 10;
72
+ --ks-z-sticky: 20;
73
+ --ks-z-modal: 30;
74
+ --ks-z-toast: 40;
75
+ --ks-z-tooltip: 50;
76
+
77
+ /* ─── Layout ─────────────────────────────────────────────── */
78
+ --ks-max-width: 1200px;
79
+ }
80
+
81
+ /* ─── Dark mode token overrides ────────────────────────────── */
82
+ .dark {
83
+ --ks-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
84
+ --ks-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -2px rgba(0, 0, 0, 0.2);
85
+ --ks-shadow-lg: 0 10px 25px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -4px rgba(0, 0, 0, 0.2);
86
+ --ks-shadow-xl: 0 20px 50px -8px rgba(0, 0, 0, 0.3);
87
+ }
88
+
89
+ /* ══════════════════════════════════════════════════════════════
90
+ kedhar-ui — Base Styles
91
+ ══════════════════════════════════════════════════════════════
92
+ Reset + base element styling. Import tokens.css first.
93
+ ══════════════════════════════════════════════════════════════ */
94
+
95
+ /* ─── Box-Sizing Reset ─────────────────────────────────────── */
96
+ *,
97
+ *::before,
98
+ *::after {
99
+ box-sizing: border-box;
100
+ }
101
+
102
+ /* ─── Body Defaults ────────────────────────────────────────── */
103
+ html {
104
+ scroll-behavior: smooth;
105
+ -webkit-text-size-adjust: 100%;
106
+ }
107
+
108
+ body {
109
+ margin: 0;
110
+ padding: 0;
111
+ font-family: var(--ks-font-sans);
112
+ font-size: var(--ks-text-base);
113
+ line-height: var(--ks-leading-normal);
114
+ color: var(--ks-color-text);
115
+ background-color: var(--ks-color-bg);
116
+ -webkit-font-smoothing: antialiased;
117
+ -moz-osx-font-smoothing: grayscale;
118
+ transition:
119
+ background-color var(--ks-duration-normal) var(--ks-ease-out),
120
+ color var(--ks-duration-normal) var(--ks-ease-out);
121
+ }
122
+
123
+ /* ─── Links ────────────────────────────────────────────────── */
124
+ a {
125
+ color: var(--ks-color-primary);
126
+ text-decoration: none;
127
+ transition: color var(--ks-duration-fast) var(--ks-ease-out);
128
+ }
129
+
130
+ a:hover {
131
+ color: var(--ks-color-primary-hover);
132
+ }
133
+
134
+ /* ─── Images ───────────────────────────────────────────────── */
135
+ img {
136
+ max-width: 100%;
137
+ height: auto;
138
+ display: block;
139
+ }
140
+
141
+ /* ─── Buttons ──────────────────────────────────────────────── */
142
+ button {
143
+ font-family: inherit;
144
+ font-size: inherit;
145
+ cursor: pointer;
146
+ }
147
+
148
+ /* ─── Code ─────────────────────────────────────────────────── */
149
+ code,
150
+ pre {
151
+ font-family: var(--ks-font-mono);
152
+ }
153
+
154
+ /* ─── Focus Visible ────────────────────────────────────────── */
155
+ :focus-visible {
156
+ outline: 2px solid var(--ks-color-primary);
157
+ outline-offset: 2px;
158
+ border-radius: var(--ks-radius-sm);
159
+ }
160
+
161
+ /* ─── Selection ────────────────────────────────────────────── */
162
+ ::selection {
163
+ background-color: var(--ks-color-primary);
164
+ color: #ffffff;
165
+ }
166
+
167
+ /* ══════════════════════════════════════════════════════════════
168
+ kedhar-ui — Component Styles
169
+ ══════════════════════════════════════════════════════════════
170
+ Ripple, scroll-to-top, theme toggle, and other shared components.
171
+ Import tokens.css and base.css first.
172
+ ══════════════════════════════════════════════════════════════ */
173
+
174
+ /* ══════════════════════════════════════════════════════════════
175
+ 1. CSS Ripple Effect
176
+ ══════════════════════════════════════════════════════════════
177
+ Pure CSS — no JavaScript required.
178
+ Expands a circle from center on :active.
179
+ ══════════════════════════════════════════════════════════════ */
180
+ .ks-ripple {
181
+ position: relative;
182
+ overflow: hidden;
183
+ cursor: pointer;
184
+ -webkit-tap-highlight-color: transparent;
185
+ }
186
+
187
+ .ks-ripple::after {
188
+ content: '';
189
+ position: absolute;
190
+ top: 50%;
191
+ left: 50%;
192
+ width: 0;
193
+ height: 0;
194
+ border-radius: 50%;
195
+ background: currentColor;
196
+ opacity: 0.15;
197
+ transform: translate(-50%, -50%);
198
+ pointer-events: none;
199
+ will-change: width, height, opacity;
200
+ }
201
+
202
+ .ks-ripple:active::after {
203
+ width: 300%;
204
+ height: 300%;
205
+ opacity: 0;
206
+ transition:
207
+ width 0.4s var(--ks-ease-out),
208
+ height 0.4s var(--ks-ease-out),
209
+ opacity 0.4s var(--ks-ease-out);
210
+ }
211
+
212
+
213
+ /* ══════════════════════════════════════════════════════════════
214
+ 2. Scroll-to-Top Button
215
+ ══════════════════════════════════════════════════════════════
216
+ Requires JS to toggle .visible class.
217
+ ══════════════════════════════════════════════════════════════ */
218
+ .ks-scroll-top {
219
+ position: fixed;
220
+ bottom: var(--ks-space-8);
221
+ right: var(--ks-space-8);
222
+ width: 44px;
223
+ height: 44px;
224
+ border-radius: var(--ks-radius-full);
225
+ border: none;
226
+ display: flex;
227
+ align-items: center;
228
+ justify-content: center;
229
+ cursor: pointer;
230
+ opacity: 0;
231
+ visibility: hidden;
232
+ transform: translateY(12px);
233
+ pointer-events: none;
234
+ z-index: var(--ks-z-sticky);
235
+ box-shadow: var(--ks-shadow-lg);
236
+ background: var(--ks-color-surface);
237
+ color: var(--ks-color-text-muted);
238
+ transition:
239
+ opacity var(--ks-duration-normal) var(--ks-ease-out),
240
+ visibility var(--ks-duration-normal) var(--ks-ease-out),
241
+ transform var(--ks-duration-normal) var(--ks-ease-out),
242
+ background var(--ks-duration-normal) var(--ks-ease-out),
243
+ color var(--ks-duration-normal) var(--ks-ease-out);
244
+ overflow: hidden;
245
+ }
246
+
247
+ .ks-scroll-top.visible {
248
+ opacity: 1;
249
+ visibility: visible;
250
+ transform: translateY(0);
251
+ pointer-events: auto;
252
+ }
253
+
254
+ .ks-scroll-top:hover {
255
+ background: var(--ks-color-surface-hover);
256
+ color: var(--ks-color-primary);
257
+ box-shadow: var(--ks-shadow-lg), 0 0 0 2px var(--ks-color-primary-alpha);
258
+ }
259
+
260
+ .ks-scroll-top svg {
261
+ width: 20px;
262
+ height: 20px;
263
+ stroke: currentColor;
264
+ fill: none;
265
+ stroke-width: 2;
266
+ stroke-linecap: round;
267
+ stroke-linejoin: round;
268
+ }
269
+
270
+
271
+ /* ══════════════════════════════════════════════════════════════
272
+ 3. Theme Toggle (Light / Dark)
273
+ ══════════════════════════════════════════════════════════════
274
+ Animated pill switch with sun/moon icons on the knob.
275
+ ══════════════════════════════════════════════════════════════ */
276
+ .ks-theme-toggle {
277
+ position: relative;
278
+ width: 56px;
279
+ height: 30px;
280
+ border-radius: var(--ks-radius-full);
281
+ border: 2px solid var(--ks-color-border);
282
+ background: var(--ks-color-surface);
283
+ cursor: pointer;
284
+ display: flex;
285
+ align-items: center;
286
+ padding: 0;
287
+ flex-shrink: 0;
288
+ transition:
289
+ background var(--ks-duration-normal) var(--ks-ease-spring),
290
+ border-color var(--ks-duration-normal) var(--ks-ease-out);
291
+ overflow: hidden;
292
+ -webkit-tap-highlight-color: transparent;
293
+ }
294
+
295
+ .ks-theme-toggle:hover {
296
+ border-color: var(--ks-color-primary);
297
+ }
298
+
299
+ /* Knob */
300
+ .ks-toggle-knob {
301
+ position: absolute;
302
+ top: 2px;
303
+ left: 2px;
304
+ width: 22px;
305
+ height: 22px;
306
+ border-radius: var(--ks-radius-full);
307
+ display: flex;
308
+ align-items: center;
309
+ justify-content: center;
310
+ transition:
311
+ transform var(--ks-duration-normal) var(--ks-ease-spring),
312
+ background var(--ks-duration-normal) var(--ks-ease-out);
313
+ z-index: 2;
314
+ background: var(--ks-color-primary);
315
+ color: #ffffff;
316
+ box-shadow: var(--ks-shadow-sm);
317
+ }
318
+
319
+ /* Dark position */
320
+ .dark .ks-toggle-knob {
321
+ transform: translateX(26px);
322
+ }
323
+
324
+ /* Icons inside knob */
325
+ .ks-toggle-knob svg {
326
+ width: 13px;
327
+ height: 13px;
328
+ fill: none;
329
+ stroke: currentColor;
330
+ stroke-width: 2;
331
+ stroke-linecap: round;
332
+ stroke-linejoin: round;
333
+ transition: transform var(--ks-duration-normal) var(--ks-ease-spring);
334
+ }
335
+
336
+ .dark .ks-toggle-knob svg {
337
+ transform: rotate(90deg);
338
+ }
339
+
340
+ /* Track background halves */
341
+ .ks-toggle-track {
342
+ display: flex;
343
+ width: 100%;
344
+ height: 100%;
345
+ }
346
+
347
+ .ks-toggle-track span {
348
+ flex: 1;
349
+ display: flex;
350
+ align-items: center;
351
+ justify-content: center;
352
+ font-size: 12px;
353
+ color: var(--ks-color-text-muted);
354
+ transition: color var(--ks-duration-fast) var(--ks-ease-out);
355
+ }
356
+
357
+ .dark .ks-toggle-track span:first-child {
358
+ color: transparent;
359
+ }
360
+
361
+ .dark .ks-toggle-track span:last-child {
362
+ color: var(--ks-color-text-muted);
363
+ }
364
+
365
+ .ks-toggle-track span:first-child {
366
+ color: var(--ks-color-text-muted);
367
+ }
368
+
369
+ .ks-toggle-track span:last-child {
370
+ color: transparent;
371
+ }
372
+
373
+
374
+ /* ══════════════════════════════════════════════════════════════
375
+ 4. Card
376
+ ══════════════════════════════════════════════════════════════
377
+ Reusable card component with consistent styling.
378
+ ══════════════════════════════════════════════════════════════ */
379
+ .ks-card {
380
+ background: var(--ks-color-surface);
381
+ border: 1px solid var(--ks-color-border);
382
+ border-radius: var(--ks-radius-lg);
383
+ padding: var(--ks-space-6);
384
+ transition:
385
+ box-shadow var(--ks-duration-normal) var(--ks-ease-out),
386
+ border-color var(--ks-duration-normal) var(--ks-ease-out),
387
+ transform var(--ks-duration-normal) var(--ks-ease-out);
388
+ }
389
+
390
+ .ks-card:hover {
391
+ border-color: var(--ks-color-primary-alpha);
392
+ box-shadow: var(--ks-shadow-md);
393
+ transform: translateY(-2px);
394
+ }
395
+
396
+
397
+ /* ══════════════════════════════════════════════════════════════
398
+ 5. Badge / Tag
399
+ ══════════════════════════════════════════════════════════════
400
+ Small label for status, tags, metadata.
401
+ ══════════════════════════════════════════════════════════════ */
402
+ .ks-badge {
403
+ display: inline-flex;
404
+ align-items: center;
405
+ padding: 2px var(--ks-space-2);
406
+ border-radius: var(--ks-radius-sm);
407
+ font-size: var(--ks-text-xs);
408
+ font-weight: var(--ks-weight-medium);
409
+ line-height: 1.4;
410
+ background: var(--ks-color-surface-hover);
411
+ color: var(--ks-color-text-muted);
412
+ border: 1px solid var(--ks-color-border);
413
+ }
414
+
415
+
416
+ /* ══════════════════════════════════════════════════════════════
417
+ 6. Section Container
418
+ ══════════════════════════════════════════════════════════════ */
419
+ .ks-section {
420
+ padding: var(--ks-space-16) var(--ks-space-4);
421
+ max-width: var(--ks-max-width);
422
+ margin: 0 auto;
423
+ }
424
+
425
+ @media (min-width: 640px) {
426
+ .ks-section {
427
+ padding: var(--ks-space-20) var(--ks-space-6);
428
+ }
429
+ }
430
+
431
+ @media (min-width: 1024px) {
432
+ .ks-section {
433
+ padding: var(--ks-space-20) var(--ks-space-8);
434
+ }
435
+ }
436
+
437
+
438
+ /* ══════════════════════════════════════════════════════════════
439
+ 7. Utility Classes
440
+ ══════════════════════════════════════════════════════════════ */
441
+ .ks-sr-only {
442
+ position: absolute;
443
+ width: 1px;
444
+ height: 1px;
445
+ padding: 0;
446
+ margin: -1px;
447
+ overflow: hidden;
448
+ clip: rect(0, 0, 0, 0);
449
+ white-space: nowrap;
450
+ border: 0;
451
+ }
@@ -0,0 +1,37 @@
1
+ /* kedhar-ui v0.1.0 — https://github.com/kedharsairam/kedhar-ui */
2
+
3
+ /* ══════════════════════════════════════════════════════════════
4
+ Theme: Amber — Projects site
5
+ ══════════════════════════════════════════════════════════════ */
6
+
7
+ :root {
8
+ --ks-color-primary: #d97706;
9
+ --ks-color-primary-hover: #b45309;
10
+ --ks-color-primary-light: #fef3c7;
11
+ --ks-color-primary-dark: #92400e;
12
+ --ks-color-primary-alpha: rgba(217, 119, 6, 0.15);
13
+
14
+ --ks-color-bg: #faf8f5;
15
+ --ks-color-surface: #ffffff;
16
+ --ks-color-surface-hover: #f5f2ed;
17
+ --ks-color-border: #e8e2d8;
18
+ --ks-color-text: #1c1917;
19
+ --ks-color-text-muted: #78716c;
20
+ --ks-color-text-inverse: #ffffff;
21
+ }
22
+
23
+ .dark {
24
+ --ks-color-primary: #f59e0b;
25
+ --ks-color-primary-hover: #d97706;
26
+ --ks-color-primary-light: #292524;
27
+ --ks-color-primary-dark: #fbbf24;
28
+ --ks-color-primary-alpha: rgba(245, 158, 11, 0.15);
29
+
30
+ --ks-color-bg: #0f0d0a;
31
+ --ks-color-surface: #1c1917;
32
+ --ks-color-surface-hover: #292524;
33
+ --ks-color-border: #3f3a36;
34
+ --ks-color-text: #f5f0eb;
35
+ --ks-color-text-muted: #a8a29e;
36
+ --ks-color-text-inverse: #0f0d0a;
37
+ }
@@ -0,0 +1,37 @@
1
+ /* kedhar-ui v0.1.0 — https://github.com/kedharsairam/kedhar-ui */
2
+
3
+ /* ══════════════════════════════════════════════════════════════
4
+ Theme: Emerald — Blog site
5
+ ══════════════════════════════════════════════════════════════ */
6
+
7
+ :root {
8
+ --ks-color-primary: #059669;
9
+ --ks-color-primary-hover: #047857;
10
+ --ks-color-primary-light: #d1fae5;
11
+ --ks-color-primary-dark: #065f46;
12
+ --ks-color-primary-alpha: rgba(5, 150, 105, 0.15);
13
+
14
+ --ks-color-bg: #f4f9f7;
15
+ --ks-color-surface: #ffffff;
16
+ --ks-color-surface-hover: #edf5f1;
17
+ --ks-color-border: #dce8e2;
18
+ --ks-color-text: #0f1a16;
19
+ --ks-color-text-muted: #6b7d76;
20
+ --ks-color-text-inverse: #ffffff;
21
+ }
22
+
23
+ .dark {
24
+ --ks-color-primary: #10b981;
25
+ --ks-color-primary-hover: #059669;
26
+ --ks-color-primary-light: #0a1f18;
27
+ --ks-color-primary-dark: #34d399;
28
+ --ks-color-primary-alpha: rgba(16, 185, 129, 0.15);
29
+
30
+ --ks-color-bg: #080f0c;
31
+ --ks-color-surface: #111f19;
32
+ --ks-color-surface-hover: #1a2f26;
33
+ --ks-color-border: #2d4036;
34
+ --ks-color-text: #e2f0e9;
35
+ --ks-color-text-muted: #94a89e;
36
+ --ks-color-text-inverse: #080f0c;
37
+ }
@@ -0,0 +1,37 @@
1
+ /* kedhar-ui v0.1.0 — https://github.com/kedharsairam/kedhar-ui */
2
+
3
+ /* ══════════════════════════════════════════════════════════════
4
+ Theme: Indigo — Portfolio site
5
+ ══════════════════════════════════════════════════════════════ */
6
+
7
+ :root {
8
+ --ks-color-primary: #6366f1;
9
+ --ks-color-primary-hover: #4f46e5;
10
+ --ks-color-primary-light: #e0e7ff;
11
+ --ks-color-primary-dark: #4338ca;
12
+ --ks-color-primary-alpha: rgba(99, 102, 241, 0.15);
13
+
14
+ --ks-color-bg: #f8f9fc;
15
+ --ks-color-surface: #ffffff;
16
+ --ks-color-surface-hover: #f1f3f9;
17
+ --ks-color-border: #e2e5f0;
18
+ --ks-color-text: #1e1e2e;
19
+ --ks-color-text-muted: #6b7280;
20
+ --ks-color-text-inverse: #ffffff;
21
+ }
22
+
23
+ .dark {
24
+ --ks-color-primary: #818cf8;
25
+ --ks-color-primary-hover: #6366f1;
26
+ --ks-color-primary-light: #1e1b4b;
27
+ --ks-color-primary-dark: #a5b4fc;
28
+ --ks-color-primary-alpha: rgba(129, 140, 248, 0.15);
29
+
30
+ --ks-color-bg: #0f0f1a;
31
+ --ks-color-surface: #1a1a2e;
32
+ --ks-color-surface-hover: #242440;
33
+ --ks-color-border: #2d2d4a;
34
+ --ks-color-text: #e2e4f0;
35
+ --ks-color-text-muted: #9ca3af;
36
+ --ks-color-text-inverse: #0f0f1a;
37
+ }
@@ -0,0 +1,37 @@
1
+ /* kedhar-ui v0.1.0 — https://github.com/kedharsairam/kedhar-ui */
2
+
3
+ /* ══════════════════════════════════════════════════════════════
4
+ Theme: Slate — mssql-scripts site (neutral / technical)
5
+ ══════════════════════════════════════════════════════════════ */
6
+
7
+ :root {
8
+ --ks-color-primary: #64748b;
9
+ --ks-color-primary-hover: #475569;
10
+ --ks-color-primary-light: #f1f5f9;
11
+ --ks-color-primary-dark: #334155;
12
+ --ks-color-primary-alpha: rgba(100, 116, 139, 0.15);
13
+
14
+ --ks-color-bg: #f8fafc;
15
+ --ks-color-surface: #ffffff;
16
+ --ks-color-surface-hover: #f1f5f9;
17
+ --ks-color-border: #e2e8f0;
18
+ --ks-color-text: #0f172a;
19
+ --ks-color-text-muted: #64748b;
20
+ --ks-color-text-inverse: #ffffff;
21
+ }
22
+
23
+ .dark {
24
+ --ks-color-primary: #94a3b8;
25
+ --ks-color-primary-hover: #64748b;
26
+ --ks-color-primary-light: #1e293b;
27
+ --ks-color-primary-dark: #cbd5e1;
28
+ --ks-color-primary-alpha: rgba(148, 163, 184, 0.15);
29
+
30
+ --ks-color-bg: #0b1120;
31
+ --ks-color-surface: #151d2b;
32
+ --ks-color-surface-hover: #1e293b;
33
+ --ks-color-border: #2d3748;
34
+ --ks-color-text: #e2e8f0;
35
+ --ks-color-text-muted: #94a3b8;
36
+ --ks-color-text-inverse: #0b1120;
37
+ }
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "kedhar-ui",
3
+ "version": "0.1.0",
4
+ "description": "Shared design system for Kedhar's projects — CSS tokens, components, and themes.",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "style": "dist/kedhar-ui.css",
8
+ "files": [
9
+ "src/",
10
+ "dist/"
11
+ ],
12
+ "scripts": {
13
+ "build": "node scripts/build.js",
14
+ "prepublishOnly": "npm run build",
15
+ "lint": "echo 'No linter configured yet'"
16
+ },
17
+ "keywords": [
18
+ "design-system",
19
+ "css",
20
+ "astro",
21
+ "kedhar-ui"
22
+ ],
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/kedharsairam/kedhar-ui.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/kedharsairam/kedhar-ui/issues"
30
+ },
31
+ "homepage": "https://github.com/kedharsairam/kedhar-ui#readme"
32
+ }
@@ -0,0 +1,53 @@
1
+ ---
2
+ /**
3
+ * ScrollToTop — Shared scroll-to-top button.
4
+ *
5
+ * Usage:
6
+ * import ScrollToTop from '@kedharsairam/kedhar-ui/src/components/ScrollToTop.astro';
7
+ * <ScrollToTop />
8
+ *
9
+ * Shows when user scrolls past threshold (default: 300px).
10
+ */
11
+
12
+ import '../styles/components.css';
13
+ ---
14
+
15
+ <button class="ks-scroll-top ks-ripple" id="ks-scroll-top" aria-label="Scroll to top" type="button">
16
+ <svg viewBox="0 0 24 24">
17
+ <polyline points="18 15 12 9 6 15" />
18
+ </svg>
19
+ </button>
20
+
21
+ <script>
22
+ (function () {
23
+ const btn = document.getElementById('ks-scroll-top');
24
+ if (!btn) return;
25
+
26
+ let visible = false;
27
+ const threshold = 300;
28
+
29
+ function onScroll() {
30
+ const shouldShow = window.scrollY > threshold;
31
+ if (shouldShow !== visible) {
32
+ visible = shouldShow;
33
+ btn.classList.toggle('visible', visible);
34
+ }
35
+ }
36
+
37
+ // Throttled scroll listener
38
+ let ticking = false;
39
+ window.addEventListener('scroll', () => {
40
+ if (!ticking) {
41
+ window.requestAnimationFrame(() => {
42
+ onScroll();
43
+ ticking = false;
44
+ });
45
+ ticking = true;
46
+ }
47
+ });
48
+
49
+ btn.addEventListener('click', () => {
50
+ window.scrollTo({ top: 0, behavior: 'smooth' });
51
+ });
52
+ })();
53
+ </script>