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