Make admin sub-navs, selects, buttons responsive (#2702)
[oweals/peertube.git] / client / src / sass / include / _mixins.scss
1 @import '_variables';
2
3 @mixin disable-default-a-behaviour {
4   &:hover, &:focus, &:active {
5     text-decoration: none !important;
6     outline: none !important;
7   }
8 }
9
10 @mixin disable-outline {
11   &:focus:not(.focus-visible) {
12     outline: none;
13   }
14 }
15
16 @mixin ellipsis {
17   white-space: nowrap;
18   overflow: hidden;
19   text-overflow: ellipsis;
20 }
21
22 @mixin ellipsis-multiline($font-size: 16px, $number-of-lines: 2) {
23   display: block;
24   /* Fallback for non-webkit */
25   display: -webkit-box;
26   max-height: $font-size * $number-of-lines;
27   /* Fallback for non-webkit */
28   font-size: $font-size;
29   line-height: $font-size;
30   overflow: hidden;
31   text-overflow: ellipsis;
32   /* Let space at right for dots */
33   position: relative;
34   margin-right: -1em;
35   padding-right: 1em;
36
37   /* Display dots if the max number of lines is exceeded */
38   &::before {
39     content: "...";
40     /* set position to right bottom corner of block */
41     position: absolute;
42     bottom: 0;
43     right: 0;
44   }
45
46   /* Hide dots if the max number of lines is not exceeded */
47   &:after {
48     content: '';
49     background-color: var(--mainBackgroundColor);
50     /* set position to right bottom corner of text */
51     position: absolute;
52     right: 0;
53     width: 1em;
54     height: 1em;
55     margin-top: 0.2em;
56   }
57 }
58
59 @mixin prefix($property, $parameters...) {
60   @each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
61     #{$prefix}#{$property}: $parameters;
62   }
63 }
64
65 @mixin peertube-word-wrap {
66   word-break: break-word;
67   word-wrap: break-word;
68   overflow-wrap: break-word;
69   -webkit-hyphens: auto;
70   -ms-hyphens: auto;
71   -moz-hyphens: auto;
72   hyphens: auto;
73 }
74
75 @mixin apply-svg-color ($color) {
76   ::ng-deep svg {
77     path[fill="#000000"],
78     g[fill="#000000"],
79     rect[fill="#000000"],
80     circle[fill="#000000"],
81     polygon[fill="#000000"] {
82       fill: $color;
83     }
84
85     path[stroke="#000000"],
86     g[stroke="#000000"],
87     rect[stroke="#000000"],
88     circle[stroke="#000000"],
89     polygon[stroke="#000000"] {
90       stroke: $color;
91     }
92
93     stop[stop-color="#000000"] {
94       stop-color: $color;
95     }
96   }
97 }
98
99 @mixin fill-svg-color ($color) {
100   ::ng-deep svg {
101     path {
102       fill: $color;
103     }
104   }
105 }
106
107 @mixin button-focus($color) {
108   &:focus,
109   &.focus-visible {
110     box-shadow: #{$focus-box-shadow-form} $color;
111   }
112 }
113
114 @mixin peertube-input-text($width) {
115   display: inline-block;
116   height: $button-height;
117   width: $width;
118   background: var(--inputBackgroundColor);
119   border: 1px solid #C6C6C6;
120   border-radius: 3px;
121   padding-left: 15px;
122   padding-right: 15px;
123   font-size: 15px;
124
125   &::placeholder {
126     color: var(--inputPlaceholderColor);
127   }
128
129   @media screen and (max-width: $width) {
130     width: 100%;
131   }
132 }
133
134 @mixin peertube-input-group($width) {
135   width: $width;
136   min-height: $button-height;
137   padding-top: 0;
138   padding-bottom: 0;
139
140   .input-group-text{
141     font-size: 14px;
142     color: gray;
143   }
144 }
145
146 @mixin peertube-textarea ($width, $height) {
147   @include peertube-input-text($width);
148
149   height: $height;
150   padding: 5px 15px;
151   font-size: 15px;
152 }
153
154 @mixin orange-button {
155   @include button-focus(var(--mainColorLightest));
156
157   &, &:active, &:focus {
158     color: #fff;
159     background-color: var(--mainColor);
160   }
161
162   &:hover {
163     color: #fff;
164     background-color: var(--mainHoverColor);
165   }
166
167   &[disabled], &.disabled {
168     cursor: default;
169     color: #fff;
170     background-color: #C6C6C6;
171   }
172
173   my-global-icon {
174     @include apply-svg-color(#fff)
175   }
176 }
177
178 @mixin tertiary-button {
179   @include button-focus($grey-button-outline-color);
180
181   color: $grey-foreground-color;
182   background-color: transparent;
183
184   &[disabled], &.disabled {
185     cursor: default;
186   }
187
188   my-global-icon {
189     @include apply-svg-color(transparent)
190   }
191 }
192
193 @mixin grey-button {
194   @include button-focus($grey-button-outline-color);
195
196   &, &:active, &:focus {
197     background-color: $grey-background-color;
198     color: $grey-foreground-color;
199   }
200
201   &:hover, &:active, &:focus, &[disabled], &.disabled {
202     color: $grey-foreground-color;
203     background-color: $grey-background-hover-color;
204   }
205
206   &[disabled], &.disabled {
207     cursor: default;
208   }
209
210   my-global-icon {
211     @include apply-svg-color($grey-foreground-color)
212   }
213 }
214
215 @mixin peertube-button {
216   border: none;
217   font-weight: $font-semibold;
218   font-size: 15px;
219   height: $button-height;
220   line-height: $button-height;
221   border-radius: 3px;
222   text-align: center;
223   padding: 0 17px 0 13px;
224   cursor: pointer;
225 }
226
227 @mixin peertube-button-link {
228   display: inline-block;
229
230   @include disable-default-a-behaviour;
231   @include peertube-button;
232 }
233
234 @mixin peertube-button-outline {
235   display: inline-block;
236
237   @include disable-default-a-behaviour;
238   @include peertube-button;
239
240   border: 1px solid;
241 }
242
243 @mixin button-with-icon($width: 20px, $margin-right: 3px, $top: -1px) {
244   my-global-icon {
245     position: relative;
246     width: $width;
247     margin-right: $margin-right;
248     top: $top;
249   }
250 }
251
252 @mixin peertube-button-file ($width) {
253   position: relative;
254   overflow: hidden;
255   display: inline-block;
256   width: $width;
257   min-height: 30px;
258
259   @include peertube-button;
260   @include orange-button;
261
262   input[type=file] {
263     position: absolute;
264     top: 0;
265     right: 0;
266     width: 100%;
267     height: 100%;
268     font-size: 100px;
269     text-align: right;
270     filter: alpha(opacity=0);
271     opacity: 0;
272     outline: none;
273     background: white;
274     cursor: inherit;
275     display: block;
276   }
277 }
278
279 @mixin icon ($size) {
280   display: inline-block;
281   background-repeat: no-repeat;
282   background-size: contain;
283   width: $size;
284   height: $size;
285   vertical-align: middle;
286   cursor: pointer;
287 }
288
289 @mixin select-arrow-down {
290   top: 50%;
291   right: calc(0% + 15px);
292   content: " ";
293   height: 0;
294   width: 0;
295   position: absolute;
296   pointer-events: none;
297   border: 5px solid rgba(0, 0, 0, 0);
298   border-top-color: #000;
299   margin-top: -2px;
300   z-index: 100;
301 }
302
303 @mixin peertube-select-container ($width) {
304   padding: 0;
305   margin: 0;
306   width: $width;
307   border-radius: 3px;
308   background: var(--inputBackgroundColor);
309   position: relative;
310   font-size: 15px;
311
312   &.disabled {
313     background-color: #E5E5E5;
314
315     select {
316       cursor: default;
317     }
318   }
319
320   @media screen and (max-width: $width) {
321     width: 100%;
322   }
323
324   &:after {
325     @include select-arrow-down;
326   }
327
328   select {
329     padding: 0 35px 0 12px;
330     width: calc(100% + 2px);
331     position: relative;
332     left: 1px;
333     border: 1px solid #C6C6C6;
334     background: transparent none;
335     appearance: none;
336     cursor: pointer;
337     height: $button-height;
338     text-overflow: ellipsis;
339     color: var(--mainForegroundColor);
340
341     &:focus {
342       outline: none;
343     }
344
345     &:-moz-focusring {
346       color: transparent;
347       text-shadow: 0 0 0 #000;
348     }
349
350     option {
351       color: #000;
352     }
353   }
354 }
355
356 // Thanks: https://codepen.io/triss90/pen/XNEdRe/
357 @mixin peertube-radio-container {
358   input[type="radio"] {
359     display: none;
360
361     & + label {
362       font-weight: $font-regular;
363       cursor: pointer;
364
365       &:before {
366         position: relative;
367         top: -2px;
368         content: '';
369         background: #fff;
370         border-radius: 100%;
371         border: 1px solid #000;
372         display: inline-block;
373         width: 15px;
374         height: 15px;
375         vertical-align: middle;
376         cursor: pointer;
377         text-align: center;
378         margin-right: 10px;
379       }
380     }
381
382     &:checked + label:before {
383       background-color: #000;
384       box-shadow: inset 0 0 0 4px #fff;
385     }
386
387     &:focus + label:before {
388       outline: none;
389       border-color: #000;
390     }
391   }
392 }
393
394 @mixin peertube-checkbox ($border-width) {
395   opacity: 0;
396   position: absolute;
397
398   &:focus + span {
399     box-shadow: #{$focus-box-shadow-form} var(--mainColorLightest);
400   }
401
402   & + span {
403     position: relative;
404     width: 18px;
405     min-width: 18px;
406     height: 18px;
407     border: $border-width solid #C6C6C6;
408     border-radius: 3px;
409     vertical-align: middle;
410     cursor: pointer;
411
412     &:after {
413       content: '';
414       position: absolute;
415       top: calc(2px - #{$border-width});
416       left: 5px;
417       width: 5px;
418       height: 12px;
419       opacity: 0;
420       transform: rotate(45deg) scale(0);
421       border-right: 2px solid $bg-color;
422       border-bottom: 2px solid $bg-color;
423     }
424   }
425
426   &:checked + span {
427     border-color: transparent;
428     background: var(--mainColor);
429     animation: jelly 0.6s ease;
430
431     &:after {
432       opacity: 1;
433       transform: rotate(45deg) scale(1);
434     }
435   }
436
437   & + span + span {
438     font-size: 15px;
439     font-weight: $font-regular;
440     margin-left: 5px;
441     cursor: pointer;
442     display: inline;
443   }
444
445   &[disabled] + span,
446   &[disabled] + span + span{
447     opacity: 0.5;
448     cursor: default;
449   }
450 }
451
452
453 @mixin avatar ($size) {
454   object-fit: cover;
455   border-radius: 50%;
456   width: $size;
457   height: $size;
458   min-width: $size;
459   min-height: $size;
460 }
461
462 @mixin chevron ($size, $border-width) {
463   border-style: solid;
464   border-width: $border-width $border-width 0 0;
465   content: '';
466   display: inline-block;
467   transform: rotate(-45deg);
468   height: $size;
469   width: $size;
470 }
471
472 @mixin chevron-right ($size, $border-width) {
473   @include chevron($size, $border-width);
474
475   left: 0;
476   transform: rotate(45deg);
477 }
478
479 @mixin chevron-left ($size, $border-width) {
480   @include chevron($size, $border-width);
481
482   left: 0.25em;
483   transform: rotate(-135deg);
484 }
485
486 @mixin in-content-small-title {
487   text-transform: uppercase;
488   color: var(--mainColor);
489   font-weight: $font-bold;
490   font-size: 13px;
491 }
492
493 @mixin settings-big-title {
494   text-transform: uppercase;
495   color: var(--mainColor);
496   font-weight: $font-bold;
497   font-size: 110%;
498   margin-bottom: 10px;
499 }
500
501 @mixin actor-owner {
502   @include disable-default-a-behaviour;
503
504   font-size: 13px;
505   margin-top: 4px;
506   color: var(--mainForegroundColor);
507
508   span:hover {
509     opacity: 0.8;
510   }
511
512   img {
513     @include avatar(18px);
514
515     margin-left: 7px;
516     position: relative;
517     top: -2px;
518   }
519 }
520
521 @mixin sub-menu-with-actor {
522   height: max-content;
523   display: flex;
524   flex-direction: column;
525   align-items: flex-start;
526
527   .actor {
528     display: flex;
529     margin-top: 20px;
530     margin-bottom: 20px;
531
532     img {
533       @include avatar(80px);
534
535       margin-right: 20px;
536     }
537
538     .actor-info {
539       display: flex;
540       flex-direction: column;
541       justify-content: center;
542
543       .actor-names {
544         display: flex;
545         align-items: center;
546         flex-wrap: wrap;
547
548         .actor-display-name {
549           font-size: 23px;
550           font-weight: $font-bold;
551           margin-right: 7px;
552         }
553
554         .actor-name {
555           position: relative;
556           top: 3px;
557           font-size: 14px;
558           color: $grey-actor-name;
559         }
560       }
561
562       .actor-lower {
563         grid-area: lower;
564       }
565
566       .actor-followers {
567         font-size: 15px;
568       }
569
570       .actor-owner {
571         @include actor-owner;
572       }
573     }
574   }
575
576   .links {
577     margin-top: 0;
578     margin-bottom: 15px;
579
580     a {
581       margin-top: 0;
582       margin-bottom: 0;
583       text-transform: uppercase;
584       font-weight: 600;
585       font-size: 110%;
586
587       @media screen and (max-width: $mobile-view) {
588         font-size: 130%;
589       }
590     }
591   }
592 }
593
594 @mixin create-button {
595   @include peertube-button-link;
596   @include orange-button;
597   @include button-with-icon(20px, 5px, -1px);
598 }
599
600 @mixin row-blocks {
601   display: flex;
602   min-height: 130px;
603   padding-bottom: 20px;
604   margin-bottom: 20px;
605   border-bottom: 1px solid #C6C6C6;
606
607   @media screen and (max-width: 800px) {
608     flex-direction: column;
609     height: auto;
610     align-items: center;
611   }
612 }
613
614 @mixin dropdown-with-icon-item {
615   padding: 6px 15px;
616
617   my-global-icon {
618     width: 22px;
619     opacity: .7;
620
621     margin-right: 10px;
622     position: relative;
623     top: -2px;
624   }
625 }
626
627 @mixin progressbar {
628   background-color: $grey-background-color;
629   display: flex;
630   height: 1rem;
631   overflow: hidden;
632   font-size: 0.75rem;
633   border-radius: 0.25rem;
634
635   .progress-bar {
636     color: var(--mainBackgroundColor);
637     background-color: var(--mainColor);
638     display: flex;
639     flex-direction: column;
640     justify-content: center;
641     text-align: center;
642     white-space: nowrap;
643     transition: width 0.6s ease;
644
645     &.secondary {
646       background-color: var(--secondaryColor);
647     }
648   }
649 }
650
651 @mixin breadcrumb {
652   display: flex;
653   flex-wrap: wrap;
654   padding: 0.75rem 1rem;
655   margin-bottom: 1rem;
656   list-style: none;
657   background-color: var(--submenuColor);
658   border-radius: 0.25rem;
659
660   .breadcrumb-item {
661     display: flex;
662
663     a {
664       color: var(--mainColor);
665     }
666
667     & + .breadcrumb-item {
668       padding-left: 0.5rem;
669       &::before {
670         display: inline-block;
671         padding-right: 0.5rem;
672         color: #6c757d;
673         content: "/";
674       }
675     }
676
677     &.active {
678       color: #6c757d;
679     }
680   }
681 }
682
683 @mixin dashboard {
684   display: flex;
685   flex-wrap: wrap;
686   margin: 0 -5px;
687
688   & > div {
689     box-sizing: border-box;
690     flex: 0 0 percentage(1/3);
691     padding: 0 5px;
692     margin-bottom: 10px;
693
694     & > a {
695       text-decoration: none;
696       color: inherit;
697       display: block;
698       font-size: 18px;
699
700       &:active,
701       &:focus,
702       &:hover {
703         opacity: .8;
704       }
705     }
706
707     & > a,
708     & > div {
709       padding: 20px;
710       background: var(--submenuColor);
711       border-radius: 4px;
712       box-sizing: border-box;
713       height: 100%;
714     }
715   }
716
717   .dashboard-num, .dashboard-text {
718     text-align: center;
719     font-size: 130%;
720     line-height: 21px;
721     color: var(--mainForegroundColor);
722     line-height: 30px;
723     margin-bottom: 20px;
724   }
725
726   .dashboard-label {
727     font-size: 90%;
728     color: var(--inputPlaceholderColor);
729     text-align: center;
730   }
731 }
732
733 @mixin ng2-tags {
734   ::ng-deep {
735     .ng2-tag-input {
736       border: none !important;
737     }
738
739     .ng2-tags-container {
740       display: flex;
741       align-items: center;
742       border: 1px solid #C6C6C6;
743       border-radius: 3px;
744       padding: 5px !important;
745       height: max-content;
746
747       &:focus-within {
748         box-shadow: #{$focus-box-shadow-form} var(--mainColorLightest);
749       }
750     }
751
752     tag-input-form {
753       input {
754         height: 30px !important;
755         font-size: 12px !important;
756
757         background-color: var(--mainBackgroundColor) !important;
758         color: var(--mainForegroundColor) !important;
759       }
760     }
761
762     tag {
763       background-color: $grey-background-color !important;
764       color: #000 !important;
765       border-radius: 3px !important;
766       font-size: 12px !important;
767       height: 30px !important;
768       line-height: 30px !important;
769       margin: 0 5px 0 0 !important;
770       cursor: default !important;
771       padding: 0 8px 0 10px !important;
772
773       div {
774         height: 100% !important;
775       }
776     }
777
778     delete-icon {
779       cursor: pointer !important;
780       height: auto !important;
781       vertical-align: middle !important;
782       padding-left: 6px !important;
783
784       svg {
785         position: relative;
786         top: -1px;
787         height: auto !important;
788         vertical-align: middle !important;
789
790         path  {
791           fill: $grey-foreground-color !important;
792         }
793       }
794
795       &:hover {
796         transform: none !important;
797       }
798     }
799   }
800 }
801
802 @mixin divider($color: var(--submenuColor), $background: var(--mainBackgroundColor)) {
803   width: 95%;
804   border-top: .05rem solid $color;
805   height: .05rem;
806   text-align: center;
807   display: block;
808   position: relative;
809
810   &[data-content] {
811     margin: .8rem 0;
812
813     &::after {
814       background: $background;
815       color: $color;
816       content: attr(data-content);
817       display: inline-block;
818       font-size: .7rem;
819       padding: 0 .4rem;
820       transform: translateY(-.65rem);
821     }
822   }
823 }
824
825 @mixin chip {
826   $avatar-height: 1.2rem;
827
828   align-items: center;
829   border-radius: 5rem;
830   display: inline-flex;
831   font-size: 90%;
832   color: var(--mainForegroundColor);
833   height: $avatar-height;
834   line-height: .8rem;
835   margin: .1rem;
836   max-width: 320px;
837   overflow: hidden;
838   padding: .2rem .4rem;
839   text-decoration: none;
840   text-overflow: ellipsis;
841   vertical-align: middle;
842   white-space: nowrap;
843
844   .avatar {
845     margin-left: -.4rem;
846     margin-right: .2rem;
847     height: $avatar-height;
848     width: $avatar-height;
849
850     border-radius: 50%;
851     display: inline-block;
852     line-height: 1.25;
853     position: relative;
854     vertical-align: middle;
855   }
856
857   &.two-lines {
858     $avatar-height: 1.8rem;
859
860     height: $avatar-height;
861
862     .avatar {
863       height: $avatar-height;
864       width: $avatar-height;
865     }
866
867     div {
868       display: flex;
869       flex-direction: column;
870       font-size: 80%;
871       height: $avatar-height;
872       margin-left: .1rem;
873       margin-right: .1rem;
874       justify-content: center;
875     }
876   }
877 }
878
879 @mixin admin-sub-header-responsive ($horizontal-margins) {
880   flex-direction: column;
881
882   .form-sub-title {
883     margin-right: 0px !important;
884     margin-bottom: 10px;
885     text-align: center;
886   }
887
888   .admin-sub-nav {
889     display: block;
890     overflow-x: auto;
891     white-space: nowrap;
892     height: 50px;
893     padding: 10px 0;
894     width: calc(100vw - #{$horizontal-margins*2});
895
896     a {
897       margin-left: 5px;
898     }
899   }
900 }