Added legal notice modal
This commit is contained in:
@@ -76,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.btn-shadow {
|
&.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;
|
aspect-ratio: 1;
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
border: 1px solid var(--slate-400);
|
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;
|
border-radius: 100vmax;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
border: 1px solid var(--slate-100);
|
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;
|
min-width: 15rem;
|
||||||
|
|
||||||
.card-arrow {
|
.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 'map';
|
||||||
|
|
||||||
@use 'radix/toast';
|
@use 'radix/toast';
|
||||||
|
@use 'radix/dialog';
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--white: #fff;
|
--white: #fff;
|
||||||
@@ -56,6 +57,10 @@ a[href^='http']::after {
|
|||||||
margin-left: .25em;
|
margin-left: .25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,36 @@
|
|||||||
<script lang="ts" setup>
|
<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 { useElementHover, useFocus } from '@vueuse/core'
|
||||||
import { PopoverArrow, PopoverContent, PopoverRoot, PopoverTrigger } from 'radix-vue'
|
import {
|
||||||
import { useStore } from '@nanostores/vue';
|
PopoverArrow,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverRoot,
|
||||||
|
PopoverTrigger,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogPortal,
|
||||||
|
DialogRoot,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger
|
||||||
|
} from 'radix-vue'
|
||||||
|
|
||||||
import { currentLang } from '@/i18n/store';
|
import { useStore } from '@nanostores/vue'
|
||||||
import { t } from '@/i18n/store';
|
|
||||||
|
|
||||||
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 wrapper = ref<HTMLDivElement | null>(null)
|
||||||
const buttonRef = ref<HTMLButtonElement | null>(null)
|
const buttonRef = ref<HTMLButtonElement | null>(null)
|
||||||
const wrapperHovered = useElementHover(wrapper, { delayEnter: 100, delayLeave: 500 })
|
const wrapperHovered = useElementHover(wrapper, { delayEnter: 100, delayLeave: 500 })
|
||||||
const { focused: buttonFocused } = useFocus(buttonRef)
|
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) => {
|
watch([wrapperHovered, buttonFocused], (value) => {
|
||||||
// Check if all values from array are false
|
// 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(() => {
|
onUpdated(() => {
|
||||||
url = new URL(window.location.href)
|
url = new URL(window.location.href)
|
||||||
@@ -132,9 +146,23 @@ const menus: Menu[] = [
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="legal">
|
<div class="legal">
|
||||||
<a :href="`/${$currentLang}/legal`">
|
<DialogRoot v-model:open="legalModelOpened">
|
||||||
{{ t('legal.cta') }}
|
<DialogTrigger as-child>
|
||||||
</a>
|
<button :href="`/${$currentLang}/legal`">
|
||||||
|
{{ t('legal.cta') }}
|
||||||
|
</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>
|
</div>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</PopoverRoot>
|
</PopoverRoot>
|
||||||
@@ -167,6 +195,10 @@ const menus: Menu[] = [
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
gap: .5ch;
|
gap: .5ch;
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
text-decoration: none;
|
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 !",
|
'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 !',
|
'toast.copyCoords.description': 'Les coordonnées ont été copiées dans le presse-papiers !',
|
||||||
'legal.cta': 'Mentions légales',
|
'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': {
|
'en': {
|
||||||
'lang.fr': 'Français',
|
'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!",
|
'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 !',
|
'toast.copyCoords.description': 'Coordinates have been copied to your clipboard !',
|
||||||
'legal.cta': 'Legal notice',
|
'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;
|
} as const;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export interface SearchConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MapProps {
|
export interface MapProps {
|
||||||
|
title?: string
|
||||||
/**
|
/**
|
||||||
* The ID of the map.
|
* The ID of the map.
|
||||||
* This is used to identify the map and store custom markers in the local storage.
|
* This is used to identify the map and store custom markers in the local storage.
|
||||||
|
|||||||
Reference in New Issue
Block a user