nodebb-theme-harmony 1.0.0 → 1.0.2

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 (155) hide show
  1. package/README.md +12 -1
  2. package/languages/en-GB/harmony.json +6 -1
  3. package/library.js +56 -25
  4. package/package.json +1 -1
  5. package/plugin.json +0 -1
  6. package/public/harmony.js +165 -41
  7. package/public/settings.js +1 -0
  8. package/screenshots/categories.png +0 -0
  9. package/screenshots/recent.png +0 -0
  10. package/screenshots/topic.png +0 -0
  11. package/scss/account.scss +1 -1
  12. package/scss/chats.scss +81 -26
  13. package/scss/common.scss +84 -10
  14. package/scss/flags.scss +5 -0
  15. package/scss/groups.scss +2 -2
  16. package/scss/harmony.scss +3 -0
  17. package/scss/mixins.scss +7 -3
  18. package/scss/modals.scss +5 -3
  19. package/scss/modules/bottom-sheet.scss +1 -1
  20. package/scss/modules/composer.scss +0 -4
  21. package/scss/modules/cover.scss +1 -11
  22. package/scss/modules/filters.scss +8 -0
  23. package/scss/modules/paginator.scss +24 -0
  24. package/scss/modules/tags.scss +2 -2
  25. package/scss/modules/topic-navigator.scss +18 -42
  26. package/scss/modules/topics-list.scss +32 -17
  27. package/scss/modules/user-menu.scss +6 -0
  28. package/scss/overrides.scss +4 -1
  29. package/scss/sidebar.scss +61 -8
  30. package/scss/topic.scss +39 -13
  31. package/templates/account/blocks.tpl +35 -40
  32. package/templates/account/categories.tpl +47 -29
  33. package/templates/account/consent.tpl +66 -10
  34. package/templates/account/edit/password.tpl +25 -30
  35. package/templates/account/edit/username.tpl +21 -26
  36. package/templates/account/edit.tpl +105 -116
  37. package/templates/account/followers.tpl +12 -19
  38. package/templates/account/following.tpl +12 -18
  39. package/templates/account/groups.tpl +12 -17
  40. package/templates/account/info.tpl +178 -206
  41. package/templates/account/posts.tpl +31 -36
  42. package/templates/account/profile.tpl +82 -72
  43. package/templates/account/sessions.tpl +8 -30
  44. package/templates/account/settings.tpl +222 -203
  45. package/templates/account/theme.tpl +39 -25
  46. package/templates/account/topics.tpl +36 -38
  47. package/templates/account/uploads.tpl +33 -40
  48. package/templates/admin/plugins/harmony.tpl +21 -3
  49. package/templates/categories.tpl +3 -6
  50. package/templates/category.tpl +13 -14
  51. package/templates/chats.tpl +9 -10
  52. package/templates/flags/detail.tpl +160 -193
  53. package/templates/flags/list.tpl +3 -70
  54. package/templates/footer.tpl +2 -2
  55. package/templates/groups/details.tpl +22 -19
  56. package/templates/groups/list.tpl +1 -1
  57. package/templates/groups/members.tpl +0 -2
  58. package/templates/header.tpl +2 -2
  59. package/templates/login.tpl +4 -4
  60. package/templates/notifications.tpl +5 -5
  61. package/templates/partials/account/admin-menu.tpl +9 -9
  62. package/templates/partials/account/category-item.tpl +14 -17
  63. package/templates/partials/account/footer.tpl +3 -0
  64. package/templates/partials/account/header.tpl +78 -81
  65. package/templates/partials/account/session-list.tpl +18 -0
  66. package/templates/partials/account/sidebar-left.tpl +31 -25
  67. package/templates/partials/breadcrumbs.tpl +6 -6
  68. package/templates/partials/buttons/newTopic.tpl +1 -1
  69. package/templates/partials/categories/item.tpl +31 -27
  70. package/templates/partials/categories/lastpost.tpl +7 -7
  71. package/templates/partials/category/filter-dropdown-content.tpl +37 -0
  72. package/templates/partials/{category-selector-content.tpl → category/selector-dropdown-content.tpl} +7 -7
  73. package/templates/partials/category/sort.tpl +22 -7
  74. package/templates/partials/category/subcategory.tpl +2 -3
  75. package/templates/partials/category/tags.tpl +0 -2
  76. package/templates/partials/category/tools.tpl +28 -25
  77. package/templates/partials/category/watch.tpl +39 -6
  78. package/templates/partials/chats/dropdown.tpl +4 -1
  79. package/templates/partials/chats/message-window.tpl +12 -8
  80. package/templates/partials/chats/message.tpl +8 -10
  81. package/templates/partials/chats/options.tpl +14 -6
  82. package/templates/partials/chats/recent_room.tpl +41 -32
  83. package/templates/partials/cookie-consent.tpl +5 -5
  84. package/templates/partials/flags/bulk-actions.tpl +9 -0
  85. package/templates/partials/flags/filters.tpl +165 -78
  86. package/templates/partials/flags/results.tpl +38 -0
  87. package/templates/partials/groups/admin.tpl +4 -4
  88. package/templates/partials/groups/badge.tpl +1 -1
  89. package/templates/partials/groups/invited.tpl +1 -1
  90. package/templates/partials/groups/list.tpl +2 -2
  91. package/templates/partials/groups/memberlist.tpl +2 -2
  92. package/templates/partials/groups/sidebar-left.tpl +10 -10
  93. package/templates/partials/header/brand.tpl +9 -2
  94. package/templates/partials/mobile-footer.tpl +69 -61
  95. package/templates/partials/notifications_list.tpl +11 -8
  96. package/templates/partials/paginator.tpl +11 -9
  97. package/templates/partials/post_bar.tpl +26 -24
  98. package/templates/partials/posts_list_item.tpl +5 -5
  99. package/templates/partials/quick-search-results.tpl +3 -3
  100. package/templates/partials/search-filters.tpl +184 -0
  101. package/templates/partials/search-results.tpl +28 -35
  102. package/templates/partials/sidebar/chats.tpl +26 -34
  103. package/templates/partials/sidebar/drafts.tpl +45 -34
  104. package/templates/partials/sidebar/logged-in-menu.tpl +5 -5
  105. package/templates/partials/sidebar/logged-out-menu.tpl +1 -1
  106. package/templates/partials/sidebar/notifications.tpl +30 -9
  107. package/templates/partials/sidebar/search-mobile.tpl +1 -1
  108. package/templates/partials/sidebar/search.tpl +1 -1
  109. package/templates/partials/sidebar/user-menu.tpl +38 -29
  110. package/templates/partials/sidebar-left.tpl +14 -11
  111. package/templates/partials/sidebar-right.tpl +1 -3
  112. package/templates/partials/skin-switcher.tpl +3 -3
  113. package/templates/partials/tags/filter-dropdown-content.tpl +34 -0
  114. package/templates/partials/tags_list.tpl +4 -4
  115. package/templates/partials/topic/browsing-users.tpl +0 -2
  116. package/templates/partials/topic/event.tpl +1 -1
  117. package/templates/partials/topic/navigation-post.tpl +5 -9
  118. package/templates/partials/topic/navigator-mobile.tpl +62 -0
  119. package/templates/partials/topic/navigator.tpl +23 -17
  120. package/templates/partials/topic/post-editor.tpl +0 -2
  121. package/templates/partials/topic/post-menu-list.tpl +60 -62
  122. package/templates/partials/topic/post-menu.tpl +16 -11
  123. package/templates/partials/topic/post.tpl +45 -27
  124. package/templates/partials/topic/quickreply.tpl +8 -8
  125. package/templates/partials/topic/reply-button.tpl +7 -7
  126. package/templates/partials/topic/sort.tpl +17 -5
  127. package/templates/partials/topic/tools.tpl +2 -2
  128. package/templates/partials/topic/topic-menu-list.tpl +22 -24
  129. package/templates/partials/topic/watch.tpl +42 -9
  130. package/templates/partials/topic-filters.tpl +6 -3
  131. package/templates/partials/topic-list-bar.tpl +50 -46
  132. package/templates/partials/topic-terms.tpl +6 -3
  133. package/templates/partials/topics_list.tpl +88 -93
  134. package/templates/partials/userFilter-placeholders.tpl +5 -0
  135. package/templates/partials/users/filter-dropdown-content.tpl +23 -0
  136. package/templates/partials/users/item.tpl +25 -27
  137. package/templates/partials/users_list.tpl +1 -1
  138. package/templates/popular.tpl +3 -1
  139. package/templates/post-queue.tpl +166 -0
  140. package/templates/recent.tpl +3 -2
  141. package/templates/register.tpl +4 -4
  142. package/templates/search.tpl +39 -177
  143. package/templates/tags.tpl +3 -3
  144. package/templates/top.tpl +3 -1
  145. package/templates/topic.tpl +86 -69
  146. package/templates/unread.tpl +3 -1
  147. package/templates/users.tpl +7 -3
  148. package/templates/modules/usercard.tpl +0 -39
  149. package/templates/partials/acceptTos.tpl +0 -11
  150. package/templates/partials/category-filter-content.tpl +0 -30
  151. package/templates/partials/category-filter-right.tpl +0 -5
  152. package/templates/partials/category-filter.tpl +0 -3
  153. package/templates/partials/category-selector-right.tpl +0 -5
  154. package/templates/partials/category-selector.tpl +0 -3
  155. package/templates/partials/slideout-menu.tpl +0 -6
@@ -1,5 +1,5 @@
1
1
  <div class="d-flex {{{ if group.isOwner }}}justify-content-between{{{ else }}}justify-content-end{{{ end }}} mb-3">
2
- {{{ if group.isOwner }}}
2
+ {{{ if isAdmin }}}
3
3
  <div class="flex-shrink-0">
4
4
  <button component="groups/members/add" type="button" class="btn btn-primary btn-sm me-3" title="[[groups:details.add-member]]"><i class="fa fa-user-plus"></i> [[groups:details.add-member]]</button>
5
5
  </div>
@@ -25,7 +25,7 @@
25
25
  <div class="d-flex align-items-center justify-content-between">
26
26
  <div class="d-flex align-items-center gap-2">
27
27
  <a class="align-text-top" href="{config.relative_path}/user/{group.members.userslug}">{group.members.username}</a>
28
- <i component="groups/owner/icon" title="[[groups:owner]]" class="user-owner-icon fa fa-star align-text-top text-warning <!-- IF !group.members.isOwner -->invisible<!-- ENDIF !group.members.isOwner -->"></i>
28
+ <i component="groups/owner/icon" title="[[groups:owner]]" class="user-owner-icon fa fa-star align-text-top text-warning {{{ if !group.members.isOwner }}}invisible{{{ end }}}"></i>
29
29
  </div>
30
30
 
31
31
  {{{ if group.isOwner }}}
@@ -1,26 +1,26 @@
1
- <div class="flex-0 pe-2 border-end-md text-sm mb-3 flex-basis-md-200">
2
- <div class="nav sticky-top d-flex flex-row flex-md-column flex-wrap gap-1" style="z-index: 1;">
1
+ <div class="flex-shrink-0 pe-2 border-end-md text-sm mb-3 flex-basis-md-200">
2
+ <div class="nav sticky-md-top d-flex flex-row flex-md-column flex-wrap gap-1" style="top: 1rem; z-index: 1;">
3
3
  <button data-bs-toggle="tab" data-bs-target="#groups-posts" class="btn-ghost fw-semibold {{{ if template.groups/details }}}active{{{ end }}}">
4
- <div class="flex-1">[[global:posts]]</div>
4
+ <div class="flex-grow-1">[[global:posts]]</div>
5
5
  </button>
6
6
  <button data-bs-toggle="tab" data-bs-target="#groups-members" class="btn-ghost fw-semibold">
7
- <div class="flex-1">[[groups:members]]</div>
8
- <span class="text-xs human-readable-number" title="{group.memberCount}">{group.memberCount}</span>
7
+ <div class="flex-grow-1">[[groups:members]]</div>
8
+ <span class="flex-shrink-0 text-xs human-readable-number" title="{group.memberCount}">{group.memberCount}</span>
9
9
  </button>
10
10
 
11
11
  {{{ if group.isOwner }}}
12
12
  <button data-bs-toggle="tab" data-bs-target="#groups-pending" class="btn-ghost fw-semibold">
13
- <div class="flex-1">[[groups:details.pending]]</div>
14
- <span class="text-xs human-readable-number" title="{group.pending.length}">{group.group.pending.length}</span>
13
+ <div class="flex-grow-1">[[groups:details.pending]]</div>
14
+ <span class="flex-shrink-0 text-xs human-readable-number" title="{group.pending.length}">{group.group.pending.length}</span>
15
15
  </button>
16
16
 
17
17
  <button data-bs-toggle="tab" data-bs-target="#groups-invited" class="btn-ghost fw-semibold">
18
- <div class="flex-1">[[groups:details.invited]]</div>
19
- <span class="text-xs human-readable-number" title="{group.invited.length}">{group.group.invited.length}</span>
18
+ <div class="flex-grow-1">[[groups:details.invited]]</div>
19
+ <span class="flex-shrink-0 text-xs human-readable-number" title="{group.invited.length}">{group.group.invited.length}</span>
20
20
  </button>
21
21
 
22
22
  <button data-bs-toggle="tab" data-bs-target="#groups-admin" class="btn-ghost fw-semibold">
23
- <div class="flex-1">[[global:header.admin]]</div>
23
+ <div class="flex-grow-1">[[global:header.admin]]</div>
24
24
  </button>
25
25
  {{{ end }}}
26
26
  </div>
@@ -1,6 +1,6 @@
1
1
  {{{ if (brand:logo || config.showSiteTitle)}}}
2
- <div class="container brand-container">
3
- <div class="col-12 d-flex border-bottom pb-3 {{{ if config.centerHeaderElements }}}justify-content-center{{{ end }}}">
2
+ <div class="container px-md-4 brand-container">
3
+ <div class="col-12 d-flex border-bottom pb-3 {{{ if config.theme.centerHeaderElements }}}justify-content-center{{{ end }}}">
4
4
  <div component="brand/wrapper" class="d-flex align-items-center gap-3 p-2 rounded-1 align-content-stretch ">
5
5
  {{{ if brand:logo }}}
6
6
  <a component="brand/anchor" href="{{{ if brand:logo:url }}}{brand:logo:url}{{{ else }}}{relative_path}/{{{ end }}}">
@@ -14,6 +14,13 @@
14
14
  </a>
15
15
  {{{ end }}}
16
16
  </div>
17
+ {{{ if widgets.brand-header.length }}}
18
+ <div data-widget-area="brand-header" class="ms-auto gap-3 p-2 align-self-center">
19
+ {{{each widgets.brand-header}}}
20
+ {{./html}}
21
+ {{{end}}}
22
+ </div>
23
+ {{{ end }}}
17
24
  </div>
18
25
  </div>
19
26
  {{{ end }}}
@@ -1,70 +1,78 @@
1
- <div class="text-dark bg-light bottombar p-2 d-flex d-md-none justify-content-between fixed-bottom ff-secondary align-items-center">
2
- <div class="bottom-sheet">
3
- <button class="btn" data-bs-toggle="dropdown">
4
- <i class="fa fa-bars"></i>
5
- </button>
6
- <ul class="dropdown-menu">
7
- {{{ each navigation }}}
8
- <!-- IF function.displayMenuItem, @index -->
9
- <li class="nav-item {./class}{{{ if ./dropdown }}} dropend{{{ end }}}" title="{./title}">
10
- <a class="nav-link nav-btn navigation-link p-3 {{{ if navigation.dropdown }}}dropdown-toggle{{{ end }}}"
11
- {{{ if ./dropdown }}} href="#" role="button" data-bs-toggle="collapse" data-bs-target="#collapse-target-{@index}" onclick="event.stopPropagation();" {{{ else }}} href="{./route}"{{{ end }}} {{{ if ./id }}}id="{./id}"{{{ end }}}{{{ if ./targetBlank }}} target="_blank"{{{ end }}}>
12
- <span class="d-inline-flex justify-content-between align-items-center w-100">
13
- <span class="text-nowrap truncate-open">
14
- {{{ if ./iconClass }}}
15
- <i class="fa fa-fw {./iconClass}" data-content="{./content}"></i>
16
- {{{ end }}}
17
- {{{ if navigation.text }}}
18
- <span class="nav-text visible-open px-2 fw-semibold">{navigation.text}</span>
19
- {{{ end }}}
1
+ <div component="bottombar" class="bottombar d-flex flex-column d-lg-none fixed-bottom ff-secondary gap-1 align-items-center">
2
+
3
+ <!-- IMPORT partials/topic/navigator-mobile.tpl -->
4
+
5
+ <div class="bottombar-nav p-2 text-dark bg-light d-flex justify-content-between align-items-center w-100">
6
+ <div class="">
7
+ <a href="#" role="button" class="nav-link nav-btn d-flex justify-content-between align-items-center position-relative" data-bs-toggle="dropdown">
8
+ <span class="position-relative">
9
+ <i class="fa fa-fw fa-lg fa-bars"></i>
10
+ <span component="unread/count" data-unread-url="{unreadCount.unreadUrl}" class="position-absolute top-0 start-100 translate-middle badge rounded-1 bg-primary {{{ if !unreadCount.mobileUnread }}}hidden{{{ end }}}">{unreadCount.mobileUnread}</span>
11
+ </span>
12
+ </a>
13
+ <ul class="navigation-dropdown dropdown-menu">
14
+ {{{ each navigation }}}
15
+ {{{ if displayMenuItem(@root, @index) }}}
16
+ <li class="nav-item {./class}{{{ if ./dropdown }}} dropend{{{ end }}}" title="{./title}">
17
+ <a class="nav-link nav-btn navigation-link px-3 py-2 {{{ if ./dropdown }}}dropdown-toggle{{{ end }}}"
18
+ {{{ if ./dropdown }}} href="#" role="button" data-bs-toggle="collapse" data-bs-target="#collapse-target-{@index}" onclick="event.stopPropagation();" {{{ else }}} href="{./route}"{{{ end }}} {{{ if ./id }}}id="{./id}"{{{ end }}}{{{ if ./targetBlank }}} target="_blank"{{{ end }}}>
19
+ <span class="d-inline-flex justify-content-between align-items-center w-100">
20
+ <span class="text-nowrap">
21
+ {{{ if ./iconClass }}}
22
+ <i class="fa fa-fw {./iconClass}" data-content="{./content}"></i>
23
+ {{{ end }}}
24
+ {{{ if ./text }}}
25
+ <span class="nav-text px-2 fw-semibold">{./text}</span>
26
+ {{{ end }}}
27
+ </span>
28
+ <span component="navigation/count" class="badge rounded-1 bg-primary {{{ if !./content }}}hidden{{{ end }}}">{./content}</span>
20
29
  </span>
21
- <span component="navigation/count" class="visible-open badge rounded-1 bg-primary {{{ if !./content }}}hidden{{{ end }}}">{./content}</span>
22
- </span>
23
- </a>
24
- {{{ if navigation.dropdown }}}
25
- <div class="ps-3">
26
- <ul id="collapse-target-{@index}" class="collapse list-unstyled ps-3">
27
- {navigation.dropdownContent}
28
- </ul>
29
- </div>
30
+ </a>
31
+ {{{ if ./dropdown }}}
32
+ <div class="ps-3">
33
+ <ul id="collapse-target-{@index}" class="collapse list-unstyled ps-3">
34
+ {./dropdownContent}
35
+ </ul>
36
+ </div>
37
+ {{{ end }}}
38
+ </li>
30
39
  {{{ end }}}
31
- </li>
32
- <!-- ENDIF function.displayMenuItem -->
33
- {{{end}}}
34
- </ul>
35
- </div>
40
+ {{{ end }}}
41
+ </ul>
42
+ </div>
36
43
 
37
- <div class="">
38
- {{{ if config.loggedIn }}}
39
- <ul id="logged-in-menu" class="list-unstyled d-flex align-items-center w-100 gap-3 mb-0">
40
- {{{ if config.searchEnabled }}}
41
- <li component="sidebar/search" class="nav-item m-0 search bottom-sheet position-relative">
42
- <!-- IMPORT partials/sidebar/search-mobile.tpl -->
43
- </li>
44
- {{{ end }}}
44
+ <div class="">
45
+ {{{ if config.loggedIn }}}
46
+ <ul id="logged-in-menu" class="list-unstyled d-flex align-items-center w-100 gap-3 mb-0">
47
+ {{{ if config.searchEnabled }}}
48
+ <li component="sidebar/search" class="nav-item m-0 search">
49
+ <!-- IMPORT partials/sidebar/search-mobile.tpl -->
50
+ </li>
51
+ {{{ end }}}
45
52
 
46
- <li component="notifications" class="nav-item m-0 notifications bottom-sheet">
47
- <!-- IMPORT partials/sidebar/notifications.tpl -->
48
- </li>
53
+ <li component="notifications" class="nav-item m-0 notifications">
54
+ <!-- IMPORT partials/sidebar/notifications.tpl -->
55
+ </li>
49
56
 
50
- {{{ if canChat }}}
51
- <li class="nav-item m-0 chats bottom-sheet">
52
- <!-- IMPORT partials/sidebar/chats.tpl -->
53
- </li>
54
- {{{ end }}}
57
+ {{{ if canChat }}}
58
+ <li class="nav-item m-0 chats">
59
+ <!-- IMPORT partials/sidebar/chats.tpl -->
60
+ </li>
61
+ {{{ end }}}
55
62
 
56
- <li component="sidebar/drafts" class="nav-item m-0 drafts bottom-sheet">
57
- <!-- IMPORT partials/sidebar/drafts.tpl -->
58
- </li>
63
+ <li component="sidebar/drafts" class="hidden nav-item m-0 drafts">
64
+ <!-- IMPORT partials/sidebar/drafts.tpl -->
65
+ </li>
59
66
 
60
- <li id="user_label" class="nav-item m-0 py-2 bottom-sheet usermenu">
61
- <!-- IMPORT partials/sidebar/user-menu.tpl -->
62
- </li>
63
- </ul>
64
- {{{ else }}}
65
- <ul id="logged-out-menu" class="list-unstyled d-flex w-100 gap-3 mb-0 logged-out-menu">
66
- <!-- IMPORT partials/sidebar/logged-out-menu.tpl -->
67
- </ul>
68
- {{{ end }}}
67
+ <li id="user_label" class="nav-item m-0 py-2 usermenu">
68
+ <!-- IMPORT partials/sidebar/user-menu.tpl -->
69
+ </li>
70
+ </ul>
71
+ {{{ else }}}
72
+ <ul id="logged-out-menu" class="list-unstyled d-flex w-100 gap-3 mb-0 logged-out-menu">
73
+ <!-- IMPORT partials/sidebar/logged-out-menu.tpl -->
74
+ </ul>
75
+ {{{ end }}}
76
+ </div>
69
77
  </div>
70
78
  </div>
@@ -1,28 +1,31 @@
1
1
  {{{ if !notifications.length }}}
2
- <li class="no-notifs text-center p-2">[[notifications:no_notifs]]</li>
2
+ <li class="no-notifs text-center p-4 d-flex flex-column">
3
+ <div class="p-4"><i class="fa-solid fa-wind fs-2 text-muted"></i></div>
4
+ <div class="text-xs fw-semibold text-muted">[[notifications:no_notifs]]</div>
5
+ </li>
3
6
  {{{ end }}}
4
7
 
5
8
  {{{ each notifications }}}
6
9
  <li class="{./readClass} mb-2 p-1" data-nid="{./nid}" data-path="{./path}" {{{ if ./pid }}}data-pid="{./pid}"{{{ end }}}{{{ if ./tid }}}data-tid="{./tid}"{{{ end }}}>
7
10
  <div class="d-flex gap-1 justify-content-between">
8
- <div class="d-flex gap-2">
11
+ <div class="btn-ghost-sm d-flex gap-2 flex-grow-1 align-items-start">
9
12
  {{{ if ./image }}}
10
13
  {{{ if ./from }}}
11
- <a class="text-decoration-none" href="{config.relative_path}/user/{./user.userslug}"><img class="avatar avatar-rounded" style="--avatar-size: 32px;" src="{./image}" /></a>
14
+ <a class="flex-grow-0 flex-shrink-0" href="{config.relative_path}/user/{./user.userslug}"><img class="avatar avatar-rounded" style="--avatar-size: 32px;" src="{./image}" /></a>
12
15
  {{{ end }}}
13
16
  {{{ else }}}
14
- <a class="text-decoration-none" href="{config.relative_path}/user/{./user.userslug}"><div class="avatar avatar-rounded" style="--avatar-size: 32px; background-color: {./user.icon:bgColor};">{./user.icon:text}</div></a>
17
+ <a class="flex-grow-0 flex-shrink-0" href="{config.relative_path}/user/{./user.userslug}"><div class="avatar avatar-rounded" style="--avatar-size: 32px; background-color: {./user.icon:bgColor};">{./user.icon:text}</div></a>
15
18
  {{{ end }}}
16
- <div class=" d-flex flex-column">
17
- <a href="{./path}" class="text-decoration-none text-reset text text-sm">
19
+ <div class="d-flex flex-grow-1 flex-column align-items-start position-relative">
20
+ <a href="{./path}" class="text-decoration-none d-inline-block text-reset text-break text-sm ff-sans stretched-link">
18
21
  {./bodyShort}
19
22
  </a>
20
23
  <div class="text-xs text-muted">{{{ if ./timeagoLong }}}{./timeagoLong}{{{ else }}}<span class="timeago" title="{./datetimeISO}"></span>{{{ end }}}</div>
21
24
  </div>
22
25
  </div>
23
- <div class="">
26
+ <div>
24
27
  {{{ if ./nid }}}
25
- <button class="mark-read btn-ghost-sm" style="width: 1.5rem; height: 1.5rem;">
28
+ <button class="mark-read btn-ghost-sm flex-grow-0 flex-shrink-0 p-1" style="width: 1.5rem; height: 1.5rem;">
26
29
  <i class="unread fa fa-2xs fa-circle text-primary {{{ if ./read }}}hidden{{{ end }}}"></i>
27
30
  <i class="read fa fa-2xs fa-circle-o text-secondary {{{ if !./read }}}hidden{{{ end }}}"></i>
28
31
  </button>
@@ -1,45 +1,47 @@
1
1
  <div component="pagination" class="pagination-container mt-3{{{ if !pagination.pages.length }}} hidden{{{ end }}}">
2
2
  <ul class="pagination pagination-sm gap-1 hidden-xs hidden-sm justify-content-center">
3
3
  <li class="page-item previous float-start{{{ if !pagination.prev.active }}} disabled{{{ end }}}">
4
- <a class="page-link rounded fw-secondary text-reset px-3" href="?{pagination.prev.qs}" data-page="{pagination.prev.page}"><i class="fa fa-chevron-left"></i> </a>
4
+ <a class="page-link rounded fw-secondary px-3" href="?{pagination.prev.qs}" data-page="{pagination.prev.page}"><i class="fa fa-chevron-left"></i> </a>
5
5
  </li>
6
6
 
7
7
  {{{each pagination.pages}}}
8
8
  {{{ if pagination.pages.separator }}}
9
9
  <li component="pagination/select-page" class="page-item page select-page">
10
- <a class="page-link rounded fw-secondary text-reset px-3" href="#"><i class="fa fa-ellipsis-h"></i></a>
10
+ <a class="page-link rounded fw-secondary px-3" href="#"><i class="fa fa-ellipsis-h"></i></a>
11
11
  </li>
12
12
  {{{ else }}}
13
13
  <li class="page-item page{{{ if pagination.pages.active }}} active{{{ end }}}" >
14
- <a class="page-link rounded fw-secondary text-reset px-3" href="?{pagination.pages.qs}" data-page="{pagination.pages.page}">{pagination.pages.page}</a>
14
+ <a class="page-link rounded fw-secondary px-3" href="?{pagination.pages.qs}" data-page="{pagination.pages.page}">{pagination.pages.page}</a>
15
15
  </li>
16
16
  {{{ end }}}
17
17
  {{{end}}}
18
18
 
19
19
  <li class="page-item next float-end {{{ if !pagination.next.active }}} disabled{{{ end }}}">
20
- <a class="page-link rounded fw-secondary text-reset px-3" href="?{pagination.next.qs}" data-page="{pagination.next.page}"> <i class="fa fa-chevron-right"></i></a>
20
+ <a class="page-link rounded fw-secondary px-3" href="?{pagination.next.qs}" data-page="{pagination.next.page}"> <i class="fa fa-chevron-right"></i></a>
21
21
  </li>
22
22
  </ul>
23
23
 
24
+ {{{ if !template.topic }}}
24
25
  <ul class="pagination pagination-sm hidden-md hidden-lg justify-content-center">
25
26
  <li class="page-item first{{{ if !pagination.prev.active }}} disabled{{{ end }}}">
26
- <a class="page-link fw-secondary text-reset" href="?{pagination.first.qs}" data-page="1"><i class="fa fa-fast-backward"></i> </a>
27
+ <a class="page-link fw-secondary" href="?{pagination.first.qs}" data-page="1"><i class="fa fa-fast-backward"></i> </a>
27
28
  </li>
28
29
 
29
30
  <li class="page-item previous{{{ if !pagination.prev.active }}} disabled{{{ end }}}">
30
- <a class="page-link fw-secondary text-reset" href="?{pagination.prev.qs}" data-page="{pagination.prev.page}"><i class="fa fa-chevron-left"></i> </a>
31
+ <a class="page-link fw-secondary" href="?{pagination.prev.qs}" data-page="{pagination.prev.page}"><i class="fa fa-chevron-left"></i> </a>
31
32
  </li>
32
33
 
33
34
  <li component="pagination/select-page" class="page-item page select-page">
34
- <a class="page-link fw-secondary text-reset" href="#">{pagination.currentPage} / {pagination.pageCount}</a>
35
+ <a class="page-link fw-secondary" href="#">{pagination.currentPage} / {pagination.pageCount}</a>
35
36
  </li>
36
37
 
37
38
  <li class="page-item next{{{ if !pagination.next.active }}} disabled{{{ end }}}">
38
- <a class="page-link fw-secondary text-reset" href="?{pagination.next.qs}" data-page="{pagination.next.page}"> <i class="fa fa-chevron-right"></i></a>
39
+ <a class="page-link fw-secondary" href="?{pagination.next.qs}" data-page="{pagination.next.page}"> <i class="fa fa-chevron-right"></i></a>
39
40
  </li>
40
41
 
41
42
  <li class="page-item last{{{ if !pagination.next.active }}} disabled{{{ end }}}">
42
- <a class="page-link fw-secondary text-reset" href="?{pagination.last.qs}" data-page="{pagination.pageCount}"><i class="fa fa-fast-forward"></i> </a>
43
+ <a class="page-link fw-secondary" href="?{pagination.last.qs}" data-page="{pagination.pageCount}"><i class="fa fa-fast-forward"></i> </a>
43
44
  </li>
44
45
  </ul>
46
+ {{{ end }}}
45
47
  </div>
@@ -1,27 +1,29 @@
1
- <nav class="{{{ if config.stickyToolbar }}}sticky-tools{{{ end }}} navbar navbar-expand mt-4 p-0 border-0 rounded topic-main-buttons">
2
- <div class="card card-header flex-row p-2 border rounded ff-secondary w-100">
3
- <ul class="navbar-nav me-auto gap-2 align-items-center">
4
- {{{ if loggedIn }}}
5
- <button component="topic/mark-unread" class="btn-ghost-sm d-flex gap-2 align-items-center">
6
- <i class="fa fa-fw fa-inbox text-primary"></i>
7
- <span class="d-none d-md-inline fw-semibold">[[topic:mark_unread]]</span>
8
- </button>
9
- {{{ end }}}
1
+ <div class="{{{ if config.theme.stickyToolbar }}}sticky-tools{{{ end }}}">
2
+ <nav class="navbar navbar-expand my-2 p-0 border-0 rounded topic-main-buttons">
3
+ <div class="card card-header flex-row p-2 border rounded w-100 align-items-center">
4
+ <ul class="navbar-nav me-auto gap-2 align-items-center flex-wrap">
5
+ {{{ if loggedIn }}}
6
+ <button component="topic/mark-unread" class="btn-ghost-sm d-flex gap-2 align-items-center">
7
+ <i class="fa fa-fw fa-inbox text-primary"></i>
8
+ <span class="d-none d-md-inline fw-semibold">[[topic:mark_unread]]</span>
9
+ </button>
10
+ {{{ end }}}
10
11
 
11
- <!-- IMPORT partials/topic/watch.tpl -->
12
- <!-- IMPORT partials/topic/sort.tpl -->
13
- <!-- IMPORT partials/topic/tools.tpl -->
12
+ <!-- IMPORT partials/topic/watch.tpl -->
13
+ <!-- IMPORT partials/topic/sort.tpl -->
14
+ <!-- IMPORT partials/topic/tools.tpl -->
14
15
 
15
- {{{ if (!feeds:disableRSS && rssFeedUrl) }}}
16
- <a class="btn-ghost-sm d-none d-lg-flex align-self-stretch" target="_blank" href="{rssFeedUrl}" itemprop="item"><i class="fa fa-rss text-primary"></i></a>
17
- {{{ end }}}
16
+ {{{ if (!feeds:disableRSS && rssFeedUrl) }}}
17
+ <a class="btn-ghost-sm d-none d-lg-flex align-self-stretch" target="_blank" href="{rssFeedUrl}"><i class="fa fa-rss text-primary"></i></a>
18
+ {{{ end }}}
18
19
 
19
- <span class="loading-indicator btn float-start text-muted navbar-text hidden" done="0">
20
- <i class="fa fa-refresh fa-spin"></i>
21
- <span class="hidden-xs">[[topic:loading_more_posts]]</span>
22
- </span>
23
- </ul>
24
- <!-- IMPORT partials/topic/reply-button.tpl -->
25
- </div>
26
-
27
- </nav>
20
+ {{{ if browsingUsers }}}
21
+ <div class="hidden-xs">
22
+ <!-- IMPORT partials/topic/browsing-users.tpl -->
23
+ </div>
24
+ {{{ end }}}
25
+ </ul>
26
+ <!-- IMPORT partials/topic/reply-button.tpl -->
27
+ </div>
28
+ </nav>
29
+ </div>
@@ -1,19 +1,19 @@
1
1
  <hr/>
2
- <a class="topic-title fw-semibold fs-5 text-reset" href="{config.relative_path}/post/{./pid}">
2
+ <a class="d-inline-block topic-title fw-semibold fs-5 mb-3 text-reset text-break" href="{config.relative_path}/post/{./pid}">
3
3
  {{{ if !./isMainPost }}}RE: {{{ end }}}{./topic.title}
4
4
  </a>
5
5
  <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}">
6
6
  <div class="post-body d-flex flex-column gap-1">
7
7
  <div class="d-flex gap-3 post-info">
8
8
  <div class="post-author d-flex gap-1">
9
- <a class="lh-1" href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(./user, "16px", true, "not-responsive")}</a>
9
+ <a class="lh-1 text-decoration-none" href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(./user, "16px", true, "not-responsive")}</a>
10
10
  <a class="fw-semibold text-sm" href="{config.relative_path}/user/{./user.userslug}">{../user.displayname}</a>
11
11
  </div>
12
- <span class="timeago text-sm text-muted" title="{../timestampISO}"></span>
12
+ <span class="timeago text-sm text-muted" title="{./timestampISO}"></span>
13
13
  </div>
14
14
 
15
- <div component="post/content" class="content text-sm">
16
- {../content}
15
+ <div component="post/content" class="content text-sm text-break">
16
+ {./content}
17
17
  </div>
18
18
  </div>
19
19
  </li>
@@ -9,12 +9,12 @@
9
9
  </div>
10
10
  {{{ end }}}
11
11
 
12
- <ul id="quick-search-results" class="quick-search-results list-unstyled mb-0 p-0 overflow-auto" style="max-width:400px; max-height: 500px;">
12
+ <ul id="quick-search-results" class="quick-search-results list-unstyled mb-0 p-0 pe-1 overflow-auto overscroll-behavior-contain ff-base" style="max-width: 400px; max-height: 500px;">
13
13
  <li role="separator" class="dropdown-divider d-none d-md-block"></li>
14
14
  {{{ each posts }}}
15
15
  <li data-tid="{posts.topic.tid}" data-pid="{posts.pid}" class="d-flex flex-column gap-1">
16
16
  <a href="{config.relative_path}/post/{posts.pid}"
17
- class="dropdown-item rounded-1 text-reset d-block text-truncate px-2 py-1">
17
+ class="btn-ghost-sm rounded-1 text-reset d-block text-truncate px-2 py-1">
18
18
  <span class="quick-search-title fw-semibold text-sm">{posts.topic.title}</span>
19
19
  <br/>
20
20
  <p class="snippet text-xs text-break text-wrap mb-0">
@@ -22,7 +22,7 @@
22
22
  </p>
23
23
  </a>
24
24
  <div class="d-flex gap-1 post-info px-2 text-xs">
25
- <div class="category-item d-inline-block">
25
+ <div class="category-item d-inline-block ff-secondary">
26
26
  <span>{function.buildCategoryLabel, posts.category}</span>
27
27
  </div>
28
28
  <span class="timeago text-muted" title="{posts.timestampISO}"></span>
@@ -0,0 +1,184 @@
1
+ <div class="d-flex flex-wrap gap-2 align-items-center" component="search/filters">
2
+ <!-- category filter -->
3
+ <div class="post-search-item">
4
+ <div component="category/filter" class="dropdown" data-filter-name="category">
5
+ <a component="category/filter/button" class="filter-btn btn btn-light btn-sm border {{{ if filters.categories.active }}}active-filter{{{ end }}} dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
6
+ <span class="filter-label">{{{ if filters.categories.active }}}{filters.categories.label}{{{ else }}}[[search:categories]]{{{ end }}}</span>
7
+ <span class="caret"></span>
8
+ </a>
9
+
10
+ <ul class="dropdown-menu p-1 text-sm">
11
+ <li class="px-3 py-1 mb-2 d-flex flex-column gap-2">
12
+ <div component="category-selector-search">
13
+ <input type="text" class="form-control" component="category/filter/search" placeholder="[[search:type-a-category]]">
14
+ </div>
15
+ </li>
16
+ <div component="category/list" class="overflow-auto" style="max-height: 350px;"></div>
17
+ <div class="px-3 py-1">
18
+ <div class="form-check">
19
+ <input id="search-children" class="form-check-input" type="checkbox"/>
20
+ <label class="form-check-label" for="search-children">[[search:search-child-categories]]</label>
21
+ </div>
22
+ </div>
23
+ </ul>
24
+ </div>
25
+ </div>
26
+
27
+
28
+ <!-- tag filter -->
29
+ <div class="post-search-item">
30
+ <div component="tag/filter" class="dropdown" data-filter-name="tag">
31
+ <a component="tag/filter/button" class="filter-btn btn btn-light btn-sm border {{{ if filters.tags.active }}}active-filter{{{ end }}} dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
32
+ <span class="filter-label">{{{ if filters.tags.active }}}{filters.tags.label}{{{ else }}}[[search:tags]]{{{ end }}}</span>
33
+ <span class="caret"></span>
34
+ </a>
35
+
36
+ <ul class="dropdown-menu p-1 text-sm" style="width: 350px;">
37
+ <li class="px-3 py-1 d-flex flex-column gap-2">
38
+ <input type="text" class="form-control" component="tag/filter/search" placeholder="[[search:type-a-tag]]">
39
+ <div component="tag/filter/selected" class="d-flex flex-wrap gap-2">
40
+ {{{ each tagFilterSelected }}}
41
+ <div class="d-flex px-2 py-1 rounded-1 text-bg-primary gap-2 align-items-center text-sm">
42
+ <div>{./valueEscaped}</div>
43
+ <button component="tag/filter/delete" data-tag="{./valueEscaped}" class="btn btn-primary btn-sm py-0"><i class="fa fa-times fa-xs"></i></button>
44
+ </div>
45
+ {{{ end }}}
46
+ </div>
47
+ <hr/>
48
+ <div component="tag/filter/results" class="d-flex flex-wrap gap-2">
49
+ {{{ each tagFilterResults }}}
50
+ <button class="btn btn-light btn-sm border" data-tag="{./valueEscaped}">{./valueEscaped}</button>
51
+ {{{ end }}}
52
+ </div>
53
+ </li>
54
+ </ul>
55
+ </div>
56
+ </div>
57
+
58
+ <!-- user name filter -->
59
+ <div class="post-search-item">
60
+ <div component="user/filter" class="dropdown" data-filter-name="user">
61
+ <a component="user/filter/button" class="filter-btn btn btn-light btn-sm border {{{ if filters.users.active }}}active-filter{{{ end }}} dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
62
+ <span class="filter-label">{{{ if filters.users.active }}}{filters.users.label}{{{ else }}}[[search:posted-by]]{{{ end }}}</span>
63
+ <span class="caret"></span>
64
+ </a>
65
+
66
+ <ul class="dropdown-menu p-1 text-sm" style="width: 350px;">
67
+ <li class="px-3 py-1 d-flex flex-column gap-2">
68
+ <input type="text" class="form-control" component="user/filter/search" placeholder="[[search:type-a-username]]">
69
+ <div component="user/filter/selected" class="d-flex flex-wrap gap-2">
70
+ {{{ each userFilterSelected }}}
71
+ <div class="d-flex px-2 py-1 rounded-1 text-bg-primary gap-2 align-items-center text-sm">
72
+ {buildAvatar(@value, "16px", true)} {./username}
73
+ <button component="user/filter/delete" data-uid="{./uid}" class="btn btn-primary btn-sm py-0"><i class="fa fa-times fa-xs"></i></button>
74
+ </div>
75
+ {{{ end }}}
76
+ </div>
77
+ <hr/>
78
+ <div component="user/filter/results" class="d-flex flex-wrap gap-2">
79
+ {{{ each userFilterResults }}}
80
+ <button class="btn btn-light btn-sm border" data-uid="{./uid}" data-username="{./username}">{buildAvatar(@value, "16px", true)} {./username}</button>
81
+ {{{ end }}}
82
+ </div>
83
+ </li>
84
+ </ul>
85
+ </div>
86
+ </div>
87
+
88
+
89
+ <!-- reply count filter -->
90
+ <div class="post-search-item">
91
+ <div class="dropdown" data-filter-name="replies">
92
+ <a id="reply-count-button" class="filter-btn btn btn-light btn-sm border {{{ if filters.replies.active }}}active-filter{{{ end }}} dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
93
+ <span class="filter-label">{{{ if filters.replies.active }}}{filters.replies.label}{{{ else }}}[[search:replies]]{{{ end }}}</span>
94
+ <span class="caret"></span>
95
+ </a>
96
+
97
+ <ul class="dropdown-menu p-1 text-sm" style="width: 300px;">
98
+ <li class="px-3 py-1 d-flex flex-nowrap gap-2">
99
+ <select id="reply-count-filter" class="form-select py-2 ps-2 pe-3">
100
+ <option value="atleast">[[search:at-least]]</option>
101
+ <option value="atmost">[[search:at-most]]</option>
102
+ </select>
103
+ <input id="reply-count" type="number" min="0" class="form-control py-2 ps-2 pe-3" />
104
+ </li>
105
+ </ul>
106
+ </div>
107
+ </div>
108
+
109
+ <!-- time filter -->
110
+ <div class="post-search-item">
111
+ <div class="dropdown" data-filter-name="time">
112
+ <a id="post-time-button" class="filter-btn btn btn-light btn-sm border {{{ if filters.time.active }}}active-filter{{{ end }}} dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
113
+ <span class="filter-label">{{{ if filters.time.active }}}{filters.time.label}{{{ else }}}[[search:time]]{{{ end }}}</span>
114
+ <span class="caret"></span>
115
+ </a>
116
+
117
+ <ul class="dropdown-menu p-1 text-sm" style="width: 350px;">
118
+ <li class="px-3 py-1 d-flex flex-nowrap gap-2">
119
+ <select id="post-time-filter" class="form-select py-2 ps-2 pe-3">
120
+ <option value="newer">[[search:newer-than]]</option>
121
+ <option value="older">[[search:older-than]]</option>
122
+ </select>
123
+ <select id="post-time-range" class="form-select py-2 ps-2 pe-3">
124
+ <option value="">[[search:any-date]]</option>
125
+ <option value="86400">[[search:yesterday]]</option>
126
+ <option value="604800">[[search:one-week]]</option>
127
+ <option value="1209600">[[search:two-weeks]]</option>
128
+ <option value="2592000">[[search:one-month]]</option>
129
+ <option value="7776000">[[search:three-months]]</option>
130
+ <option value="15552000">[[search:six-months]]</option>
131
+ <option value="31104000">[[search:one-year]]</option>
132
+ </select>
133
+ </li>
134
+ </ul>
135
+ </div>
136
+ </div>
137
+
138
+ <!-- sort filter -->
139
+ <div class="post-search-item">
140
+ <div class="dropdown" data-filter-name="sort">
141
+ <a id="sort-by-button" class="filter-btn btn btn-light btn-sm border {{{ if filters.sort.active }}}active-filter{{{ end }}} dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
142
+ <span class="filter-label">{{{ if filters.sort.active }}}{filters.sort.label}{{{ else }}}[[search:sort]]{{{ end }}}</span>
143
+ <span class="caret"></span>
144
+ </a>
145
+
146
+ <ul class="dropdown-menu p-1 text-sm" style="width: 250px;">
147
+ <li class="px-3 py-1 d-flex flex-column gap-2">
148
+ <select id="post-sort-by" class="form-select py-2 ps-2 pe-3">
149
+ <option value="relevance">[[search:relevance]]</option>
150
+ <option value="timestamp">[[search:post-time]]</option>
151
+ <option value="votes">[[search:votes]]</option>
152
+ <option value="topic.lastposttime">[[search:last-reply-time]]</option>
153
+ <option value="topic.title">[[search:topic-title]]</option>
154
+ <option value="topic.postcount">[[search:number-of-replies]]</option>
155
+ <option value="topic.viewcount">[[search:number-of-views]]</option>
156
+ <option value="topic.votes">[[search:topic-votes]]</option>
157
+ <option value="topic.timestamp">[[search:topic-start-date]]</option>
158
+ <option value="user.username">[[search:username]]</option>
159
+ <option value="category.name">[[search:category]]</option>
160
+ </select>
161
+ <select id="post-sort-direction" class="form-select py-2 ps-2 pe-3">
162
+ <option value="desc">[[search:descending]]</option>
163
+ <option value="asc">[[search:ascending]]</option>
164
+ </select>
165
+ </li>
166
+ </ul>
167
+ </div>
168
+ </div>
169
+
170
+ <!-- save & reset preferences -->
171
+ <div class="post-search-item">
172
+ <div class="dropdown">
173
+ <a class="btn btn-light btn-sm border border-gray-300 dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">[[search:save]] <span class="caret"></span>
174
+ </a>
175
+
176
+ <ul class="dropdown-menu p-1 text-sm" style="width: 300px;">
177
+ <li class="px-3 py-1 d-flex flex-column gap-2">
178
+ <button id="save-preferences" class="btn btn-primary">[[search:save-preferences]]</button>
179
+ <button id="clear-preferences" class="btn-outline border">[[search:clear-preferences]]</button>
180
+ </li>
181
+ </ul>
182
+ </div>
183
+ </div>
184
+ </div>