]> git.openstreetmap.org Git - rails.git/blob - app/assets/stylesheets/common.scss
Merge remote-tracking branch 'upstream/pull/5951'
[rails.git] / app / assets / stylesheets / common.scss
1 @use "sass:map";
2 @import "parameters";
3 @import "bootstrap";
4 @import "rails_bootstrap_forms";
5
6 /* Styles common to large and small screens */
7
8 /* Default rules for the body of every page */
9
10 body {
11   font-size: $typeheight;
12   --dark-mode-map-filter: none;
13 }
14
15 time[title] {
16   text-decoration: underline dotted;
17 }
18
19 /* Rules for icons */
20
21 .icon {
22   display: inline-block;
23   vertical-align: top;
24   width: 20px;
25   height: 20px;
26   background: transparent image-url("sprite.svg") no-repeat 0 0;
27   text-indent: -9999px;
28   overflow: hidden;
29 }
30
31 .icon.search      { /*rtl:ignore*/ background-position: 0 0; }
32 .icon.donate      { /*rtl:ignore*/ background-position: -20px 0; }
33 .icon.zoomin      { /*rtl:ignore*/ background-position: -40px 0; }
34 .icon.zoomout     { /*rtl:ignore*/ background-position: -60px 0; }
35 .icon.geolocate   { /*rtl:ignore*/ background-position: -80px 0; }
36 .active .icon.geolocate   { /*rtl:ignore*/ background-position: -80px -20px; }
37 .icon.layers      { /*rtl:ignore*/ background-position: -100px 0; }
38 .icon.key         { /*rtl:ignore*/ background-position: -120px 0; }
39 .icon.share       { /*rtl:ignore*/ background-position: -140px 0; }
40 .icon.clipboard   { /*rtl:ignore*/ background-position: -160px 0; }
41 .icon.link        { /*rtl:ignore*/ background-position: -180px 0; }
42 .icon.close       { /*rtl:ignore*/ background-position: -200px 0; }
43 .icon.close:hover { /*rtl:ignore*/ background-position: -200px -20px; }
44 .icon.check       { /*rtl:ignore*/ background-position: -220px 0; }
45 .icon.note        { /*rtl:ignore*/ background-position: -240px 0; }
46 .icon.note.grey   { /*rtl:ignore*/ background-position: -240px -20px; }
47 .icon.query       { /*rtl:ignore*/ background-position: -260px 0; }
48
49 /* Utility for de-emphasizing content */
50
51 .text-body-secondary a {
52   color: $blue;
53 }
54
55 /* Bootstrap contextual table classes overrides in dark mode */
56
57 @include color-mode(dark) {
58   .table-primary {
59     --bs-table-bg: rgb(var(--bs-primary-rgb), .25);
60   }
61   .table-secondary {
62     --bs-table-bg: rgb(var(--bs-secondary-rgb), .25);
63   }
64   .table-success {
65     --bs-table-bg: rgb(var(--bs-success-rgb), .25);
66   }
67   .table-primary, .table-secondary, .table-success {
68     --bs-table-color: initial;
69     border-color: inherit;
70   }
71 }
72
73 /* Utility for delayed loading spinner */
74
75 .delayed-fade-in {
76   animation: 300ms linear forwards delayed-fade-in;
77 }
78
79 @keyframes delayed-fade-in {
80   0%   { opacity: 0 }
81   66%  { opacity: 0 }
82   100% { opacity: 1 }
83 }
84
85 /* Rules for the header */
86
87 #menu-icon {
88   display: none;
89   position: absolute;
90   top: 0;
91   right: 0;
92   background: image-url("menu-icon.svg") no-repeat;
93   background-size: 30px 30px;
94   width: 30px;
95   height: 30px;
96   margin: 14px 10px 0 0;
97   opacity: 0.6;
98 }
99
100 @include color-mode(dark) {
101   #menu-icon {
102     filter: invert(1);
103   }
104 }
105
106 header {
107   height: $headerHeight;
108   position: relative;
109   font-size: 14px;
110
111   > * {
112     padding: $lineheight * 0.5;
113   }
114
115   h1 {
116     height: $headerHeight;
117     font-size: 18px;
118   }
119
120   .btn {
121     font-size: 14px;
122   }
123
124   .username {
125     max-width: 12em;
126   }
127 }
128
129 nav.primary {
130   #edit_tab .btn-outline-primary {
131     @include button-outline-variant($green, $color-hover: $white, $active-color: $white);
132   }
133
134   .disabled {
135     .btn-outline-primary {
136       color: $grey;
137       cursor: default;
138
139       .caret {
140         border-top-color: $grey;
141       }
142
143       &:hover {
144         background-color: lighten($green, 30%);
145       }
146     }
147   }
148
149   // Small tweaks to the toggle to stop the primary colour showing through
150   // when the menu is shown
151   .show > .btn-outline-primary.dropdown-toggle {
152     background-color: $green;
153     border-color: $green;
154
155     &:focus {
156       box-shadow: 0 0 0 0.2rem fade-out($green, 0.5);
157     }
158   }
159 }
160
161 nav.secondary {
162   .nav-link {
163     padding: 0 0.3rem;
164   }
165
166   > ul {
167     height: 1.5em;
168   }
169 }
170
171 nav.primary, nav.secondary {
172   .dropdown-item {
173     &:hover, &:active {
174       background-color: $green;
175       color: white;
176     }
177   }
178 }
179
180 #compact-secondary-nav {
181   display: none;
182 }
183
184 body.small-nav {
185   #menu-icon {
186     display: block;
187   }
188
189   header {
190     flex-direction: column;
191     height: auto;
192     min-height: $headerHeight;
193
194     &.closed nav {
195       display: none !important;
196     }
197
198     .search_forms {
199       display: block;
200     }
201
202     .username {
203       max-width: unset;
204     }
205   }
206
207   #sidebar .search_forms {
208     display: none;
209   }
210
211   nav.primary {
212     margin-right: 0;
213     padding: 0;
214
215     #edit_tab {
216       width: 100%;
217       padding: 10px;
218     }
219   }
220
221   nav.secondary {
222     flex-direction: column;
223
224     > ul {
225       height: auto;
226       justify-content: center;
227     }
228
229     .user-menu, .login-menu {
230       width: 100%;
231     }
232   }
233
234   #compact-secondary-nav {
235     display: none;
236   }
237
238   .compact-hide {
239     display: inline-block;
240   }
241
242   .overlay-sidebar #sidebar .welcome {
243     display: none;
244   }
245
246   .overlay-sidebar #sidebar #banner {
247     display: none;
248   }
249 }
250
251 /* Utility for styling notification numbers */
252
253 .count-number {
254   background: transparentize(lighten($green, 25%), .25);
255   color: $gray-800;
256   font-weight: $font-weight-normal;
257 }
258
259 /* Rules for Leaflet maps */
260
261 .leaflet-top.leaflet-right,
262 .leaflet-top.leaflet-left {
263   height: 100%;
264   column-gap: 10px;
265   display: flex;
266   flex-direction: column;
267   flex-wrap: wrap-reverse;
268 }
269
270 .leaflet-control .control-button {
271   display: block;
272   height: 40px;
273   width: 40px;
274   background-color: #333;
275   background-color: rgba(0,0,0,.6);
276   outline: none;
277
278   &:hover,
279   &:focus {
280     background-color: black;
281   }
282
283   &.disabled,
284   &.leaflet-disabled {
285     background-color: #333;
286     background-color: rgba(0,0,0,.5);
287     cursor: default;
288   }
289
290   &.active {
291     background-color: $vibrant-green;
292   }
293
294   &-first {
295     border-start-start-radius: 4px;
296   }
297
298   &-last {
299     border-end-start-radius: 4px;
300     margin-bottom: 10px;
301   }
302
303   .icon {
304     margin: 10px;
305   }
306 }
307
308 /* Rules for the sidebar and main map area */
309
310 .map-layout {
311   #content {
312     overflow: hidden;
313     position: absolute;
314     top: $headerHeight;
315     bottom: 0;
316     width: 100%;
317   }
318
319   #sidebar, #map {
320     position: relative;
321     height: 100%;
322     overflow-x: hidden;
323     overflow-y: auto;
324   }
325
326   #sidebar {
327     float: left;
328     width: $sidebarWidth;
329   }
330
331   .overlay-sidebar #sidebar {
332     position: absolute;
333     height: auto;
334     overflow: hidden;
335
336     #banner {
337       display: block;
338     }
339
340     .welcome {
341       display: block;
342     }
343
344     .sidebar-close-controls,
345     #sidebar_loader,
346     #sidebar_content {
347       display: none;
348     }
349   }
350
351   .welcome {
352     display: none;
353   }
354
355   #banner {
356     display: none;
357
358     img {
359       display: block;
360       width: $sidebarWidth;
361     }
362   }
363
364   #map {
365     height: 100%;
366     overflow: hidden;
367
368     &.query-active {
369       cursor: help;
370     }
371
372     &.query-disabled {
373       cursor: not-allowed;
374     }
375
376     .leaflet-marker-draggable {
377       cursor: move;
378     }
379
380     .query-marker {
381       animation: 1500ms forwards query-marker-fade;
382
383       @keyframes query-marker-fade {
384         to { opacity: 0 }
385       }
386     }
387   }
388
389   #map-ui {
390     display: none;
391     position: relative;
392     float: right;
393     width: 250px;
394     height: 100%;
395     overflow: auto;
396   }
397 }
398
399 @include media-breakpoint-down(md) {
400   body.map-layout {
401     #sidebar, #map {
402       position: relative;
403       overflow-x: hidden;
404       width: 100%;
405       height: 50%;
406     }
407
408     #map-ui {
409       width: 100%;
410       height: 50%;
411       overflow-y: scroll;
412     }
413
414     .overlay-sidebar.overlay-right-sidebar {
415       #sidebar {
416         position: absolute;
417         width: 350px;
418         height: auto;
419         overflow: hidden;
420       }
421
422       #map {
423         height: 100%;
424       }
425     }
426   }
427 }
428
429 .layers-ui {
430   .base-layers > * {
431     height: 3.5rem;
432
433     > .btn {
434       box-sizing: content-box;
435       top: - map.get($border-widths, 4);
436       left: - map.get($border-widths, 4);
437       --bs-btn-border-color: var(--bs-body-bg);
438     }
439     > .btn:hover {
440       --bs-btn-border-color: var(--bs-primary-border-subtle);
441     }
442   }
443
444   .overlay-layers {
445     li.disabled { color: $darkgrey; }
446   }
447 }
448
449 .share-ui {
450   #mapnik_scale {
451     width: 100px;
452   }
453 }
454
455 .leaflet-top {
456   top: 10px !important;
457   .leaflet-control {
458     margin-right: 0px !important;
459     margin-top: 0px !important;
460   }
461 }
462
463 .leaflet-popup-scrolled {
464   padding-right: $lineheight;
465   border-bottom: 0px !important;
466   border-top: 0px !important;
467 }
468
469 .leaflet-popup-content-wrapper, .leaflet-popup-tip,
470 .leaflet-contextmenu, .leaflet-contextmenu-item,
471 .leaflet-control-attribution, .leaflet-control-scale-line {
472   @extend .bg-body, .text-body;
473 }
474
475 .leaflet-control-attribution, .leaflet-control-scale-line {
476   @extend .bg-opacity-75;
477   text-shadow: none !important;
478 }
479
480 .leaflet-contextmenu-item.over {
481   @extend .bg-body-secondary, .border-secondary, .border-opacity-10;
482 }
483
484 .leaflet-popup-content-wrapper {
485   @extend .rounded-1;
486
487   a {
488     color: var(--bs-link-color) !important;
489   }
490 }
491
492 @include color-mode(dark) {
493   .leaflet-container .leaflet-control-attribution a {
494     color: var(--bs-link-color);
495   }
496
497   .leaflet-control-scale-line {
498     border-color: rgba(var(--bs-light-rgb), .75) !important;
499   }
500 }
501
502 @mixin dark-map-color-scheme {
503   .leaflet-tile-container,
504   .mapkey-table-entry td:first-child > * {
505     filter: var(--dark-mode-map-filter);
506   }
507
508   .leaflet-tile-container .leaflet-tile {
509     filter: none;
510   }
511 }
512
513 body[data-map-theme="dark"] {
514   @include dark-map-color-scheme;
515 }
516
517 @include color-mode(dark) {
518   body:not([data-map-theme]) {
519     @include dark-map-color-scheme;
520   }
521 }
522
523 /* Rules for attribution text under the main map shown on printouts */
524
525 .donate-attr { color: darken($green, 10%) !important; }
526
527 /* Temporary label size override until we remove site-wide font customisation */
528
529 form {
530   label {
531     font-size: 16px;
532   }
533   .col-form-label {
534     font-size: 16px;
535   }
536 }
537
538 /* Stop bootstrap 5 from floating legends when they don't need to be */
539 legend {
540   float: none;
541 }
542
543 /* Override the text colour for primary and secondary buttons, to match our
544    bootstrap 4 colours. Note this has accessibility issues, which is why
545    bootstrap 5 calculates black as the appropriate colour, and we should
546    reconsider our colours at some point with that in mind. */
547
548 .btn-primary {
549   @include button-variant($primary, $primary, $color: $white, $hover-color: $white, $active-color: $white, $disabled-color: $white);
550 }
551
552 .btn-secondary {
553   @include button-variant($secondary, $secondary, $color: $white, $hover-color: $white, $active-color: $white, $disabled-color: $white);
554 }
555
556 .btn-outline-secondary {
557   @include button-outline-variant($secondary, $color-hover: $white, $active-color: $white);
558 }
559
560 /* Rules for the search and direction forms */
561
562 header .search_forms,
563 .directions_form {
564   display: none;
565 }
566
567 .search_form {
568   .describe_location {
569     font-size: 10px;
570   }
571 }
572
573 /* Rules for routing */
574
575 td.distance {
576     font-size: x-small;
577 }
578 tr.turn {
579     cursor: pointer;
580 }
581
582 .routing_marker_column {
583   margin-left: .35rem;
584   margin-right: .35rem;
585   width: 15px;
586
587   img {
588     cursor: move;
589   }
590 }
591
592 /* Rules for the history sidebar */
593
594 .changeset-above-sidebar-viewport {
595   --changeset-border-color: #CC7755;
596   --changeset-fill-color: #888888;
597 }
598 .changeset-in-sidebar-viewport {
599   --changeset-border-color: #FF9500;
600   &.changeset-highlighted {
601     --changeset-border-color: #FF6600;
602   }
603   --changeset-fill-color: #FFFFAF;
604 }
605 .changeset-below-sidebar-viewport {
606   --changeset-border-color: #8888AA;
607   --changeset-fill-color: #888888;
608 }
609
610 #sidebar .changesets {
611   .changeset-color-hint-bar {
612     height: 2px;
613     background: var(--changeset-border-color);
614   }
615
616   li {
617     &.selected {
618       @extend :hover;
619     }
620
621     a.stretched-link > span, a:not(.stretched-link), [title] {
622       position: relative;
623       z-index: 2; /* needs to be higher than Bootstrap's stretched link ::after z-index */
624     }
625   }
626 }
627
628 /* Rules for the browse sidebar */
629
630 #sidebar_content {
631   .browse-section {
632     padding-bottom: $spacer;
633     margin-bottom: $spacer;
634     border-bottom: 1px solid $grey;
635
636     h4:first-child {
637       word-wrap: break-word;
638     }
639   }
640
641   .browse-section:last-of-type {
642     border-bottom: none;
643   }
644
645   .browse-tag-list {
646     table-layout: fixed;
647     white-space: pre-wrap;
648     word-wrap: break-word;
649     word-break: break-word;
650
651     tr:last-child th, tr:last-child td {
652       border-bottom: 0;
653     }
654   }
655
656   .query-results {
657     display: none;
658   }
659 }
660
661 /* Force LTR/RTL alignment for placeholder text */
662
663 .form-control::placeholder {
664   text-align: left;
665 }
666
667 /* Rules for export sidebar */
668
669 .export_form {
670   .export_area_inputs {
671     input[type="text"] {
672       width: 100px;
673     }
674   }
675
676   .export_boxy {
677     > * {
678         margin: -1px;
679     }
680   }
681 }
682
683 /* Rules for edit pages */
684
685 .site-edit {
686   #content {
687     position: absolute;
688     top: $headerHeight;
689     bottom: 0;
690     width: 100%;
691   }
692 }
693
694 /* Rules for non-map content pages */
695
696 .content-inner {
697   max-width: 960px;
698   padding: $lineheight;
699 }
700
701 /* Rules for login and signup pages */
702
703 .sessions-new, .users-new, .users-create {
704   #content .content-inner {
705     max-width: 760px;
706   }
707 }
708
709 .header-illustration {
710   background-position: right;
711   background-repeat: no-repeat;
712   position: relative;
713   min-height: 200px;
714   width: 100%;
715   left: 0;
716   bottom: 0;
717
718   &.new-user-main {
719     background-image: image-url("sign-up-illustration.svg");
720     background-position-x: 70px;
721   }
722
723   &.confirm-main {
724     background-image: image-url("confirm-illustration.svg");
725   }
726
727   &.new-user-terms {
728     background-image: image-url("terms-illustration.svg");
729   }
730 }
731
732 [dir=rtl] .header-illustration {
733   transform: scaleX(-1);
734
735   h1 {
736     transform: scaleX(-1);
737   }
738
739   ul {
740     transform: scaleX(-1);
741   }
742 }
743
744 /* Rules for small maps in content areas */
745
746 .content_map {
747   height: 200px;
748   margin-bottom: $lineheight;
749 }
750
751 @include media-breakpoint-up(md) {
752   .content_map {
753     height: 400px;
754   }
755 }
756
757 /* Rules for the user map */
758
759 .content_map .leaflet-popup-content {
760   margin: $spacer;
761   min-height: 50px;
762 }
763
764 /* Rules for user popups on maps */
765
766 .user_popup {
767   p {
768     padding: 0 0 5px 0;
769     margin: 0 0 0 60px;
770     font-size: 12px;
771   }
772 }
773
774 /* Rules for the diary entry page */
775
776 .diary_entries {
777   #map {
778     height: 400px;
779     display: none;
780   }
781   .diary-comment .col-auto {
782     width: 62px;
783   }
784   .diary-comment .col {
785     max-width: 690px;
786   }
787 }
788
789 /* Rules for the issues page */
790
791 .issues.issues-index {
792   td.reporting_users {
793     max-width: 5rem;
794   }
795 }
796
797 /* Rules for the account confirmation page */
798
799 .accounts-terms-show {
800   .legale {
801     padding: $lineheight;
802     margin-bottom: $lineheight;
803     overflow: auto;
804     height: 20em;
805
806     li {
807       list-style: inherit;
808     }
809
810     ol ol {
811       list-style-type: lower-alpha;
812     }
813   }
814 }
815
816 /* Rules for user images */
817
818 img.user_image {
819   max-width: 100px;
820   max-height: 100px;
821 }
822
823 img.user_thumbnail {
824   max-width: 50px;
825   max-height: 50px;
826 }
827
828 img.user_thumbnail_tiny {
829   width: 25px;
830   height: 25px;
831   object-fit: contain;
832 }
833
834 /* General styles for action lists / subnavs */
835
836 nav.secondary-actions {
837   margin-left: -11px;
838   overflow: hidden;
839   > ul {
840     display: flex;
841     flex-direction: row;
842     flex-wrap: wrap;
843     margin-bottom: 0;
844     margin-left: -1px;
845     padding: 0;
846     > li {
847       flex-basis: auto;
848       list-style: none;
849       border-left: 1px solid $grey;
850       padding-left: $lineheight * 0.5;
851       margin-right: $lineheight * 0.5;
852       margin-bottom: $lineheight * 0.125;
853     }
854   }
855 }
856
857 div.secondary-actions {
858   padding: 10px;
859   text-align: center;
860 }
861
862 /* Rules for rich text */
863
864 .richtext {
865   code {
866     background: var(--bs-secondary-bg);
867     padding: 2px 3px;
868   }
869
870   pre {
871     background: var(--bs-secondary-bg);
872     padding: 2px 3px;
873     white-space: pre-wrap;
874
875     code {
876       padding: 0;
877     }
878   }
879
880   img {
881     padding: $lineheight;
882     background-color: var(--bs-tertiary-bg);
883     display: block;
884     max-width: 100%;
885     margin: auto;
886   }
887
888   blockquote {
889     border-left: $lineheight solid var(--bs-tertiary-bg);
890     padding-left: $lineheight;
891     margin: 0;
892     color: var(--bs-secondary-color);
893   }
894 }
895
896 /* Rules for the "About" page */
897
898 .site-about #content {
899   .content-inner {
900     max-width: 760px;
901   }
902
903   .attr {
904     margin-top: -20px;
905
906     h1 {
907       span {
908         color: $vibrant-green;
909       }
910     }
911
912     .user-image {
913       height: 150px;
914       background-position: 0 50%;
915       background-repeat: no-repeat;
916       background-image: image-url('about/osm.png');
917       background-size: cover;
918       background-color: $vibrant-green;
919     }
920
921     .byosm {
922       background: $vibrant-green;
923     }
924
925     .byosm span {
926       display: inline-block;
927       width: 1em;
928       margin-left: -1em;
929     }
930   }
931 }
932
933 /* Rules for tables with usernames */
934
935 .messages-table .username,
936 #block_list .username {
937   max-width: 20em;
938 }
939
940 /* Rules for navigation tabs */
941
942 .nav-tabs .username {
943   max-width: 20em;
944 }
945
946 .bg-body-secondary .nav-tabs {
947   --bs-border-color: var(--bs-secondary-border-subtle);
948   --bs-secondary-bg: var(--bs-secondary-border-subtle);
949   margin-bottom: -1px;
950 }
951
952 /* Rules for traces */
953
954 img.trace_image {
955   mix-blend-mode: darken;
956 }
957
958 @include color-mode(dark) {
959   img.trace_image {
960     filter: invert(1);
961     mix-blend-mode: lighten;
962   }
963 }
964
965 /* Rules for map sidebar icons */
966
967 .browse-section .browse-element-list {
968   line-height: 1.25rem;
969
970   .browse-icon {
971     height: 1.25rem;
972   }
973
974   .d-flex > .browse-icon {
975     height: max(20px, 1.25rem);
976   }
977
978   @include color-mode(dark) {
979     .browse-icon-invertible {
980       filter: invert(.8) hue-rotate(180deg);
981     }
982   }
983 }
984
985 .heatmap-wrapper {
986   height: 130px;
987 }