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