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