@okjavis/nodebb-theme-javis 2.5.3 → 3.0.1

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.
@@ -6,13 +6,13 @@
6
6
  // ===========================================================
7
7
  // JAVIS SIDEBAR LOGO
8
8
  // ===========================================================
9
- // Height should match the sticky header (64px) for visual alignment
9
+ // Height should match the sticky header (56px) for visual alignment
10
10
  .javis-sidebar-logo {
11
11
  display: flex;
12
12
  align-items: center;
13
13
  justify-content: center;
14
- height: 65px; // Match header height (12px + 40px + 12px)
15
- min-height: 65px;
14
+ height: 56px; // Match header height (8px + 36px + 8px + border)
15
+ min-height: 56px;
16
16
  padding: 0 $jv-space-4; // Only horizontal padding
17
17
  margin-bottom: $jv-space-3; // 12px space below border before nav items
18
18
  border-bottom: 1px solid $jv-border-subtle;
@@ -26,17 +26,17 @@
26
26
  text-decoration: none;
27
27
  }
28
28
 
29
- // Icon logo (collapsed state) - 28px to match header logo
29
+ // Icon logo (collapsed state) - 36px for better visibility
30
30
  .javis-logo-icon {
31
- width: 28px;
32
- height: 28px;
31
+ width: 36px;
32
+ height: 36px;
33
33
  object-fit: contain;
34
34
  }
35
35
 
36
- // Full logo (expanded state) - max 140px width, 28px height
36
+ // Full logo (expanded state) - max 140px width, 36px height
37
37
  .javis-logo-full {
38
38
  max-width: 140px;
39
- height: 28px;
39
+ height: 36px;
40
40
  object-fit: contain;
41
41
  }
42
42
  }
@@ -50,6 +50,7 @@
50
50
  // ===========================================================
51
51
  // LEFT SIDEBAR (Main Navigation)
52
52
  // ===========================================================
53
+ // Reddit-style wider sidebar (200px) with expanded state as default
53
54
 
54
55
  // Override Bootstrap's bg-light class on sidebar
55
56
  .sidebar.bg-light,
@@ -59,9 +60,18 @@ nav.sidebar.bg-light {
59
60
 
60
61
  .sidebar {
61
62
  background: $jv-surface !important; // Pure white - cohesive with header
62
- border-right: 1px solid $jv-border-subtle;
63
+ border-right: none !important; // Clean look - no vertical divider
63
64
  padding-top: 0 !important; // Remove top padding so logo sits at top edge
64
65
 
66
+ // Desktop: Use 270px width when expanded (Reddit-style)
67
+ @media (min-width: 992px) {
68
+ &.open {
69
+ min-width: 270px !important;
70
+ max-width: 270px !important;
71
+ width: 270px !important;
72
+ }
73
+ }
74
+
65
75
  // Nav items - proper spacing between items
66
76
  .nav-item {
67
77
  margin-bottom: $jv-space-2; // 4px between nav items - compact like Slack/Discord
@@ -498,7 +508,8 @@ div[data-widget-area] {
498
508
  // RIGHT SIDEBAR WIDGET AREA (Reddit-style)
499
509
  // ===========================================================
500
510
  div[data-widget-area="right"],
501
- .col-lg-3.col-sm-12 {
511
+ div[data-widget-area="right"].col-lg-3.col-sm-12,
512
+ .col-lg-3.col-sm-12[data-widget-area="right"] {
502
513
  display: flex;
503
514
  flex-direction: column;
504
515
 
@@ -506,33 +517,49 @@ div[data-widget-area="right"],
506
517
  position: sticky;
507
518
  top: 72px; // Adjust based on your header height
508
519
  align-self: flex-start;
509
- max-height: calc(100vh - 100px); // Account for header + padding
510
- overflow-y: auto; // Allow scrolling if content is too tall
511
-
512
- // Smooth scrollbar styling (webkit browsers)
513
- &::-webkit-scrollbar {
514
- width: 6px;
515
- }
516
-
517
- &::-webkit-scrollbar-track {
518
- background: transparent;
519
- }
520
520
 
521
- &::-webkit-scrollbar-thumb {
522
- background: rgba(0, 0, 0, 0.15);
523
- border-radius: 3px;
524
-
525
- &:hover {
526
- background: rgba(0, 0, 0, 0.25);
527
- }
528
- }
521
+ // CRITICAL: Remove all overflow/scroll from sidebar and ALL descendants
522
+ overflow: visible !important;
523
+ max-height: none !important;
529
524
 
530
525
  // Widget card container
531
526
  > div {
532
527
  background: $jv-surface;
533
528
  border: 1px solid $jv-border-subtle;
534
529
  border-radius: $jv-radius-lg;
535
- overflow: hidden;
530
+ overflow: hidden; // Hide overflow on card itself
531
+ }
532
+
533
+ // Trending Now widget - needs scrollable content
534
+ > div:has(#recent_posts),
535
+ > div:has(ul[id*="recent"]),
536
+ > div:has(.widget-posts) {
537
+ overflow: hidden !important; // Card clips content
538
+
539
+ // Inner scrollable container
540
+ > div {
541
+ max-height: 500px !important;
542
+ overflow-y: auto !important;
543
+ overflow-x: hidden !important;
544
+
545
+ // Scrollbar styling
546
+ &::-webkit-scrollbar {
547
+ width: 6px;
548
+ }
549
+ &::-webkit-scrollbar-track {
550
+ background: rgba(0, 0, 0, 0.03);
551
+ border-radius: 3px;
552
+ }
553
+ &::-webkit-scrollbar-thumb {
554
+ background: rgba(0, 0, 0, 0.15);
555
+ border-radius: 3px;
556
+ &:hover {
557
+ background: rgba(0, 0, 0, 0.25);
558
+ }
559
+ }
560
+ scrollbar-width: thin;
561
+ scrollbar-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.03);
562
+ }
536
563
  }
537
564
 
538
565
  // Widget header/title - clean and simple
@@ -542,14 +569,19 @@ div[data-widget-area="right"],
542
569
  text-transform: uppercase;
543
570
  letter-spacing: 0.5px;
544
571
  color: $jv-text-soft;
545
- padding: $jv-space-4 $jv-space-4 $jv-space-4 $jv-space-4;
572
+ padding: $jv-space-4 0 $jv-space-3 0 !important; // top right bottom left - no horizontal padding (body handles it)
546
573
  margin: 0 !important;
547
574
  border-bottom: none !important; // Removed border
548
575
  }
549
576
 
577
+ // Remove hr dividers after widget headers
578
+ hr {
579
+ display: none !important;
580
+ }
581
+
550
582
  // Add spacing between widgets
551
583
  > div + div {
552
- margin-top: $jv-space-4;
584
+ margin-top: $jv-space-3; // Reduced from 16px to 12px
553
585
  }
554
586
  }
555
587
 
@@ -563,30 +595,35 @@ div[data-widget-area="right"] {
563
595
  border: none !important;
564
596
  border-radius: 0 !important;
565
597
  overflow: visible !important;
566
-
567
- // Keep the header styled
568
- h5 {
569
- padding: $jv-space-3 0 !important;
570
- border-bottom: none !important;
571
- }
598
+ padding: 0 $jv-space-4 !important; // Horizontal padding for alignment
599
+ margin-bottom: 0 !important; // Remove extra margin
572
600
  }
573
601
 
574
602
  .popular-tags {
575
603
  padding: 0 !important;
576
- margin: 0;
604
+ margin: 0 !important; // Reset all margins
605
+
606
+ // Override Bootstrap mb-3 class
607
+ &.mb-3 {
608
+ margin-bottom: $jv-space-2 !important; // Space between widgets (reduced to 8px)
609
+ }
577
610
  }
578
611
 
579
612
  // Override Bootstrap's grid - make it a flowing wrap layout
580
- .tag-list {
613
+ .tag-list,
614
+ .tag-list.row {
581
615
  display: flex !important;
582
616
  flex-wrap: wrap !important;
583
617
  gap: $jv-space-2 !important; // 8px gap between pills
584
618
  padding: 0 !important;
585
619
  margin: 0 !important;
620
+ margin-left: -$jv-space-3 !important; // Offset to align first pill's text with header (compensate for pill padding)
621
+ margin-bottom: $jv-space-2 !important; // Space between widgets (8px)
586
622
 
587
623
  // Reset Bootstrap row/column styles
588
624
  &.row {
589
- margin: 0 !important;
625
+ margin-left: -$jv-space-3 !important;
626
+ margin-bottom: $jv-space-2 !important;
590
627
  display: flex !important;
591
628
  flex-wrap: wrap !important;
592
629
  }
@@ -672,43 +709,13 @@ div[data-widget-area="right"] {
672
709
  }
673
710
 
674
711
  // ===========================================================
675
- // TRENDING POSTS WIDGET - Widget Essentials Specific
712
+ // TRENDING POSTS WIDGET - Widget Essentials / Recent Posts
676
713
  // ===========================================================
677
714
 
678
- // Override Bootstrap's overflow-hidden on wrapper divs
679
- .overflow-hidden {
680
- overflow: visible !important;
681
- }
682
-
683
- // The wrapper div after h5 (Trending Posts header) - make it scrollable
684
- h5 + div {
685
- max-height: 420px;
686
- overflow-y: auto !important;
687
- overflow-x: hidden !important;
688
-
689
- // Scrollbar styling
690
- &::-webkit-scrollbar {
691
- width: 6px;
692
- }
693
- &::-webkit-scrollbar-track {
694
- background: transparent;
695
- }
696
- &::-webkit-scrollbar-thumb {
697
- background: rgba(0, 0, 0, 0.15);
698
- border-radius: 3px;
699
- &:hover {
700
- background: rgba(0, 0, 0, 0.25);
701
- }
702
- }
703
- }
704
-
705
- // Recent posts container - no scroll here, parent wrapper handles it
715
+ // Recent posts container styling
706
716
  #recent_posts,
707
717
  ul[id*="recent"] {
708
- max-height: none !important;
709
- overflow: visible !important;
710
- padding: $jv-space-3 !important;
711
- padding-bottom: $jv-space-5 !important;
718
+ padding: $jv-space-3 $jv-space-4 $jv-space-4 $jv-space-4 !important;
712
719
  margin: 0;
713
720
  list-style: none;
714
721
  display: flex !important;
@@ -829,4 +836,51 @@ div[data-widget-area="right"] {
829
836
  }
830
837
  }
831
838
  }
839
+ }
840
+
841
+ // ===========================================================
842
+ // CRITICAL: Override ALL overflow rules on right sidebar
843
+ // This MUST be at the end to have highest specificity
844
+ // The selector [data-widget-area=right] gets overflow-y:auto from somewhere
845
+ // ===========================================================
846
+
847
+ // Override the base selector that has overflow-y: auto
848
+ [data-widget-area="right"] {
849
+ overflow: visible !important;
850
+ overflow-y: visible !important;
851
+ overflow-x: visible !important;
852
+ max-height: none !important;
853
+ }
854
+
855
+ // More specific selectors to ensure override
856
+ div[data-widget-area="right"],
857
+ .col-lg-3[data-widget-area="right"],
858
+ .col-sm-12[data-widget-area="right"] {
859
+ overflow: visible !important;
860
+ overflow-y: visible !important;
861
+ overflow-x: visible !important;
862
+ max-height: none !important;
863
+ }
864
+
865
+ // Override Bootstrap's overflow-hidden utility
866
+ div[data-widget-area="right"] .overflow-hidden,
867
+ [data-widget-area="right"] .overflow-hidden {
868
+ overflow: visible !important;
869
+ overflow-x: visible !important;
870
+ overflow-y: visible !important;
871
+ max-height: none !important;
872
+ }
873
+
874
+ // Hide any scrollbar that might appear (as backup)
875
+ [data-widget-area="right"]::-webkit-scrollbar,
876
+ div[data-widget-area="right"]::-webkit-scrollbar {
877
+ display: none !important;
878
+ width: 0 !important;
879
+ height: 0 !important;
880
+ }
881
+
882
+ [data-widget-area="right"],
883
+ div[data-widget-area="right"] {
884
+ scrollbar-width: none !important;
885
+ -ms-overflow-style: none !important;
832
886
  }
package/scss/_topic.scss CHANGED
@@ -63,7 +63,7 @@ body.template-topic {
63
63
  display: flex;
64
64
  flex-wrap: wrap;
65
65
  gap: $jv-space-2;
66
- margin-bottom: $jv-space-4;
66
+ margin-bottom: 0;
67
67
 
68
68
  .badge,
69
69
  .tag {
@@ -12,8 +12,8 @@
12
12
  $(document).ready(function() {
13
13
  console.log('JAVIS Community Theme initialized');
14
14
 
15
- // Ensure sidebar toggle works (reinitialize if Harmony's handler isn't loaded)
16
- initSidebarToggle();
15
+ // Auto-expand sidebar on desktop (Reddit-style default)
16
+ initSidebarAutoExpand();
17
17
 
18
18
  // Initialize image carousels for posts with multiple images
19
19
  initPostImageCarousels();
@@ -198,41 +198,38 @@
198
198
  console.log('JAVIS: Created carousel with ' + $images.length + ' images');
199
199
  }
200
200
 
201
- function initSidebarToggle() {
202
- // Check if the toggle element exists
203
- var toggleEl = $('[component="sidebar/toggle"]');
204
- if (!toggleEl.length) {
205
- console.log('JAVIS: Sidebar toggle element not found');
201
+ /**
202
+ * Auto-expand sidebar on desktop (Reddit-style default)
203
+ * The sidebar will be expanded by default on desktop, but users can still toggle it.
204
+ * Their preference is saved and respected on subsequent visits.
205
+ */
206
+ function initSidebarAutoExpand() {
207
+ // Only run on desktop (min-width: 992px)
208
+ if ($(window).width() < 992) {
206
209
  return;
207
210
  }
208
211
 
209
- // Remove any existing handlers to avoid duplicates, then add our handler
210
- toggleEl.off('click.javis').on('click.javis', function(e) {
211
- e.preventDefault();
212
- e.stopPropagation();
212
+ var $sidebar = $('.sidebar-left');
213
+ if (!$sidebar.length) {
214
+ return;
215
+ }
213
216
 
214
- var sidebarEl = $('.sidebar');
215
- sidebarEl.toggleClass('open');
216
-
217
- console.log('JAVIS: Sidebar toggled, open:', sidebarEl.hasClass('open'));
218
-
219
- // Save preference if user is logged in
220
- if (typeof app !== 'undefined' && app.user && app.user.uid) {
221
- require(['api'], function(api) {
222
- api.put('/users/' + app.user.uid + '/settings', {
223
- settings: {
224
- openSidebars: sidebarEl.hasClass('open') ? 'on' : 'off',
225
- },
226
- }).catch(function(err) {
227
- console.warn('JAVIS: Could not save sidebar preference', err);
228
- });
229
- });
217
+ // Check if user has a saved preference (via config.theme.openSidebars)
218
+ // If they've explicitly closed the sidebar before, respect that
219
+ var hasUserPreference = typeof config !== 'undefined' &&
220
+ config.theme &&
221
+ typeof config.theme.openSidebars !== 'undefined';
222
+
223
+ // If sidebar is not already open and user hasn't explicitly closed it, expand it
224
+ if (!$sidebar.hasClass('open')) {
225
+ // If no user preference set, auto-expand (first-time visitors)
226
+ // If user preference is 'on', also expand
227
+ if (!hasUserPreference || config.theme.openSidebars === 'on' || config.theme.openSidebars === true) {
228
+ $sidebar.addClass('open');
229
+ $(window).trigger('action:sidebar.toggle');
230
+ console.log('JAVIS: Auto-expanded sidebar (Reddit-style default)');
230
231
  }
231
-
232
- $(window).trigger('action:sidebar.toggle');
233
- });
234
-
235
- console.log('JAVIS: Sidebar toggle initialized');
232
+ }
236
233
  }
237
234
 
238
235
  /**
@@ -0,0 +1,67 @@
1
+ <li component="categories/category" data-cid="{./cid}" class="category-card w-100 py-3 py-lg-4 gap-lg-0 gap-2 d-flex flex-column flex-lg-row align-items-start category-{./cid} {./unread-class}">
2
+ <meta itemprop="name" content="{./name}">
3
+
4
+ <div class="d-flex col-lg-7 gap-2 gap-lg-3">
5
+ <div class="flex-shrink-0">
6
+ {buildCategoryIcon(@value, "48px", "rounded-1 category-icon-enhanced")}
7
+ </div>
8
+ <div class="flex-grow-1 d-flex flex-wrap gap-1 me-0 me-lg-2">
9
+ <h2 class="title text-break fs-5 fw-semibold m-0 tracking-tight w-100">
10
+ <!-- IMPORT partials/categories/link.tpl -->
11
+ </h2>
12
+ {{{ if ./descriptionParsed }}}
13
+ <div class="description text-muted text-sm w-100">
14
+ {./descriptionParsed}
15
+ </div>
16
+ {{{ end }}}
17
+
18
+ <!-- Activity Badge Row -->
19
+ <div class="category-activity-row d-flex align-items-center gap-2 w-100 mt-1">
20
+ {{{ each ./posts }}}
21
+ {{{ if @first }}}
22
+ <span class="activity-badge" title="Last activity">
23
+ <i class="fa fa-clock-o"></i>
24
+ <span class="timeago" title="{./timestampISO}"></span>
25
+ </span>
26
+ {{{ end }}}
27
+ {{{ end }}}
28
+ </div>
29
+
30
+ {{{ if !config.hideSubCategories }}}
31
+ {{{ if ./children.length }}}
32
+ <div class="subcategory-pills d-flex flex-wrap gap-2 mt-2 w-100">
33
+ {{{ each ./children }}}
34
+ {{{ if !./isSection }}}
35
+ <a href="{{{ if ./link }}}{./link}{{{ else }}}{config.relative_path}/category/{./slug}{{{ end }}}" class="subcategory-pill" style="--pill-color: {./bgColor};">
36
+ <span class="pill-icon" style="background-color: {./bgColor};">
37
+ <i class="{./icon}"></i>
38
+ </span>
39
+ <span class="pill-name">{./name}</span>
40
+ </a>
41
+ {{{ end }}}
42
+ {{{ end }}}
43
+ </div>
44
+ {{{ end }}}
45
+ {{{ end }}}
46
+ </div>
47
+ </div>
48
+ {{{ if !./link }}}
49
+ <div class="d-flex col-lg-5 col-12 align-content-stretch">
50
+ <div class="meta stats-minimal d-none d-lg-flex col-4 gap-3 pe-3 text-muted align-items-center justify-content-end">
51
+ <div class="stat-item text-center">
52
+ <span class="stat-number" title="{./totalTopicCount}">{humanReadableNumber(./totalTopicCount, 0)}</span>
53
+ <span class="stat-label">topics</span>
54
+ </div>
55
+ <div class="stat-item text-center">
56
+ <span class="stat-number" title="{./totalPostCount}">{humanReadableNumber(./totalPostCount, 0)}</span>
57
+ <span class="stat-label">posts</span>
58
+ </div>
59
+ </div>
60
+ {{{ if !config.hideCategoryLastPost }}}
61
+ <div component="topic/teaser" class="teaser col-lg-8 col-12 {{{ if !config.theme.mobileTopicTeasers }}}d-none d-lg-block{{{ end }}}">
62
+ <!-- IMPORT partials/categories/lastpost.tpl -->
63
+ </div>
64
+ {{{ end }}}
65
+ </div>
66
+ {{{ end }}}
67
+ </li>
@@ -0,0 +1,30 @@
1
+ <div class="lastpost teaser-enhanced lh-sm h-100" style="--teaser-color: {./bgColor};">
2
+ {{{ each ./posts }}}
3
+ {{{ if @first }}}
4
+ <div component="category/posts" class="d-flex flex-column h-100 gap-2">
5
+ <div class="teaser-header d-flex align-items-center gap-2">
6
+ <a class="text-decoration-none avatar-tooltip" title="{./user.displayname}" href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(posts.user, "24px", true)}</a>
7
+ <div class="teaser-meta">
8
+ <span class="teaser-user">{./user.displayname}</span>
9
+ <a class="permalink timeago teaser-time" href="{config.relative_path}/topic/{./topic.slug}{{{ if ./index }}}/{./index}{{{ end }}}" title="{./timestampISO}" aria-label="[[global:lastpost]]"></a>
10
+ </div>
11
+ </div>
12
+ <div class="teaser-content-wrapper position-relative flex-fill">
13
+ <div class="teaser-content text-break line-clamp-2">
14
+ {./content}
15
+ </div>
16
+ <a class="teaser-read-more" href="{config.relative_path}/topic/{./topic.slug}{{{ if ./index }}}/{./index}{{{ end }}}">Read more →</a>
17
+ </div>
18
+ </div>
19
+ {{{ end }}}
20
+ {{{ end }}}
21
+
22
+ {{{ if !./posts.length }}}
23
+ <div component="category/posts" class="ps-2 empty-category-state">
24
+ <div class="d-flex flex-column align-items-start gap-1">
25
+ <span class="empty-icon"><i class="fa fa-inbox"></i></span>
26
+ <span class="empty-text">Be the first to post</span>
27
+ </div>
28
+ </div>
29
+ {{{ end }}}
30
+ </div>
@@ -0,0 +1,5 @@
1
+ {{{ if ./isSection }}}
2
+ {./name}
3
+ {{{ else }}}
4
+ <a class="text-reset" href="{{{ if ./link }}}{./link}{{{ else }}}{config.relative_path}/category/{./slug}{{{ end }}}" itemprop="url">{../name}</a>
5
+ {{{ end }}}
@@ -1,11 +1,64 @@
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
+ <!-- Search widget area (left/center) -->
4
5
  <div data-widget-area="brand-header" class="flex-fill gap-3 p-2 align-self-center">
5
6
  {{{each widgets.brand-header}}}
6
7
  {{./html}}
7
8
  {{{end}}}
8
9
  </div>
10
+
11
+ <!-- Right side: Notifications -->
12
+ <div class="header-right-actions d-flex align-items-center gap-2 ms-auto">
13
+ {{{ if config.loggedIn }}}
14
+ <!-- Notifications dropdown (logged-in users) -->
15
+ <div class="dropdown" component="notifications">
16
+ <a data-bs-toggle="dropdown" href="#" role="button" class="nav-link d-flex align-items-center position-relative p-2 rounded-circle" aria-haspopup="true" aria-expanded="false" aria-label="[[global:header.notifications]]" style="width: 40px; height: 40px; justify-content: center;">
17
+ <span class="position-relative">
18
+ <i component="notifications/icon" class="fa fa-fw fa-lg {{{ if unreadCount.notification}}}fa-bell{{{ else }}}fa-bell-o{{{ end }}}" style="color: #6b7280;"></i>
19
+ <span component="notifications/count" class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger {{{ if !unreadCount.notification }}}hidden{{{ end }}}" style="font-size: 10px; min-width: 18px;">{unreadCount.notification}</span>
20
+ </span>
21
+ </a>
22
+ <ul class="notifications-dropdown dropdown-menu dropdown-menu-end p-1 shadow" role="menu" style="min-width: 320px;">
23
+ <li>
24
+ <div component="notifications/list" class="list-container notification-list overscroll-behavior-contain pe-1 ff-base ghost-scrollbar" style="max-height: 400px; overflow-y: auto;">
25
+ <div class="mb-2 p-1">
26
+ <div class="d-flex gap-1 justify-content-between">
27
+ <div class="d-flex gap-2 flex-grow-1 placeholder-wave">
28
+ <div class="placeholder rounded-circle" style="width: 32px; height: 32px;"></div>
29
+ <div class="flex-grow-1">
30
+ <div class="d-flex flex-column">
31
+ <div class="text-sm">
32
+ <span class="placeholder placeholder-sm col-4"></span>
33
+ <span class="placeholder placeholder-sm col-6"></span>
34
+ <span class="placeholder placeholder-sm col-7"></span>
35
+ </div>
36
+ <div class="text-xs">
37
+ <div class="placeholder placeholder-xs col-6"></div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </li>
46
+ <li class="dropdown-divider"></li>
47
+ <li>
48
+ <div class="d-flex justify-content-center gap-1 flex-wrap p-1">
49
+ <a role="button" href="#" class="btn btn-sm btn-light mark-all-read flex-fill text-nowrap text-truncate"><i class="fa fa-check-double"></i> [[notifications:mark-all-read]]</a>
50
+ <a class="btn btn-sm btn-primary flex-fill text-nowrap text-truncate" href="{relative_path}/notifications"><i class="fa fa-list"></i> [[notifications:see-all]]</a>
51
+ </div>
52
+ </li>
53
+ </ul>
54
+ </div>
55
+ {{{ else }}}
56
+ <!-- Notification icon for guests (redirects to login) -->
57
+ <a href="{relative_path}/login" class="nav-link d-flex align-items-center position-relative p-2 rounded-circle guest-notification-btn" aria-label="[[global:header.notifications]]" title="Sign in to view notifications" style="width: 40px; height: 40px; justify-content: center;">
58
+ <i class="fa fa-fw fa-lg fa-bell-o" style="color: #6b7280;"></i>
59
+ </a>
60
+ {{{ end }}}
61
+ </div>
9
62
  </div>
10
63
  </div>
11
64
  {{{ end }}}