@okjavis/nodebb-theme-javis 1.0.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.
- package/README.md +201 -0
- package/less/_base.less +70 -0
- package/less/_buttons.less +90 -0
- package/less/_cards.less +118 -0
- package/less/_categories.less +121 -0
- package/less/_forms.less +104 -0
- package/less/_sidebar.less +110 -0
- package/less/_variables.less +54 -0
- package/less/theme.less +18 -0
- package/package.json +58 -0
- package/plugin.json +23 -0
- package/static/lib/theme.css +1 -0
- package/static/lib/theme.js +17 -0
- package/templates/partials/posts_list_item.tpl +38 -0
- package/theme.js +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# JAVIS Community Theme
|
|
2
|
+
|
|
3
|
+
A modern, premium NodeBB theme for JAVIS Community. Inspired by the clean aesthetics of Apple, Stripe, and Linear design systems.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Design System First**: Built on a comprehensive design token system for consistency
|
|
8
|
+
- **Modern Aesthetics**: Clean, premium look with smooth interactions
|
|
9
|
+
- **Fully Customizable**: Organized LESS files make customization easy
|
|
10
|
+
- **Responsive**: Works beautifully on all devices
|
|
11
|
+
- **Performance Optimized**: Clean, efficient CSS with no bloat
|
|
12
|
+
|
|
13
|
+
## Design System
|
|
14
|
+
|
|
15
|
+
The JAVIS design system includes:
|
|
16
|
+
|
|
17
|
+
- **Typography**: SF Pro-based system font stack
|
|
18
|
+
- **Color Palette**: Primary blue (#0051ff) with neutral grays
|
|
19
|
+
- **Spacing**: 8pt grid system (4px, 8px, 12px, 16px, 20px, 24px)
|
|
20
|
+
- **Border Radius**: Consistent radii (4px, 8px, 12px, 16px, pill)
|
|
21
|
+
- **Shadows**: Soft, subtle elevation system
|
|
22
|
+
|
|
23
|
+
## Installation & Development
|
|
24
|
+
|
|
25
|
+
### 1. Install Dependencies
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd /Users/chiragdugar/Desktop/Javis/javis-community-theme
|
|
29
|
+
npm install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Build the Theme
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This compiles `less/theme.less` into `static/lib/theme.css`.
|
|
39
|
+
|
|
40
|
+
### 3. Development Mode (Watch for Changes)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm run dev
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This watches your LESS files and rebuilds automatically on changes.
|
|
47
|
+
|
|
48
|
+
## Deployment to NodeBB Cloud
|
|
49
|
+
|
|
50
|
+
### Option 1: Direct Upload via ACP (Recommended)
|
|
51
|
+
|
|
52
|
+
1. **Package the theme**:
|
|
53
|
+
```bash
|
|
54
|
+
cd /Users/chiragdugar/Desktop/Javis
|
|
55
|
+
zip -r javis-community-theme.zip javis-community-theme/ -x "*/node_modules/*" "*/.git/*"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
2. **Upload to NodeBB Cloud**:
|
|
59
|
+
- Go to your NodeBB Admin Panel (ACP)
|
|
60
|
+
- Navigate to: **Extend → Install Plugins**
|
|
61
|
+
- Click "Upload Plugin"
|
|
62
|
+
- Select `javis-community-theme.zip`
|
|
63
|
+
- Wait for installation to complete
|
|
64
|
+
- Rebuild NodeBB when prompted
|
|
65
|
+
|
|
66
|
+
3. **Activate the theme**:
|
|
67
|
+
- Go to: **Appearance → Themes**
|
|
68
|
+
- Select "JAVIS Community Theme"
|
|
69
|
+
- Click "Apply" and rebuild
|
|
70
|
+
|
|
71
|
+
### Option 2: Git Repository (For Version Control)
|
|
72
|
+
|
|
73
|
+
1. **Initialize git** (if not already):
|
|
74
|
+
```bash
|
|
75
|
+
cd /Users/chiragdugar/Desktop/Javis/javis-community-theme
|
|
76
|
+
git init
|
|
77
|
+
git add .
|
|
78
|
+
git commit -m "Initial JAVIS theme setup"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
2. **Push to GitHub**:
|
|
82
|
+
```bash
|
|
83
|
+
git remote add origin https://github.com/yourusername/javis-community-theme.git
|
|
84
|
+
git push -u origin main
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
3. **Install from GitHub in NodeBB**:
|
|
88
|
+
- NodeBB ACP → Extend → Install Plugins
|
|
89
|
+
- Enter: `yourusername/javis-community-theme`
|
|
90
|
+
- Click "Install"
|
|
91
|
+
|
|
92
|
+
## File Structure
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
javis-community-theme/
|
|
96
|
+
├── less/
|
|
97
|
+
│ ├── theme.less # Main entry point
|
|
98
|
+
│ ├── _variables.less # Design tokens
|
|
99
|
+
│ ├── _base.less # Global styles & typography
|
|
100
|
+
│ ├── _buttons.less # Button system
|
|
101
|
+
│ ├── _forms.less # Input & form controls
|
|
102
|
+
│ ├── _cards.less # Feed post cards
|
|
103
|
+
│ ├── _sidebar.less # Sidebar widgets
|
|
104
|
+
│ └── _categories.less # Category list styling
|
|
105
|
+
├── static/
|
|
106
|
+
│ └── lib/
|
|
107
|
+
│ ├── theme.css # Compiled CSS (generated)
|
|
108
|
+
│ └── theme.js # Client-side JS
|
|
109
|
+
├── templates/ # Custom template overrides (if needed)
|
|
110
|
+
├── theme.js # Server-side theme logic
|
|
111
|
+
├── plugin.json # NodeBB theme manifest
|
|
112
|
+
└── package.json # NPM configuration
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Customization Guide
|
|
116
|
+
|
|
117
|
+
### Changing Colors
|
|
118
|
+
|
|
119
|
+
Edit `less/_variables.less`:
|
|
120
|
+
|
|
121
|
+
```less
|
|
122
|
+
@jv-primary: #0051ff; // Your primary brand color
|
|
123
|
+
@jv-primary-hover: #0044dd; // Hover state
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Adjusting Spacing
|
|
127
|
+
|
|
128
|
+
Modify the spacing scale in `less/_variables.less`:
|
|
129
|
+
|
|
130
|
+
```less
|
|
131
|
+
@jv-space-2: 4px;
|
|
132
|
+
@jv-space-4: 8px;
|
|
133
|
+
// ... etc
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Component Styling
|
|
137
|
+
|
|
138
|
+
Each component has its own file:
|
|
139
|
+
- **Buttons**: `less/_buttons.less`
|
|
140
|
+
- **Forms**: `less/_forms.less`
|
|
141
|
+
- **Cards**: `less/_cards.less`
|
|
142
|
+
- **Sidebar**: `less/_sidebar.less`
|
|
143
|
+
- **Categories**: `less/_categories.less`
|
|
144
|
+
|
|
145
|
+
### Adding Custom Components
|
|
146
|
+
|
|
147
|
+
1. Create a new LESS file: `less/_yourcomponent.less`
|
|
148
|
+
2. Import it in `less/theme.less`:
|
|
149
|
+
```less
|
|
150
|
+
@import "_yourcomponent";
|
|
151
|
+
```
|
|
152
|
+
3. Rebuild: `npm run build`
|
|
153
|
+
|
|
154
|
+
## Maintenance
|
|
155
|
+
|
|
156
|
+
### After Making Changes
|
|
157
|
+
|
|
158
|
+
1. Edit LESS files in the `less/` directory
|
|
159
|
+
2. Run `npm run build` to compile
|
|
160
|
+
3. If deployed, re-upload the theme to NodeBB Cloud
|
|
161
|
+
4. Rebuild NodeBB in the ACP
|
|
162
|
+
|
|
163
|
+
### Updating NodeBB
|
|
164
|
+
|
|
165
|
+
Since this is a standalone theme, NodeBB updates won't affect your design. However:
|
|
166
|
+
- Test the theme after major NodeBB version updates
|
|
167
|
+
- Check for any DOM structure changes that might need CSS adjustments
|
|
168
|
+
|
|
169
|
+
## Troubleshooting
|
|
170
|
+
|
|
171
|
+
### Theme Not Applying
|
|
172
|
+
|
|
173
|
+
1. Check that the theme is activated in ACP → Appearance → Themes
|
|
174
|
+
2. Make sure you rebuilt NodeBB after installation
|
|
175
|
+
3. Clear browser cache (Cmd+Shift+R)
|
|
176
|
+
|
|
177
|
+
### Styles Not Updating
|
|
178
|
+
|
|
179
|
+
1. Make sure you ran `npm run build` after editing LESS files
|
|
180
|
+
2. Check that `static/lib/theme.css` was generated
|
|
181
|
+
3. Rebuild NodeBB in the ACP
|
|
182
|
+
|
|
183
|
+
### Missing Dependencies
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm install
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Support
|
|
190
|
+
|
|
191
|
+
For issues or questions:
|
|
192
|
+
- Check NodeBB documentation: https://docs.nodebb.org
|
|
193
|
+
- NodeBB Community: https://community.nodebb.org
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
MIT License - feel free to customize for your needs!
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
**Built with ❤️ for JAVIS Community**
|
package/less/_base.less
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// BASE STYLES – Global Reset & Typography
|
|
3
|
+
// ============================================
|
|
4
|
+
|
|
5
|
+
html, body {
|
|
6
|
+
font-family: @jv-font-sans;
|
|
7
|
+
font-size: @jv-font-size-base;
|
|
8
|
+
line-height: @jv-line-height-base;
|
|
9
|
+
background-color: @jv-bg;
|
|
10
|
+
color: @jv-text-main;
|
|
11
|
+
-webkit-font-smoothing: antialiased;
|
|
12
|
+
-moz-osx-font-smoothing: grayscale;
|
|
13
|
+
margin: 0;
|
|
14
|
+
padding: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Paragraph
|
|
18
|
+
p {
|
|
19
|
+
margin: 0 0 @jv-space-6 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Headings
|
|
23
|
+
h1 {
|
|
24
|
+
font-size: @jv-font-size-xxl;
|
|
25
|
+
font-weight: 600;
|
|
26
|
+
letter-spacing: -0.02em;
|
|
27
|
+
margin-bottom: @jv-space-8;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
h2 {
|
|
31
|
+
font-size: @jv-font-size-xl;
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
letter-spacing: -0.01em;
|
|
34
|
+
margin-bottom: @jv-space-6;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
h3 {
|
|
38
|
+
font-size: @jv-font-size-xl;
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
margin-bottom: @jv-space-6;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
h4 {
|
|
44
|
+
font-size: 20px;
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
margin-bottom: @jv-space-6;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
h5 {
|
|
50
|
+
font-size: 17px;
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
margin-bottom: @jv-space-6;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
h6 {
|
|
56
|
+
font-size: @jv-font-size-base;
|
|
57
|
+
font-weight: 600;
|
|
58
|
+
margin-bottom: @jv-space-4;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Links
|
|
62
|
+
a {
|
|
63
|
+
color: @jv-primary;
|
|
64
|
+
text-decoration: none;
|
|
65
|
+
transition: color 0.15s ease;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
color: @jv-primary-hover;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// ===========================================================
|
|
2
|
+
// BUTTON SYSTEM – JAVIS Design System
|
|
3
|
+
// ===========================================================
|
|
4
|
+
|
|
5
|
+
// Base Button Reset
|
|
6
|
+
.btn {
|
|
7
|
+
border-radius: @jv-radius-pill;
|
|
8
|
+
padding: 6px 16px;
|
|
9
|
+
font-size: 14px;
|
|
10
|
+
font-weight: 500;
|
|
11
|
+
line-height: 1.32;
|
|
12
|
+
transition: all 0.15s ease;
|
|
13
|
+
border-width: 1px;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// PRIMARY BUTTON
|
|
18
|
+
.btn-primary {
|
|
19
|
+
background-color: @jv-primary;
|
|
20
|
+
border-color: @jv-primary;
|
|
21
|
+
color: #fff;
|
|
22
|
+
box-shadow: @jv-shadow-button;
|
|
23
|
+
|
|
24
|
+
&:hover,
|
|
25
|
+
&:focus {
|
|
26
|
+
background-color: @jv-primary-hover;
|
|
27
|
+
border-color: @jv-primary-hover;
|
|
28
|
+
box-shadow: @jv-shadow-button-hover;
|
|
29
|
+
transform: translateY(-1px);
|
|
30
|
+
color: #fff;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:active {
|
|
34
|
+
transform: translateY(0);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// OUTLINE PRIMARY
|
|
39
|
+
.btn-outline-primary {
|
|
40
|
+
background-color: transparent;
|
|
41
|
+
border-color: @jv-primary;
|
|
42
|
+
color: @jv-primary;
|
|
43
|
+
|
|
44
|
+
&:hover,
|
|
45
|
+
&:focus {
|
|
46
|
+
background-color: @jv-primary-soft;
|
|
47
|
+
border-color: @jv-primary;
|
|
48
|
+
color: @jv-primary;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// SECONDARY BUTTON
|
|
53
|
+
.btn-secondary,
|
|
54
|
+
.btn-default {
|
|
55
|
+
background-color: #f7f8fa;
|
|
56
|
+
border-color: @jv-border-subtle;
|
|
57
|
+
color: @jv-text-main;
|
|
58
|
+
|
|
59
|
+
&:hover,
|
|
60
|
+
&:focus {
|
|
61
|
+
background-color: #eef0f3;
|
|
62
|
+
border-color: @jv-border-subtle;
|
|
63
|
+
color: @jv-text-main;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// LINK-STYLE BUTTON
|
|
68
|
+
.btn-link {
|
|
69
|
+
color: @jv-primary;
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
padding: 0;
|
|
72
|
+
|
|
73
|
+
&:hover {
|
|
74
|
+
text-decoration: underline;
|
|
75
|
+
color: @jv-primary-hover;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// SMALL BUTTONS
|
|
80
|
+
.btn-sm {
|
|
81
|
+
padding: 4px 12px;
|
|
82
|
+
font-size: @jv-font-size-sm;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// LARGE BUTTONS
|
|
86
|
+
.btn-lg {
|
|
87
|
+
padding: 10px 22px;
|
|
88
|
+
font-size: @jv-font-size-base;
|
|
89
|
+
border-radius: @jv-radius-pill;
|
|
90
|
+
}
|
package/less/_cards.less
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ===========================================================
|
|
2
|
+
// CARD COMPONENT – Feed Posts
|
|
3
|
+
// Inspired by Circle.so's spacing and Apple's depth
|
|
4
|
+
// ===========================================================
|
|
5
|
+
|
|
6
|
+
// CARD WRAPPER
|
|
7
|
+
li[component="post"].posts-list-item {
|
|
8
|
+
background: @jv-surface;
|
|
9
|
+
border-radius: @jv-radius-lg;
|
|
10
|
+
border: 1px solid rgba(0,0,0,0.05);
|
|
11
|
+
box-shadow: @jv-shadow-card;
|
|
12
|
+
padding: 24px 22px 20px 22px;
|
|
13
|
+
margin-bottom: 24px;
|
|
14
|
+
transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
|
15
|
+
|
|
16
|
+
&:hover {
|
|
17
|
+
box-shadow: 0 6px 14px rgba(0,0,0,0.08);
|
|
18
|
+
border-color: rgba(0,0,0,0.08);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// IMAGE BLOCK
|
|
23
|
+
li[component="post"] {
|
|
24
|
+
.overflow-hidden,
|
|
25
|
+
img.w-100 {
|
|
26
|
+
border-radius: @jv-radius-lg;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// CARD BODY LAYOUT
|
|
31
|
+
li[component="post"] .post-body {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: @jv-space-6;
|
|
35
|
+
padding-top: @jv-space-2;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// TITLE
|
|
39
|
+
li[component="post"] .topic-title {
|
|
40
|
+
display: block;
|
|
41
|
+
margin-bottom: 6px;
|
|
42
|
+
font-size: @jv-font-size-lg;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
letter-spacing: -0.01em;
|
|
45
|
+
line-height: @jv-line-height-tight;
|
|
46
|
+
color: @jv-text-main;
|
|
47
|
+
|
|
48
|
+
a {
|
|
49
|
+
color: inherit;
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
|
|
52
|
+
&:hover {
|
|
53
|
+
color: @jv-primary;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// META (author + time)
|
|
59
|
+
li[component="post"] .d-flex.gap-2 {
|
|
60
|
+
margin-bottom: 10px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
li[component="post"] {
|
|
64
|
+
.timeago,
|
|
65
|
+
.post-meta a,
|
|
66
|
+
.topic-meta {
|
|
67
|
+
font-size: @jv-font-size-sm;
|
|
68
|
+
color: @jv-text-muted;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// CONTENT
|
|
73
|
+
li[component="post"] .content p {
|
|
74
|
+
font-size: @jv-font-size-base;
|
|
75
|
+
line-height: @jv-line-height-base;
|
|
76
|
+
margin-bottom: 18px;
|
|
77
|
+
color: @jv-text-main;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// DIVIDER
|
|
81
|
+
li[component="post"] hr {
|
|
82
|
+
margin: 16px 0;
|
|
83
|
+
border-color: @jv-border-subtle;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ===========================================================
|
|
87
|
+
// ACTION ROW (quiet, modern, premium)
|
|
88
|
+
// ===========================================================
|
|
89
|
+
|
|
90
|
+
li[component="post"] .d-flex.justify-content-between {
|
|
91
|
+
margin-top: 6px;
|
|
92
|
+
padding-bottom: 2px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
li[component="post"] .d-flex.gap-3 a {
|
|
96
|
+
background: transparent;
|
|
97
|
+
border: none;
|
|
98
|
+
padding: 0;
|
|
99
|
+
font-size: @jv-font-size-sm;
|
|
100
|
+
color: @jv-text-muted;
|
|
101
|
+
opacity: 0.85;
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: 6px;
|
|
105
|
+
box-shadow: none;
|
|
106
|
+
text-decoration: none;
|
|
107
|
+
transition: color 0.15s ease, opacity 0.15s ease;
|
|
108
|
+
|
|
109
|
+
&:hover {
|
|
110
|
+
color: @jv-primary;
|
|
111
|
+
opacity: 1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
i {
|
|
115
|
+
font-size: 15px;
|
|
116
|
+
color: inherit;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ===========================================================
|
|
2
|
+
// CATEGORIES – Enterprise Clean Style (Linear-inspired)
|
|
3
|
+
// ===========================================================
|
|
4
|
+
|
|
5
|
+
// Category Header
|
|
6
|
+
.feed h2 {
|
|
7
|
+
font-size: 16px;
|
|
8
|
+
font-weight: 600;
|
|
9
|
+
margin: 0 0 @jv-space-6 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
color: @jv-text-main;
|
|
12
|
+
letter-spacing: -0.2px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Wrapper list spacing
|
|
16
|
+
ul.categories-list.list-unstyled {
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
gap: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ===========================================================
|
|
25
|
+
// PARENT CATEGORY BLOCK
|
|
26
|
+
// ===========================================================
|
|
27
|
+
|
|
28
|
+
li[component="categories/category"] {
|
|
29
|
+
padding: 16px 0;
|
|
30
|
+
border-bottom: 1px solid #f1f1f1;
|
|
31
|
+
transition: background 120ms ease;
|
|
32
|
+
|
|
33
|
+
&:last-child {
|
|
34
|
+
border-bottom: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&:hover {
|
|
38
|
+
background: rgba(0, 0, 0, 0.02);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Parent title
|
|
42
|
+
.title {
|
|
43
|
+
font-size: @jv-font-size-base;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
color: @jv-text-main;
|
|
46
|
+
margin-bottom: 4px;
|
|
47
|
+
display: flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
gap: 6px;
|
|
50
|
+
|
|
51
|
+
a {
|
|
52
|
+
text-decoration: none;
|
|
53
|
+
color: inherit;
|
|
54
|
+
|
|
55
|
+
&:hover {
|
|
56
|
+
color: @jv-primary;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
i {
|
|
61
|
+
font-size: @jv-font-size-base;
|
|
62
|
+
opacity: 0.95;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Category description
|
|
67
|
+
.description {
|
|
68
|
+
font-size: @jv-font-size-sm;
|
|
69
|
+
color: @jv-text-muted;
|
|
70
|
+
line-height: 1.45;
|
|
71
|
+
margin-bottom: 10px;
|
|
72
|
+
max-width: 92%;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ===========================================================
|
|
77
|
+
// CHILD CATEGORY ITEMS – Linear-style tiny dot list
|
|
78
|
+
// ===========================================================
|
|
79
|
+
|
|
80
|
+
li[component="categories/category"] .category-children {
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
gap: 6px;
|
|
84
|
+
margin-top: 4px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.category-children-item {
|
|
88
|
+
small > .d-flex {
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
gap: 6px;
|
|
92
|
+
font-size: 14px;
|
|
93
|
+
color: #333;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Dot (neutral by default)
|
|
97
|
+
i {
|
|
98
|
+
font-size: 6px;
|
|
99
|
+
color: #999;
|
|
100
|
+
margin-top: 1px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Child link
|
|
104
|
+
a {
|
|
105
|
+
text-decoration: none;
|
|
106
|
+
font-size: 14px;
|
|
107
|
+
color: #333;
|
|
108
|
+
transition: color 120ms ease, transform 80ms ease;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Hover state: blue dot + blue text
|
|
112
|
+
&:hover {
|
|
113
|
+
i {
|
|
114
|
+
color: @jv-primary;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
a {
|
|
118
|
+
color: @jv-primary;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
package/less/_forms.less
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// ===========================================================
|
|
2
|
+
// INPUT SYSTEM – Global Form Controls
|
|
3
|
+
// ===========================================================
|
|
4
|
+
|
|
5
|
+
.form-control,
|
|
6
|
+
input[type="text"],
|
|
7
|
+
input[type="search"],
|
|
8
|
+
input[type="email"],
|
|
9
|
+
input[type="password"],
|
|
10
|
+
textarea,
|
|
11
|
+
.form-select {
|
|
12
|
+
background: @jv-surface;
|
|
13
|
+
border: 1px solid @jv-border-subtle;
|
|
14
|
+
border-radius: @jv-radius-pill;
|
|
15
|
+
padding: 10px 16px;
|
|
16
|
+
font-size: @jv-font-size-base;
|
|
17
|
+
color: @jv-text-main;
|
|
18
|
+
line-height: @jv-line-height-tight;
|
|
19
|
+
box-shadow: none;
|
|
20
|
+
transition: all 0.15s ease;
|
|
21
|
+
|
|
22
|
+
&::placeholder {
|
|
23
|
+
color: @jv-text-muted;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&:focus {
|
|
27
|
+
outline: none;
|
|
28
|
+
border-color: @jv-primary;
|
|
29
|
+
box-shadow: 0 0 0 3px @jv-primary-soft;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Textarea specific
|
|
34
|
+
textarea {
|
|
35
|
+
border-radius: @jv-radius-md;
|
|
36
|
+
resize: vertical;
|
|
37
|
+
min-height: 100px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ===========================================================
|
|
41
|
+
// SEARCH BAR
|
|
42
|
+
// ===========================================================
|
|
43
|
+
|
|
44
|
+
.search-widget .input-group {
|
|
45
|
+
.form-control {
|
|
46
|
+
border-top-right-radius: 0;
|
|
47
|
+
border-bottom-right-radius: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.btn-primary {
|
|
51
|
+
border-top-left-radius: 0;
|
|
52
|
+
border-bottom-left-radius: 0;
|
|
53
|
+
padding: 0 18px;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ===========================================================
|
|
58
|
+
// COMPOSER TRIGGER (Write a Post…)
|
|
59
|
+
// ===========================================================
|
|
60
|
+
|
|
61
|
+
.jlc-trigger {
|
|
62
|
+
width: 100%;
|
|
63
|
+
background: @jv-surface;
|
|
64
|
+
border: 1px solid @jv-border-subtle;
|
|
65
|
+
border-radius: @jv-radius-pill;
|
|
66
|
+
padding: 12px 18px;
|
|
67
|
+
font-size: @jv-font-size-base;
|
|
68
|
+
font-weight: 400;
|
|
69
|
+
text-align: left;
|
|
70
|
+
color: @jv-text-muted;
|
|
71
|
+
box-shadow: @jv-shadow-soft;
|
|
72
|
+
transition: all 0.15s ease;
|
|
73
|
+
|
|
74
|
+
&:hover,
|
|
75
|
+
&:focus {
|
|
76
|
+
background: @jv-surface;
|
|
77
|
+
border-color: @jv-primary;
|
|
78
|
+
color: @jv-primary;
|
|
79
|
+
box-shadow: @jv-shadow-soft;
|
|
80
|
+
outline: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&:active {
|
|
84
|
+
transform: scale(0.99);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Override Bootstrap button states
|
|
88
|
+
&.btn,
|
|
89
|
+
&.btn:focus,
|
|
90
|
+
&.btn:hover,
|
|
91
|
+
&.btn:active {
|
|
92
|
+
background: @jv-surface;
|
|
93
|
+
border-radius: @jv-radius-pill;
|
|
94
|
+
box-shadow: @jv-shadow-soft;
|
|
95
|
+
border-color: @jv-border-subtle;
|
|
96
|
+
outline: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&.btn:hover,
|
|
100
|
+
&.btn:focus {
|
|
101
|
+
border-color: @jv-primary;
|
|
102
|
+
color: @jv-primary;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// ===========================================================
|
|
2
|
+
// SIDEBAR SYSTEM – Trending Tags + Trending Now
|
|
3
|
+
// ===========================================================
|
|
4
|
+
|
|
5
|
+
// Sidebar Widget Titles
|
|
6
|
+
div[data-widget-area="right"] {
|
|
7
|
+
h5, h8 {
|
|
8
|
+
font-size: 16px;
|
|
9
|
+
font-weight: 600;
|
|
10
|
+
margin-bottom: @jv-space-4;
|
|
11
|
+
color: @jv-text-main;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ===========================================================
|
|
16
|
+
// TRENDING TAGS
|
|
17
|
+
// ===========================================================
|
|
18
|
+
|
|
19
|
+
.popular-tags {
|
|
20
|
+
gap: 6px;
|
|
21
|
+
|
|
22
|
+
.tag-list > div {
|
|
23
|
+
background: @jv-surface;
|
|
24
|
+
border: 1px solid @jv-border-subtle;
|
|
25
|
+
border-radius: 10px;
|
|
26
|
+
padding: 10px 12px;
|
|
27
|
+
font-size: 14px;
|
|
28
|
+
color: @jv-text-main;
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
gap: 2px;
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
transition: border-color 0.15s ease, background 0.15s ease;
|
|
34
|
+
|
|
35
|
+
&:hover {
|
|
36
|
+
border-color: rgba(0,0,0,0.12);
|
|
37
|
+
background: rgba(0,0,0,0.03);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
small {
|
|
41
|
+
color: @jv-text-muted;
|
|
42
|
+
font-size: @jv-font-size-xs;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ===========================================================
|
|
48
|
+
// TRENDING NOW
|
|
49
|
+
// ===========================================================
|
|
50
|
+
|
|
51
|
+
#recent_posts {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
gap: 10px;
|
|
55
|
+
margin-top: @jv-space-6;
|
|
56
|
+
|
|
57
|
+
li.widget-posts {
|
|
58
|
+
background: @jv-surface;
|
|
59
|
+
border: 1px solid rgba(0,0,0,0.05);
|
|
60
|
+
border-radius: @jv-radius-md;
|
|
61
|
+
padding: 10px 14px;
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: @jv-space-4;
|
|
65
|
+
transition: box-shadow 0.15s ease, border 0.15s ease;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
border-color: rgba(0,0,0,0.08);
|
|
69
|
+
box-shadow: @jv-shadow-soft;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Meta info
|
|
73
|
+
.d-flex.gap-2,
|
|
74
|
+
.timeago {
|
|
75
|
+
font-size: @jv-font-size-xs;
|
|
76
|
+
color: @jv-text-muted;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Title inside mini post
|
|
80
|
+
a {
|
|
81
|
+
font-size: 14px;
|
|
82
|
+
font-weight: 500;
|
|
83
|
+
color: @jv-text-main;
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
line-height: @jv-line-height-tight;
|
|
86
|
+
|
|
87
|
+
&:hover {
|
|
88
|
+
color: @jv-primary;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 2-line clamp for content preview
|
|
93
|
+
p,
|
|
94
|
+
.content {
|
|
95
|
+
display: -webkit-box;
|
|
96
|
+
-webkit-line-clamp: 2;
|
|
97
|
+
-webkit-box-orient: vertical;
|
|
98
|
+
overflow: hidden;
|
|
99
|
+
font-size: @jv-font-size-sm;
|
|
100
|
+
color: @jv-text-muted;
|
|
101
|
+
margin: 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Read more alignment
|
|
105
|
+
a.stretched-link {
|
|
106
|
+
font-size: @jv-font-size-xs;
|
|
107
|
+
color: @jv-primary;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -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;
|
package/less/theme.less
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// JAVIS Community Theme
|
|
3
|
+
// Modern, premium NodeBB theme
|
|
4
|
+
// Inspired by Apple, Stripe, and Linear
|
|
5
|
+
// ============================================
|
|
6
|
+
|
|
7
|
+
// Core Design System
|
|
8
|
+
@import "_variables";
|
|
9
|
+
|
|
10
|
+
// Base Styles
|
|
11
|
+
@import "_base";
|
|
12
|
+
|
|
13
|
+
// Components
|
|
14
|
+
@import "_buttons";
|
|
15
|
+
@import "_forms";
|
|
16
|
+
@import "_cards";
|
|
17
|
+
@import "_sidebar";
|
|
18
|
+
@import "_categories";
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@okjavis/nodebb-theme-javis",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Modern, premium NodeBB theme for JAVIS Community - Extends Harmony with custom styling",
|
|
5
|
+
"main": "theme.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "npm run build:less",
|
|
8
|
+
"build:less": "lessc less/theme.less static/lib/theme.css --clean-css",
|
|
9
|
+
"watch": "npm-watch",
|
|
10
|
+
"dev": "npm run watch",
|
|
11
|
+
"prepublishOnly": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"watch": {
|
|
14
|
+
"build:less": {
|
|
15
|
+
"patterns": [
|
|
16
|
+
"less"
|
|
17
|
+
],
|
|
18
|
+
"extensions": "less",
|
|
19
|
+
"quiet": false
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/javis-admin/nodebb-community-theme.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/javis-admin/nodebb-community-theme/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/javis-admin/nodebb-community-theme#readme",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"nodebb-theme",
|
|
32
|
+
"nodebb",
|
|
33
|
+
"theme",
|
|
34
|
+
"javis",
|
|
35
|
+
"community",
|
|
36
|
+
"harmony"
|
|
37
|
+
],
|
|
38
|
+
"author": "Chirag Dugar",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"nodebb-theme-harmony": "^1.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"less": "^4.2.0",
|
|
45
|
+
"less-plugin-clean-css": "^1.5.1",
|
|
46
|
+
"npm-watch": "^0.11.0"
|
|
47
|
+
},
|
|
48
|
+
"nbbpm": {
|
|
49
|
+
"compatibility": "^3.0.0"
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"less/",
|
|
53
|
+
"static/",
|
|
54
|
+
"templates/",
|
|
55
|
+
"theme.js",
|
|
56
|
+
"plugin.json"
|
|
57
|
+
]
|
|
58
|
+
}
|
package/plugin.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "@okjavis/nodebb-theme-javis",
|
|
3
|
+
"name": "JAVIS Community Theme",
|
|
4
|
+
"description": "Modern, premium NodeBB theme for JAVIS Community - Extends Harmony with custom styling and selective template overrides",
|
|
5
|
+
"url": "https://github.com/javis-admin/nodebb-community-theme",
|
|
6
|
+
"library": "./theme.js",
|
|
7
|
+
"baseTheme": "nodebb-theme-harmony",
|
|
8
|
+
"staticDirs": {
|
|
9
|
+
"static": "./static"
|
|
10
|
+
},
|
|
11
|
+
"less": [
|
|
12
|
+
"less/theme.less"
|
|
13
|
+
],
|
|
14
|
+
"scripts": [
|
|
15
|
+
"static/lib/theme.js"
|
|
16
|
+
],
|
|
17
|
+
"templates": "templates",
|
|
18
|
+
"screenshot": "screenshot.png",
|
|
19
|
+
"version": "1.0.0",
|
|
20
|
+
"nbbpm": {
|
|
21
|
+
"compatibility": "^3.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
body,html{font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text",system-ui,"Helvetica Neue",Arial,sans-serif;font-size:15px;line-height:1.52;background-color:#f5f6f8;color:#111;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin:0;padding:0}p{margin:0 0 12px 0}h1{font-size:32px;font-weight:600;letter-spacing:-.02em;margin-bottom:16px}h2{font-size:22px;font-weight:600;letter-spacing:-.01em;margin-bottom:12px}h3{font-size:22px;font-weight:600;margin-bottom:12px}h4{font-size:20px;font-weight:600;margin-bottom:12px}h5{font-size:17px;font-weight:600;margin-bottom:12px}h6{font-size:15px;font-weight:600;margin-bottom:8px}a{color:#0051ff;text-decoration:none;transition:color .15s ease}a:hover{color:#04d}.btn{border-radius:999px;padding:6px 16px;font-size:14px;font-weight:500;line-height:1.32;transition:all .15s ease;border-width:1px;cursor:pointer}.btn-primary{background-color:#0051ff;border-color:#0051ff;color:#fff;box-shadow:0 4px 12px rgba(0,81,255,.25)}.btn-primary:focus,.btn-primary:hover{background-color:#04d;border-color:#04d;box-shadow:0 6px 16px rgba(0,81,255,.35);transform:translateY(-1px);color:#fff}.btn-primary:active{transform:translateY(0)}.btn-outline-primary{background-color:transparent;border-color:#0051ff;color:#0051ff}.btn-outline-primary:focus,.btn-outline-primary:hover{background-color:rgba(0,81,255,.12);border-color:#0051ff;color:#0051ff}.btn-default,.btn-secondary{background-color:#f7f8fa;border-color:rgba(0,0,0,.06);color:#111}.btn-default:focus,.btn-default:hover,.btn-secondary:focus,.btn-secondary:hover{background-color:#eef0f3;border-color:rgba(0,0,0,.06);color:#111}.btn-link{color:#0051ff;font-weight:500;padding:0}.btn-link:hover{text-decoration:underline;color:#04d}.btn-sm{padding:4px 12px;font-size:13px}.btn-lg{padding:10px 22px;font-size:15px;border-radius:999px}.form-control,.form-select,input[type=email],input[type=password],input[type=search],input[type=text],textarea{background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:999px;padding:10px 16px;font-size:15px;color:#111;line-height:1.4;box-shadow:none;transition:all .15s ease}.form-control::placeholder,.form-select::placeholder,input[type=email]::placeholder,input[type=password]::placeholder,input[type=search]::placeholder,input[type=text]::placeholder,textarea::placeholder{color:#6b7280}.form-control:focus,.form-select:focus,input[type=email]:focus,input[type=password]:focus,input[type=search]:focus,input[type=text]:focus,textarea:focus{outline:0;border-color:#0051ff;box-shadow:0 0 0 3px rgba(0,81,255,.12)}textarea{border-radius:12px;resize:vertical;min-height:100px}.search-widget .input-group .form-control{border-top-right-radius:0;border-bottom-right-radius:0}.search-widget .input-group .btn-primary{border-top-left-radius:0;border-bottom-left-radius:0;padding:0 18px}.jlc-trigger{width:100%;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:999px;padding:12px 18px;font-size:15px;font-weight:400;text-align:left;color:#6b7280;box-shadow:0 2px 8px rgba(0,0,0,.04);transition:all .15s ease}.jlc-trigger:focus,.jlc-trigger:hover{background:#fff;border-color:#0051ff;color:#0051ff;box-shadow:0 2px 8px rgba(0,0,0,.04);outline:0}.jlc-trigger:active{transform:scale(.99)}.jlc-trigger.btn,.jlc-trigger.btn:active,.jlc-trigger.btn:focus,.jlc-trigger.btn:hover{background:#fff;border-radius:999px;box-shadow:0 2px 8px rgba(0,0,0,.04);border-color:rgba(0,0,0,.06);outline:0}.jlc-trigger.btn:focus,.jlc-trigger.btn:hover{border-color:#0051ff;color:#0051ff}li[component=post].posts-list-item{background:#fff;border-radius:16px;border:1px solid rgba(0,0,0,.05);box-shadow:0 4px 10px rgba(0,0,0,.05);padding:24px 22px 20px 22px;margin-bottom:24px;transition:box-shadow .15s ease,border-color .15s ease}li[component=post].posts-list-item:hover{box-shadow:0 6px 14px rgba(0,0,0,.08);border-color:rgba(0,0,0,.08)}li[component=post] .overflow-hidden,li[component=post] img.w-100{border-radius:16px}li[component=post] .post-body{display:flex;flex-direction:column;gap:12px;padding-top:4px}li[component=post] .topic-title{display:block;margin-bottom:6px;font-size:18px;font-weight:600;letter-spacing:-.01em;line-height:1.4;color:#111}li[component=post] .topic-title a{color:inherit;text-decoration:none}li[component=post] .topic-title a:hover{color:#0051ff}li[component=post] .d-flex.gap-2{margin-bottom:10px}li[component=post] .post-meta a,li[component=post] .timeago,li[component=post] .topic-meta{font-size:13px;color:#6b7280}li[component=post] .content p{font-size:15px;line-height:1.52;margin-bottom:18px;color:#111}li[component=post] hr{margin:16px 0;border-color:rgba(0,0,0,.06)}li[component=post] .d-flex.justify-content-between{margin-top:6px;padding-bottom:2px}li[component=post] .d-flex.gap-3 a{background:0 0;border:none;padding:0;font-size:13px;color:#6b7280;opacity:.85;display:flex;align-items:center;gap:6px;box-shadow:none;text-decoration:none;transition:color .15s ease,opacity .15s ease}li[component=post] .d-flex.gap-3 a:hover{color:#0051ff;opacity:1}li[component=post] .d-flex.gap-3 a i{font-size:15px;color:inherit}div[data-widget-area=right] h5,div[data-widget-area=right] h8{font-size:16px;font-weight:600;margin-bottom:8px;color:#111}.popular-tags{gap:6px}.popular-tags .tag-list>div{background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:10px;padding:10px 12px;font-size:14px;color:#111;display:flex;flex-direction:column;gap:2px;cursor:pointer;transition:border-color .15s ease,background .15s ease}.popular-tags .tag-list>div:hover{border-color:rgba(0,0,0,.12);background:rgba(0,0,0,.03)}.popular-tags .tag-list>div small{color:#6b7280;font-size:12px}#recent_posts{display:flex;flex-direction:column;gap:10px;margin-top:12px}#recent_posts li.widget-posts{background:#fff;border:1px solid rgba(0,0,0,.05);border-radius:12px;padding:10px 14px;display:flex;flex-direction:column;gap:8px;transition:box-shadow .15s ease,border .15s ease}#recent_posts li.widget-posts:hover{border-color:rgba(0,0,0,.08);box-shadow:0 2px 8px rgba(0,0,0,.04)}#recent_posts li.widget-posts .d-flex.gap-2,#recent_posts li.widget-posts .timeago{font-size:12px;color:#6b7280}#recent_posts li.widget-posts a{font-size:14px;font-weight:500;color:#111;text-decoration:none;line-height:1.4}#recent_posts li.widget-posts a:hover{color:#0051ff}#recent_posts li.widget-posts .content,#recent_posts li.widget-posts p{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:13px;color:#6b7280;margin:0}#recent_posts li.widget-posts a.stretched-link{font-size:12px;color:#0051ff}.feed h2{font-size:16px;font-weight:600;margin:0 0 12px 0;padding:0;color:#111;letter-spacing:-.2px}ul.categories-list.list-unstyled{margin:0;padding:0;display:flex;flex-direction:column;gap:0}li[component="categories/category"]{padding:16px 0;border-bottom:1px solid #f1f1f1;transition:background 120ms ease}li[component="categories/category"]:last-child{border-bottom:none}li[component="categories/category"]:hover{background:rgba(0,0,0,.02)}li[component="categories/category"] .title{font-size:15px;font-weight:600;color:#111;margin-bottom:4px;display:flex;align-items:center;gap:6px}li[component="categories/category"] .title a{text-decoration:none;color:inherit}li[component="categories/category"] .title a:hover{color:#0051ff}li[component="categories/category"] .title i{font-size:15px;opacity:.95}li[component="categories/category"] .description{font-size:13px;color:#6b7280;line-height:1.45;margin-bottom:10px;max-width:92%}li[component="categories/category"] .category-children{display:flex;flex-direction:column;gap:6px;margin-top:4px}.category-children-item small>.d-flex{display:flex;align-items:center;gap:6px;font-size:14px;color:#333}.category-children-item i{font-size:6px;color:#999;margin-top:1px}.category-children-item a{text-decoration:none;font-size:14px;color:#333;transition:color 120ms ease,transform 80ms ease}.category-children-item:hover i{color:#0051ff}.category-children-item:hover a{color:#0051ff}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JAVIS Community Theme - Client-side JavaScript
|
|
3
|
+
* Handles theme-specific interactions and behaviors
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function() {
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
// Theme initialization
|
|
10
|
+
$(document).ready(function() {
|
|
11
|
+
console.log('JAVIS Community Theme initialized');
|
|
12
|
+
|
|
13
|
+
// Add any custom client-side interactions here
|
|
14
|
+
// Example: smooth scrolling, animations, custom widgets, etc.
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
})();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{{{
|
|
2
|
+
JAVIS Community Theme - Post List Item
|
|
3
|
+
|
|
4
|
+
This template overrides Harmony's posts_list_item.tpl
|
|
5
|
+
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
|
+
}}}
|
|
10
|
+
<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
|
+
|
|
12
|
+
<a class="topic-title fw-semibold fs-5 mb-2 text-reset text-break d-block" href="{config.relative_path}/post/{encodeURIComponent(./pid)}">
|
|
13
|
+
{{{ if ./isMainPost }}}<i class="fa fa-book text-muted" title="[[topic:topic]]"></i> {{{ end }}}{./topic.title}
|
|
14
|
+
</a>
|
|
15
|
+
|
|
16
|
+
<div class="post-body d-flex flex-column gap-1 mb-2">
|
|
17
|
+
<div class="d-flex gap-2 post-info text-sm align-items-center">
|
|
18
|
+
<div class="post-author d-flex align-items-center gap-1">
|
|
19
|
+
<a class="lh-1 text-decoration-none" href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(./user, "16px", true, "not-responsive")}</a>
|
|
20
|
+
<a class="lh-1 fw-semibold" href="{config.relative_path}/user/{./user.userslug}">{../user.displayname}</a>
|
|
21
|
+
</div>
|
|
22
|
+
<span class="timeago text-muted lh-1" title="{./timestampISO}"></span>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div component="post/content" class="content text-sm text-break">
|
|
26
|
+
{./content}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="mb-3 d-flex flex-wrap gap-1 w-100">
|
|
31
|
+
{buildCategoryLabel(./category, "a", "border")}
|
|
32
|
+
<span data-tid="{./topic.tid}" component="topic/tags" class="lh-1 tag-list d-flex flex-wrap gap-1 {{{ if !./topic.tags.length }}}hidden{{{ end }}}">
|
|
33
|
+
{{{ each ./topic.tags }}}
|
|
34
|
+
<a href="{config.relative_path}/tags/{./valueEncoded}"><span class="badge border border-gray-300 fw-normal tag tag-class-{./class}" data-tag="{./value}">{./valueEscaped}</span></a>
|
|
35
|
+
{{{ end }}}
|
|
36
|
+
</span>
|
|
37
|
+
</div>
|
|
38
|
+
</li>
|
package/theme.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JAVIS Community Theme
|
|
3
|
+
* Main theme configuration and initialization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const theme = {};
|
|
9
|
+
|
|
10
|
+
theme.defineWidgetAreas = async (areas) => {
|
|
11
|
+
// Define custom widget areas for JAVIS theme
|
|
12
|
+
areas = areas.concat([
|
|
13
|
+
{
|
|
14
|
+
name: 'JAVIS Right Sidebar',
|
|
15
|
+
template: 'categories.tpl',
|
|
16
|
+
location: 'sidebar-right',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'JAVIS Left Sidebar',
|
|
20
|
+
template: 'categories.tpl',
|
|
21
|
+
location: 'sidebar-left',
|
|
22
|
+
},
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
return areas;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
theme.addAdminNavigation = (header) => {
|
|
29
|
+
header.plugins.push({
|
|
30
|
+
route: '/plugins/javis-community-theme',
|
|
31
|
+
icon: 'fa-paint-brush',
|
|
32
|
+
name: 'JAVIS Theme',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return header;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
module.exports = theme;
|