forked from MapComplete/MapComplete
		
	More styling of the new menu UX
This commit is contained in:
		
							parent
							
								
									124e816abe
								
							
						
					
					
						commit
						806646ec06
					
				
					 11 changed files with 353 additions and 246 deletions
				
			
		|  | @ -1041,8 +1041,8 @@ video { | |||
|   margin-bottom: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .mr-10 { | ||||
|   margin-right: 2.5rem; | ||||
| .mr-16 { | ||||
|   margin-right: 4rem; | ||||
| } | ||||
| 
 | ||||
| .mb-1\.5 { | ||||
|  | @ -1280,6 +1280,10 @@ video { | |||
|   height: 1.25rem; | ||||
| } | ||||
| 
 | ||||
| .h-14 { | ||||
|   height: 3.5rem; | ||||
| } | ||||
| 
 | ||||
| .h-16 { | ||||
|   height: 4rem; | ||||
| } | ||||
|  | @ -1420,10 +1424,6 @@ video { | |||
|   height: 0.625rem; | ||||
| } | ||||
| 
 | ||||
| .h-14 { | ||||
|   height: 3.5rem; | ||||
| } | ||||
| 
 | ||||
| .h-72 { | ||||
|   height: 18rem; | ||||
| } | ||||
|  | @ -1440,6 +1440,10 @@ video { | |||
|   max-height: 3rem; | ||||
| } | ||||
| 
 | ||||
| .max-h-full { | ||||
|   max-height: 100%; | ||||
| } | ||||
| 
 | ||||
| .max-h-24 { | ||||
|   max-height: 6rem; | ||||
| } | ||||
|  | @ -1448,10 +1452,6 @@ video { | |||
|   max-height: 16rem; | ||||
| } | ||||
| 
 | ||||
| .max-h-full { | ||||
|   max-height: 100%; | ||||
| } | ||||
| 
 | ||||
| .max-h-60 { | ||||
|   max-height: 15rem; | ||||
| } | ||||
|  | @ -1530,6 +1530,10 @@ video { | |||
|   width: 1.25rem; | ||||
| } | ||||
| 
 | ||||
| .w-14 { | ||||
|   width: 3.5rem; | ||||
| } | ||||
| 
 | ||||
| .w-1\/2 { | ||||
|   width: 50%; | ||||
| } | ||||
|  | @ -1620,10 +1624,6 @@ video { | |||
|   width: 2.25rem; | ||||
| } | ||||
| 
 | ||||
| .w-14 { | ||||
|   width: 3.5rem; | ||||
| } | ||||
| 
 | ||||
| .w-2 { | ||||
|   width: 0.5rem; | ||||
| } | ||||
|  | @ -2356,6 +2356,11 @@ video { | |||
|   border-radius: 0.125rem; | ||||
| } | ||||
| 
 | ||||
| .rounded-t-lg { | ||||
|   border-top-left-radius: 0.5rem; | ||||
|   border-top-right-radius: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .rounded-b { | ||||
|   border-bottom-right-radius: 0.25rem; | ||||
|   border-bottom-left-radius: 0.25rem; | ||||
|  | @ -2366,11 +2371,6 @@ video { | |||
|   border-bottom-left-radius: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .rounded-t-lg { | ||||
|   border-top-left-radius: 0.5rem; | ||||
|   border-top-right-radius: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .rounded-b-\[1rem\] { | ||||
|   border-bottom-right-radius: 1rem; | ||||
|   border-bottom-left-radius: 1rem; | ||||
|  | @ -3302,6 +3302,10 @@ video { | |||
|   padding: 0.125rem; | ||||
| } | ||||
| 
 | ||||
| .p-6 { | ||||
|   padding: 1.5rem; | ||||
| } | ||||
| 
 | ||||
| .p-5 { | ||||
|   padding: 1.25rem; | ||||
| } | ||||
|  | @ -4963,6 +4967,10 @@ svg.apply-fill path { | |||
|   max-width: 100%; | ||||
| } | ||||
| 
 | ||||
| .max-w-screen { | ||||
|   max-width: 100vw; | ||||
| } | ||||
| 
 | ||||
| /************************* Experimental support for foldable devices ********************************/ | ||||
| 
 | ||||
| @media (horizontal-viewport-segments: 2) { | ||||
|  | @ -7562,6 +7570,11 @@ svg.apply-fill path { | |||
|     padding: 0px; | ||||
|   } | ||||
| 
 | ||||
|   .md\:px-5 { | ||||
|     padding-left: 1.25rem; | ||||
|     padding-right: 1.25rem; | ||||
|   } | ||||
| 
 | ||||
|   .md\:px-6 { | ||||
|     padding-left: 1.5rem; | ||||
|     padding-right: 1.5rem; | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| import ThemeViewState from "../../Models/ThemeViewState" | ||||
| import Hash from "./Hash" | ||||
| import { MenuState } from "../../Models/MenuState" | ||||
| import hash from "svelte/types/compiler/compile/utils/hash" | ||||
| 
 | ||||
| export default class ThemeViewStateHashActor { | ||||
|     private readonly _state: ThemeViewState | ||||
|     private isUpdatingHash = false | ||||
| 
 | ||||
|     public static readonly documentation = [ | ||||
|         "The URL-hash can contain multiple values:", | ||||
|  | @ -49,7 +49,9 @@ export default class ThemeViewStateHashActor { | |||
| 
 | ||||
|         // Register a hash change listener to correctly handle the back button
 | ||||
|         Hash.hash.addCallback((hash) => { | ||||
|                 console.trace("Going back with hash", hash) | ||||
|             if(this.isUpdatingHash){ | ||||
|                 return | ||||
|             } | ||||
|             if (!hash) { | ||||
|                 this.back() | ||||
|             } else { | ||||
|  | @ -121,6 +123,9 @@ export default class ThemeViewStateHashActor { | |||
|      * returns 'true' if a hash was set | ||||
|      */ | ||||
|     private setHash(): boolean { | ||||
|         this.isUpdatingHash = true | ||||
|         try { | ||||
| 
 | ||||
|             const selectedElement = this._state.selectedElement.data | ||||
|             if (selectedElement) { | ||||
|                 Hash.hash.set(selectedElement.properties.id) | ||||
|  | @ -135,11 +140,13 @@ export default class ThemeViewStateHashActor { | |||
|             } | ||||
|             Hash.hash.set(undefined) | ||||
|             return false | ||||
|         } finally { | ||||
|             this.isUpdatingHash = false | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private back() { | ||||
|         const state = this._state | ||||
|         console.log("Got a 'back' event") | ||||
|         if (state.previewedImage.data) { | ||||
|             state.previewedImage.setData(undefined) | ||||
|             return | ||||
|  |  | |||
|  | @ -9,10 +9,20 @@ | |||
|     duration: 200, | ||||
|     easing: sineIn | ||||
|   }; | ||||
|   let hidden = !shown.data | ||||
|   $: { | ||||
|     shown.setData(!hidden) | ||||
|   } | ||||
|   shown.addCallback(sh => { | ||||
|     hidden = !sh | ||||
|   }) | ||||
| </script> | ||||
| 
 | ||||
| 
 | ||||
| <Drawer placement="left" transitionType="fly" transitionParams={transitionParams} hidden={!$shown} on:close={() => shown.set(false)}> | ||||
| <Drawer placement="left" | ||||
|         transitionType="fly" {transitionParams} | ||||
|         divClass = "overflow-y-auto z-50 " | ||||
|         bind:hidden={hidden}> | ||||
|   <slot> | ||||
|     CONTENTS | ||||
|   </slot> | ||||
|  |  | |||
|  | @ -1,18 +1,19 @@ | |||
| <script lang="ts"> | ||||
|   import { OsmConnection } from "../../Logic/Osm/OsmConnection" | ||||
|   import Logout from "../../assets/svg/Logout.svelte" | ||||
|   import Translations from "../i18n/Translations" | ||||
|   import Tr from "./Tr.svelte" | ||||
|   import ArrowRightOnRectangle from "@babeard/svelte-heroicons/solid/ArrowRightOnRectangle" | ||||
| 
 | ||||
|   export let osmConnection: OsmConnection | ||||
|   export let clss = "" | ||||
| </script> | ||||
| 
 | ||||
| <button | ||||
|   class={clss} | ||||
|   on:click={() => { | ||||
|     osmConnection.LogOut() | ||||
|   }} | ||||
| > | ||||
|   <ArrowRightOnRectangle class="h-6 w-6" /> | ||||
|   <ArrowRightOnRectangle class="h-6 w-6 max-h-full" /> | ||||
|   <Tr t={Translations.t.general.logout} /> | ||||
| </button> | ||||
|  |  | |||
|  | @ -16,16 +16,20 @@ | |||
|   if (fullscreen) { | ||||
|     defaultClass = shared | ||||
|   } | ||||
|   let dialogClass = "fixed top-0 start-0 end-0 h-modal inset-0 z-50 w-full p-4 flex"; | ||||
|   let dialogClass = "fixed top-0 start-0 end-0 h-modal inset-0 z-50 w-full p-4 flex" | ||||
|   if (fullscreen) { | ||||
|     dialogClass += " h-full-child" | ||||
|   } | ||||
|   let bodyClass = "h-full p-4 md:p-5 space-y-4 flex-1 overflow-y-auto overscroll-contain" | ||||
|   let headerClass = "flex justify-between items-center p-2 px-4 md:px-5 rounded-t-lg"; | ||||
| </script> | ||||
| 
 | ||||
| {#if !onlyLink} | ||||
|   <Modal open={_shown} on:close={() => shown.set(false)} size="xl" {defaultClass} {bodyClass} {dialogClass} color="none"> | ||||
|     <slot name="header" slot="header" /> | ||||
|   <Modal open={_shown} on:close={() => shown.set(false)} size="xl" {defaultClass} {bodyClass} {dialogClass} {headerClass} | ||||
|          color="none"> | ||||
|     <h1 slot="header" class="w-full"> | ||||
|       <slot name="header" /> | ||||
|     </h1> | ||||
|     <slot /> | ||||
|     {#if $$slots.footer} | ||||
|       <slot name="footer" /> | ||||
|  | @ -33,6 +37,8 @@ | |||
|   </Modal> | ||||
| {:else} | ||||
|   <button class="as-link" on:click={() => shown.setData(true)}> | ||||
|     <slot name="link"> | ||||
|     <slot name="header" /> | ||||
|     </slot> | ||||
|   </button> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -50,7 +50,11 @@ | |||
| </script> | ||||
| 
 | ||||
| <Page {onlyLink} shown={state.guistate.pageStates.filter}> | ||||
|   <div class="mr-10 flex w-full flex-wrap items-center justify-between" slot="header"> | ||||
|   <div class="flex" slot="link"> | ||||
|     <Filter class="h-6 w-6 pr-2" /> | ||||
|     <Tr t={Translations.t.general.menu.filter} /> | ||||
|   </div> | ||||
|   <div class="mr-16 flex w-full flex-wrap items-center justify-between" slot="header"> | ||||
|     <div class="flex"> | ||||
|       <Filter class="h-6 w-6 pr-2" /> | ||||
|       <Tr t={Translations.t.general.menu.filter} /> | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
|   import CommunityIndexView from "./CommunityIndexView.svelte" | ||||
|   import Community from "../../assets/svg/Community.svelte" | ||||
|   import LoginToggle from "../Base/LoginToggle.svelte" | ||||
|   import { Avatar, Sidebar, SidebarWrapper } from "flowbite-svelte" | ||||
|   import {  Sidebar, SidebarWrapper } from "flowbite-svelte" | ||||
|   import HotkeyTable from "./HotkeyTable.svelte" | ||||
|   import { Utils } from "../../Utils" | ||||
|   import Constants from "../../Models/Constants" | ||||
|  | @ -45,6 +45,7 @@ | |||
|   import ThemeIntroPanel from "./ThemeIntroPanel.svelte" | ||||
|   import Marker from "../Map/Marker.svelte" | ||||
|   import LogoutButton from "../Base/LogoutButton.svelte" | ||||
|   import { LanguageIcon } from "@babeard/svelte-heroicons/solid" | ||||
| 
 | ||||
|   export let state: ThemeViewState | ||||
|   let userdetails = state.osmConnection.userDetails | ||||
|  | @ -58,19 +59,23 @@ | |||
|   export let onlyLink: boolean | ||||
| </script> | ||||
| 
 | ||||
| <Sidebar> | ||||
|   <SidebarWrapper divClass="link-underline"> | ||||
| <Sidebar asideClass="max-w-screen p-0 low-interaction p-6 link-underline"> | ||||
| <h2>Menu</h2> | ||||
|     <div class="flex flex-col"> | ||||
| 
 | ||||
|       <!-- User related: avatar, settings, favourits, logout --> | ||||
|     <div> | ||||
|       <div class="sidebar-unit"> | ||||
|         <LoginToggle {state}> | ||||
|           <LoginButton osmConnection={state.osmConnection} slot="not-logged-in"></LoginButton> | ||||
|         <div class="flex"> | ||||
|           <div class="flex gap-x-2"> | ||||
|             {#if $userdetails.img} | ||||
|               <img src={$userdetails.img} class="rounded-full w-14 h-14" /> | ||||
|             {/if} | ||||
|             <div class="flex flex-col justify-between"> | ||||
|               <b>{$userdetails.name}</b> | ||||
| 
 | ||||
|           <Avatar src={$userdetails.img} rounded /> | ||||
|           Welcome <b>{$userdetails.name}</b> | ||||
|             </div> | ||||
|         <LogoutButton osmConnection={state.osmConnection}/> | ||||
|           </div> | ||||
|         </LoginToggle> | ||||
| 
 | ||||
| 
 | ||||
|  | @ -123,20 +128,27 @@ | |||
|               <ReviewsOverview {state} /> | ||||
|             </div> | ||||
|           </Page> | ||||
|           <div class="self-end"> | ||||
|             <LogoutButton osmConnection={state.osmConnection}  /> | ||||
|           </div> | ||||
|         </LoginToggle> | ||||
| 
 | ||||
| 
 | ||||
|         <LanguagePicker/> | ||||
| 
 | ||||
|       </div> | ||||
| 
 | ||||
| 
 | ||||
|       <!-- Theme related: documentation links, download, ... --> | ||||
|     <div> | ||||
|       <div class="sidebar-unit"> | ||||
|         <h3> | ||||
|         About {layout.id} | ||||
|           About this map | ||||
|         </h3> | ||||
| 
 | ||||
|         <Page {onlyLink} shown={pg.about_theme}> | ||||
|           <dic slot="link"> | ||||
|             Show introduction | ||||
|           </dic> | ||||
|           <div class="flex" slot="header"> | ||||
|             <Marker icons={layout.icon} size="h-4 w-4" /> | ||||
|             <Tr t={layout.title} /> | ||||
|  | @ -190,37 +202,9 @@ | |||
|         {/if} | ||||
|       </div> | ||||
| 
 | ||||
|     <!-- Legal info: privacy policy, map attribution, icon attribution --> | ||||
|     <div> | ||||
|       <h3>Legal</h3> | ||||
| 
 | ||||
|       <Page {onlyLink} shown={pg.copyright}> | ||||
|         <Tr slot="header" t={Translations.t.general.attribution.attributionTitle} /> | ||||
|         <CopyrightPanel {state} /> | ||||
|       </Page> | ||||
| 
 | ||||
| 
 | ||||
|       <Page {onlyLink} shown={pg.copyright_icons}> | ||||
|         <div slot="header"> | ||||
|           <Tr t={ Translations.t.general.attribution.iconAttribution.title} /> | ||||
|         </div> | ||||
|         <CopyrightAllIcons {state} /> | ||||
| 
 | ||||
|       </Page> | ||||
| 
 | ||||
| 
 | ||||
|       <Page {onlyLink} shown={pg.privacy}> | ||||
|         <div class="flex gap-x-2" slot="header"> | ||||
|           <EyeIcon class="w-6 pr-2" /> | ||||
|           <Tr t={Translations.t.privacy.title} /> | ||||
|         </div> | ||||
|         <PrivacyPolicy {state} /> | ||||
|       </Page> | ||||
| 
 | ||||
|     </div> | ||||
| 
 | ||||
|       <!-- Other links and tools for the given location: open iD/JOSM; community index, ... --> | ||||
|     <div> | ||||
|       <div class="sidebar-unit"> | ||||
| 
 | ||||
|         <h3> | ||||
|           Discover more | ||||
|  | @ -242,8 +226,10 @@ | |||
|         </If> | ||||
| 
 | ||||
|       </div> | ||||
|     <!-- About MC: various hints --> | ||||
|     <div> | ||||
| 
 | ||||
| 
 | ||||
|       <!-- About MC: various outward links, legal info, ... --> | ||||
|       <div class="sidebar-unit"> | ||||
| 
 | ||||
|         <h3> | ||||
|           <Tr t={Translations.t.general.menu.aboutMapComplete} /> | ||||
|  | @ -287,10 +273,83 @@ | |||
|           <Tr t={Translations.t.general.attribution.donate} /> | ||||
|         </a> | ||||
| 
 | ||||
|       <div class="subtle"> | ||||
| 
 | ||||
|         <Page {onlyLink} shown={pg.copyright}> | ||||
|           <Tr slot="header" t={Translations.t.general.attribution.attributionTitle} /> | ||||
|           <CopyrightPanel {state} /> | ||||
|         </Page> | ||||
| 
 | ||||
| 
 | ||||
|         <Page {onlyLink} shown={pg.copyright_icons}> | ||||
|           <div slot="header"> | ||||
|             <Tr t={ Translations.t.general.attribution.iconAttribution.title} /> | ||||
|           </div> | ||||
|           <CopyrightAllIcons {state} /> | ||||
| 
 | ||||
|         </Page> | ||||
| 
 | ||||
| 
 | ||||
|         <Page {onlyLink} shown={pg.privacy}> | ||||
|           <div class="flex gap-x-2" slot="header"> | ||||
|             <EyeIcon class="w-6 pr-2" /> | ||||
|             <Tr t={Translations.t.privacy.title} /> | ||||
|           </div> | ||||
|           <PrivacyPolicy {state} /> | ||||
|         </Page> | ||||
| 
 | ||||
| 
 | ||||
|         <div class="subtle self-end"> | ||||
|           {Constants.vNumber} | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|   </SidebarWrapper> | ||||
| </Sidebar> | ||||
| 
 | ||||
| 
 | ||||
| <style> | ||||
|     :global(.sidebar-unit) { | ||||
|         width: calc(100% + 1rem); | ||||
|         margin-top: 0.75rem; | ||||
|         margin-left: -0.5rem; | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         row-gap: 0.25rem; | ||||
|         background: var(--background-color); | ||||
|         padding: 1rem; | ||||
|         border-radius: 0.5rem; | ||||
|     } | ||||
|     :global(.sidebar-unit > h3) { | ||||
|         margin-top: 0; | ||||
|         margin-bottom: 0.5rem | ||||
|     } | ||||
|     :global(.sidebar-unit svg) { | ||||
|         width: 1.5rem; | ||||
|         height: 1.5rem; | ||||
|         margin-right: 0.5rem; | ||||
|         margin-left: 0.5rem; | ||||
|         flex-shrink: 0; | ||||
|     } | ||||
| 
 | ||||
|     :global(.sidebar-unit img) { | ||||
|         width: 1.5rem; | ||||
|         height: 1.5rem; | ||||
|         margin-right: 0.5rem; | ||||
|         flex-shrink: 0; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     :global(.sidebar-unit  a) { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         margin-left: 1rem; | ||||
|     } | ||||
| 
 | ||||
|     :global(.sidebar-unit button) { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         margin-left: 0.5rem; | ||||
|     } | ||||
| 
 | ||||
| </style> | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
|   import Loading from "../Base/Loading.svelte" | ||||
|   import Page from "../Base/Page.svelte" | ||||
|   import ThemeViewState from "../../Models/ThemeViewState" | ||||
|   import { Square3Stack3dIcon } from "@babeard/svelte-heroicons/solid" | ||||
| 
 | ||||
|   export let state: ThemeViewState | ||||
| 
 | ||||
|  | @ -54,7 +55,11 @@ | |||
| </script> | ||||
| 
 | ||||
| <Page {onlyLink} shown={shown} fullscreen={true}> | ||||
|   <Tr slot="header" t={Translations.t.general.backgroundMap} /> | ||||
|   <div slot="header" class="flex" > | ||||
|     <Square3Stack3dIcon class="h-6 w-6" /> | ||||
| 
 | ||||
|   <Tr t={Translations.t.general.backgroundMap} /> | ||||
|   </div> | ||||
|   {#if $_availableLayers?.length < 1} | ||||
|     <Loading /> | ||||
|   {:else} | ||||
|  |  | |||
|  | @ -42,7 +42,6 @@ | |||
|   import { BBox } from "../Logic/BBox" | ||||
|   import ExtraLinkButton from "./BigComponents/ExtraLinkButton.svelte" | ||||
|   import { LastClickFeatureSource } from "../Logic/FeatureSource/Sources/LastClickFeatureSource" | ||||
|   import ChevronRight from "@babeard/svelte-heroicons/solid/ChevronRight" | ||||
|   import Marker from "./Map/Marker.svelte" | ||||
|   import SelectedElementPanel from "./Base/SelectedElementPanel.svelte" | ||||
|   import MenuDrawer from "./BigComponents/MenuDrawer.svelte" | ||||
|  | @ -224,7 +223,6 @@ | |||
|             <b class="mr-1"> | ||||
|               <Tr t={layout.title} /> | ||||
|             </b> | ||||
|             <ChevronRight class="h-4 w-4" /> | ||||
|           </div> | ||||
|         </MapControlButton> | ||||
| 
 | ||||
|  |  | |||
|  | @ -630,6 +630,10 @@ svg.apply-fill path { | |||
|   max-width: 100%; | ||||
| } | ||||
| 
 | ||||
| .max-w-screen { | ||||
|     max-width: 100vw; | ||||
| } | ||||
| 
 | ||||
| /************************* Experimental support for foldable devices ********************************/ | ||||
| @media (horizontal-viewport-segments: 2) { | ||||
|   .theme-list { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue