forked from MapComplete/MapComplete
UX: add dots menu to images with overflow menu
This commit is contained in:
parent
c4ae41e0e1
commit
85a12971ab
3 changed files with 57 additions and 23 deletions
|
@ -1462,10 +1462,6 @@ input[type="range"].range-lg::-moz-range-thumb {
|
||||||
margin-right: 4rem;
|
margin-right: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb-4 {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mt-4 {
|
.mt-4 {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
@ -1482,6 +1478,10 @@ input[type="range"].range-lg::-moz-range-thumb {
|
||||||
margin-bottom: 4rem;
|
margin-bottom: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.ml-1 {
|
.ml-1 {
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -1698,14 +1698,14 @@ input[type="range"].range-lg::-moz-range-thumb {
|
||||||
height: 6rem;
|
height: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-screen {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-full {
|
.h-full {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-screen {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
.h-fit {
|
.h-fit {
|
||||||
height: -webkit-fit-content;
|
height: -webkit-fit-content;
|
||||||
height: -moz-fit-content;
|
height: -moz-fit-content;
|
||||||
|
|
|
@ -7,6 +7,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export let open = new UIEventSource(false)
|
export let open = new UIEventSource(false)
|
||||||
|
export let dotsSize = `w-6 h-6`
|
||||||
|
export let dotsPosition = `top-0 right-0`
|
||||||
|
export let hideBackground= false
|
||||||
|
let menuPosition = ``
|
||||||
|
if(dotsPosition.indexOf("left-0") >= 0){
|
||||||
|
menuPosition = "left-0"
|
||||||
|
}else{
|
||||||
|
menuPosition = `right-0`
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dotsPosition.indexOf("top-0") > 0){
|
||||||
|
menuPosition += " bottom-0"
|
||||||
|
}else{
|
||||||
|
menuPosition += ` top-0`
|
||||||
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
open.set(!open.data)
|
open.set(!open.data)
|
||||||
|
@ -17,18 +32,22 @@
|
||||||
|
|
||||||
<div class="relative" style="z-index: 50">
|
<div class="relative" style="z-index: 50">
|
||||||
<div
|
<div
|
||||||
class="sidebar-unit absolute right-0 top-0 collapsable normal-background button-unstyled"
|
class="sidebar-unit absolute {menuPosition} collapsable normal-background button-unstyled "
|
||||||
|
class:transition-background={hideBackground}
|
||||||
class:collapsed={!$open}>
|
class:collapsed={!$open}>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
<DotsCircleHorizontal class={ `absolute top-0 right-0 w-6 h-6 dots-menu transition-colors ${$open?"dots-menu-opened":""}`} on:click={toggle} />
|
<DotsCircleHorizontal
|
||||||
|
class={ `absolute ${dotsPosition} ${dotsSize} dots-menu transition-colors ${$open?"dots-menu-opened":""}`}
|
||||||
|
on:click={toggle} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dots-menu{
|
.dots-menu {
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dots-menu > path) {
|
:global(.dots-menu > path) {
|
||||||
fill: var(--interactive-background);
|
fill: var(--interactive-background);
|
||||||
transition: fill 350ms linear;
|
transition: fill 350ms linear;
|
||||||
|
@ -41,16 +60,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsable {
|
.collapsable {
|
||||||
max-width: 100rem;
|
max-width: 50rem;
|
||||||
max-height: 100rem;
|
max-height: 10rem;
|
||||||
transition: border 150ms linear, max-width 500ms linear, max-height 500ms linear;
|
transition: max-width 500ms linear, max-height 500ms linear, border 500ms linear;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
text-wrap: none;
|
text-wrap: none;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
box-shadow: #ccc ;
|
box-shadow: #ccc;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border: 1px solid var(--button-background);
|
border: 1px solid var(--button-background);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transition-background {
|
||||||
|
transition: background-color 150ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transition-background.collapsed {
|
||||||
|
background-color: #00000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsed {
|
.collapsed {
|
||||||
|
|
|
@ -13,11 +13,13 @@
|
||||||
import Loading from "../Base/Loading.svelte"
|
import Loading from "../Base/Loading.svelte"
|
||||||
import Tr from "../Base/Tr.svelte"
|
import Tr from "../Base/Tr.svelte"
|
||||||
import Translations from "../i18n/Translations"
|
import Translations from "../i18n/Translations"
|
||||||
|
import DotMenu from "../Base/DotMenu.svelte"
|
||||||
|
|
||||||
export let image: ProvidedImage
|
export let image: ProvidedImage
|
||||||
export let clss: string = undefined
|
export let clss: string = undefined
|
||||||
|
|
||||||
let isLoaded = new UIEventSource(false)
|
let isLoaded = new UIEventSource(false)
|
||||||
|
|
||||||
async function download() {
|
async function download() {
|
||||||
const response = await fetch(image.url_hd ?? image.url)
|
const response = await fetch(image.url_hd ?? image.url)
|
||||||
const blob = await response.blob()
|
const blob = await response.blob()
|
||||||
|
@ -36,6 +38,16 @@
|
||||||
{/if}
|
{/if}
|
||||||
<ImagePreview {image} {isLoaded} />
|
<ImagePreview {image} {isLoaded} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<DotMenu dotsPosition="top-0 left-0" dotsSize="w-8 h-8" hideBackground>
|
||||||
|
<button
|
||||||
|
class="no-image-background pointer-events-auto flex items-center"
|
||||||
|
on:click={() => download()}
|
||||||
|
>
|
||||||
|
<DownloadIcon class="h-6 w-6 px-2 opacity-100" />
|
||||||
|
<Tr t={Translations.t.general.download.downloadImage} />
|
||||||
|
</button>
|
||||||
|
</DotMenu>
|
||||||
<div
|
<div
|
||||||
class="pointer-events-none absolute bottom-0 left-0 flex w-full flex-wrap items-end justify-between"
|
class="pointer-events-none absolute bottom-0 left-0 flex w-full flex-wrap items-end justify-between"
|
||||||
>
|
>
|
||||||
|
@ -43,14 +55,8 @@
|
||||||
<ImageAttribution {image} attributionFormat="large" />
|
<ImageAttribution {image} attributionFormat="large" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot/>
|
<slot />
|
||||||
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="no-image-background pointer-events-auto flex items-center bg-black text-white opacity-50 transition-colors duration-200 hover:opacity-100"
|
|
||||||
on:click={() => download()}
|
|
||||||
>
|
|
||||||
<DownloadIcon class="h-6 w-6 px-2 opacity-100" />
|
|
||||||
<Tr t={Translations.t.general.download.downloadImage} />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue