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