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