@okjavis/nodebb-theme-javis 5.0.2 → 5.0.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okjavis/nodebb-theme-javis",
3
- "version": "5.0.2",
3
+ "version": "5.0.6",
4
4
  "description": "Modern, premium NodeBB theme for JAVIS Community - Extends Harmony with custom styling",
5
5
  "main": "theme.js",
6
6
  "scripts": {
package/scss/_base.scss CHANGED
@@ -307,3 +307,127 @@ a {
307
307
  border-top: 1px solid $jv-border-subtle;
308
308
  }
309
309
  }
310
+
311
+ // ===========================================================
312
+ // MOBILE NAVIGATION - Hide Chat and Notification Widgets
313
+ // ===========================================================
314
+ // Hide chat and notifications from mobile bottom navbar only
315
+ @media (max-width: 767px) {
316
+ // Hide notifications widget - multiple selectors for comprehensive coverage
317
+ li[component="notifications"],
318
+ nav[component="sidebar/left"] li[component="notifications"],
319
+ .sidebar-left li[component="notifications"],
320
+ .nav-item.notifications {
321
+ display: none !important;
322
+ visibility: hidden !important;
323
+ }
324
+
325
+ // Hide chat widget - multiple selectors for comprehensive coverage
326
+ li.chats,
327
+ nav[component="sidebar/left"] li.chats,
328
+ .sidebar-left li.chats,
329
+ .nav-item.chats {
330
+ display: none !important;
331
+ visibility: hidden !important;
332
+ }
333
+
334
+ // Also hide drafts widget if present
335
+ li[component="sidebar/drafts"],
336
+ nav[component="sidebar/left"] li[component="sidebar/drafts"],
337
+ .sidebar-left li[component="sidebar/drafts"],
338
+ .nav-item.drafts {
339
+ display: none !important;
340
+ visibility: hidden !important;
341
+ }
342
+ }
343
+
344
+ // ===========================================================
345
+ // ACCOUNT/PROFILE SIDEBAR - Structured layout for mobile
346
+ // ===========================================================
347
+ @media (max-width: 767px) {
348
+ // Account sidebar container - force column layout
349
+ .account [component="sidebar/left"] .flex-shrink-0,
350
+ .account .flex-shrink-0.pe-2.border-end-md {
351
+ width: 100% !important;
352
+ padding: 0 !important;
353
+ border: none !important;
354
+ margin-bottom: $jv-space-4 !important;
355
+ }
356
+
357
+ // Inner container - structured grid layout
358
+ .account [component="sidebar/left"] .sticky-md-top,
359
+ .account .sticky-md-top.d-flex {
360
+ display: grid !important;
361
+ grid-template-columns: 1fr 1fr !important;
362
+ gap: $jv-space-2 !important;
363
+ padding: $jv-space-3 !important;
364
+ background: $jv-surface !important;
365
+ border-radius: $jv-radius-md !important;
366
+ border: 1px solid $jv-border-subtle !important;
367
+ }
368
+
369
+ // Menu items - consistent sizing
370
+ .account [component="sidebar/left"] a.btn {
371
+ margin: 0 !important;
372
+ padding: $jv-space-3 !important;
373
+ border-radius: $jv-radius-sm !important;
374
+ background: $jv-bg !important;
375
+ border: 1px solid $jv-border-subtle !important;
376
+ transition: all $jv-transition-fast !important;
377
+ min-height: 56px !important;
378
+ display: flex !important;
379
+ flex-direction: column !important;
380
+ align-items: flex-start !important;
381
+ justify-content: center !important;
382
+
383
+ &:hover {
384
+ background: $jv-hover-bg !important;
385
+ border-color: $jv-border-strong !important;
386
+ }
387
+
388
+ &.active {
389
+ background: $jv-primary !important;
390
+ color: white !important;
391
+ border-color: $jv-primary !important;
392
+
393
+ .text-xs {
394
+ color: rgba(255, 255, 255, 0.9) !important;
395
+ }
396
+ }
397
+
398
+ // Text content
399
+ .flex-grow-1 {
400
+ font-size: $jv-font-size-sm !important;
401
+ font-weight: 600 !important;
402
+ margin-bottom: 2px !important;
403
+ }
404
+
405
+ // Count badges
406
+ .text-xs {
407
+ font-size: $jv-font-size-xs !important;
408
+ color: $jv-text-soft !important;
409
+ font-weight: 500 !important;
410
+ }
411
+ }
412
+
413
+ // Horizontal rules - full width dividers
414
+ .account [component="sidebar/left"] hr {
415
+ grid-column: 1 / -1 !important;
416
+ margin: $jv-space-2 0 !important;
417
+ border-color: $jv-border-subtle !important;
418
+ }
419
+
420
+ // Settings and action links - full width buttons
421
+ .account [component="sidebar/left"] a.btn.ff-secondary.text-xs,
422
+ .account [component="sidebar/left"] a[href*="/edit"],
423
+ .account [component="sidebar/left"] a[component*="account/"] {
424
+ grid-column: 1 / -1 !important;
425
+ flex-direction: row !important;
426
+ gap: $jv-space-2 !important;
427
+ align-items: center !important;
428
+
429
+ i {
430
+ flex-shrink: 0 !important;
431
+ }
432
+ }
433
+ }
@@ -856,4 +856,32 @@ html.composing .composer.reply {
856
856
  padding-bottom: max($jv-space-3, env(safe-area-inset-bottom)) !important;
857
857
  border-radius: 0 !important;
858
858
  }
859
+
860
+ // Fix composer category dropdown positioning on mobile
861
+ html.composing .composer .category-list-container {
862
+ [component="category-selector"],
863
+ .btn-group {
864
+ position: relative !important;
865
+ }
866
+
867
+ .dropdown-menu {
868
+ transition: none !important;
869
+ animation: none !important;
870
+
871
+ &.show {
872
+ position: absolute !important;
873
+ top: 100% !important;
874
+ left: 0 !important;
875
+ right: auto !important;
876
+ bottom: auto !important;
877
+ transform: none !important;
878
+ margin: 4px 0 0 0 !important;
879
+ width: auto !important;
880
+ min-width: 280px !important;
881
+ max-width: 320px !important;
882
+ max-height: none !important;
883
+ height: auto !important;
884
+ }
885
+ }
886
+ }
859
887
  }
package/scss/_feed.scss CHANGED
@@ -1017,6 +1017,8 @@ ul.categories-list {
1017
1017
  }
1018
1018
 
1019
1019
  .feed-category-filter {
1020
+ // Ensure proper positioning context for dropdown
1021
+ position: relative !important;
1020
1022
  .category-dropdown-container,
1021
1023
  [component="category/dropdown"] {
1022
1024
  // Override the btn-group styling
@@ -1135,3 +1137,41 @@ ul.categories-list {
1135
1137
  }
1136
1138
  }
1137
1139
  }
1140
+
1141
+ // ===========================================================
1142
+ // MOBILE FIX - Category dropdown positioning
1143
+ // Fix dropdown opening from bottom left corner on mobile
1144
+ // ===========================================================
1145
+ @media (max-width: 767px) {
1146
+ .feed-category-filter {
1147
+ // Ensure button group has proper positioning
1148
+ .category-dropdown-container,
1149
+ [component="category/dropdown"],
1150
+ .btn-group {
1151
+ position: relative !important;
1152
+ }
1153
+
1154
+ // Force dropdown to position relative to button, not viewport
1155
+ // Use extremely high specificity to override Popper's inline styles
1156
+ .dropdown-menu {
1157
+ // Disable all transitions and animations on mobile
1158
+ transition: none !important;
1159
+ animation: none !important;
1160
+
1161
+ &.show {
1162
+ position: absolute !important;
1163
+ top: 100% !important;
1164
+ right: 0 !important;
1165
+ left: auto !important;
1166
+ bottom: auto !important;
1167
+ transform: none !important;
1168
+ margin: 4px 0 0 0 !important;
1169
+ // Ensure dropdown has proper dimensions
1170
+ width: auto !important;
1171
+ min-width: 200px !important;
1172
+ max-height: none !important;
1173
+ height: auto !important;
1174
+ }
1175
+ }
1176
+ }
1177
+ }
package/scss/_header.scss CHANGED
@@ -237,6 +237,15 @@
237
237
  }
238
238
  }
239
239
 
240
+ // ===========================================================
241
+ // NOTIFICATION DROPDOWN - Reduced width for better fit
242
+ // ===========================================================
243
+ .notifications-dropdown {
244
+ min-width: 300px !important;
245
+ max-width: 340px !important;
246
+ width: 300px !important;
247
+ }
248
+
240
249
  // ===========================================================
241
250
  // RESPONSIVE ADJUSTMENTS
242
251
  // ===========================================================
@@ -262,6 +271,26 @@
262
271
  }
263
272
  }
264
273
 
274
+ // ===========================================================
275
+ // MOBILE HEADER LOGO (hidden on desktop)
276
+ // ===========================================================
277
+ .javis-mobile-header-logo {
278
+ display: none !important; // Hidden by default on desktop
279
+
280
+ .javis-mobile-logo-link {
281
+ display: flex;
282
+ align-items: center;
283
+ justify-content: center;
284
+ text-decoration: none;
285
+ }
286
+
287
+ .javis-mobile-logo-img {
288
+ max-width: 120px; // Logo width on mobile
289
+ height: 32px; // Logo height on mobile
290
+ object-fit: contain;
291
+ }
292
+ }
293
+
265
294
  @media (max-width: 767px) {
266
295
  .brand-container {
267
296
  // Hide search in header on mobile (use mobile header instead)
@@ -272,6 +301,21 @@
272
301
  > .col-12 {
273
302
  justify-content: center;
274
303
  }
304
+
305
+ // Show mobile logo on mobile devices only
306
+ .javis-mobile-header-logo {
307
+ display: flex !important; // Show on mobile
308
+ align-items: center;
309
+ justify-content: center;
310
+ flex-shrink: 0;
311
+ }
312
+
313
+ // Reduce notification dropdown width on mobile to prevent cutoff
314
+ .notifications-dropdown {
315
+ min-width: 280px !important;
316
+ max-width: 90vw !important;
317
+ width: 280px !important;
318
+ }
275
319
  }
276
320
  }
277
321
 
@@ -51,11 +51,19 @@
51
51
  // Initialize immediate category filter navigation on feed page
52
52
  initFeedCategoryFilter();
53
53
 
54
+ // Fix mobile category dropdown positioning on feed page
55
+ fixMobileFeedCategoryDropdown();
56
+
57
+ // Fix mobile category dropdown positioning in composer
58
+ fixMobileComposerCategoryDropdown();
59
+
54
60
  // Re-initialize carousels when new posts are loaded (infinite scroll, etc.)
55
61
  // Also handle post edits by clearing the processed flag
56
62
  $(window).on('action:posts.loaded action:topic.loaded action:ajaxify.end', function() {
57
63
  initPostImageCarousels();
58
64
  initParentPostNavigation();
65
+ fixMobileFeedCategoryDropdown();
66
+ fixMobileComposerCategoryDropdown();
59
67
  initPostHoverActions();
60
68
  initFeedComposerPromptHandler();
61
69
  initTopicListVoting();
@@ -75,6 +83,11 @@
75
83
  initPostImageCarousels();
76
84
  }
77
85
  });
86
+
87
+ // Handle composer events - fix category dropdown on mobile when composer is shown
88
+ $(window).on('action:composer.loaded action:composer.enhanced', function() {
89
+ fixMobileComposerCategoryDropdown();
90
+ });
78
91
  });
79
92
 
80
93
  /**
@@ -728,6 +741,145 @@
728
741
  });
729
742
  }
730
743
 
744
+ /**
745
+ * Fix mobile category dropdown positioning on feed page
746
+ * Aggressively overrides Popper.js positioning on mobile to prevent bottom-left corner issue
747
+ */
748
+ function fixMobileFeedCategoryDropdown() {
749
+ console.log('JAVIS: fixMobileFeedCategoryDropdown called, window width:', window.innerWidth);
750
+
751
+ // Only run on feed page
752
+ if (!$('.feed').length) {
753
+ console.log('JAVIS: Not on feed page, exiting');
754
+ return;
755
+ }
756
+
757
+ console.log('JAVIS: On feed page, looking for category filter');
758
+
759
+ var $categoryFilter = $('.feed-category-filter [component="category/dropdown"]');
760
+ if (!$categoryFilter.length) {
761
+ console.log('JAVIS: Category filter not found');
762
+ return;
763
+ }
764
+
765
+ console.log('JAVIS: Category filter found, setting up mobile fix');
766
+
767
+ // Find the dropdown button and menu
768
+ var $dropdownButton = $categoryFilter.find('.dropdown-toggle');
769
+ var $dropdownMenu = $categoryFilter.find('.dropdown-menu');
770
+
771
+ if (!$dropdownButton.length || !$dropdownMenu.length) {
772
+ console.log('JAVIS: Dropdown button or menu not found');
773
+ return;
774
+ }
775
+
776
+ // Disable Popper immediately on mobile to prevent animation from bottom-left
777
+ if (window.innerWidth <= 767) {
778
+ $dropdownButton.attr('data-bs-display', 'static');
779
+ console.log('JAVIS: Disabled Popper positioning on mobile');
780
+ }
781
+
782
+ // Always bind the event, but check window width when it fires
783
+ $categoryFilter.off('shown.bs.dropdown.javisMobileFix').on('shown.bs.dropdown.javisMobileFix', function() {
784
+ console.log('JAVIS: Dropdown shown event fired, window width:', window.innerWidth);
785
+
786
+ // Only apply fix on mobile
787
+ if (window.innerWidth > 767) {
788
+ console.log('JAVIS: Not mobile, skipping positioning fix');
789
+ return;
790
+ }
791
+
792
+ console.log('JAVIS: Applying mobile positioning fix');
793
+
794
+ // Use requestAnimationFrame to ensure we override after Popper runs
795
+ requestAnimationFrame(function() {
796
+ $dropdownMenu.css({
797
+ 'position': 'absolute',
798
+ 'top': '100%',
799
+ 'right': '0',
800
+ 'left': 'auto',
801
+ 'bottom': 'auto',
802
+ 'transform': 'none',
803
+ 'margin': '4px 0 0 0',
804
+ 'inset': 'auto'
805
+ });
806
+
807
+ // Also remove Popper attributes
808
+ $dropdownMenu.removeAttr('data-popper-placement');
809
+
810
+ console.log('JAVIS: Mobile positioning applied successfully');
811
+ });
812
+ });
813
+
814
+ console.log('JAVIS: Mobile fix event listener attached');
815
+ }
816
+
817
+ /**
818
+ * Fix mobile category dropdown positioning in composer
819
+ * Aggressively overrides Popper.js positioning on mobile to prevent bottom-left corner issue
820
+ */
821
+ function fixMobileComposerCategoryDropdown() {
822
+ console.log('JAVIS: fixMobileComposerCategoryDropdown called, window width:', window.innerWidth);
823
+
824
+ // Find the composer category selector
825
+ var $categorySelector = $('.composer [component="category-selector"]');
826
+ if (!$categorySelector.length) {
827
+ console.log('JAVIS: Composer category selector not found');
828
+ return;
829
+ }
830
+
831
+ console.log('JAVIS: Composer category selector found, setting up mobile fix');
832
+
833
+ // Find the dropdown button and menu
834
+ var $dropdownButton = $categorySelector.find('.dropdown-toggle');
835
+ var $dropdownMenu = $categorySelector.find('.dropdown-menu');
836
+
837
+ if (!$dropdownButton.length || !$dropdownMenu.length) {
838
+ console.log('JAVIS: Composer dropdown button or menu not found');
839
+ return;
840
+ }
841
+
842
+ // Disable Popper immediately on mobile to prevent animation from bottom-left
843
+ if (window.innerWidth <= 767) {
844
+ $dropdownButton.attr('data-bs-display', 'static');
845
+ console.log('JAVIS: Disabled Popper positioning on mobile for composer');
846
+ }
847
+
848
+ // Always bind the event, but check window width when it fires
849
+ $categorySelector.off('shown.bs.dropdown.javisComposerMobileFix').on('shown.bs.dropdown.javisComposerMobileFix', function() {
850
+ console.log('JAVIS: Composer dropdown shown event fired, window width:', window.innerWidth);
851
+
852
+ // Only apply fix on mobile
853
+ if (window.innerWidth > 767) {
854
+ console.log('JAVIS: Not mobile, skipping composer positioning fix');
855
+ return;
856
+ }
857
+
858
+ console.log('JAVIS: Applying mobile positioning fix for composer');
859
+
860
+ // Use requestAnimationFrame to ensure we override after Popper runs
861
+ requestAnimationFrame(function() {
862
+ $dropdownMenu.css({
863
+ 'position': 'absolute',
864
+ 'top': '100%',
865
+ 'left': '0',
866
+ 'right': 'auto',
867
+ 'bottom': 'auto',
868
+ 'transform': 'none',
869
+ 'margin': '4px 0 0 0',
870
+ 'inset': 'auto'
871
+ });
872
+
873
+ // Also remove Popper attributes
874
+ $dropdownMenu.removeAttr('data-popper-placement');
875
+
876
+ console.log('JAVIS: Composer mobile positioning applied successfully');
877
+ });
878
+ });
879
+
880
+ console.log('JAVIS: Composer mobile fix event listener attached');
881
+ }
882
+
731
883
  /**
732
884
  * Initialize immediate category filter navigation on feed page
733
885
  * When a category is selected, navigate immediately instead of waiting for dropdown close
@@ -1,6 +1,13 @@
1
1
  {{{ if widgets.brand-header.length }}}
2
2
  <div class="container-lg px-md-4 brand-container">
3
3
  <div class="col-12 d-flex border-bottom pb-3 {{{ if config.theme.centerHeaderElements }}}justify-content-center{{{ end }}}">
4
+ <!-- Mobile Logo (only visible on mobile) -->
5
+ <div class="javis-mobile-header-logo d-none">
6
+ <a href="{relative_path}/" class="javis-mobile-logo-link" title="JAVIS Community">
7
+ <img src="{relative_path}/plugins/@okjavis/nodebb-theme-javis/static/images/logo-full.png" alt="JAVIS Community" class="javis-mobile-logo-img" />
8
+ </a>
9
+ </div>
10
+
4
11
  <!-- Search widget area (left/center) -->
5
12
  <div data-widget-area="brand-header" class="flex-fill gap-3 p-2 align-self-center">
6
13
  {{{each widgets.brand-header}}}