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