Added legal notice modal
This commit is contained in:
@@ -76,7 +76,7 @@
|
||||
}
|
||||
|
||||
&.btn-shadow {
|
||||
box-shadow: rgba(0, 0, 0, 0.15) 0 .2rem .3rem;
|
||||
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0 .2rem .3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
aspect-ratio: 1;
|
||||
background-color: var(--white);
|
||||
border: 1px solid var(--slate-400);
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
|
||||
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0px 4px 12px;
|
||||
border-radius: 100vmax;
|
||||
pointer-events: all;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
border-radius: 8px;
|
||||
background-color: var(--white);
|
||||
border: 1px solid var(--slate-100);
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
|
||||
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0px 4px 12px;
|
||||
min-width: 15rem;
|
||||
|
||||
.card-arrow {
|
||||
|
||||
80
src/assets/scss/radix/_dialog.scss
Normal file
80
src/assets/scss/radix/_dialog.scss
Normal file
@@ -0,0 +1,80 @@
|
||||
.dialog-overlay {
|
||||
background-color: color-mix(in srgb, var(--black) 40%, transparent);
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
animation: show-overlay 150ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.dialog-content {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 200;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 50rem;
|
||||
max-width: calc(100% - 4rem);
|
||||
max-height: 85vh;
|
||||
padding: 25px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--white);
|
||||
border: 1px solid var(--slate-100);
|
||||
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0px 4px 12px;
|
||||
animation: show-content 150ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
margin-bottom: .5em;
|
||||
font-size: 1.5em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.dialog-description {
|
||||
h3 {
|
||||
font-size: 1.25em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
font-size: 1em;
|
||||
color: var(--slate-800);
|
||||
line-height: 1.5;
|
||||
|
||||
> * + * {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-underline-offset: 2px;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
text-decoration: none;
|
||||
color: var(--green-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-overlay {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-content {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -48%) scale(0.96);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
@use 'map';
|
||||
|
||||
@use 'radix/toast';
|
||||
@use 'radix/dialog';
|
||||
|
||||
:root {
|
||||
--white: #fff;
|
||||
@@ -56,6 +57,10 @@ a[href^='http']::after {
|
||||
margin-left: .25em;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1em;
|
||||
}
|
||||
@@ -1,22 +1,36 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onUpdated, ref, watch } from 'vue';
|
||||
import { computed, onUpdated, ref, watch } from 'vue'
|
||||
import { useElementHover, useFocus } from '@vueuse/core'
|
||||
import { PopoverArrow, PopoverContent, PopoverRoot, PopoverTrigger } from 'radix-vue'
|
||||
import { useStore } from '@nanostores/vue';
|
||||
import {
|
||||
PopoverArrow,
|
||||
PopoverContent,
|
||||
PopoverRoot,
|
||||
PopoverTrigger,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
DialogRoot,
|
||||
DialogTitle,
|
||||
DialogTrigger
|
||||
} from 'radix-vue'
|
||||
|
||||
import { currentLang } from '@/i18n/store';
|
||||
import { t } from '@/i18n/store';
|
||||
import { useStore } from '@nanostores/vue'
|
||||
|
||||
const $currentLang = useStore(currentLang);
|
||||
import { currentLang } from '@/i18n/store'
|
||||
import { t } from '@/i18n/store'
|
||||
|
||||
const navModel = ref(false);
|
||||
const $currentLang = useStore(currentLang)
|
||||
|
||||
const navModel = ref(false)
|
||||
const legalModelOpened = ref(false)
|
||||
|
||||
const wrapper = ref<HTMLDivElement | null>(null)
|
||||
const buttonRef = ref<HTMLButtonElement | null>(null)
|
||||
const wrapperHovered = useElementHover(wrapper, { delayEnter: 100, delayLeave: 500 })
|
||||
const { focused: buttonFocused } = useFocus(buttonRef)
|
||||
|
||||
const isNavOpened = computed(() => navModel.value || wrapperHovered.value)
|
||||
const isNavOpened = computed(() => navModel.value || wrapperHovered.value || legalModelOpened.value )
|
||||
|
||||
watch([wrapperHovered, buttonFocused], (value) => {
|
||||
// Check if all values from array are false
|
||||
@@ -25,7 +39,7 @@ watch([wrapperHovered, buttonFocused], (value) => {
|
||||
}
|
||||
})
|
||||
|
||||
let url: URL | null = null;
|
||||
let url: URL | null = null
|
||||
|
||||
onUpdated(() => {
|
||||
url = new URL(window.location.href)
|
||||
@@ -132,9 +146,23 @@ const menus: Menu[] = [
|
||||
</template>
|
||||
|
||||
<div class="legal">
|
||||
<a :href="`/${$currentLang}/legal`">
|
||||
<DialogRoot v-model:open="legalModelOpened">
|
||||
<DialogTrigger as-child>
|
||||
<button :href="`/${$currentLang}/legal`">
|
||||
{{ t('legal.cta') }}
|
||||
</a>
|
||||
</button>
|
||||
</DialogTrigger>
|
||||
<DialogPortal>
|
||||
<DialogOverlay class="dialog-overlay" />
|
||||
|
||||
<DialogContent class="dialog-content">
|
||||
<DialogTitle class="dialog-title">
|
||||
{{ t('legal.cta') }}
|
||||
</DialogTitle>
|
||||
<DialogDescription class="dialog-description" v-html="t('legal.text')" />
|
||||
</DialogContent>
|
||||
</DialogPortal>
|
||||
</DialogRoot>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</PopoverRoot>
|
||||
@@ -167,6 +195,10 @@ const menus: Menu[] = [
|
||||
text-decoration: underline;
|
||||
gap: .5ch;
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
text-decoration: none;
|
||||
|
||||
@@ -37,6 +37,15 @@ export const translations: LanguageDict = {
|
||||
'maps.markers.newNotice': "Le marqueur sera sauvegardé mais n'apparaîtra que sur votre carte !",
|
||||
'toast.copyCoords.description': 'Les coordonnées ont été copiées dans le presse-papiers !',
|
||||
'legal.cta': 'Mentions légales',
|
||||
'legal.text': `
|
||||
<p>Cette application est construite avec <a href="https://astro.build/" target="_blank">astro</a>, <a href="https://leafletjs.com/" target="_blank">leaflet</a> et <a href="https://vuejs.org/" target="_blank">vue</a>. J'utilise également des icônes de <a href="https://phosphoricons.com/" target="_blank">phosphor</a> et elle est actuellement hébergée sur <a href="https://www.ovhcloud.com" target="_blank">OVH</a>.</p>
|
||||
<h3>Données personelles</h3>
|
||||
<p>Je ne collecte aucune donnée sur votre activité dans cette application. Les marqueurs personnalisés que vous pouvez placer n'existent que sur votre navigateur en tant que données de <a href="https://developer.mozilla.org/fr/docs/Web/API/Window/localStorage" target="_blank">local storage</a>.</p>
|
||||
<p>Mon hébergeur collecte des données de trafic pour des raisons de sécurité ; comme les adresses IP et leur emplacement approximatif, les types de navigateurs, les agents utilisateurs (si vous êtes un robot ou un humain) et l'état de la demande. </p>
|
||||
<p>Ce site n'utilise pas de pixels de suivi ou d'analyse, et je n'utilise aucune autre application tierce qui pourrait collecter des données sur vous (comme Youtube ou autre)</p>
|
||||
<p>Malgré cela, <strong>aucune de vos données n'est vendue ou transmise à un tiers quel qu'il soit</strong>.</p>
|
||||
<p>Si vous avez des questions, vous pouvez me contacter à <a href="mailto:contact@alexcreates.fr">contact@alexcreates.fr</a>.</p>
|
||||
`
|
||||
},
|
||||
'en': {
|
||||
'lang.fr': 'Français',
|
||||
@@ -70,5 +79,14 @@ export const translations: LanguageDict = {
|
||||
'maps.markers.newNotice': "The marker will be saved but will only appear on your map!",
|
||||
'toast.copyCoords.description': 'Coordinates have been copied to your clipboard !',
|
||||
'legal.cta': 'Legal notice',
|
||||
'legal.text': `
|
||||
<p>This app is built with <a href="https://astro.build/" target="_blank">astro</a>, <a href="https://leafletjs.com/" target="_blank">leaflet</a> and <a href="https://vuejs.org/" target="_blank">vue</a>. I also use icons from <a href="https://phosphoricons.com/" target="_blank">phosphor</a> and it's currently hosted on <a href="https://www.ovhcloud.com" target="_blank">OVH</a>.</p>
|
||||
<h3>Privacy</h3>
|
||||
<p>I don't collect any data of your activity with this app. The custom markers that you may place only exist on your browser as <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage" target="_blank">local storage</a> data.</p>
|
||||
<p>My hosting provider collects traffic data for security reasons ; like IP addresses and their approximate location, browsers types, user agents (if you're a robot or a human) and the request status.</p>
|
||||
<p>This website doesn't use any tracking pixels or analytics, and I don't use any other third-party app that might collect stuff from you (like Youtube or anything else)</p>
|
||||
<p>Regardless, <strong>none of your data is sold or passed to any third-party whatsoever</strong>.</p>
|
||||
<p>If you have any questions, you can contact me at <a href="mailto:contact@alexcreates.fr">contact@alexcreates.fr</a>.</p>
|
||||
`
|
||||
}
|
||||
} as const;
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface SearchConfig {
|
||||
}
|
||||
|
||||
export interface MapProps {
|
||||
title?: string
|
||||
/**
|
||||
* The ID of the map.
|
||||
* This is used to identify the map and store custom markers in the local storage.
|
||||
|
||||
Reference in New Issue
Block a user