@okjavis/nodebb-theme-javis 1.0.1 → 1.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,539 @@
1
+ // ===========================================================
2
+ // SIDEBAR SYSTEM – Widget Styles
3
+ // Modern, clean sidebar with card-based widgets
4
+ // ===========================================================
5
+
6
+ // ===========================================================
7
+ // LEFT SIDEBAR (Main Navigation)
8
+ // ===========================================================
9
+ .sidebar {
10
+ background: $jv-surface;
11
+ border-right: 1px solid $jv-border-subtle;
12
+
13
+ // Sidebar navigation links
14
+ .nav-link {
15
+ display: flex;
16
+ align-items: center;
17
+ gap: $jv-space-4;
18
+ padding: $jv-space-4 $jv-space-6;
19
+ color: $jv-text-muted;
20
+ font-size: $jv-font-size-sm;
21
+ font-weight: 500;
22
+ border-radius: $jv-radius-sm;
23
+ transition: all 0.15s ease;
24
+ margin: 2px 0;
25
+
26
+ i {
27
+ width: 18px;
28
+ text-align: center;
29
+ font-size: 14px;
30
+ }
31
+
32
+ &:hover {
33
+ background: rgba(0, 81, 255, 0.06);
34
+ color: $jv-primary;
35
+ }
36
+
37
+ &.active {
38
+ background: $jv-primary-soft;
39
+ color: $jv-primary;
40
+ font-weight: 600;
41
+ }
42
+ }
43
+
44
+ // Sidebar section headers
45
+ .sidebar-header {
46
+ font-size: $jv-font-size-xs;
47
+ font-weight: 600;
48
+ color: $jv-text-soft;
49
+ text-transform: uppercase;
50
+ letter-spacing: 0.5px;
51
+ padding: $jv-space-6 $jv-space-6 $jv-space-2;
52
+ margin-top: $jv-space-4;
53
+ }
54
+
55
+ // Category list in sidebar
56
+ .category-list-container {
57
+ padding: $jv-space-2 0;
58
+
59
+ .category-item {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: $jv-space-4;
63
+ padding: $jv-space-4 $jv-space-6;
64
+ color: $jv-text-main;
65
+ font-size: $jv-font-size-sm;
66
+ border-radius: $jv-radius-sm;
67
+ transition: background-color 0.15s ease;
68
+
69
+ &:hover {
70
+ background: rgba(0, 0, 0, 0.03);
71
+ }
72
+
73
+ .category-icon {
74
+ width: 24px;
75
+ height: 24px;
76
+ border-radius: $jv-radius-xs;
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ font-size: 12px;
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ // ===========================================================
87
+ // WIDGET CONTAINER (General)
88
+ // ===========================================================
89
+ .widget-area,
90
+ div[data-widget-area] {
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: $jv-space-6;
94
+ }
95
+
96
+ // Individual widget card
97
+ .widget {
98
+ background: $jv-surface;
99
+ border: 1px solid $jv-border-subtle;
100
+ border-radius: $jv-radius-lg;
101
+ padding: $jv-space-8;
102
+ transition: box-shadow 0.15s ease;
103
+
104
+ &:hover {
105
+ box-shadow: $jv-shadow-soft;
106
+ }
107
+ }
108
+
109
+ // Widget titles
110
+ .widget-title,
111
+ div[data-widget-area] h5,
112
+ div[data-widget-area] h6,
113
+ div[data-widget-area="right"] h5,
114
+ div[data-widget-area="right"] h8 {
115
+ font-size: 14px;
116
+ font-weight: 700;
117
+ margin-bottom: $jv-space-6;
118
+ color: $jv-text-main;
119
+ text-transform: uppercase;
120
+ letter-spacing: 0.3px;
121
+ }
122
+
123
+ // ===========================================================
124
+ // TRENDING TAGS
125
+ // ===========================================================
126
+
127
+ .popular-tags {
128
+ gap: 6px;
129
+
130
+ .tag-list > div {
131
+ background: $jv-surface;
132
+ border: 1px solid $jv-border-subtle;
133
+ border-radius: 10px;
134
+ padding: 10px 12px;
135
+ font-size: 14px;
136
+ color: $jv-text-main;
137
+ display: flex;
138
+ flex-direction: column;
139
+ gap: 2px;
140
+ cursor: pointer;
141
+ transition: border-color 0.15s ease, background 0.15s ease;
142
+
143
+ &:hover {
144
+ border-color: rgba(0,0,0,0.12);
145
+ background: rgba(0,0,0,0.03);
146
+ }
147
+
148
+ small {
149
+ color: $jv-text-muted;
150
+ font-size: $jv-font-size-xs;
151
+ }
152
+ }
153
+ }
154
+
155
+ // ===========================================================
156
+ // TRENDING NOW
157
+ // ===========================================================
158
+
159
+ #recent_posts {
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: 10px;
163
+ margin-top: $jv-space-6;
164
+
165
+ li.widget-posts {
166
+ background: $jv-surface;
167
+ border: 1px solid rgba(0,0,0,0.05);
168
+ border-radius: $jv-radius-md;
169
+ padding: 10px 14px;
170
+ display: flex;
171
+ flex-direction: column;
172
+ gap: $jv-space-4;
173
+ transition: box-shadow 0.15s ease, border 0.15s ease;
174
+
175
+ &:hover {
176
+ border-color: rgba(0,0,0,0.08);
177
+ box-shadow: $jv-shadow-soft;
178
+ }
179
+
180
+ // Meta info
181
+ .d-flex.gap-2,
182
+ .timeago {
183
+ font-size: $jv-font-size-xs;
184
+ color: $jv-text-muted;
185
+ }
186
+
187
+ // Title inside mini post
188
+ a {
189
+ font-size: 14px;
190
+ font-weight: 500;
191
+ color: $jv-text-main;
192
+ text-decoration: none;
193
+ line-height: $jv-line-height-tight;
194
+
195
+ &:hover {
196
+ color: $jv-primary;
197
+ }
198
+ }
199
+
200
+ // 2-line clamp for content preview
201
+ p,
202
+ .content {
203
+ display: -webkit-box;
204
+ -webkit-line-clamp: 2;
205
+ -webkit-box-orient: vertical;
206
+ overflow: hidden;
207
+ font-size: $jv-font-size-sm;
208
+ color: $jv-text-muted;
209
+ margin: 0;
210
+ }
211
+
212
+ // Read more alignment
213
+ a.stretched-link {
214
+ font-size: $jv-font-size-xs;
215
+ color: $jv-primary;
216
+ }
217
+ }
218
+ }
219
+
220
+ // ===========================================================
221
+ // SEARCH WIDGET
222
+ // ===========================================================
223
+ .search-widget {
224
+ .input-group {
225
+ display: flex;
226
+
227
+ .form-control {
228
+ flex: 1;
229
+ border-top-right-radius: 0;
230
+ border-bottom-right-radius: 0;
231
+ border-right: none;
232
+ }
233
+
234
+ .btn {
235
+ border-top-left-radius: 0;
236
+ border-bottom-left-radius: 0;
237
+ padding: 8px 14px;
238
+ }
239
+ }
240
+ }
241
+
242
+ // ===========================================================
243
+ // ONLINE USERS WIDGET
244
+ // ===========================================================
245
+ .online-users,
246
+ .online-now {
247
+ .user-avatar {
248
+ width: 32px;
249
+ height: 32px;
250
+ border-radius: 50%;
251
+ object-fit: cover;
252
+ border: 2px solid $jv-surface;
253
+ transition: transform 0.15s ease;
254
+
255
+ &:hover {
256
+ transform: scale(1.1);
257
+ z-index: 10;
258
+ }
259
+ }
260
+
261
+ .avatar-stack {
262
+ display: flex;
263
+ flex-wrap: wrap;
264
+ gap: 4px;
265
+
266
+ .user-avatar {
267
+ margin-left: -8px;
268
+
269
+ &:first-child {
270
+ margin-left: 0;
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+ // ===========================================================
277
+ // CATEGORIES WIDGET
278
+ // ===========================================================
279
+ .categories-widget {
280
+ .category-item {
281
+ display: flex;
282
+ align-items: center;
283
+ gap: $jv-space-4;
284
+ padding: $jv-space-4 0;
285
+ border-bottom: 1px solid $jv-border-subtle;
286
+ transition: background-color 0.15s ease;
287
+
288
+ &:last-child {
289
+ border-bottom: none;
290
+ }
291
+
292
+ &:hover {
293
+ background: rgba(0, 0, 0, 0.02);
294
+ margin: 0 (-$jv-space-4);
295
+ padding-left: $jv-space-4;
296
+ padding-right: $jv-space-4;
297
+ border-radius: $jv-radius-sm;
298
+ }
299
+
300
+ .category-icon {
301
+ width: 24px;
302
+ height: 24px;
303
+ border-radius: $jv-radius-xs;
304
+ display: flex;
305
+ align-items: center;
306
+ justify-content: center;
307
+ font-size: 12px;
308
+ flex-shrink: 0;
309
+ }
310
+
311
+ .category-name {
312
+ flex: 1;
313
+ font-size: $jv-font-size-sm;
314
+ font-weight: 500;
315
+ color: $jv-text-main;
316
+ }
317
+
318
+ .category-count {
319
+ font-size: $jv-font-size-xs;
320
+ color: $jv-text-soft;
321
+ background: rgba(0, 0, 0, 0.05);
322
+ padding: 2px 6px;
323
+ border-radius: $jv-radius-pill;
324
+ }
325
+ }
326
+ }
327
+
328
+ // ===========================================================
329
+ // STATS WIDGET
330
+ // ===========================================================
331
+ .stats-widget {
332
+ display: grid;
333
+ grid-template-columns: repeat(2, 1fr);
334
+ gap: $jv-space-6;
335
+
336
+ .stat-item {
337
+ text-align: center;
338
+ padding: $jv-space-4;
339
+ background: rgba(0, 0, 0, 0.02);
340
+ border-radius: $jv-radius-sm;
341
+
342
+ .stat-value {
343
+ font-size: $jv-font-size-xl;
344
+ font-weight: 700;
345
+ color: $jv-text-main;
346
+ line-height: 1;
347
+ }
348
+
349
+ .stat-label {
350
+ font-size: $jv-font-size-xs;
351
+ color: $jv-text-muted;
352
+ margin-top: $jv-space-2;
353
+ text-transform: uppercase;
354
+ letter-spacing: 0.3px;
355
+ }
356
+ }
357
+ }
358
+
359
+ // ===========================================================
360
+ // INFO WIDGET
361
+ // ===========================================================
362
+ .info-widget {
363
+ font-size: $jv-font-size-sm;
364
+ color: $jv-text-muted;
365
+ line-height: $jv-line-height-base;
366
+
367
+ p {
368
+ margin-bottom: $jv-space-4;
369
+
370
+ &:last-child {
371
+ margin-bottom: 0;
372
+ }
373
+ }
374
+
375
+ a {
376
+ color: $jv-primary;
377
+
378
+ &:hover {
379
+ text-decoration: underline;
380
+ }
381
+ }
382
+ }
383
+
384
+ // ===========================================================
385
+ // USER CARD WIDGET (in left sidebar)
386
+ // ===========================================================
387
+ .user-card-widget {
388
+ .user-header {
389
+ display: flex;
390
+ align-items: center;
391
+ gap: $jv-space-4;
392
+ margin-bottom: $jv-space-6;
393
+
394
+ .user-avatar {
395
+ width: 48px;
396
+ height: 48px;
397
+ border-radius: 50%;
398
+ object-fit: cover;
399
+ }
400
+
401
+ .user-info {
402
+ flex: 1;
403
+
404
+ .user-name {
405
+ font-size: $jv-font-size-base;
406
+ font-weight: 600;
407
+ color: $jv-text-main;
408
+ }
409
+
410
+ .user-title {
411
+ font-size: $jv-font-size-xs;
412
+ color: $jv-text-muted;
413
+ }
414
+ }
415
+ }
416
+
417
+ .user-stats {
418
+ display: flex;
419
+ justify-content: space-around;
420
+ padding: $jv-space-4 0;
421
+ border-top: 1px solid $jv-border-subtle;
422
+ border-bottom: 1px solid $jv-border-subtle;
423
+ margin-bottom: $jv-space-6;
424
+
425
+ .stat {
426
+ text-align: center;
427
+
428
+ .value {
429
+ font-size: $jv-font-size-lg;
430
+ font-weight: 600;
431
+ color: $jv-text-main;
432
+ }
433
+
434
+ .label {
435
+ font-size: $jv-font-size-xs;
436
+ color: $jv-text-muted;
437
+ }
438
+ }
439
+ }
440
+
441
+ .user-actions {
442
+ display: flex;
443
+ flex-direction: column;
444
+ gap: $jv-space-2;
445
+
446
+ .btn {
447
+ width: 100%;
448
+ }
449
+ }
450
+ }
451
+
452
+ // ===========================================================
453
+ // SUGGESTED TOPICS WIDGET
454
+ // ===========================================================
455
+ .suggested-topics {
456
+ .topic-item {
457
+ display: flex;
458
+ gap: $jv-space-4;
459
+ padding: $jv-space-4 0;
460
+ border-bottom: 1px solid $jv-border-subtle;
461
+
462
+ &:last-child {
463
+ border-bottom: none;
464
+ }
465
+
466
+ .topic-thumb {
467
+ width: 48px;
468
+ height: 48px;
469
+ border-radius: $jv-radius-sm;
470
+ object-fit: cover;
471
+ flex-shrink: 0;
472
+ }
473
+
474
+ .topic-info {
475
+ flex: 1;
476
+ min-width: 0;
477
+
478
+ .topic-title {
479
+ font-size: $jv-font-size-sm;
480
+ font-weight: 500;
481
+ color: $jv-text-main;
482
+ line-height: $jv-line-height-tight;
483
+ display: -webkit-box;
484
+ -webkit-line-clamp: 2;
485
+ -webkit-box-orient: vertical;
486
+ overflow: hidden;
487
+
488
+ &:hover {
489
+ color: $jv-primary;
490
+ }
491
+ }
492
+
493
+ .topic-meta {
494
+ font-size: $jv-font-size-xs;
495
+ color: $jv-text-soft;
496
+ margin-top: $jv-space-2;
497
+ }
498
+ }
499
+ }
500
+ }
501
+
502
+ // ===========================================================
503
+ // RESPONSIVE SIDEBAR
504
+ // ===========================================================
505
+ @media (max-width: 992px) {
506
+ .sidebar {
507
+ position: fixed;
508
+ top: 0;
509
+ left: 0;
510
+ bottom: 0;
511
+ width: 280px;
512
+ z-index: 1050;
513
+ transform: translateX(-100%);
514
+ transition: transform 0.3s ease;
515
+ box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
516
+
517
+ &.open {
518
+ transform: translateX(0);
519
+ }
520
+ }
521
+
522
+ .sidebar-backdrop {
523
+ position: fixed;
524
+ top: 0;
525
+ left: 0;
526
+ right: 0;
527
+ bottom: 0;
528
+ background: rgba(0, 0, 0, 0.4);
529
+ z-index: 1040;
530
+ opacity: 0;
531
+ visibility: hidden;
532
+ transition: opacity 0.3s ease, visibility 0.3s ease;
533
+
534
+ &.show {
535
+ opacity: 1;
536
+ visibility: visible;
537
+ }
538
+ }
539
+ }
@@ -0,0 +1,54 @@
1
+ // ============================================
2
+ // JAVIS Design System – Tokens
3
+ // ============================================
4
+
5
+ // Brand Colors
6
+ $jv-primary: #0051ff;
7
+ $jv-primary-hover: #0044dd;
8
+ $jv-primary-soft: rgba(0, 81, 255, 0.12);
9
+
10
+ // Neutrals
11
+ $jv-bg: #f5f6f8; // app background
12
+ $jv-surface: #ffffff; // cards, panels
13
+ $jv-border-subtle: rgba(0,0,0,0.06);
14
+ $jv-border-strong: rgba(0,0,0,0.12);
15
+
16
+ // Text
17
+ $jv-text-main: #111111;
18
+ $jv-text-muted: #6b7280;
19
+ $jv-text-soft: #9ca3af;
20
+
21
+ // Radii
22
+ $jv-radius-xs: 4px;
23
+ $jv-radius-sm: 8px;
24
+ $jv-radius-md: 12px;
25
+ $jv-radius-lg: 16px;
26
+ $jv-radius-pill: 999px;
27
+
28
+ // Shadows
29
+ $jv-shadow-soft: 0 2px 8px rgba(0,0,0,0.04);
30
+ $jv-shadow-card: 0 4px 10px rgba(0,0,0,0.05);
31
+ $jv-shadow-button: 0 4px 12px rgba(0, 81, 255, 0.25);
32
+ $jv-shadow-button-hover: 0 6px 16px rgba(0, 81, 255, 0.35);
33
+
34
+ // Spacing (8pt-ish scale)
35
+ $jv-space-2: 4px;
36
+ $jv-space-4: 8px;
37
+ $jv-space-6: 12px;
38
+ $jv-space-8: 16px;
39
+ $jv-space-10: 20px;
40
+ $jv-space-12: 24px;
41
+
42
+ // Typography
43
+ $jv-font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Helvetica Neue", Arial, sans-serif;
44
+ $jv-font-size-base: 15px;
45
+ $jv-font-size-sm: 13px;
46
+ $jv-font-size-xs: 12px;
47
+ $jv-font-size-lg: 18px;
48
+ $jv-font-size-xl: 22px;
49
+ $jv-font-size-xxl: 32px;
50
+
51
+ // Line Heights
52
+ $jv-line-height-base: 1.52;
53
+ $jv-line-height-tight: 1.4;
54
+ $jv-line-height-relaxed: 1.6;
@@ -0,0 +1,39 @@
1
+ // ============================================
2
+ // JAVIS Theme - Bootstrap Variable Overrides
3
+ // This file is imported BEFORE Bootstrap variables
4
+ // Use it to customize Bootstrap's defaults
5
+ // ============================================
6
+
7
+ // Import Harmony's overrides first (inherits their Bootstrap customizations)
8
+ @import "nodebb-theme-harmony/scss/overrides";
9
+
10
+ // JAVIS Brand Colors
11
+ $primary: #0051ff;
12
+ $link-color: #0051ff;
13
+
14
+ // Typography
15
+ $font-family-sans-serif: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Helvetica Neue", Arial, sans-serif;
16
+
17
+ // Body
18
+ $body-bg: #f5f6f8;
19
+ $body-color: #111111;
20
+
21
+ // Borders
22
+ $border-radius: 8px;
23
+ $border-radius-sm: 4px;
24
+ $border-radius-lg: 12px;
25
+ $border-radius-pill: 999px;
26
+
27
+ // Buttons
28
+ $btn-border-radius: 999px;
29
+ $btn-border-radius-sm: 999px;
30
+ $btn-border-radius-lg: 999px;
31
+
32
+ // Cards
33
+ $card-border-radius: 16px;
34
+ $card-border-color: rgba(0, 0, 0, 0.05);
35
+
36
+ // Inputs
37
+ $input-border-radius: 999px;
38
+ $input-focus-border-color: #0051ff;
39
+ $input-focus-box-shadow: 0 0 0 3px rgba(0, 81, 255, 0.12);
@@ -10,8 +10,45 @@
10
10
  $(document).ready(function() {
11
11
  console.log('JAVIS Community Theme initialized');
12
12
 
13
- // Add any custom client-side interactions here
14
- // Example: smooth scrolling, animations, custom widgets, etc.
13
+ // Ensure sidebar toggle works (reinitialize if Harmony's handler isn't loaded)
14
+ initSidebarToggle();
15
15
  });
16
16
 
17
+ function initSidebarToggle() {
18
+ // Check if the toggle element exists
19
+ var toggleEl = $('[component="sidebar/toggle"]');
20
+ if (!toggleEl.length) {
21
+ console.log('JAVIS: Sidebar toggle element not found');
22
+ return;
23
+ }
24
+
25
+ // Remove any existing handlers to avoid duplicates, then add our handler
26
+ toggleEl.off('click.javis').on('click.javis', function(e) {
27
+ e.preventDefault();
28
+ e.stopPropagation();
29
+
30
+ var sidebarEl = $('.sidebar');
31
+ sidebarEl.toggleClass('open');
32
+
33
+ console.log('JAVIS: Sidebar toggled, open:', sidebarEl.hasClass('open'));
34
+
35
+ // Save preference if user is logged in
36
+ if (typeof app !== 'undefined' && app.user && app.user.uid) {
37
+ require(['api'], function(api) {
38
+ api.put('/users/' + app.user.uid + '/settings', {
39
+ settings: {
40
+ openSidebars: sidebarEl.hasClass('open') ? 'on' : 'off',
41
+ },
42
+ }).catch(function(err) {
43
+ console.warn('JAVIS: Could not save sidebar preference', err);
44
+ });
45
+ });
46
+ }
47
+
48
+ $(window).trigger('action:sidebar.toggle');
49
+ });
50
+
51
+ console.log('JAVIS: Sidebar toggle initialized');
52
+ }
53
+
17
54
  })();
@@ -1,12 +1,8 @@
1
- {{{
1
+ <!--
2
2
  JAVIS Community Theme - Post List Item
3
-
4
- This template overrides Harmony's posts_list_item.tpl
3
+ Overrides Harmony's posts_list_item.tpl
5
4
  Used on: Recent, Popular, Unread pages (feed view)
6
-
7
- To customize: Edit the HTML structure below
8
- Original: https://github.com/NodeBB/nodebb-theme-harmony/blob/master/templates/partials/posts_list_item.tpl
9
- }}}
5
+ -->
10
6
  <li component="post" class="posts-list-item {{{ if ./deleted }}} deleted{{{ else }}}{{{ if ./topic.deleted }}} deleted{{{ end }}}{{{ end }}}{{{ if ./topic.scheduled }}} scheduled{{{ end }}}" data-pid="{./pid}" data-uid="{./uid}">
11
7
 
12
8
  <a class="topic-title fw-semibold fs-5 mb-2 text-reset text-break d-block" href="{config.relative_path}/post/{encodeURIComponent(./pid)}">