A11y: add labels to previously unlabeled buttons, fix order
This commit is contained in:
parent
736ab13ceb
commit
fdde0aaeb3
21 changed files with 287 additions and 86 deletions
|
@ -524,7 +524,7 @@
|
|||
},
|
||||
{
|
||||
"id": "Reservation",
|
||||
"condition": "amenity=restaurant",
|
||||
"condition": "takeaway=only",
|
||||
"question": {
|
||||
"en": "Is a reservation required for this place?",
|
||||
"nl": "Is reserveren verplicht voor deze zaak?",
|
||||
|
@ -581,7 +581,8 @@
|
|||
"cs": "Rezervace na tomto místě není možná"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"#condition": "If one can only do takeaway or deliveries, it is nonsensical to ask if a 'reservation' is possible"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
|
@ -731,6 +732,13 @@
|
|||
"pl": "Wszystkie dania są wegetariańskie",
|
||||
"cs": "Všechna jídla jsou vegetariánská"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "diet:vegetarian=on_demand",
|
||||
"then": {
|
||||
"en": "Some dishes might be adapted to a vegetarian version, but this should be demanded",
|
||||
"nl": "Sommige gerechten kunnen op vraag vegetarisch gemaakt worden"
|
||||
}
|
||||
}
|
||||
],
|
||||
"condition": "cuisine!=friture",
|
||||
|
@ -798,6 +806,13 @@
|
|||
"pl": "Wszystkie dania są wegańskie",
|
||||
"cs": "Všechna jídla jsou veganská"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "diet:vegan=on_demand",
|
||||
"then": {
|
||||
"en": "Some dishes might be adapted to a vegan version if asked for",
|
||||
"nl": "Op vraag kan een veganistische variant van een gerecht gemaakt worden"
|
||||
}
|
||||
}
|
||||
],
|
||||
"condition": "cuisine!=friture",
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
{
|
||||
"#": "ignore-image-in-then",
|
||||
"if": "wikipedia=",
|
||||
"then": "<a class='h-8' href='https://www.wikidata.org/wiki/{wikidata}' target='_blank' rel='noopener'><img src='./assets/svg/wikidata.svg' alt='WD'/></a>"
|
||||
"then": "<a class='h-8' href='https://www.wikidata.org/wiki/{wikidata}' target='_blank' rel='noopener'><img src='./assets/svg/wikidata.svg' alt='Wikidata'/></a>"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -119,12 +119,32 @@
|
|||
"defaults",
|
||||
"in_favourite"
|
||||
],
|
||||
"render": "<a href='tel:{phone}'><img textmode='📞' alt='phone' src='./assets/layers/questions/phone.svg'/></a>",
|
||||
"render": {
|
||||
"special": {
|
||||
"type": "link",
|
||||
"href": "tel:{phone}",
|
||||
"text": "<img textmode='📞' alt='phone' src='./assets/layers/questions/phone.svg'/>",
|
||||
"arialabel": {
|
||||
"en": "phone",
|
||||
"nl": "Telefoneer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"#": "ignore-image-in-then",
|
||||
"if": "contact:phone~*",
|
||||
"then": "<a href='tel:{contact:phone}'><img textmode='📞' alt='phone' src='./assets/layers/questions/phone.svg'/></a>"
|
||||
"then": {
|
||||
"special": {
|
||||
"type": "link",
|
||||
"href": "tel:{contact:phone}",
|
||||
"text": "<img textmode='📞' alt='phone' src='./assets/layers/questions/phone.svg'/>",
|
||||
"arialabel": {
|
||||
"en": "phone",
|
||||
"nl": "Telefoneer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"condition": {
|
||||
|
@ -174,12 +194,12 @@
|
|||
{
|
||||
"#": "ignore-image-in-then",
|
||||
"if": "smoking=no",
|
||||
"then": "<img textmode='🚭️' alt='no-smoking' src='./assets/layers/questions/no_smoking.svg'/>"
|
||||
"then": "<img textmode='🚭️' alt='no smoking' src='./assets/layers/questions/no_smoking.svg'/>"
|
||||
},
|
||||
{
|
||||
"#": "ignore-image-in-then",
|
||||
"if": "smoking=yes",
|
||||
"then": "<img textmode='🚬️' alt='smoking-allowed' src='./assets/layers/questions/smoking.svg'/>"
|
||||
"then": "<img textmode='🚬️' alt='smoking allowed' src='./assets/layers/questions/smoking.svg'/>"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -206,7 +226,17 @@
|
|||
"labels": [
|
||||
"defaults"
|
||||
],
|
||||
"render": "<a href='https://openstreetmap.org/{id}' target='_blank' rel='noopener'><img alt='on osm' textmode='🗺️' src='./assets/svg/osm-logo-us.svg'/></a>",
|
||||
"render": {
|
||||
"special": {
|
||||
"type": "link",
|
||||
"text": "<img alt='on osm' textmode='🗺️' src='./assets/svg/osm-logo-us.svg'/>",
|
||||
"href": "https://openstreetmap.org/{id}",
|
||||
"arialabel": {
|
||||
"en": "Open on openstreetmap.org",
|
||||
"nl": "Bekijk op openstreetmap.org"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "id~.*/-.*",
|
||||
|
@ -215,7 +245,17 @@
|
|||
{
|
||||
"#": "ignore-image-in-then",
|
||||
"if": "_backend~*",
|
||||
"then": "<a href='{_backend}/{id}' target='_blank' rel='noopener'><img src='./assets/svg/osm-logo-us.svg'/></a>"
|
||||
"then": {
|
||||
"special": {
|
||||
"type": "link",
|
||||
"text": "<img alt='on osm' textmode='🗺️' src='./assets/svg/osm-logo-us.svg'/>",
|
||||
"href": "{_backend}/{id}",
|
||||
"arialabel": {
|
||||
"en": "Open on openstreetmap.org",
|
||||
"nl": "Bekijk op openstreetmap.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"condition": "id~(node|way|relation)/[0-9]*"
|
||||
|
|
|
@ -4721,6 +4721,9 @@
|
|||
},
|
||||
"3": {
|
||||
"then": "All dishes are vegan"
|
||||
},
|
||||
"4": {
|
||||
"then": "Some dishes might be adapted to a vegan version if asked for"
|
||||
}
|
||||
},
|
||||
"question": "Does this business serve vegan meals?"
|
||||
|
@ -4738,6 +4741,9 @@
|
|||
},
|
||||
"3": {
|
||||
"then": "All dishes are vegetarian"
|
||||
},
|
||||
"4": {
|
||||
"then": "Some dishes might be adapted to a vegetarian version, but this should be demanded"
|
||||
}
|
||||
},
|
||||
"question": "Does this restaurant have a vegetarian option?"
|
||||
|
@ -5252,7 +5258,41 @@
|
|||
}
|
||||
},
|
||||
"icons": {
|
||||
"description": "A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI"
|
||||
"description": "A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI",
|
||||
"tagRenderings": {
|
||||
"osmlink": {
|
||||
"mappings": {
|
||||
"1": {
|
||||
"then": {
|
||||
"special": {
|
||||
"arialabel": "Open on openstreetmap.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"render": {
|
||||
"special": {
|
||||
"arialabel": "Open on openstreetmap.org"
|
||||
}
|
||||
}
|
||||
},
|
||||
"phonelink": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": {
|
||||
"special": {
|
||||
"arialabel": "phone"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"render": {
|
||||
"special": {
|
||||
"arialabel": "phone"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"indoors": {
|
||||
"description": "Basic indoor mapping: shows room outlines",
|
||||
|
|
|
@ -4190,6 +4190,9 @@
|
|||
},
|
||||
"3": {
|
||||
"then": "Enkel veganistische opties zijn beschikbaar"
|
||||
},
|
||||
"4": {
|
||||
"then": "Op vraag kan een veganistische variant van een gerecht gemaakt worden"
|
||||
}
|
||||
},
|
||||
"question": "Heeft deze eetgelegenheid een veganistische optie?"
|
||||
|
@ -4207,6 +4210,9 @@
|
|||
},
|
||||
"3": {
|
||||
"then": "Enkel vegetarische opties zijn beschikbaar"
|
||||
},
|
||||
"4": {
|
||||
"then": "Sommige gerechten kunnen op vraag vegetarisch gemaakt worden"
|
||||
}
|
||||
},
|
||||
"question": "Heeft deze eetgelegenheid een vegetarische optie?"
|
||||
|
@ -4654,6 +4660,42 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"icons": {
|
||||
"tagRenderings": {
|
||||
"osmlink": {
|
||||
"mappings": {
|
||||
"1": {
|
||||
"then": {
|
||||
"special": {
|
||||
"arialabel": "Bekijk op openstreetmap.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"render": {
|
||||
"special": {
|
||||
"arialabel": "Bekijk op openstreetmap.org"
|
||||
}
|
||||
}
|
||||
},
|
||||
"phonelink": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": {
|
||||
"special": {
|
||||
"arialabel": "Telefoneer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"render": {
|
||||
"special": {
|
||||
"arialabel": "Telefoneer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"indoors": {
|
||||
"description": "Een basis voor indoor-navigatie: toont binnenruimtes",
|
||||
"name": "Binnenruimtes",
|
||||
|
|
|
@ -886,16 +886,6 @@ video {
|
|||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.mx-10 {
|
||||
margin-left: 2.5rem;
|
||||
margin-right: 2.5rem;
|
||||
}
|
||||
|
||||
.my-3 {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.mx-12 {
|
||||
margin-left: 3rem;
|
||||
margin-right: 3rem;
|
||||
|
@ -969,10 +959,6 @@ video {
|
|||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.mb-10 {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.mt-8 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
@ -1529,10 +1515,6 @@ video {
|
|||
justify-self: end;
|
||||
}
|
||||
|
||||
.justify-self-center {
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.overflow-auto {
|
||||
overflow: auto;
|
||||
}
|
||||
|
@ -1935,6 +1917,11 @@ video {
|
|||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
.text-5xl {
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.font-extrabold {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import ImageProvider, { ProvidedImage } from "./ImageProvider"
|
||||
import BaseUIElement from "../../UI/BaseUIElement"
|
||||
import Svg from "../../Svg"
|
||||
import { Utils } from "../../Utils"
|
||||
import { LicenseInfo } from "./LicenseInfo"
|
||||
import Constants from "../../Models/Constants"
|
||||
import Link from "../../UI/Base/Link"
|
||||
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
|
||||
import MapillaryIcon from "./MapillaryIcon.svelte"
|
||||
|
||||
export class Mapillary extends ImageProvider {
|
||||
public static readonly singleton = new Mapillary()
|
||||
|
@ -112,11 +112,11 @@ export class Mapillary extends ImageProvider {
|
|||
lat: number
|
||||
}
|
||||
): BaseUIElement {
|
||||
const icon = Svg.mapillary_svg()
|
||||
if (!id) {
|
||||
return icon
|
||||
let url: string = undefined
|
||||
if (id) {
|
||||
url = Mapillary.createLink(location, 16, "" + id)
|
||||
}
|
||||
return new Link(icon, Mapillary.createLink(location, 16, "" + id), true)
|
||||
return new SvelteUIElement(MapillaryIcon, { url })
|
||||
}
|
||||
|
||||
async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
|
||||
|
|
21
src/Logic/ImageProviders/MapillaryIcon.svelte
Normal file
21
src/Logic/ImageProviders/MapillaryIcon.svelte
Normal file
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import Mapillary from "../../assets/svg/Mapillary.svelte"
|
||||
import { ariaLabel } from "../../Utils/ariaLabel"
|
||||
import Translations from "../../UI/i18n/Translations"
|
||||
|
||||
/**
|
||||
* Accessible, linked mapillary icon
|
||||
*/
|
||||
export let url: string = undefined
|
||||
</script>
|
||||
|
||||
{#if url}
|
||||
<a href={url}
|
||||
use:ariaLabel={Translations.t.general.attribution.seeOnMapillary}
|
||||
target="_blank"
|
||||
rel="noopener nofollower" >
|
||||
<Mapillary />
|
||||
</a>
|
||||
{:else}
|
||||
<Mapillary />
|
||||
{/if}
|
12
src/UI/Base/Link.svelte
Normal file
12
src/UI/Base/Link.svelte
Normal file
|
@ -0,0 +1,12 @@
|
|||
<script lang="ts">
|
||||
export let text : string
|
||||
export let href : string
|
||||
export let classnames : string = undefined
|
||||
export let download : string = undefined
|
||||
export let ariaLabel : string = undefined
|
||||
|
||||
export let newTab: boolean = false
|
||||
</script>
|
||||
|
||||
<a {href} aria-label={ariaLabel} target={newTab ? "_blank" : undefined} {download} class={classnames}>
|
||||
{@html text}</a>
|
|
@ -1,7 +1,6 @@
|
|||
import Translations from "../i18n/Translations"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import { Store } from "../../Logic/UIEventSource"
|
||||
import { Utils } from "../../Utils"
|
||||
|
||||
export default class Link extends BaseUIElement {
|
||||
private readonly _href: string | Store<string>
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import { ariaLabel } from "../../Utils/ariaLabel"
|
||||
|
||||
/**
|
||||
* A round button with an icon and possible a small text, which hovers above the map
|
||||
*/
|
||||
const dispatch = createEventDispatcher()
|
||||
export let cls = ""
|
||||
export let arialabel: Translation = undefined
|
||||
</script>
|
||||
|
||||
<button
|
||||
on:click={(e) => dispatch("click", e)}
|
||||
on:keydown
|
||||
use:ariaLabel={arialabel}
|
||||
class={twJoin("pointer-events-auto m-0.5 h-fit w-fit rounded-full p-0.5 sm:p-1 md:m-1", cls)}
|
||||
>
|
||||
<slot />
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import ToSvelte from "./ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import Share from "../../assets/svg/Share.svelte"
|
||||
import { ariaLabel } from "../../Utils/ariaLabel"
|
||||
import Translations from "../i18n/Translations"
|
||||
|
||||
export let generateShareData: () => {
|
||||
text: string
|
||||
|
@ -24,7 +26,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<button on:click={share} class="secondary m-0 h-8 w-8 p-0">
|
||||
<button on:click={share} class="secondary m-0 h-8 w-8 p-0" use:ariaLabel={Translations.t.general.share}>
|
||||
<slot name="content">
|
||||
<Share class="h-7 w-7 p-1" />
|
||||
</slot>
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
export let hideTooltip = false
|
||||
</script>
|
||||
|
||||
<MapControlButton on:click={() => state.guistate.backgroundLayerSelectionIsOpened.setData(true)}>
|
||||
<MapControlButton arialabel={Translations.t.general.labels.background}
|
||||
on:click={() => state.guistate.backgroundLayerSelectionIsOpened.setData(true)}>
|
||||
<Square3Stack3dIcon class="h-6 w-6" />
|
||||
{#if !hideTooltip}
|
||||
<Tr cls="mx-2" t={Translations.t.general.backgroundSwitch} />
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import Translations from "../i18n/Translations";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import { XCircleIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||
import { ariaLabel } from "../../Utils/ariaLabel"
|
||||
|
||||
export let state: SpecialVisualizationState;
|
||||
export let layer: LayerConfig;
|
||||
|
@ -50,8 +51,10 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button on:click={() => state.selectedElement.setData(undefined)} class="border-none p-0">
|
||||
<XCircleIcon class="h-8 w-8" />
|
||||
<button on:click={() => state.selectedElement.setData(undefined)}
|
||||
use:ariaLabel={Translations.t.general.backToMap}
|
||||
class="border-none p-0">
|
||||
<XCircleIcon aria-hidden={true} class="h-8 w-8" />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<Tr t={title} />
|
||||
|
||||
{#if selected}
|
||||
<span class="alert">
|
||||
<span class="alert" aria-hidden="true">
|
||||
<Tr t={Translations.t.general.morescreen.enterToOpen} />
|
||||
</span>
|
||||
{/if}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<div class="flex flex-col">
|
||||
{#if $license.title}
|
||||
{#if $license.informationLocation}
|
||||
<a href={$license.informationLocation} target="_blank" rel="noopener nofollower">{$license.title}</a>
|
||||
<a href={$license.informationLocation.href} target="_blank" rel="noopener nofollower">{$license.title}</a>
|
||||
{:else}
|
||||
$license.title
|
||||
{/if}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
import DateInput from "./Helpers/DateInput.svelte"
|
||||
import ColorInput from "./Helpers/ColorInput.svelte"
|
||||
import OpeningHoursInput from "./Helpers/OpeningHoursInput.svelte"
|
||||
import SlopeInput from "./Helpers/SlopeInput.svelte"
|
||||
|
||||
export let type: ValidatorType
|
||||
export let value: UIEventSource<string | object>
|
||||
|
@ -47,6 +48,8 @@
|
|||
<SimpleTagInput {value} {args} on:submit />
|
||||
{:else if type === "opening_hours"}
|
||||
<OpeningHoursInput {value} />
|
||||
{:else if type === "slope"}
|
||||
<SlopeInput {value} />
|
||||
{:else if type === "wikidata"}
|
||||
<ToSvelte construct={() => InputHelpers.constructWikidataHelper(value, properties)} />
|
||||
{/if}
|
||||
|
|
|
@ -1,36 +1,39 @@
|
|||
<script lang="ts">
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import { HeartIcon as HeartSolidIcon } from "@babeard/svelte-heroicons/solid";
|
||||
import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline";
|
||||
import Translations from "../i18n/Translations";
|
||||
import LoginToggle from "../Base/LoginToggle.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import { HeartIcon as HeartSolidIcon } from "@babeard/svelte-heroicons/solid"
|
||||
import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline"
|
||||
import Translations from "../i18n/Translations"
|
||||
import LoginToggle from "../Base/LoginToggle.svelte"
|
||||
import type { Feature } from "geojson"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { ariaLabel } from "../../Utils/ariaLabel"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
|
||||
/**
|
||||
* A small 'mark as favourite'-button to serve as title-icon
|
||||
*/
|
||||
export let state: SpecialVisualizationState;
|
||||
export let feature: Feature;
|
||||
export let tags: Record<string, string>;
|
||||
export let layer: LayerConfig;
|
||||
let isFavourite = tags?.map(tags => tags._favourite === "yes");
|
||||
const t = Translations.t.favouritePoi;
|
||||
export let state: SpecialVisualizationState
|
||||
export let feature: Feature
|
||||
export let tags: UIEventSource<Record<string, string>>
|
||||
export let layer: LayerConfig
|
||||
let isFavourite = tags?.map(tags => tags._favourite === "yes")
|
||||
const t = Translations.t.favouritePoi
|
||||
|
||||
function markFavourite(isFavourite: boolean) {
|
||||
state.favourites.markAsFavourite(feature, layer.id, state.layout.id, tags, isFavourite);
|
||||
state.favourites.markAsFavourite(feature, layer.id, state.layout.id, tags, isFavourite)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<LoginToggle ignoreLoading={true} {state}>
|
||||
{#if $isFavourite}
|
||||
<button class="p-0 m-0 h-8 w-8" on:click={() => markFavourite(false)}>
|
||||
<HeartSolidIcon/>
|
||||
<button class="p-0 m-0 h-8 w-8" on:click={() => markFavourite(false)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isMarkedShort}>
|
||||
<HeartSolidIcon aria-hidden={true} />
|
||||
</button>
|
||||
{:else}
|
||||
<button class="p-0 m-0 h-8 w-8 no-image-background" on:click={() => markFavourite(true)} >
|
||||
<HeartOutlineIcon/>
|
||||
<button class="p-0 m-0 h-8 w-8 no-image-background" on:click={() => markFavourite(true)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isNotMarkedShort}>
|
||||
<HeartOutlineIcon aria-hidden={true} />
|
||||
</button>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
|
|
|
@ -45,7 +45,6 @@ import { GeoOperations } from "../Logic/GeoOperations"
|
|||
import CreateNewNote from "./Popup/CreateNewNote.svelte"
|
||||
import AddNewPoint from "./Popup/AddNewPoint/AddNewPoint.svelte"
|
||||
import UserProfile from "./BigComponents/UserProfile.svelte"
|
||||
import Link from "./Base/Link"
|
||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig"
|
||||
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
|
||||
import { WayId } from "../Models/OsmFeature"
|
||||
|
@ -81,9 +80,9 @@ import MarkAsFavouriteMini from "./Popup/MarkAsFavouriteMini.svelte"
|
|||
import NextChangeViz from "./OpeningHours/NextChangeViz.svelte"
|
||||
import NearbyImages from "./Image/NearbyImages.svelte"
|
||||
import NearbyImagesCollapsed from "./Image/NearbyImagesCollapsed.svelte"
|
||||
import { svelte } from "@sveltejs/vite-plugin-svelte"
|
||||
import MoveWizard from "./Popup/MoveWizard.svelte"
|
||||
import { Unit } from "../Models/Unit"
|
||||
import Link from "./Base/Link.svelte"
|
||||
|
||||
class NearbyImageVis implements SpecialVisualization {
|
||||
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
||||
|
@ -1288,6 +1287,10 @@ export default class SpecialVisualizations {
|
|||
name: "download",
|
||||
doc: "If set, this link will act as a download-button. The contents of `href` will be offered for download; this parameter will act as the proposed filename",
|
||||
},
|
||||
{
|
||||
name: "arialabel",
|
||||
doc: "If set, this text will be used as aria-label",
|
||||
},
|
||||
],
|
||||
needsUrls: [],
|
||||
constr(
|
||||
|
@ -1295,15 +1298,19 @@ export default class SpecialVisualizations {
|
|||
tagSource: UIEventSource<Record<string, string>>,
|
||||
args: string[]
|
||||
): BaseUIElement {
|
||||
const [text, href, classnames, download] = args
|
||||
const [text, href, classnames, download, ariaLabel] = args
|
||||
const newTab = download === undefined && !href.startsWith("#")
|
||||
return new VariableUiElement(
|
||||
tagSource.map((tags) =>
|
||||
new Link(
|
||||
Utils.SubstituteKeys(text, tags),
|
||||
Utils.SubstituteKeys(href, tags),
|
||||
download === undefined && !href.startsWith("#"),
|
||||
Utils.SubstituteKeys(download, tags)
|
||||
).SetClass(classnames)
|
||||
tagSource.map(
|
||||
(tags) =>
|
||||
new SvelteUIElement(Link, {
|
||||
text: Utils.SubstituteKeys(text, tags),
|
||||
href: Utils.SubstituteKeys(href, tags),
|
||||
classnames,
|
||||
download: Utils.SubstituteKeys(download, tags),
|
||||
ariaLabel: Utils.SubstituteKeys(ariaLabel, tags),
|
||||
newTab,
|
||||
})
|
||||
)
|
||||
)
|
||||
},
|
||||
|
@ -1422,12 +1429,11 @@ export default class SpecialVisualizations {
|
|||
const [_, username, host] = fediAccount.match(
|
||||
FediverseValidator.usernameAtServer
|
||||
)
|
||||
|
||||
return new Link(
|
||||
fediAccount,
|
||||
"https://" + host + "/@" + username,
|
||||
true
|
||||
)
|
||||
return new SvelteUIElement(Link, {
|
||||
text: fediAccount,
|
||||
url: "https://" + host + "/@" + username,
|
||||
newTab: true,
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<script lang="ts">
|
||||
// Testing grounds
|
||||
import { UIEventSource } from "../Logic/UIEventSource"
|
||||
import SlopeInput from "./InputElement/Helpers/SlopeInput.svelte"
|
||||
let value: UIEventSource<string> = new UIEventSource(undefined)
|
||||
</script>
|
||||
|
||||
<div class="w-full">No tests</div>
|
||||
<div class="w-full flex flex-col">
|
||||
<div>Value: {$value}</div>
|
||||
</div>
|
||||
<SlopeInput {value}></SlopeInput>
|
||||
|
|
|
@ -64,10 +64,10 @@
|
|||
import Share from "../assets/svg/Share.svelte"
|
||||
import Favourites from "./Favourites/Favourites.svelte"
|
||||
import ImageOperations from "./Image/ImageOperations.svelte"
|
||||
import { ariaLabel } from "../Utils/ariaLabel"
|
||||
|
||||
export let state: ThemeViewState
|
||||
let layout = state.layout
|
||||
|
||||
let maplibremap: UIEventSource<MlMap> = state.map
|
||||
let selectedElement: UIEventSource<Feature> = new UIEventSource<Feature>(undefined)
|
||||
|
||||
|
@ -142,7 +142,8 @@
|
|||
</div>
|
||||
</If>
|
||||
<div class="float-left m-1 flex flex-col sm:mt-2">
|
||||
<MapControlButton on:click={() => state.guistate.themeIsOpened.setData(true)} on:keydown={forwardEventToMap}>
|
||||
<MapControlButton on:click={() => state.guistate.themeIsOpened.setData(true)}
|
||||
on:keydown={forwardEventToMap}>
|
||||
<div class="m-0.5 mx-1 flex cursor-pointer items-center max-[480px]:w-full sm:mx-1 md:mx-2">
|
||||
<img class="mr-0.5 block h-6 w-6 sm:mr-1 md:mr-2 md:h-8 md:w-8" src={layout.icon} />
|
||||
<b class="mr-1">
|
||||
|
@ -150,15 +151,19 @@
|
|||
</b>
|
||||
</div>
|
||||
</MapControlButton>
|
||||
<MapControlButton on:click={() => state.guistate.menuIsOpened.setData(true)} on:keydown={forwardEventToMap}>
|
||||
<MapControlButton
|
||||
on:click={() => state.guistate.menuIsOpened.setData(true)}
|
||||
on:keydown={forwardEventToMap}
|
||||
arialabel={Translations.t.general.labels.menu}
|
||||
>
|
||||
<MenuIcon class="h-8 w-8 cursor-pointer" />
|
||||
</MapControlButton>
|
||||
{#if currentViewLayer?.tagRenderings && currentViewLayer.defaultIcon()}
|
||||
<MapControlButton
|
||||
on:click={() => {
|
||||
selectedElement.setData(state.currentView.features?.data?.[0])
|
||||
}} on:keydown={forwardEventToMap}
|
||||
|
||||
}}
|
||||
on:keydown={forwardEventToMap}
|
||||
>
|
||||
<ToSvelte
|
||||
construct={() => currentViewLayer.defaultIcon().SetClass("w-8 h-8 cursor-pointer")}
|
||||
|
@ -206,7 +211,9 @@
|
|||
<div class="flex">
|
||||
<!-- bottom left elements -->
|
||||
<If condition={state.featureSwitches.featureSwitchFilter}>
|
||||
<MapControlButton on:click={() => state.guistate.openFilterView()} on:keydown={forwardEventToMap}>
|
||||
<MapControlButton on:click={() => state.guistate.openFilterView()} on:keydown={forwardEventToMap}
|
||||
arialabel={Translations.t.general.labels.filter}
|
||||
>
|
||||
<Filter class="h-6 w-6" />
|
||||
</MapControlButton>
|
||||
</If>
|
||||
|
@ -246,14 +253,21 @@
|
|||
/>
|
||||
</div>
|
||||
</If>
|
||||
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z + 1)} on:keydown={forwardEventToMap}>
|
||||
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z + 1)}
|
||||
on:keydown={forwardEventToMap}
|
||||
arialabel={Translations.t.general.labels.zoomIn}
|
||||
>
|
||||
<Plus class="h-8 w-8" />
|
||||
</MapControlButton>
|
||||
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z - 1)} on:keydown={forwardEventToMap}>
|
||||
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z - 1)} on:keydown={forwardEventToMap}
|
||||
arialabel={Translations.t.general.labels.zoomOut}
|
||||
>
|
||||
<Min class="h-8 w-8" />
|
||||
</MapControlButton>
|
||||
<If condition={featureSwitches.featureSwitchGeolocation}>
|
||||
<MapControlButton on:keydown={forwardEventToMap} on:click={() => geolocationControl.handleClick()}>
|
||||
<MapControlButton on:keydown={forwardEventToMap} on:click={() => geolocationControl.handleClick()}
|
||||
arialabel={Translations.t.general.labels.jumpToLocation}
|
||||
>
|
||||
<ToSvelte
|
||||
construct={geolocationControl.SetClass("block w-8 h-8")}
|
||||
/>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { Translation } from "../UI/i18n/Translation"
|
||||
|
||||
export function ariaLabel(htmlElement: Element, t: Translation) {
|
||||
if (!t) {
|
||||
return
|
||||
}
|
||||
let destroy: () => void = undefined
|
||||
|
||||
t.current.map(
|
||||
|
|
Loading…
Reference in a new issue