forked from MapComplete/MapComplete
		
	Usersettings: use a collapsable dropdown, introduce dropdown special visualisation
This commit is contained in:
		
							parent
							
								
									1f9ef8158b
								
							
						
					
					
						commit
						8e98502960
					
				
					 14 changed files with 319 additions and 257 deletions
				
			
		|  | @ -34,11 +34,187 @@ | |||
|   "lineRendering": null, | ||||
|   "tagRenderings": [ | ||||
|     { | ||||
|       "id": "profile", | ||||
|       "id": "profile-group", | ||||
|       "render": { | ||||
|         "*": "{user_profile()}" | ||||
|         "special": { | ||||
|           "type": "group", | ||||
|           "header": "profile-title", | ||||
|           "labels": "profile-content" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "id": "profile-title", | ||||
|       "labels": ["hidden"], | ||||
|       "icon": "user_circle", | ||||
|       "render": { | ||||
|         "*": "<h3>{_name}</h3>" | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_img!=", | ||||
|           "#": "ignore-image-in-then", | ||||
|           "then": { | ||||
|             "*": "<div class='flex'><img src={_img} class='w-12 h-12 rounded-full' style='margin-right: 0.75rem'/> <h3>{_name}</h3></div>" | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "profile-description", | ||||
|       "labels": [ | ||||
|         "profile-content","hidden" | ||||
|       ], | ||||
|       "render": { | ||||
|         "*": "{_description_html}" | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_description=", | ||||
| 
 | ||||
|           "then": { | ||||
|             "special": { | ||||
|               "type": "link", | ||||
|               "class": "button link-no-underline", | ||||
|               "icon": "pencil", | ||||
|               "href": "{_backend}/profile/edit", | ||||
|               "text": { | ||||
|                 "ca": "Afegeix una descripció del perfil", | ||||
|                 "cs": "Přidat popis profilu", | ||||
|                 "de": "Profilbeschreibung hinzufügen", | ||||
|                 "en": "Add a profile description", | ||||
|                 "fi": "Lisää profiilin kuvaus", | ||||
|                 "nb_NO": "Legg til profilbeskrivelse", | ||||
|                 "nl": "Voeg een profielbeschrijving toe", | ||||
|                 "pl": "Dodaj opis profilu", | ||||
|                 "pt": "Adicionar uma descrição do perfil", | ||||
|                 "zh_Hant": "新增個人檔敘述" | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "edit-profile", | ||||
|       "labels": [ | ||||
|         "profile-content","hidden" | ||||
|       ], | ||||
|       "condition": "_description!=", | ||||
|       "render": { | ||||
|         "special": { | ||||
|           "type": "link", | ||||
|           "href": "{_backend}/profile/edit", | ||||
|           "class": "button link-no-underline", | ||||
|           "icon": "pencil", | ||||
|           "text": { | ||||
|             "ca": "Editeu la descripció del vostre perfil", | ||||
|             "cs": "Úprava popisu vašeho profilu", | ||||
|             "da": "Ret din profilbeskrivelse", | ||||
|             "de": "Eigene Profilbeschreibung bearbeiten", | ||||
|             "en": "Edit your profile description", | ||||
|             "fi": "Muokkaa profiilin kuvausta", | ||||
|             "fr": "Modifier ton profil", | ||||
|             "nl": "Pas je profielbeschrijving aan", | ||||
|             "pl": "Edytuj opis swojego profilu", | ||||
|             "pt": "Editar a descrição do seu perfil", | ||||
|             "zh_Hant": "編輯你的個人檔敘述" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "id": "verified-mastodon", | ||||
|       "labels": [ | ||||
|         "profile-content","hidden" | ||||
|       ], | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_mastodon_link~*", | ||||
|           "then": { | ||||
|             "en": "A link to your Mastodon-profile has been been found: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "de": "Es wurde ein Link zu deinem Mastodon-Profil gefunden: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "nl": "Een link naar je Mastodon-profiel werd gevonden: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "fr": "Un lien vers votre profil Mastodon a été trouvé : <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "ca": "S'ha trobat un enllaç al vostre perfil de Mastodon: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "cs": "Byl nalezen odkaz na váš profil Mastodon: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>" | ||||
|           }, | ||||
|           "icon": "mastodon" | ||||
|         }, | ||||
|         { | ||||
|           "if": "_mastodon_candidate~*", | ||||
|           "then": { | ||||
|             "en": "We found a link to what looks to be a mastodon account, but it is unverified. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Edit your profile description</a> and place the following there: <span class='code'><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "de": "Wir haben einen Link gefunden, der aussieht wie ein Mastodon-Konto, aber nicht verifiziert ist. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Bearbeiten Sie Ihre Profilbeschreibung</a> und fügen Sie dort Folgendes ein: <span class='code'><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "nl": "Je profielbeschrijving bevat een link die vermoedelijk naar je Mastodon gaat, maar deze link is niet verifieerdbaar voor Mastodon.<a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Pas je profielbeschrijving aan</a> en plaats er de volgende code: <span class='code'><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "ca": "Hem trobat un enllaç al que sembla ser un compte de mastodon, però no està verificat. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Editeu la descripció del vostre perfil</a> i col·loqueu-hi el següent: <span class='code '><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "cs": "Našli jsme odkaz na to, co vypadá jako účet mastodon, ale je neověřený. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Upravte popis svého profilu</a> a umístěte tam následující: <span class='code '><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" | ||||
|           }, | ||||
|           "icon": "invalid" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "cscount-thanks", | ||||
|       "labels": [ | ||||
|         "profile-content","hidden" | ||||
|       ], | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_csCount>0", | ||||
|           "then": { | ||||
|             "en": "You have made changes on {_csCount} different occasions! That is awesome!", | ||||
|             "de": "Sie haben bei {_csCount} verschiedenen Gelegenheiten Änderungen vorgenommen! Das ist großartig!", | ||||
|             "ca": "Has fet {_csCount} en diferents ocasions! Això és sorprenent!", | ||||
|             "fr": "Vous avez fait {_csCount} modifications ! C'est génial !", | ||||
|             "pt": "Você fez alterações em {_csCount} ocasiões diferentes! Isso é incrível!", | ||||
|             "nl": "Je hebt {_csCount} verschillende keren bijgedragen! Dat is indrukwekkend!", | ||||
|             "da": "Du har lavet ændringer ved {_csCount} forskellige begivenheder! Det er fantastisk!", | ||||
|             "es": "Has hecho cambios en {_csCount} ocasiones diferentes. ¡Es alucinante!", | ||||
|             "cs": "Změny jste provedli při {_csCount} různých příležitostech! To je úžasné!" | ||||
|           }, | ||||
|           "icon": "party" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "translation-thanks", | ||||
|       "labels": [ | ||||
|         "profile-content","hidden" | ||||
|       ], | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_translation_contributions>0", | ||||
|           "then": { | ||||
|             "en": "You have contributed to translating MapComplete with {_translation_contributions} commits! That's awesome!", | ||||
|             "nl": "Je hebt MapComplete helpen vertalen met {_translation_contributions} commits! Dat is fantastisch! Bedankt hiervoor!", | ||||
|             "de": "Du hast mit {_translation_contributions} Änderungen zur Übersetzung von MapComplete beigetragen! Das ist großartig!" | ||||
|           }, | ||||
|           "icon": "party" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "contributor-thanks", | ||||
|       "labels": [ | ||||
|         "profile-content","hidden" | ||||
|       ], | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_code_contributions>0", | ||||
|           "then": { | ||||
|             "en": "You have contributed code to MapComplete with {_code_contributions} commits! That's awesome!", | ||||
|             "de": "Sie haben Code zu MapComplete mit {_code_contributions} Commits beigetragen! Das ist großartig!", | ||||
|             "nl": "Je hebt mee geprogrammeerd aan MapComplete met {_code_contributions} commits! Das supercool van je! Bedankt hiervoor!", | ||||
|             "ca": "Heu aportat codi a MapComplete amb {_code_contributions} commits! Això és increïble!", | ||||
|             "cs": "Přispěli jste do MapComplete kódem s {_code_contributions} revizemi! To je úžasné!", | ||||
|             "da": "Du har bidraget kode til MapComplete med {_code_contributions} commits! Det er fantastisk!" | ||||
|           }, | ||||
|           "icon": "party", | ||||
|           "hideInAnswer": true | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "language_picker", | ||||
|       "render": { | ||||
|  | @ -624,7 +800,6 @@ | |||
|           "href": "data:application/json,{mangroveidentity}", | ||||
|           "download": "mangrove_private_key_{_name}", | ||||
|           "class": "button", | ||||
| 
 | ||||
|           "text": { | ||||
|             "en": "Download the private key for your Mangrove Account", | ||||
|             "de": "Laden Sie den privaten Schlüssel für Ihr Mangrove-Konto herunter", | ||||
|  | @ -824,86 +999,6 @@ | |||
|         } | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "id": "verified-mastodon", | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_mastodon_link~*", | ||||
|           "then": { | ||||
|             "en": "A link to your Mastodon-profile has been been found: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "de": "Es wurde ein Link zu deinem Mastodon-Profil gefunden: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "nl": "Een link naar je Mastodon-profiel werd gevonden: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "fr": "Un lien vers votre profil Mastodon a été trouvé : <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "ca": "S'ha trobat un enllaç al vostre perfil de Mastodon: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>", | ||||
|             "cs": "Byl nalezen odkaz na váš profil Mastodon: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>" | ||||
|           }, | ||||
|           "icon": "mastodon" | ||||
|         }, | ||||
|         { | ||||
|           "if": "_mastodon_candidate~*", | ||||
|           "then": { | ||||
|             "en": "We found a link to what looks to be a mastodon account, but it is unverified. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Edit your profile description</a> and place the following there: <span class='code'><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "de": "Wir haben einen Link gefunden, der aussieht wie ein Mastodon-Konto, aber nicht verifiziert ist. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Bearbeiten Sie Ihre Profilbeschreibung</a> und fügen Sie dort Folgendes ein: <span class='code'><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "nl": "Je profielbeschrijving bevat een link die vermoedelijk naar je Mastodon gaat, maar deze link is niet verifieerdbaar voor Mastodon.<a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Pas je profielbeschrijving aan</a> en plaats er de volgende code: <span class='code'><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "ca": "Hem trobat un enllaç al que sembla ser un compte de mastodon, però no està verificat. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Editeu la descripció del vostre perfil</a> i col·loqueu-hi el següent: <span class='code '><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", | ||||
|             "cs": "Našli jsme odkaz na to, co vypadá jako účet mastodon, ale je neověřený. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Upravte popis svého profilu</a> a umístěte tam následující: <span class='code '><a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" | ||||
|           }, | ||||
|           "icon": "invalid" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "cscount-thanks", | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_csCount>0", | ||||
|           "then": { | ||||
|             "en": "You have made changes on {_csCount} different occasions! That is awesome!", | ||||
|             "de": "Sie haben bei {_csCount} verschiedenen Gelegenheiten Änderungen vorgenommen! Das ist großartig!", | ||||
|             "ca": "Has fet {_csCount} en diferents ocasions! Això és sorprenent!", | ||||
|             "fr": "Vous avez fait {_csCount} modifications ! C'est génial !", | ||||
|             "pt": "Você fez alterações em {_csCount} ocasiões diferentes! Isso é incrível!", | ||||
|             "nl": "Je hebt {_csCount} verschillende keren bijgedragen! Dat is indrukwekkend!", | ||||
|             "da": "Du har lavet ændringer ved {_csCount} forskellige begivenheder! Det er fantastisk!", | ||||
|             "es": "Has hecho cambios en {_csCount} ocasiones diferentes. ¡Es alucinante!", | ||||
|             "cs": "Změny jste provedli při {_csCount} různých příležitostech! To je úžasné!" | ||||
|           }, | ||||
|           "icon": "party" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "translation-thanks", | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_translation_contributions>0", | ||||
|           "then": { | ||||
|             "en": "You have contributed to translating MapComplete with {_translation_contributions} commits! That's awesome!", | ||||
|             "nl": "Je hebt MapComplete helpen vertalen met {_translation_contributions} commits! Dat is fantastisch! Bedankt hiervoor!", | ||||
|             "de": "Du hast mit {_translation_contributions} Änderungen zur Übersetzung von MapComplete beigetragen! Das ist großartig!" | ||||
|           }, | ||||
|           "icon": "party" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "contributor-thanks", | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "_code_contributions>0", | ||||
|           "then": { | ||||
|             "en": "You have contributed code to MapComplete with {_code_contributions} commits! That's awesome!", | ||||
|             "de": "Sie haben Code zu MapComplete mit {_code_contributions} Commits beigetragen! Das ist großartig!", | ||||
|             "nl": "Je hebt mee geprogrammeerd aan MapComplete met {_code_contributions} commits! Das supercool van je! Bedankt hiervoor!", | ||||
|             "ca": "Heu aportat codi a MapComplete amb {_code_contributions} commits! Això és increïble!", | ||||
|             "cs": "Přispěli jste do MapComplete kódem s {_code_contributions} revizemi! To je úžasné!", | ||||
|             "da": "Du har bidraget kode til MapComplete med {_code_contributions} commits! Det er fantastisk!" | ||||
|           }, | ||||
|           "icon": "party", | ||||
|           "hideInAnswer": true | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "id": "debug-title", | ||||
|       "render": { | ||||
|  |  | |||
|  | @ -1221,14 +1221,14 @@ video { | |||
|   height: 6rem; | ||||
| } | ||||
| 
 | ||||
| .h-screen { | ||||
|   height: 100vh; | ||||
| } | ||||
| 
 | ||||
| .h-full { | ||||
|   height: 100%; | ||||
| } | ||||
| 
 | ||||
| .h-screen { | ||||
|   height: 100vh; | ||||
| } | ||||
| 
 | ||||
| .h-fit { | ||||
|   height: -webkit-fit-content; | ||||
|   height: -moz-fit-content; | ||||
|  | @ -2043,6 +2043,10 @@ video { | |||
|   column-gap: 0px; | ||||
| } | ||||
| 
 | ||||
| .gap-x-4 { | ||||
|   column-gap: 1rem; | ||||
| } | ||||
| 
 | ||||
| .gap-y-8 { | ||||
|   row-gap: 2rem; | ||||
| } | ||||
|  | @ -2336,10 +2340,6 @@ video { | |||
|   border-radius: 1rem; | ||||
| } | ||||
| 
 | ||||
| .rounded-md { | ||||
|   border-radius: 0.375rem; | ||||
| } | ||||
| 
 | ||||
| .rounded-lg { | ||||
|   border-radius: 0.5rem; | ||||
| } | ||||
|  | @ -2558,11 +2558,6 @@ video { | |||
|   border-color: rgb(209 213 219 / var(--tw-border-opacity)); | ||||
| } | ||||
| 
 | ||||
| .border-gray-600 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(75 85 99 / var(--tw-border-opacity)); | ||||
| } | ||||
| 
 | ||||
| .border-gray-800 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(31 41 55 / var(--tw-border-opacity)); | ||||
|  | @ -4405,10 +4400,12 @@ video { | |||
|   --interactive-foreground: black; | ||||
|   --interactive-contrast: #ff00ff; | ||||
|   --button-background: #282828; | ||||
|   --button-background-hover: #686868; | ||||
|   --button-background-hover: #484848; | ||||
|   --button-primary-background-hover: #353535; | ||||
|   --button-foreground: white; | ||||
|   --button-border-color: #F7F7F7; | ||||
|   --disabled: #DBDBDB; | ||||
|   --disabled: #B8B8B8; | ||||
|   --disabled-font: #B8B8B8; | ||||
|   /** | ||||
|      * Base colour of interactive elements, mainly the 'subtle button' | ||||
|      * @deprecated | ||||
|  | @ -4592,19 +4589,19 @@ button.primary, .button.primary { | |||
| } | ||||
| 
 | ||||
| button.primary:hover:not(.disabled), .button.primary:hover:not(.disabled) { | ||||
|   background-color: var(--button-background-hover); | ||||
|   background-color: var(--button-primary-background-hover); | ||||
| } | ||||
| 
 | ||||
| button.disabled { | ||||
|   border-color: var(--disabled); | ||||
|   color: var(--disabled); | ||||
|   border-color: var(--disabled-font); | ||||
|   color: var(--disabled-font); | ||||
|   cursor: unset; | ||||
| } | ||||
| 
 | ||||
| button.disabled svg path { | ||||
|   transition: all 200ms; | ||||
|   fill: var(--disabled); | ||||
|   stroke: var(--disabled); | ||||
|   fill: var(--disabled-font); | ||||
|   stroke: var(--disabled-font); | ||||
| } | ||||
| 
 | ||||
| button.primary.disabled, .button.primary.disabled { | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ import Constants from "../../Models/Constants" | |||
| import { QueryParameters } from "../Web/QueryParameters" | ||||
| import { ThemeMetaTagging } from "./UserSettingsMetaTagging" | ||||
| import { MapProperties } from "../../Models/MapProperties" | ||||
| import Showdown from "showdown" | ||||
| 
 | ||||
| /** | ||||
|  * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection, | ||||
|  | @ -390,6 +391,13 @@ export default class UserRelatedState { | |||
|             for (const k in userDetails) { | ||||
|                 amendedPrefs.data["_" + k] = "" + userDetails[k] | ||||
|             } | ||||
|             if(userDetails.description){ | ||||
|                 amendedPrefs.data["_description_html"] =  Utils.purify(new Showdown.Converter() | ||||
|                     .makeHtml(userDetails.description) | ||||
|                     ?.replace(/>/g, ">") | ||||
|                     ?.replace(/</g, "<") | ||||
|                     ?.replace(/\n/g, "")) | ||||
|             } | ||||
| 
 | ||||
|             usersettingMetaTagging.metaTaggging_for_usersettings({ properties: amendedPrefs.data }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -151,6 +151,7 @@ export default class Constants { | |||
|         "not_found", | ||||
|         "note", | ||||
|         "party", | ||||
|         "pencil", | ||||
|         "pin", | ||||
|         "resolved", | ||||
|         "ring", | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ | |||
|   class={$classnames} | ||||
| > | ||||
|   {#if $icon} | ||||
|     <Icon clss="w-8 h-8" icon={$icon}/> | ||||
|     <Icon clss="w-4 h-4" icon={$icon}/> | ||||
|     {/if} | ||||
|   {@html $text} | ||||
| </a> | ||||
|  |  | |||
|  | @ -17,31 +17,44 @@ | |||
|   export let highlightedRendering: UIEventSource<string> = undefined | ||||
| 
 | ||||
|   export let tags: UIEventSource<Record<string, string>> = state?.featureProperties?.getStore( | ||||
|     selectedElement.properties.id | ||||
|     selectedElement.properties.id, | ||||
|   ) | ||||
| 
 | ||||
|   let isAddNew = tags.mapD( | ||||
|     (t) => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false | ||||
|     (t) => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false, | ||||
|   ) | ||||
| 
 | ||||
|   export let layer: LayerConfig | ||||
| 
 | ||||
|   export let mustMatchLabels: Set<string> | undefined = undefined | ||||
|   export let dontMatchLabels: Set<string> | undefined = new Set(["hidden"]) | ||||
|   let _metatags: Record<string, string> | ||||
|   if (state?.userRelatedState?.preferencesAsTags) { | ||||
|     onDestroy( | ||||
|       state.userRelatedState.preferencesAsTags.addCallbackAndRun((tags) => { | ||||
|         _metatags = tags | ||||
|       }) | ||||
|       }), | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   let knownTagRenderings: Store<TagRenderingConfig[]> = tags.mapD((tgs) => | ||||
|     layer?.tagRenderings?.filter( | ||||
|       (config) => | ||||
|         (config.condition?.matchesProperties(tgs) ?? true) && | ||||
|         (config.metacondition?.matchesProperties({ ...tgs, ..._metatags }) ?? true) && | ||||
|         config.IsKnown(tgs) | ||||
|     ) | ||||
|       (config) => { | ||||
|         if (mustMatchLabels !== undefined) { | ||||
|           if (!mustMatchLabels.has(config.id) && !config?.labels?.some(l => mustMatchLabels.has(l))) { | ||||
|             return false | ||||
|           } | ||||
|         } else if (dontMatchLabels) { | ||||
|           if (dontMatchLabels.has(config.id) || config?.labels?.some(l => dontMatchLabels.has(l))) { | ||||
|             return false | ||||
|           } | ||||
|         } | ||||
|         if (!config.IsKnown(tgs)) { | ||||
|           return false | ||||
|         } | ||||
|         return (config.condition?.matchesProperties(tgs) ?? true) && | ||||
|           (config.metacondition?.matchesProperties({ ...tgs, ..._metatags }) ?? true) | ||||
|       }, | ||||
|     ), | ||||
|   ) | ||||
| </script> | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,8 +14,8 @@ | |||
|   import { ExclamationTriangleIcon } from "@babeard/svelte-heroicons/mini" | ||||
|   import Location_refused from "../../assets/svg/Location_refused.svelte" | ||||
|   import Location from "../../assets/svg/Location.svelte" | ||||
|   import ChevronDoubleLeft from "@babeard/svelte-heroicons/mini/ChevronDoubleLeft" | ||||
|   import Constants from "../../Models/Constants" | ||||
|   import ChevronDoubleLeft from "@babeard/svelte-heroicons/solid/ChevronDoubleLeft" | ||||
|   import GeolocationIndicator from "./GeolocationIndicator.svelte" | ||||
| 
 | ||||
|   /** | ||||
|    * The theme introduction panel | ||||
|  | @ -27,9 +27,11 @@ | |||
|   let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined) | ||||
|   let searchEnabled = false | ||||
| 
 | ||||
|   let geopermission: Store<GeolocationPermissionState> = | ||||
|     state.geolocation.geolocationState.permission | ||||
|   let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation | ||||
|   let geolocation = state.geolocation.geolocationState | ||||
|   let geopermission: Store<GeolocationPermissionState> = geolocation.permission | ||||
|   let currentGPSLocation = geolocation.currentGPSLocation | ||||
|   let gpsExplanation = geolocation.gpsStateExplanation | ||||
|   let gpsAvailable = geolocation.gpsAvailable | ||||
| 
 | ||||
|   function jumpToCurrentLocation() { | ||||
|     const glstate = state.geolocation.geolocationState | ||||
|  | @ -75,38 +77,12 @@ | |||
| 
 | ||||
|     <div class="flex w-full flex-wrap sm:flex-nowrap"> | ||||
|       <If condition={state.featureSwitches.featureSwitchGeolocation}> | ||||
|         {#if $currentGPSLocation !== undefined || $geopermission === "prompt"} | ||||
|           <button class="flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}> | ||||
|             <Location class="h-8 w-8" /> | ||||
|             <Tr t={Translations.t.general.openTheMapAtGeolocation} /> | ||||
|           </button> | ||||
|           <!-- No geolocation granted - we don't show the button --> | ||||
|         {:else if $geopermission === "requested"} | ||||
|           <button | ||||
|             class="disabled flex w-full items-center gap-x-2" | ||||
|             on:click={jumpToCurrentLocation} | ||||
|           > | ||||
|             <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup --> | ||||
|             <Location | ||||
|               class="h-8 w-8" | ||||
|               style="animation: 3s linear 0s infinite normal none running spin;" | ||||
|             /> | ||||
|             <Tr t={Translations.t.general.waitingForGeopermission} /> | ||||
|           </button> | ||||
|         {:else if $geopermission === "denied"} | ||||
|           <button class="disabled flex w-full items-center gap-x-2"> | ||||
|             <Location_refused class="h-8 w-8" /> | ||||
|             <Tr t={Translations.t.general.geopermissionDenied} /> | ||||
|           </button> | ||||
|         {:else} | ||||
|           <button class="disabled flex w-full items-center gap-x-2"> | ||||
|             <Location | ||||
|               class="h-8 w-8" | ||||
|               style="animation: 3s linear 0s infinite normal none running spin;" | ||||
|             /> | ||||
|             <Tr t={Translations.t.general.waitingForLocation} /> | ||||
|           </button> | ||||
|         {/if} | ||||
| 
 | ||||
|         <button disabled={!$gpsAvailable} class:disabled={!$gpsAvailable} class="flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}> | ||||
| 
 | ||||
|           <GeolocationIndicator {state} /> | ||||
|           <Tr t={$gpsExplanation} /> | ||||
|         </button> | ||||
|       </If> | ||||
| 
 | ||||
|       <If condition={state.featureSwitches.featureSwitchSearch}> | ||||
|  |  | |||
|  | @ -1,55 +0,0 @@ | |||
| <script lang="ts"> | ||||
|   import UserDetails, { OsmConnection } from "../../Logic/Osm/OsmConnection" | ||||
|   import { UIEventSource } from "../../Logic/UIEventSource" | ||||
|   import { PencilAltIcon, UserCircleIcon } from "@rgossiaux/svelte-heroicons/solid" | ||||
|   import { onDestroy } from "svelte" | ||||
|   import Showdown from "showdown" | ||||
|   import FromHtml from "../Base/FromHtml.svelte" | ||||
|   import Tr from "../Base/Tr.svelte" | ||||
|   import Translations from "../i18n/Translations.js" | ||||
|   import Pencil from "@babeard/svelte-heroicons/solid/Pencil" | ||||
| 
 | ||||
|   /** | ||||
|    * This panel shows information about the logged-in user, showing account name, profile pick, description and an edit-button | ||||
|    */ | ||||
|   export let osmConnection: OsmConnection | ||||
|   let userdetails: UIEventSource<UserDetails> = osmConnection.userDetails | ||||
|   let description: string | ||||
|   onDestroy( | ||||
|     userdetails.addCallbackAndRunD((userdetails) => { | ||||
|       description = new Showdown.Converter() | ||||
|         .makeHtml(userdetails.description) | ||||
|         ?.replace(/>/g, ">") | ||||
|         ?.replace(/</g, "<") | ||||
|     }) | ||||
|   ) | ||||
| </script> | ||||
| 
 | ||||
| <div class="link-underline m-1 flex rounded-md border border-dashed border-gray-600 p-1"> | ||||
|   {#if $userdetails.img} | ||||
|     <img src={$userdetails.img} class="m-4 h-12 w-12 rounded-full" /> | ||||
|   {:else} | ||||
|     <UserCircleIcon class="h-12 w-12" /> | ||||
|   {/if} | ||||
|   <div class="flex flex-col"> | ||||
|     <h3>{$userdetails.name}</h3> | ||||
|     {#if description} | ||||
|       <FromHtml src={description} /> | ||||
|       <a | ||||
|         href={osmConnection.Backend() + "/profile/edit"} | ||||
|         target="_blank" | ||||
|         rel="noopener" | ||||
|         class="link-no-underline flex items-center self-end" | ||||
|       > | ||||
|         <PencilAltIcon slot="image" class="h-8 w-8 p-2" /> | ||||
|         <Tr t={Translations.t.userinfo.editDescription} /> | ||||
|       </a> | ||||
|     {:else} | ||||
|       <Tr t={Translations.t.userinfo.noDescription} /> | ||||
|       <a href={osmConnection.Backend() + "/profile/edit"} target="_blank" class="flex items-center"> | ||||
|         <Pencil class="h-8 w-8 p-2" /> | ||||
|         <Tr t={Translations.t.userinfo.noDescriptionCallToAction} /> | ||||
|       </a> | ||||
|     {/if} | ||||
|   </div> | ||||
| </div> | ||||
|  | @ -22,7 +22,7 @@ | |||
|   import Brick_wall_square from "../../assets/svg/Brick_wall_square.svelte" | ||||
|   import Brick_wall_round from "../../assets/svg/Brick_wall_round.svelte" | ||||
|   import Gps_arrow from "../../assets/svg/Gps_arrow.svelte" | ||||
|   import { HeartIcon, WifiIcon } from "@babeard/svelte-heroicons/solid" | ||||
|   import { HeartIcon, PencilIcon, WifiIcon } from "@babeard/svelte-heroicons/solid" | ||||
|   import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline" | ||||
|   import Confirm from "../../assets/svg/Confirm.svelte" | ||||
|   import Not_found from "../../assets/svg/Not_found.svelte" | ||||
|  | @ -37,7 +37,7 @@ | |||
|   import Cross_bottom_right from "../../assets/svg/Cross_bottom_right.svelte" | ||||
|   import { Utils } from "../../Utils" | ||||
|   import Gear from "../../assets/svg/Gear.svelte" | ||||
|   import { DesktopComputerIcon } from "@rgossiaux/svelte-heroicons/solid" | ||||
|   import { DesktopComputerIcon, UserCircleIcon } from "@rgossiaux/svelte-heroicons/solid" | ||||
|   import Relocation from "../../assets/svg/Relocation.svelte" | ||||
| 
 | ||||
|   /** | ||||
|  | @ -142,9 +142,13 @@ | |||
|     <DesktopComputerIcon class={"m-0 " + clss} {color} /> | ||||
|   {:else if icon === "relocation"} | ||||
|     <Relocation class={clss} {color} /> | ||||
|   {:else if icon === "pencil"} | ||||
|     <PencilIcon class={clss} {color} /> | ||||
|   {:else if icon === "user_circle"} | ||||
|     <UserCircleIcon class={clss} {color} /> | ||||
|   {:else if Utils.isEmoji(icon)} | ||||
|     <span style={`font-size: ${emojiHeight}px; line-height: ${emojiHeight}px`}> | ||||
|       {icon} | ||||
|     {icon} | ||||
|     </span> | ||||
|   {:else} | ||||
|     <img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" alt="" /> | ||||
|  |  | |||
							
								
								
									
										27
									
								
								src/UI/Popup/GroupedView.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/UI/Popup/GroupedView.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| <script lang="ts"> | ||||
|   import type { SpecialVisualizationState } from "../SpecialVisualization" | ||||
|   import type { Feature } from "geojson" | ||||
|   import { UIEventSource } from "../../Logic/UIEventSource" | ||||
|   import type { OsmTags } from "../../Models/OsmFeature" | ||||
|   import LayerConfig from "../../Models/ThemeConfig/LayerConfig" | ||||
|   import AccordionSingle from "../Flowbite/AccordionSingle.svelte" | ||||
|   import SelectedElementView from "../BigComponents/SelectedElementView.svelte" | ||||
|   import TagRenderingAnswer from "./TagRendering/TagRenderingAnswer.svelte" | ||||
| 
 | ||||
|   export let state: SpecialVisualizationState | ||||
|   export let selectedElement: Feature | ||||
|   export let tags: UIEventSource<OsmTags> | ||||
|   export let labels: string[] | ||||
|   export let header: string | ||||
|   export let layer: LayerConfig | ||||
| 
 | ||||
|   let headerTr = layer.tagRenderings.find(tr => tr.id === header) | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <AccordionSingle> | ||||
|   <div slot="header"> | ||||
|     <TagRenderingAnswer {tags} {layer} config={headerTr} {state} {selectedElement} /> | ||||
|   </div> | ||||
|   <SelectedElementView mustMatchLabels={new Set(labels)} {state} {layer} {tags} {selectedElement}/> | ||||
| </AccordionSingle> | ||||
|  | @ -271,6 +271,7 @@ | |||
|         feedback.setData(undefined) | ||||
|       } | ||||
|       tags.ping() | ||||
|       dispatch("saved", { config, applied: selectedTags }) | ||||
|       return | ||||
|     } | ||||
|     dispatch("saved", { config, applied: selectedTags }) | ||||
|  |  | |||
|  | @ -40,7 +40,6 @@ import { Feature, GeoJsonProperties } from "geojson" | |||
| import { GeoOperations } from "../Logic/GeoOperations" | ||||
| import CreateNewNote from "./Popup/Notes/CreateNewNote.svelte" | ||||
| import AddNewPoint from "./Popup/AddNewPoint/AddNewPoint.svelte" | ||||
| import UserProfile from "./BigComponents/UserProfile.svelte" | ||||
| import LayerConfig from "../Models/ThemeConfig/LayerConfig" | ||||
| import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig" | ||||
| import { ExportAsGpxViz } from "./Popup/ExportAsGpxViz" | ||||
|  | @ -102,6 +101,7 @@ import CloseNoteButton from "./Popup/Notes/CloseNoteButton.svelte" | |||
| import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte" | ||||
| import QrCode from "./Popup/QrCode.svelte" | ||||
| import ClearCaches from "./Popup/ClearCaches.svelte" | ||||
| import GroupedView from "./Popup/GroupedView.svelte" | ||||
| 
 | ||||
| class NearbyImageVis implements SpecialVisualization { | ||||
|     // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
 | ||||
|  | @ -425,17 +425,6 @@ export default class SpecialVisualizations { | |||
|                     }).SetClass("w-full h-full overflow-auto") | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|                 funcName: "user_profile", | ||||
|                 args: [], | ||||
| 
 | ||||
|                 docs: "A component showing information about the currently logged in user (username, profile description, profile picture + link to edit them). Mostly meant to be used in the 'user-settings'", | ||||
|                 constr(state: SpecialVisualizationState): BaseUIElement { | ||||
|                     return new SvelteUIElement(UserProfile, { | ||||
|                         osmConnection: state.osmConnection, | ||||
|                     }) | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|                 funcName: "language_picker", | ||||
|                 args: [], | ||||
|  | @ -1340,6 +1329,7 @@ export default class SpecialVisualizations { | |||
|                         download: tagSource.map((tags) => Utils.SubstituteKeys(download, tags)), | ||||
|                         ariaLabel: tagSource.map((tags) => Utils.SubstituteKeys(ariaLabel, tags)), | ||||
|                         newTab: new ImmutableStore(newTab), | ||||
|                         icon: tagSource.map((tags) => Utils.SubstituteKeys(icon, tags)) | ||||
|                     }).setSpan() | ||||
|                 }, | ||||
|             }, | ||||
|  | @ -2006,6 +1996,27 @@ export default class SpecialVisualizations { | |||
|                 ], | ||||
|                 constr(state: SpecialVisualizationState, tagSource: UIEventSource<Record<string, string>>, argument: string[], feature: Feature, layer: LayerConfig): SvelteUIElement { | ||||
|                     return new SvelteUIElement<any, any, any>(ClearCaches, {msg: argument[0] ?? "Clear local caches"}) | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|                 funcName: "group", | ||||
|                 docs: "A collapsable group (accordion)", | ||||
|                 args: [ | ||||
|                     { | ||||
|                         name: "header", | ||||
|                         doc: "The _identifier_ of a single tagRendering. This will be used as header" | ||||
|                     }, | ||||
|                     { | ||||
|                         name: "labels", | ||||
|                         doc: "A `;`-separated list of either identifiers or label names. All tagRenderings matching this value will be shown in the accordion" | ||||
|                     } | ||||
|                 ], | ||||
|                 constr(state: SpecialVisualizationState, tags: UIEventSource<Record<string, string>>, argument: string[], selectedElement: Feature, layer: LayerConfig): SvelteUIElement { | ||||
|                     const [header, labelsStr] = argument | ||||
|                     const labels = labelsStr.split(";").map(x => x.trim()) | ||||
|                     return new SvelteUIElement<any, any, any>(GroupedView, { | ||||
|                         state, tags, selectedElement, layer, header, labels | ||||
|                     }) | ||||
|                 } | ||||
|             } | ||||
|         ] | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ | |||
|   import ImageOperations from "./Image/ImageOperations.svelte" | ||||
|   import VisualFeedbackPanel from "./BigComponents/VisualFeedbackPanel.svelte" | ||||
|   import { Orientation } from "../Sensors/Orientation" | ||||
|   import GeolocationControl from "./BigComponents/GeolocationControl.svelte" | ||||
|   import GeolocationIndicator from "./BigComponents/GeolocationIndicator.svelte" | ||||
|   import Compass_arrow from "../assets/svg/Compass_arrow.svelte" | ||||
|   import ReverseGeocoding from "./BigComponents/ReverseGeocoding.svelte" | ||||
|   import FilterPanel from "./BigComponents/FilterPanel.svelte" | ||||
|  | @ -209,30 +209,7 @@ | |||
|   let addNewFeatureMode = state.userRelatedState.addNewFeatureMode | ||||
| 
 | ||||
|   let gpsAvailable = state.geolocation.geolocationState.gpsAvailable | ||||
|   let gpsButtonAriaLabel = gpsAvailable.map(available => { | ||||
|     if (!available) { | ||||
|       return Translations.t.general.labels.locationNotAvailable | ||||
|     } | ||||
|     if (state.geolocation.geolocationState.permission.data === "denied") { | ||||
|       return Translations.t.general.geopermissionDenied | ||||
|     } | ||||
| 
 | ||||
|     if (state.geolocation.geolocationState.permission.data === "requested") { | ||||
|       return Translations.t.general.waitingForGeopermission | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     if (!state.geolocation.geolocationState.allowMoving.data) { | ||||
|       return Translations.t.general.visualFeedback.islocked | ||||
|     } | ||||
| 
 | ||||
|     if (state.geolocation.geolocationState.currentGPSLocation.data === undefined) { | ||||
|       return Translations.t.general.waitingForLocation | ||||
|     } | ||||
| 
 | ||||
|     return Translations.t.general.labels.jumpToLocation | ||||
|   }, [state.geolocation.geolocationState.allowMoving, state.geolocation.geolocationState.permission]) | ||||
| 
 | ||||
|   let gpsButtonAriaLabel = state.geolocation.geolocationState.gpsStateExplanation | ||||
| </script> | ||||
| 
 | ||||
| <main> | ||||
|  | @ -435,7 +412,7 @@ | |||
|               on:click={() => state.geolocationControl.handleClick()} | ||||
|               on:keydown={forwardEventToMap} | ||||
|             > | ||||
|               <GeolocationControl {state} /> | ||||
|               <GeolocationIndicator {state} /> | ||||
|               <!-- h-8 w-8 + p-0.5 sm:p-1 + 2px border => 9 sm: 10 in total--> | ||||
|             </MapControlButton> | ||||
|             {#if $compassLoaded} | ||||
|  | @ -501,14 +478,15 @@ | |||
|     {/if} | ||||
|   {/if} | ||||
| 
 | ||||
|   <!-- Image preview --> | ||||
|   <If condition={state.previewedImage.map((i) => i !== undefined)}> | ||||
|     <FloatOver on:close={() => state.previewedImage.setData(undefined)}> | ||||
|       <ImageOperations image={$previewedImage} /> | ||||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
|   <!-- big theme menu --> | ||||
|   <If condition={state.guistate.themeIsOpened}> | ||||
|     <!-- Theme menu --> | ||||
|     <FloatOver on:close={() => state.guistate.themeIsOpened.setData(false)}> | ||||
|       <span slot="close-button"><!-- Disable the close button --></span> | ||||
|       <TabbedGroup | ||||
|  | @ -524,7 +502,6 @@ | |||
| 
 | ||||
|         <div class="flex" slot="title0"> | ||||
|           <Marker icons={layout.icon} size="h-4 w-4" /> | ||||
| 
 | ||||
|           <Tr t={layout.title} /> | ||||
|         </div> | ||||
| 
 | ||||
|  | @ -561,14 +538,15 @@ | |||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
|   <!-- Filterpane --> | ||||
|   <If condition={state.guistate.filtersPanelIsOpened}> | ||||
|     <FloatOver on:close={() => state.guistate.filtersPanelIsOpened.setData(false)}> | ||||
|       <FilterPanel {state} /> | ||||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
|   <!-- background layer selector --> | ||||
|   <IfHidden condition={state.guistate.backgroundLayerSelectionIsOpened}> | ||||
|     <!-- background layer selector --> | ||||
|     <FloatOver | ||||
|       on:close={() => { | ||||
|         state.guistate.backgroundLayerSelectionIsOpened.setData(false) | ||||
|  | @ -584,8 +562,8 @@ | |||
|     </FloatOver> | ||||
|   </IfHidden> | ||||
| 
 | ||||
|   <!-- Menu page --> | ||||
|   <If condition={state.guistate.menuIsOpened}> | ||||
|     <!-- Menu page --> | ||||
|     <FloatOver on:close={() => state.guistate.menuIsOpened.setData(false)}> | ||||
|       <span slot="close-button"><!-- Hide the default close button --></span> | ||||
|       <TabbedGroup | ||||
|  | @ -656,6 +634,7 @@ | |||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
|   <!-- Privacy policy --> | ||||
|   <If condition={state.guistate.privacyPanelIsOpened}> | ||||
|     <FloatOver on:close={() => state.guistate.privacyPanelIsOpened.setData(false)}> | ||||
|       <div class="flex h-full flex-col overflow-hidden"> | ||||
|  | @ -670,6 +649,7 @@ | |||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
|   <!-- Attribution, copyright and about MapComplete (no menu case) --> | ||||
|   <If condition={state.guistate.copyrightPanelIsOpened}> | ||||
|     <FloatOver on:close={() => state.guistate.copyrightPanelIsOpened.setData(false)}> | ||||
|       <div class="flex h-full flex-col overflow-hidden"> | ||||
|  | @ -687,6 +667,7 @@ | |||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
|   <!-- Community index --> | ||||
|   <If condition={state.guistate.communityIndexPanelIsOpened}> | ||||
|     <FloatOver on:close={() => state.guistate.communityIndexPanelIsOpened.setData(false)}> | ||||
|       <div class="flex h-full flex-col overflow-hidden"> | ||||
|  |  | |||
|  | @ -39,10 +39,13 @@ | |||
|   --interactive-contrast: #ff00ff; | ||||
| 
 | ||||
|   --button-background: #282828; | ||||
|   --button-background-hover: #686868; | ||||
|   --button-background-hover: #484848; | ||||
|     --button-primary-background-hover: #353535; | ||||
| 
 | ||||
|   --button-foreground: white; | ||||
|   --button-border-color: #F7F7F7; | ||||
|   --disabled: #DBDBDB; | ||||
|   --disabled: #B8B8B8; | ||||
|     --disabled-font: #B8B8B8; | ||||
| 
 | ||||
|   /** | ||||
|      * Base colour of interactive elements, mainly the 'subtle button' | ||||
|  | @ -232,20 +235,20 @@ button.primary, .button.primary { | |||
| } | ||||
| 
 | ||||
| button.primary:hover:not(.disabled), .button.primary:hover:not(.disabled) { | ||||
|     background-color: var(--button-background-hover); | ||||
|     background-color: var(--button-primary-background-hover); | ||||
| } | ||||
| 
 | ||||
| button.disabled { | ||||
|     border-color: var(--disabled); | ||||
|     color: var(--disabled); | ||||
|     border-color: var(--disabled-font); | ||||
|     color: var(--disabled-font); | ||||
|     cursor: unset; | ||||
| } | ||||
| button.disabled svg path { | ||||
|     transition: all 200ms; | ||||
| } | ||||
| button.disabled svg path { | ||||
|     fill: var(--disabled); | ||||
|     stroke: var(--disabled); | ||||
|     fill: var(--disabled-font); | ||||
|     stroke: var(--disabled-font); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue