@okjavis/nodebb-theme-javis 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,724 @@
1
+ // ===========================================================
2
+ // COMPOSER MODAL – JAVIS Design System
3
+ // Transforms the default NodeBB composer into a centered modal
4
+ // ===========================================================
5
+
6
+ // ===========================================================
7
+ // BACKDROP
8
+ // ===========================================================
9
+ html.composing::before {
10
+ content: '';
11
+ position: fixed;
12
+ top: 0;
13
+ left: 0;
14
+ right: 0;
15
+ bottom: 0;
16
+ background: rgba(0, 0, 0, 0.5);
17
+ backdrop-filter: blur(4px);
18
+ -webkit-backdrop-filter: blur(4px);
19
+ z-index: 1040;
20
+ }
21
+
22
+ // ===========================================================
23
+ // MODAL CONTAINER
24
+ // ===========================================================
25
+ html.composing .composer {
26
+ position: fixed !important;
27
+ top: 50% !important;
28
+ left: 50% !important;
29
+ right: auto !important;
30
+ bottom: auto !important;
31
+ transform: translate(-50%, -50%) !important;
32
+ width: 720px !important;
33
+ max-width: calc(100vw - 32px) !important;
34
+ height: 600px !important;
35
+ max-height: 85vh !important;
36
+ background: $jv-surface !important;
37
+ border-radius: $jv-radius-lg !important;
38
+ border: 1px solid $jv-border-subtle !important;
39
+ box-shadow: $jv-shadow-xl !important;
40
+ z-index: 1050 !important;
41
+ overflow: visible !important; // Allow absolute children to overflow
42
+ margin: 0 !important;
43
+ }
44
+
45
+ html.composing body {
46
+ overflow: hidden !important;
47
+ }
48
+
49
+ // ===========================================================
50
+ // COMPOSER CONTAINER
51
+ // ===========================================================
52
+ html.composing .composer .composer-container {
53
+ display: flex !important;
54
+ flex-direction: column !important;
55
+ height: 100% !important;
56
+ padding: 0 !important;
57
+ gap: 0 !important;
58
+ overflow: hidden !important;
59
+ border-radius: $jv-radius-lg !important;
60
+ }
61
+
62
+ html.composing .composer .composer-container > .p-2 {
63
+ display: flex !important;
64
+ flex-direction: column !important;
65
+ height: 100% !important;
66
+ padding: 0 !important;
67
+ gap: 0 !important;
68
+ }
69
+
70
+ // ===========================================================
71
+ // HIDE MOBILE NAVBAR
72
+ // ===========================================================
73
+ html.composing .composer .mobile-navbar {
74
+ display: none !important;
75
+ }
76
+
77
+ // ===========================================================
78
+ // HIDE PREVIEW AND HELP BUTTONS
79
+ // ===========================================================
80
+ html.composing .composer [data-action="preview"],
81
+ html.composing .composer [data-action="help"] {
82
+ display: none !important;
83
+ }
84
+
85
+ // ===========================================================
86
+ // HEADER
87
+ // ===========================================================
88
+ html.composing .composer .title-container {
89
+ display: flex !important;
90
+ align-items: center !important;
91
+ gap: $jv-space-3 !important;
92
+ padding: $jv-space-4 $jv-space-5 !important;
93
+ border-bottom: 1px solid $jv-border-subtle !important;
94
+ background: $jv-surface !important;
95
+ flex-shrink: 0 !important;
96
+ min-height: 56px !important;
97
+ border-radius: $jv-radius-lg $jv-radius-lg 0 0 !important;
98
+ }
99
+
100
+ // Category selector
101
+ html.composing .composer .category-list-container {
102
+ flex-shrink: 0 !important;
103
+ display: block !important;
104
+
105
+ [component="category-selector"] {
106
+ .btn {
107
+ background: $jv-bg !important;
108
+ border: 1px solid $jv-border-subtle !important;
109
+ border-radius: $jv-radius-sm !important;
110
+ padding: $jv-space-2 $jv-space-3 !important;
111
+ font-size: $jv-font-size-sm !important;
112
+ color: $jv-text-main !important;
113
+
114
+ &:hover {
115
+ border-color: $jv-border-strong !important;
116
+ background: $jv-hover-bg !important;
117
+ }
118
+ }
119
+
120
+ .dropdown-menu {
121
+ min-width: 280px !important;
122
+ max-height: 320px !important;
123
+ overflow-y: auto !important;
124
+ padding: $jv-space-2 !important;
125
+
126
+ // Fix category list spacing
127
+ .category-dropdown-menu {
128
+ margin: 0 !important;
129
+ padding: 0 !important;
130
+ }
131
+
132
+ // Category items inside dropdown
133
+ li.category {
134
+ margin: 0 !important;
135
+ padding: 0 !important;
136
+
137
+ a.dropdown-item {
138
+ display: flex !important;
139
+ align-items: center !important;
140
+ gap: $jv-space-2 !important;
141
+ padding: $jv-space-2 $jv-space-3 !important;
142
+ margin: 2px 0 !important;
143
+ font-size: $jv-font-size-sm !important;
144
+ color: $jv-text-main !important;
145
+ border-radius: $jv-radius-xs !important;
146
+ white-space: nowrap !important;
147
+ overflow: hidden !important;
148
+ text-overflow: ellipsis !important;
149
+
150
+ &:hover {
151
+ background: $jv-hover-bg !important;
152
+ }
153
+
154
+ // Category icon
155
+ .category-item {
156
+ display: inline-flex !important;
157
+ align-items: center !important;
158
+ gap: $jv-space-2 !important;
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ // Title input
167
+ html.composing .composer [data-component="composer/title"] {
168
+ flex: 1 !important;
169
+ min-width: 0 !important;
170
+
171
+ .title {
172
+ width: 100% !important;
173
+ font-size: $jv-font-size-lg !important;
174
+ font-weight: 600 !important;
175
+ border: none !important;
176
+ background: transparent !important;
177
+ padding: $jv-space-2 0 !important;
178
+ color: $jv-text-main !important;
179
+ box-shadow: none !important;
180
+
181
+ &::placeholder {
182
+ color: $jv-text-soft !important;
183
+ font-weight: 400 !important;
184
+ }
185
+
186
+ &:focus {
187
+ outline: none !important;
188
+ box-shadow: none !important;
189
+ }
190
+ }
191
+ }
192
+
193
+ // ===========================================================
194
+ // ACTION BAR - X close button in header, Submit at bottom
195
+ // ===========================================================
196
+ html.composing .composer .action-bar {
197
+ flex-shrink: 0 !important;
198
+ display: flex !important;
199
+ align-items: center !important;
200
+ gap: $jv-space-2 !important;
201
+
202
+ // HIDE minimize button
203
+ .composer-minimize {
204
+ display: none !important;
205
+ }
206
+
207
+ // Style discard as X close button - stays in header
208
+ .composer-discard {
209
+ display: flex !important;
210
+ align-items: center !important;
211
+ justify-content: center !important;
212
+ width: 36px !important;
213
+ height: 36px !important;
214
+ padding: 0 !important;
215
+ margin: 0 !important;
216
+ border-radius: $jv-radius-sm !important;
217
+ background: transparent !important;
218
+ border: none !important;
219
+ color: $jv-text-muted !important;
220
+ cursor: pointer !important;
221
+
222
+ &:hover {
223
+ background: $jv-hover-bg !important;
224
+ color: $jv-text-main !important;
225
+ }
226
+
227
+ // Hide text
228
+ span {
229
+ display: none !important;
230
+ }
231
+
232
+ // Style icon as X
233
+ i.fa-trash {
234
+ font-size: 18px !important;
235
+ margin: 0 !important;
236
+
237
+ &::before {
238
+ content: '\f00d' !important; // fa-times
239
+ }
240
+ }
241
+ }
242
+
243
+ }
244
+
245
+ // ===========================================================
246
+ // SUBMIT BUTTON - Positioned at bottom right of modal (footer)
247
+ // Vertically centered with the footer (56px height, button ~40px)
248
+ // ===========================================================
249
+ html.composing .composer .action-bar [component="composer/submit/container"] {
250
+ position: absolute !important;
251
+ bottom: 8px !important; // Centered: (56px footer - 40px button) / 2 = 8px
252
+ right: $jv-space-5 !important;
253
+ top: auto !important;
254
+ left: auto !important;
255
+ z-index: 1060 !important;
256
+ display: flex !important;
257
+ align-items: center !important;
258
+
259
+ .btn-group {
260
+ display: flex !important;
261
+ }
262
+
263
+ .composer-submit {
264
+ background: $jv-primary !important;
265
+ border-color: $jv-primary !important;
266
+ color: white !important;
267
+ font-weight: 600 !important;
268
+ padding: $jv-space-2 $jv-space-5 !important;
269
+ border-radius: $jv-radius-sm !important;
270
+ font-size: $jv-font-size-sm !important;
271
+ display: inline-flex !important;
272
+ align-items: center !important;
273
+ gap: $jv-space-1 !important;
274
+ height: 40px !important;
275
+
276
+ &:hover {
277
+ background: $jv-primary-hover !important;
278
+ border-color: $jv-primary-hover !important;
279
+ }
280
+
281
+ i {
282
+ margin-right: $jv-space-1 !important;
283
+ }
284
+
285
+ span {
286
+ display: inline !important;
287
+ }
288
+ }
289
+
290
+ // HIDE schedule/options dropdown - not needed
291
+ [component="composer/submit/options/container"],
292
+ .dropdown-toggle {
293
+ display: none !important;
294
+ }
295
+ }
296
+
297
+ // ===========================================================
298
+ // FORMATTING BAR
299
+ // ===========================================================
300
+ html.composing .composer .formatting-bar {
301
+ display: flex !important;
302
+ align-items: center !important;
303
+ justify-content: space-between !important;
304
+ padding: $jv-space-2 $jv-space-4 !important;
305
+ background: $jv-bg !important;
306
+ border-bottom: 1px solid $jv-border-subtle !important;
307
+ margin: 0 !important;
308
+ flex-shrink: 0 !important;
309
+ gap: $jv-space-3 !important;
310
+ }
311
+
312
+ html.composing .composer .formatting-group {
313
+ display: flex !important;
314
+ align-items: center !important;
315
+ gap: 2px !important;
316
+ flex-wrap: nowrap !important;
317
+ overflow-x: auto !important;
318
+
319
+ li {
320
+ flex-shrink: 0 !important;
321
+ list-style: none !important;
322
+
323
+ .btn {
324
+ color: $jv-text-muted !important;
325
+ padding: $jv-space-2 !important;
326
+ border-radius: $jv-radius-sm !important;
327
+ min-width: 32px !important;
328
+ height: 32px !important;
329
+ display: flex !important;
330
+ align-items: center !important;
331
+ justify-content: center !important;
332
+ background: transparent !important;
333
+ border: none !important;
334
+
335
+ &:hover {
336
+ background: $jv-hover-bg !important;
337
+ color: $jv-text-main !important;
338
+ }
339
+ }
340
+ }
341
+
342
+ .spacer {
343
+ width: 1px !important;
344
+ height: 20px !important;
345
+ background: $jv-border-subtle !important;
346
+ margin: 0 $jv-space-1 !important;
347
+ }
348
+ }
349
+
350
+ // Preview/Help buttons
351
+ html.composing .composer .formatting-bar > .d-flex {
352
+ flex-shrink: 0 !important;
353
+ gap: $jv-space-2 !important;
354
+ align-items: center !important;
355
+
356
+ .draft-icon {
357
+ color: $jv-success !important;
358
+ }
359
+
360
+ [data-action="preview"],
361
+ [data-action="help"] {
362
+ color: $jv-text-muted !important;
363
+ font-size: $jv-font-size-sm !important;
364
+ padding: $jv-space-2 $jv-space-3 !important;
365
+ border-radius: $jv-radius-sm !important;
366
+ background: transparent !important;
367
+ border: none !important;
368
+
369
+ &:hover {
370
+ background: $jv-hover-bg !important;
371
+ color: $jv-text-main !important;
372
+ }
373
+ }
374
+ }
375
+
376
+ // ===========================================================
377
+ // WRITE/PREVIEW CONTAINER
378
+ // ===========================================================
379
+ html.composing .composer .write-preview-container {
380
+ flex: 1 !important;
381
+ display: flex !important;
382
+ flex-direction: row !important;
383
+ min-height: 0 !important;
384
+ overflow: hidden !important;
385
+ gap: 0 !important;
386
+ }
387
+
388
+ // Write container - OVERRIDE w-50
389
+ html.composing .composer .write-container {
390
+ flex: 1 !important;
391
+ display: flex !important;
392
+ flex-direction: column !important;
393
+ width: 100% !important;
394
+ min-width: 0 !important;
395
+ position: relative !important;
396
+
397
+ &.w-50 {
398
+ width: 100% !important;
399
+ }
400
+
401
+ .write {
402
+ flex: 1 !important;
403
+ width: 100% !important;
404
+ height: 100% !important;
405
+ min-height: 150px !important;
406
+ padding: $jv-space-4 !important;
407
+ border: none !important;
408
+ border-radius: 0 !important;
409
+ resize: none !important;
410
+ font-size: $jv-font-size-base !important;
411
+ line-height: $jv-line-height-relaxed !important;
412
+ color: $jv-text-main !important;
413
+ background: $jv-surface !important;
414
+
415
+ &::placeholder {
416
+ color: $jv-text-soft !important;
417
+ }
418
+
419
+ &:focus {
420
+ outline: none !important;
421
+ box-shadow: none !important;
422
+ }
423
+ }
424
+ }
425
+
426
+ // Preview container - toggles via d-none/d-flex classes from NodeBB JS
427
+ html.composing .composer .preview-container {
428
+ width: 100% !important;
429
+ overflow-y: auto !important;
430
+ padding: $jv-space-4 !important;
431
+ background: $jv-surface !important;
432
+ flex: 1 !important;
433
+ flex-direction: column !important;
434
+
435
+ &.w-50 {
436
+ width: 100% !important;
437
+ }
438
+
439
+ // Allow NodeBB's d-none to work (hide by default unless d-flex is added)
440
+ &.d-none {
441
+ display: none !important;
442
+ }
443
+
444
+ &:not(.d-none) {
445
+ display: flex !important;
446
+ }
447
+
448
+ .preview {
449
+ width: 100% !important;
450
+ }
451
+ }
452
+
453
+ // Write container visibility - controlled by NodeBB JS
454
+ html.composing .composer .write-container.d-none {
455
+ display: none !important;
456
+ }
457
+
458
+ html.composing .composer .write-container:not(.d-none) {
459
+ display: flex !important;
460
+ }
461
+
462
+ // ===========================================================
463
+ // FOOTER - Tags row
464
+ // ===========================================================
465
+ html.composing .composer .tag-row {
466
+ display: flex !important;
467
+ align-items: center !important;
468
+ padding: 8px 20px !important;
469
+ border-top: 1px solid $jv-border-subtle !important;
470
+ background: $jv-surface !important;
471
+ flex-shrink: 0 !important;
472
+ min-height: 56px !important;
473
+ gap: $jv-space-4 !important;
474
+ border-radius: 0 0 $jv-radius-lg $jv-radius-lg !important;
475
+ }
476
+
477
+ html.composing .composer .tags-container {
478
+ display: flex !important;
479
+ align-items: center !important;
480
+ gap: $jv-space-2 !important;
481
+ flex: 1 !important;
482
+ min-width: 0 !important;
483
+ max-width: calc(100% - 140px) !important; // Leave space for submit button
484
+ background: $jv-bg !important;
485
+ border: 1px solid $jv-border-subtle !important;
486
+ border-radius: $jv-radius-sm !important;
487
+ padding: $jv-space-1 $jv-space-3 !important;
488
+ min-height: 40px !important;
489
+ cursor: text !important;
490
+ transition: border-color 0.15s ease !important;
491
+
492
+ &:hover {
493
+ border-color: $jv-border-strong !important;
494
+ }
495
+
496
+ &:focus-within {
497
+ border-color: $jv-primary !important;
498
+ box-shadow: 0 0 0 2px rgba($jv-primary, 0.1) !important;
499
+ }
500
+
501
+ [component="composer/tag/dropdown"] {
502
+ flex-shrink: 0 !important;
503
+
504
+ .btn {
505
+ color: $jv-text-muted !important;
506
+ font-size: $jv-font-size-sm !important;
507
+ padding: $jv-space-1 $jv-space-2 !important;
508
+ border-radius: $jv-radius-xs !important;
509
+ background: transparent !important;
510
+ border: none !important;
511
+
512
+ i {
513
+ color: $jv-primary !important;
514
+ }
515
+
516
+ &:hover {
517
+ background: $jv-hover-bg !important;
518
+ }
519
+ }
520
+ }
521
+
522
+ // Wrapper that appears when tags are present
523
+ .bootstrap-tagsinput {
524
+ flex: 1 !important;
525
+ display: flex !important;
526
+ flex-wrap: wrap !important;
527
+ align-items: center !important;
528
+ gap: $jv-space-2 !important;
529
+ background: transparent !important;
530
+ border: none !important;
531
+ padding: 0 !important;
532
+ box-shadow: none !important;
533
+ min-height: auto !important;
534
+
535
+ // Individual tags - beautiful pills
536
+ .tag {
537
+ display: inline-flex !important;
538
+ align-items: center !important;
539
+ gap: 4px !important;
540
+ background: $jv-primary-soft !important;
541
+ color: $jv-primary !important;
542
+ border-radius: $jv-radius-pill !important;
543
+ padding: 4px 10px !important;
544
+ font-size: $jv-font-size-xs !important;
545
+ font-weight: 500 !important;
546
+ border: none !important;
547
+ line-height: 1.4 !important;
548
+
549
+ // Remove button inside tag
550
+ [data-role="remove"] {
551
+ margin-left: 2px !important;
552
+ cursor: pointer !important;
553
+ opacity: 0.7 !important;
554
+ font-size: 12px !important;
555
+
556
+ &:hover {
557
+ opacity: 1 !important;
558
+ }
559
+ }
560
+ }
561
+
562
+ // The input inside bootstrap-tagsinput
563
+ input {
564
+ flex: 1 !important;
565
+ min-width: 80px !important;
566
+ border: none !important;
567
+ background: transparent !important;
568
+ font-size: $jv-font-size-sm !important;
569
+ color: $jv-text-main !important;
570
+ padding: $jv-space-1 0 !important;
571
+ outline: none !important;
572
+
573
+ &::placeholder {
574
+ color: $jv-text-soft !important;
575
+ }
576
+ }
577
+ }
578
+
579
+ // Plain input when no bootstrap-tagsinput
580
+ > input.tags {
581
+ flex: 1 !important;
582
+ border: none !important;
583
+ background: transparent !important;
584
+ font-size: $jv-font-size-sm !important;
585
+ color: $jv-text-main !important;
586
+ padding: $jv-space-1 0 !important;
587
+
588
+ &::placeholder {
589
+ color: $jv-text-soft !important;
590
+ }
591
+
592
+ &:focus {
593
+ outline: none !important;
594
+ }
595
+ }
596
+ }
597
+
598
+ // ===========================================================
599
+ // IMAGE DROP ZONE
600
+ // ===========================================================
601
+ html.composing .composer .imagedrop {
602
+ position: absolute !important;
603
+ inset: 0 !important;
604
+ background: rgba($jv-primary, 0.1) !important;
605
+ border: 2px dashed $jv-primary !important;
606
+ border-radius: $jv-radius-md !important;
607
+ display: none !important;
608
+ align-items: center !important;
609
+ justify-content: center !important;
610
+ z-index: 100 !important;
611
+
612
+ > div {
613
+ background: $jv-surface !important;
614
+ padding: $jv-space-4 $jv-space-8 !important;
615
+ border-radius: $jv-radius-sm !important;
616
+ font-weight: 500 !important;
617
+ color: $jv-primary !important;
618
+ }
619
+ }
620
+
621
+ // ===========================================================
622
+ // RESIZER - HIDE
623
+ // ===========================================================
624
+ html.composing .composer .resizer {
625
+ display: none !important;
626
+ }
627
+
628
+ // ===========================================================
629
+ // DROPDOWN MENUS
630
+ // ===========================================================
631
+ html.composing .composer .dropdown-menu {
632
+ border: 1px solid $jv-border-subtle !important;
633
+ border-radius: $jv-radius-sm !important;
634
+ box-shadow: $jv-shadow-lg !important;
635
+ background: $jv-surface !important;
636
+ padding: $jv-space-2 !important;
637
+
638
+ .dropdown-item {
639
+ font-size: $jv-font-size-sm !important;
640
+ padding: $jv-space-2 $jv-space-3 !important;
641
+ border-radius: $jv-radius-xs !important;
642
+
643
+ &:hover {
644
+ background: $jv-hover-bg !important;
645
+ }
646
+ }
647
+ }
648
+
649
+ // ===========================================================
650
+ // FILE FORM - HIDE
651
+ // ===========================================================
652
+ html.composing .composer #fileForm {
653
+ display: none !important;
654
+ }
655
+
656
+ // ===========================================================
657
+ // QUICK SEARCH
658
+ // ===========================================================
659
+ html.composing .composer .quick-search-container {
660
+ position: absolute !important;
661
+ top: 100% !important;
662
+ left: 0 !important;
663
+ right: 0 !important;
664
+ background: $jv-surface !important;
665
+ border: 1px solid $jv-border-subtle !important;
666
+ border-radius: $jv-radius-sm !important;
667
+ box-shadow: $jv-shadow-lg !important;
668
+ z-index: 50 !important;
669
+ }
670
+
671
+ // ===========================================================
672
+ // REPLY MODE
673
+ // ===========================================================
674
+ html.composing .composer.reply {
675
+ height: 450px !important;
676
+
677
+ .tags-container {
678
+ display: none !important;
679
+ }
680
+ }
681
+
682
+ // ===========================================================
683
+ // MOBILE RESPONSIVE
684
+ // ===========================================================
685
+ @media (max-width: 767px) {
686
+ html.composing .composer {
687
+ top: 0 !important;
688
+ left: 0 !important;
689
+ transform: none !important;
690
+ width: 100vw !important;
691
+ max-width: 100vw !important;
692
+ height: 100vh !important;
693
+ max-height: 100vh !important;
694
+ border-radius: 0 !important;
695
+ border: none !important;
696
+ }
697
+
698
+ html.composing .composer .composer-container {
699
+ height: 100vh !important;
700
+ border-radius: 0 !important;
701
+ }
702
+
703
+ html.composing .composer .title-container {
704
+ padding: $jv-space-3 $jv-space-4 !important;
705
+ padding-top: max($jv-space-3, env(safe-area-inset-top)) !important;
706
+ border-radius: 0 !important;
707
+ }
708
+
709
+ html.composing .composer .formatting-bar {
710
+ padding: $jv-space-2 $jv-space-3 !important;
711
+ overflow-x: auto !important;
712
+
713
+ [data-action="preview"] span,
714
+ [data-action="help"] span {
715
+ display: none !important;
716
+ }
717
+ }
718
+
719
+ html.composing .composer .tag-row {
720
+ padding: $jv-space-3 $jv-space-4 !important;
721
+ padding-bottom: max($jv-space-3, env(safe-area-inset-bottom)) !important;
722
+ border-radius: 0 !important;
723
+ }
724
+ }