39 Commits

Author SHA1 Message Date
Alexis
dae2bb7524 Added matomo tracking 2026-07-11 14:54:17 +02:00
Alexis
b06ef38fd7 Updated privacy policy 2026-07-11 14:44:12 +02:00
Alexis
2e0884a6b7 Updated package 2026-07-11 14:26:57 +02:00
Alexis
d43b7761f0 Astro upgrade 2026-07-11 14:25:16 +02:00
Alexis
7164ec65b9 Fixed dist watching issues 2026-07-11 14:23:07 +02:00
Alexis
e7a793a25e Added pnpm workspace 2026-07-11 14:00:30 +02:00
Alexis
5198dcf656 Fixed typo 2026-07-07 20:15:16 +02:00
Alexis
39a4f91e2e Updated package 2026-03-25 12:14:46 +01:00
Alexis
ae3bd70e3c Version bump 2025-11-19 18:30:03 +01:00
Alexis
3b70b878a4 Merge branch 'dev' 2025-11-19 18:27:45 +01:00
Alexis
232ef4d914 Updated package 2025-11-19 18:27:35 +01:00
Alexis
df81c74d76 Updated package 2025-10-15 17:39:32 +02:00
Alexis
d85708a571 Updated package 2025-09-17 21:55:09 +02:00
Alexis
3911e55a6c Updated package 2025-09-12 19:53:47 +02:00
Alexis
c09df15821 Updated package 2025-09-03 21:07:55 +02:00
Alexis
defd3968fd Updated readme with .env specs 2025-08-27 19:51:20 +02:00
Alexis
0386cc3fe0 Updated readme 2025-08-27 19:47:21 +02:00
Alexis
832c37ef9d Updated packages 2025-08-27 19:46:29 +02:00
Alexis
f2f42c0400 Updated packages 2025-08-23 22:38:51 +02:00
Alexis
d49d5e79f2 Updated packages 2025-08-13 16:12:05 +02:00
Alexis
4209771189 Version bump 2025-07-17 23:20:18 +02:00
Alexis
e43baa13da Merge branch 'dev' 2025-07-17 23:19:29 +02:00
Alexis
b243c3129d Fixed some accessibility issues 2025-07-17 23:19:24 +02:00
Alexis
3f60672bb0 Fixed some SEO data 2025-07-17 23:11:02 +02:00
Alexis
5792d7d15f Sample missing icons 2025-07-17 22:12:00 +02:00
Alexis
91ea78c632 Updated package 2025-07-17 22:11:53 +02:00
Alexis
961fd0d198 Updated package 2025-07-14 18:49:30 +02:00
Alexis
1cba7b398b Updated package 2025-06-25 16:16:01 +02:00
Alexis
05d3bca10b Version bump 2025-06-22 14:35:09 +02:00
Alexis
3acfc6db47 Merge branch 'dev' 2025-06-22 14:29:08 +02:00
Alexis
6c350bf2d5 Removed new item for mine map 2025-06-22 14:28:26 +02:00
Alexis
712d408736 Added theme switcher 2025-06-21 21:33:25 +02:00
Alexis
bfdd433a5f Added dark mode ui for leaflet controls 2025-06-21 14:32:23 +02:00
Alexis
ac6558392c Fixed some more UI with dark mode 2025-06-21 11:49:15 +02:00
Alexis
484fe3b031 Fixed search results in dark mode 2025-06-21 11:33:20 +02:00
Alexis
c88133a9a3 Moved some variables to root 2025-06-20 20:06:07 +02:00
Alexis
1cb77dd6f0 Version bump 2025-06-20 17:20:42 +02:00
Alexis
a2fe47210f Updated packages 2025-06-20 17:20:29 +02:00
Alexis
38dfd3c952 Updated readme 2025-06-20 17:11:59 +02:00
41 changed files with 2922 additions and 2985 deletions

View File

@@ -1,5 +1,25 @@
# Leim Maps # Leim Maps
Repository for interactive maps using Leim's Wiki data 🗺️ A simple Astro static site to display custom maps with Leaflet. Includes sample images with maps from my own world.
## Demo ## Features
Live demo available at https://maps.alexcreates.fr * Add your own markers for cities, NPCs, or quests
* Search through markers
* Create multiple maps for different continents or countries
* Measure distances between two points
* Custom client-side markers
## Documentation
### Making usable map assets
Since we're not using earth maps, we need to build one compatible with Leaflet. I used Zoomify to generate usable tile data from my SVG maps. I don't know if this will fit your use case ; if you use something else, you can contact me !
> [!IMPORTANT]
> As of writing this, it appears Zoomify Unlimited Converter (which is what I used) is not available on Linux or for download anymore
### Enabling features
Some features are able to be toggled on and off. If you don't use multiple languages, or if you don't want the custom markers, you can disable them in the .env file. By default, all of them are true.
## Contributing
I'm not currently accepting pull-requests for this project, but if you have a suggestion, feel free to contact me !
## Notes
As someone with some degree of [aphantasia](https://en.wikipedia.org/wiki/Aphantasia), I struggle with visualization and immersion, and DMing in general. If you find yourself in the same situation, I hope my little thing made your life easier !

View File

@@ -5,17 +5,26 @@ import sitemap from "@astrojs/sitemap";
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
integrations: [vue(), sitemap()], integrations: [vue(), sitemap()],
output: 'static', output: 'static',
site: 'https://maps.alexcreates.fr', site: 'https://maps.alexcreates.fr',
prefetch: true, prefetch: true,
env: { env: {
schema: { schema: {
ENABLE_TOOLBAR: envField.boolean({ context: "server", access: "secret", default: true }), ENABLE_TOOLBAR: envField.boolean({ context: "server", access: "secret", default: true }),
ENABLE_TOOLBAR_TAGS: envField.boolean({ context: "server", access: "secret", default: true }), ENABLE_TOOLBAR_TAGS: envField.boolean({ context: "server", access: "secret", default: true }),
ENABLE_CUSTOM_MARKERS: envField.boolean({ context: "server", access: "secret", default: true }), ENABLE_CUSTOM_MARKERS: envField.boolean({ context: "server", access: "secret", default: true }),
ENABLE_BREADCRUMB: envField.boolean({ context: "server", access: "secret", default: true }), ENABLE_BREADCRUMB: envField.boolean({ context: "server", access: "secret", default: true }),
ENABLE_I18N: envField.boolean({ context: "server", access: "secret", default: true }), ENABLE_I18N: envField.boolean({ context: "server", access: "secret", default: true }),
}
},
vite: {
server: {
watch: {
ignored: [
'**/dist/**', // dist shouldn't be watched
],
},
},
} }
}
}); });

View File

@@ -1,7 +1,7 @@
{ {
"name": "leim-maps", "name": "leim-maps",
"type": "module", "type": "module",
"version": "1.4.10", "version": "1.4.14",
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"start": "astro dev", "start": "astro dev",
@@ -10,18 +10,18 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/sitemap": "^3.4.1", "@astrojs/sitemap": "^3.7.3",
"@astrojs/vue": "^5.1.0", "@astrojs/vue": "^7.0.1",
"@nanostores/persistent": "1.0.0", "@nanostores/persistent": "1.3.4",
"@nanostores/vue": "^1.0.0", "@nanostores/vue": "^1.1.0",
"@types/leaflet": "^1.9.18", "@types/leaflet": "^1.9.21",
"@vueuse/core": "^13.3.0", "@vueuse/core": "^14.3.0",
"astro": "^5.9.3", "astro": "^7.0.7",
"nanostores": "^1.0.1", "nanostores": "^1.4.0",
"radix-vue": "^1.9.17", "radix-vue": "^1.9.17",
"vue": "^3.5.16" "vue": "^3.5.39"
}, },
"devDependencies": { "devDependencies": {
"sass": "^1.89.2" "sass": "^1.101.0"
} }
} }

5239
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,8 @@
allowBuilds:
'@parcel/watcher': true
esbuild: true
sharp: true
vue-demi: true
onlyBuiltDependencies: onlyBuiltDependencies:
- '@parcel/watcher' - '@parcel/watcher'
- esbuild - esbuild

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="#FFF"><path d="M140,180a12,12,0,1,1-12-12A12,12,0,0,1,140,180ZM128,72c-22.06,0-40,16.15-40,36v4a8,8,0,0,0,16,0v-4c0-11,10.77-20,24-20s24,9,24,20-10.77,20-24,20a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-.72c18.24-3.35,32-17.9,32-35.28C168,88.15,150.06,72,128,72Zm104,56A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z"></path></svg>

After

Width:  |  Height:  |  Size: 440 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#FFF" viewBox="0 0 256 256"><path d="M235.32,73.37,182.63,20.69a16,16,0,0,0-22.63,0L20.68,160a16,16,0,0,0,0,22.63l52.69,52.68a16,16,0,0,0,22.63,0L235.32,96A16,16,0,0,0,235.32,73.37ZM84.68,224,32,171.31l32-32,26.34,26.35a8,8,0,0,0,11.32-11.32L75.31,128,96,107.31l26.34,26.35a8,8,0,0,0,11.32-11.32L107.31,96,128,75.31l26.34,26.35a8,8,0,0,0,11.32-11.32L139.31,64l32-32L224,84.69Z"></path></svg>

After

Width:  |  Height:  |  Size: 461 B

1
public/icon/ruler.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#020617" viewBox="0 0 256 256"><path d="M235.32,73.37,182.63,20.69a16,16,0,0,0-22.63,0L20.68,160a16,16,0,0,0,0,22.63l52.69,52.68a16,16,0,0,0,22.63,0L235.32,96A16,16,0,0,0,235.32,73.37ZM84.68,224,32,171.31l32-32,26.34,26.35a8,8,0,0,0,11.32-11.32L75.31,128,96,107.31l26.34,26.35a8,8,0,0,0,11.32-11.32L107.31,96,128,75.31l26.34,26.35a8,8,0,0,0,11.32-11.32L139.31,64l32-32L224,84.69Z"></path></svg>

After

Width:  |  Height:  |  Size: 464 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M224,104a8,8,0,0,1-13.66,5.66L184,83.31l-42.34,42.35a8,8,0,0,1-11.32-11.32L172.69,72,146.34,45.66A8,8,0,0,1,152,32h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z" fill="#FFF" /></svg>

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,7 +1,7 @@
// Animations on load // Animations on load
@media screen and (prefers-reduced-motion: no-preference) { @media screen and (prefers-reduced-motion: no-preference) {
.appear-from-top { .appear-from-top {
animation: fadeIn .2s cubic-bezier(0.785, 0.135, 0.15, 0.86); animation: fadeIn .2s var(--timing-function);
} }
@keyframes fadeIn { @keyframes fadeIn {

View File

@@ -5,12 +5,13 @@
gap: .5rem; gap: .5rem;
font-size: .9em; font-size: .9em;
font-weight: 500; font-weight: 500;
color: var(--foreground);
border: 1px solid transparent; border: 1px solid transparent;
border-radius: .2rem; border-radius: var(--border-radius);
cursor: pointer; cursor: pointer;
transition-property: color, background-color, border-color; transition-property: color, background-color, border-color;
transition-duration: .2s; transition-duration: .2s;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86); transition-timing-function: var(--timing-function);
&:disabled { &:disabled {
cursor: not-allowed; cursor: not-allowed;
@@ -18,40 +19,40 @@
&.btn-secondary { &.btn-secondary {
&:not(:disabled) { &:not(:disabled) {
background-color: var(--slate-200); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
&:hover, &:hover,
&:focus-visible { &:focus-visible {
color: var(--white); color: var(--background);
background-color: var(--blue-500); background-color: var(--accent);
} }
} }
&:disabled { &:disabled {
color: var(--slate-500); color: color-mix(in srgb, var(--foreground) 50%, var(--background));
background-color: var(--slate-100); background-color: color-mix(in srgb, var(--foreground) 10%, var(--background));
} }
} }
&.btn-info { &.btn-info {
&:not(:disabled) { &:not(:disabled) {
background-color: var(--slate-200); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
&:hover, &:hover,
&:focus-visible { &:focus-visible {
color: var(--white); color: var(--background);
background-color: var(--blue-500); background-color: var(--accent);
} }
} }
} }
&.btn-danger { &.btn-danger {
&:not(:disabled) { &:not(:disabled) {
background-color: var(--slate-200); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
&:hover, &:hover,
&:focus-visible { &:focus-visible {
color: var(--white); color: var(--background);
background-color: var(--red-500); background-color: var(--red-500);
} }
} }
@@ -76,7 +77,7 @@
} }
&.btn-shadow { &.btn-shadow {
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0 .2rem .3rem; box-shadow: var(--shadow);
} }
} }
@@ -85,41 +86,42 @@
place-items: center; place-items: center;
height: 45px; height: 45px;
aspect-ratio: 1; aspect-ratio: 1;
background-color: var(--white); background-color: var(--background);
border: 1px solid var(--slate-400); border: 1px solid var(--border);
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0px 4px 12px; box-shadow: var(--shadow);
border-radius: 100vmax; border-radius: 100vmax;
pointer-events: all; pointer-events: all;
cursor: pointer; cursor: pointer;
outline: .2rem solid transparent; outline: .2rem solid transparent;
transition-property: color, background-color, border-color, outline-color; transition-property: color, background-color, border-color, outline-color;
transition-duration: .15s; transition-duration: .15s;
transition-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95); transition-timing-function: var(--timing-function);
svg { svg {
fill: var(--foreground);
width: 1.15em; width: 1.15em;
transition-property: fill; transition-property: fill;
transition-duration: .15s; transition-duration: .15s;
transition-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95); transition-timing-function: var(--timing-function);
} }
&:hover, &:hover,
&:focus-visible { &:focus-visible {
outline-color: color-mix(in srgb, var(--blue-500) 20%, transparent); outline-color: color-mix(in srgb, var(--accent) 20%, transparent);
border-color: var(--blue-500); border-color: var(--accent);
svg { svg {
fill: var(--blue-500); fill: var(--accent);
} }
} }
&.active { &.active {
color: var(--white); color: var(--background);
background-color: var(--blue-500); background-color: var(--accent);
border-color: var(--blue-700); border-color: color-mix(in srgb, var(--accent) 75%, var(--background));
svg { svg {
fill: var(--white); fill: var(--background);
} }
} }
} }

View File

@@ -2,13 +2,14 @@
padding-block: 0.75rem; padding-block: 0.75rem;
padding-inline: .75rem; padding-inline: .75rem;
border-radius: 8px; border-radius: 8px;
background-color: var(--white); color: var(--foreground);
border: 1px solid var(--slate-100); background-color: var(--background);
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0px 4px 12px; border: 1px solid var(--border);
box-shadow: var(--shadow);
min-width: 15rem; min-width: 15rem;
.card-arrow { .card-arrow {
fill: var(--white); fill: var(--background);
} }
&.p-sm { &.p-sm {

View File

@@ -14,15 +14,15 @@
display: block; display: block;
width: 100%; width: 100%;
padding: .4rem .5rem; padding: .4rem .5rem;
border: 1px solid var(--slate-300); border: 1px solid color-mix(in srgb, var(--foreground) 30%, var(--background));
font-size: .8em; font-size: .8em;
border-radius: .2rem; border-radius: var(--border-radius);
transition-property: box-shadow; transition-property: box-shadow;
transition-duration: .2s; transition-duration: .2s;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86); transition-timing-function: var(--timing-function);
&:focus-visible { &:focus-visible {
box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--slate-300) 20%, transparent); box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--accent) 20%, transparent);
} }
} }
} }

View File

@@ -10,7 +10,9 @@
.leaflet-map-pane { .leaflet-map-pane {
.leaflet-popup-pane { .leaflet-popup-pane {
.leaflet-popup-content-wrapper { .leaflet-popup-content-wrapper {
border-radius: .25rem; color: var(--foreground);
background-color: var(--background);
border-radius: var(--border-radius);
overflow: clip; overflow: clip;
.leaflet-popup-content { .leaflet-popup-content {
@@ -22,6 +24,7 @@
.leaflet-popup-tip { .leaflet-popup-tip {
width: .8rem; width: .8rem;
height: .8rem; height: .8rem;
background-color: var(--background);
} }
} }
@@ -29,15 +32,18 @@
.leaflet-tooltip { .leaflet-tooltip {
&.capital-name { &.capital-name {
padding: .2rem .4rem; padding: .2rem .4rem;
color: #EEE; color: var(--foreground);
font-weight: bold; font-weight: bold;
background: none; background: none;
border: none; border: none;
box-shadow: none; box-shadow: none;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
transition-property: color, text-shadow;
transition-duration: .15s;
transition-timing-function: var(--timing-function);
@include text.stroke(2, #18181b); @include text.stroke(2, var(--background));
&::before { &::before {
display: none; display: none;
@@ -47,3 +53,56 @@
} }
} }
} }
.leaflet-touch .leaflet-bar {
border-color: var(--border);
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
color: var(--foreground);
background-color: var(--background);
border-color: var(--border);
transition-property: color, background-color, border-color, outline-color;
transition-duration: .15s;
transition-timing-function: var(--timing-function);
&:hover,
&:focus-visible {
color: var(--background);
background-color: var(--accent);
}
}
}
.leaflet-touch .leaflet-control-measure {
color: var(--foreground);
background-color: var(--background);
transition-property: color, background-color, border-color, outline-color;
transition-duration: .15s;
transition-timing-function: var(--timing-function);
.leaflet-control-measure-toggle {
color: var(--foreground);
background-color: var(--background);
border-color: var(--border);
background-image: url('/icon/ruler.svg');
background-size: 66%;
transition-property: color, background-color, border-color, outline-color;
transition-duration: .15s;
transition-timing-function: var(--timing-function);
&:hover,
&:focus-visible {
color: var(--background);
background-color: var(--accent);
}
}
}
.dark {
.leaflet-touch .leaflet-control-measure {
.leaflet-control-measure-toggle {
background-image: url('/icon/ruler-dark.svg');
}
}
}

View File

@@ -1,8 +1,8 @@
.dialog-overlay { .dialog-overlay {
background-color: color-mix(in srgb, var(--black) 40%, transparent); background-color: color-mix(in srgb, var(--black) 50%, transparent);
position: fixed; position: fixed;
inset: 0; inset: 0;
animation: show-overlay 150ms cubic-bezier(0.16, 1, 0.3, 1); animation: show-overlay 150ms var(--timing-function);
z-index: 100; z-index: 100;
} }
@@ -19,11 +19,12 @@
padding: 25px; padding: 25px;
display: grid; display: grid;
grid-template-rows: auto 1fr; grid-template-rows: auto 1fr;
border-radius: 8px; color: var(--foreground);
background-color: var(--white); border-radius: var(--border-radius);
border: 1px solid var(--slate-100); background-color: var(--background);
box-shadow: color-mix(in srgb, var(--black) 10%, transparent) 0px 4px 12px; border: 1px solid var(--border);
animation: show-content 150ms cubic-bezier(0.16, 1, 0.3, 1); box-shadow: var(--shadow);
animation: show-content 150ms var(--timing-function);
&:focus { &:focus {
outline: none; outline: none;
@@ -46,7 +47,7 @@
} }
font-size: 1em; font-size: 1em;
color: var(--slate-800); color: color-mix(in srgb, var(--foreground) 80%, var(--background));
line-height: 1.5; line-height: 1.5;
> * + * { > * + * {
@@ -63,11 +64,6 @@
text-decoration: none; text-decoration: none;
color: var(--green-500); color: var(--green-500);
} }
&::after {
top: 50%;
transform: translateY(-70%);
}
} }
} }

View File

@@ -23,16 +23,16 @@
grid-template-columns: auto max-content; grid-template-columns: auto max-content;
column-gap: 15px; column-gap: 15px;
align-items: center; align-items: center;
color: var(--slate-800); color: var(--foreground);
border: 1px solid var(--slate-400); border: 1px solid var(--border);
background-color: var(--white); background-color: var(--background);
border-radius: 6px; border-radius: var(--border-radius);
box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
&.toast-success { &.toast-success {
color: var(--green-700); color: var(--green-700);
border: 1px solid var(--green-700); border: 1px solid var(--green-700);
background-color: color-mix(in srgb, var(--green-500) 17.5%, var(--white)); background-color: color-mix(in srgb, var(--green-500) 17.5%, var(--background));
.toast-icon svg { .toast-icon svg {
fill: var(--green-700); fill: var(--green-700);
@@ -51,20 +51,20 @@
} }
} }
.toast-root[data-state='open'] { .toast-root[data-state='open'] {
animation: slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1); animation: slideIn 150ms var(--timing-function);
} }
.toast-root[data-state='closed'] { .toast-root[data-state='closed'] {
animation: hide 100ms ease-in; animation: hide 100ms var(--timing-function);
} }
.toast-root[data-swipe='move'] { .toast-root[data-swipe='move'] {
transform: translateX(var(--radix-toast-swipe-move-x)); transform: translateX(var(--radix-toast-swipe-move-x));
} }
.toast-root[data-swipe='cancel'] { .toast-root[data-swipe='cancel'] {
transform: translateX(0); transform: translateX(0);
transition: transform 200ms ease-out; transition: transform 200ms var(--timing-function);
} }
.toast-root[data-swipe='end'] { .toast-root[data-swipe='end'] {
animation: swipeOut 100ms ease-out; animation: swipeOut 100ms var(--timing-function);
} }
@keyframes hide { @keyframes hide {

View File

@@ -37,19 +37,34 @@
--orange-700: #c2410c; --orange-700: #c2410c;
--purple-500: #8b5cf6; --purple-500: #8b5cf6;
--purple-700: #6d28d9; --purple-700: #6d28d9;
--foreground: var(--black);
--background: var(--white);
--border: var(--slate-400);
--accent: var(--blue-500);
--border-radius: .25rem;
--shadow: color-mix(in srgb, var(--foreground) 10%, transparent) 0px 4px 12px;
--timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
.dark {
--foreground: var(--slate-300);
--background: var(--slate-950);
--border: var(--slate-600);
} }
html { html {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
color: var(--slate-900); color: var(--foreground);
} }
a[href^='http'] { a[href^='http'] {
padding-right: 1.25em; white-space: nowrap;
orphans: 2;
} }
a[href^='http']::after { a[href^='http']::after {
position: absolute;
content: url('/icon/square-arrow-out.svg'); content: url('/icon/square-arrow-out.svg');
display: inline-block; display: inline-block;
width: 1em; width: 1em;
@@ -57,6 +72,12 @@ a[href^='http']::after {
margin-left: .25em; margin-left: .25em;
} }
.dark {
a[href^='http']::after {
content: url('/icon/square-arrow-out-dark.svg');
}
}
strong { strong {
font-weight: 600; font-weight: 600;
} }

View File

@@ -62,7 +62,7 @@ button {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: .5ch; gap: .5ch;
color: var(--slate-700); color: color-mix(in srgb, var(--foreground) 70%, var(--background));
cursor: pointer; cursor: pointer;
text-underline-offset: 2px; text-underline-offset: 2px;
text-decoration: none; text-decoration: none;
@@ -75,7 +75,7 @@ button {
svg { svg {
width: 1rem; width: 1rem;
height: 1rem; height: 1rem;
fill: var(--slate-700); fill: color-mix(in srgb, var(--foreground) 70%, var(--background));
} }
} }
</style> </style>

View File

@@ -0,0 +1,32 @@
<script lang="ts" setup>
import { useDark, useToggle } from '@vueuse/core'
import { currentLang, t } from '@/i18n/store';
const isDark = useDark({ storageKey: "theme", disableTransition: false })
const toggleDark = useToggle(isDark)
</script>
<template>
<div data-theme-toggle id="theme-switcher" class="wrapper appear-from-top">
<button @click="toggleDark()" class="btn-round" :title="t('nav.theme.aria-label')">
<svg v-if="isDark" xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M120,40V32a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0Zm72,88a64,64,0,1,1-64-64A64.07,64.07,0,0,1,192,128Zm-16,0a48,48,0,1,0-48,48A48.05,48.05,0,0,0,176,128ZM58.34,69.66A8,8,0,0,0,69.66,58.34l-8-8A8,8,0,0,0,50.34,61.66Zm0,116.68-8,8a8,8,0,0,0,11.32,11.32l8-8a8,8,0,0,0-11.32-11.32ZM192,72a8,8,0,0,0,5.66-2.34l8-8a8,8,0,0,0-11.32-11.32l-8,8A8,8,0,0,0,192,72Zm5.66,114.34a8,8,0,0,0-11.32,11.32l8,8a8,8,0,0,0,11.32-11.32ZM40,120H32a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Zm88,88a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,128,208Zm96-88h-8a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Z"></path></svg>
<svg v-else xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M233.54,142.23a8,8,0,0,0-8-2,88.08,88.08,0,0,1-109.8-109.8,8,8,0,0,0-10-10,104.84,104.84,0,0,0-52.91,37A104,104,0,0,0,136,224a103.09,103.09,0,0,0,62.52-20.88,104.84,104.84,0,0,0,37-52.91A8,8,0,0,0,233.54,142.23ZM188.9,190.34A88,88,0,0,1,65.66,67.11a89,89,0,0,1,31.4-26A106,106,0,0,0,96,56,104.11,104.11,0,0,0,200,160a106,106,0,0,0,14.92-1.06A89,89,0,0,1,188.9,190.34Z"></path></svg>
</button>
</div>
</template>
<style lang="scss" scoped>
.wrapper {
pointer-events: all;
}
.btn-round {
position: relative;
> svg {
width: 1.25em;
height: 1.25em;
}
}
</style>

View File

@@ -8,6 +8,7 @@ import SearchMarkers from "./overlay/SearchMarkers.vue";
import LangSwitcher from "./overlay/LangSwitcher.vue"; import LangSwitcher from "./overlay/LangSwitcher.vue";
import MapOverlayBreadcrumbs from "./MapOverlayBreadcrumbs.astro"; import MapOverlayBreadcrumbs from "./MapOverlayBreadcrumbs.astro";
import ToastService from "./overlay/ToastService.vue"; import ToastService from "./overlay/ToastService.vue";
import ThemeSwitch from "../global/ThemeSwitch.vue";
interface Props extends MapOverlayProps {} interface Props extends MapOverlayProps {}
@@ -41,9 +42,14 @@ const currentUrl = Astro.url
</SearchMarkers> </SearchMarkers>
} }
{ENABLE_I18N &&
<LangSwitcher currentUrl={currentUrl} client:only="vue" /> <div class="right-menu">
} {ENABLE_I18N &&
<LangSwitcher currentUrl={currentUrl} client:only="vue" />
}
<ThemeSwitch client:only="vue" />
</div>
</div> </div>
{ENABLE_BREADCRUMB && {ENABLE_BREADCRUMB &&
@@ -71,5 +77,15 @@ const currentUrl = Astro.url
align-items: top; align-items: top;
gap: 1rem; gap: 1rem;
} }
.right-menu {
display: grid;
gap: .5rem;
align-content: flex-start;
@media screen and (width >= 900px) {
display: flex;
}
}
} }
</style> </style>

View File

@@ -14,7 +14,7 @@ const { breadcrumbs = [] } = Astro.props
{breadcrumbs.map((breadcrumb, index) => ( {breadcrumbs.map((breadcrumb, index) => (
<li> <li>
{index === breadcrumbs.length - 1 && {index === breadcrumbs.length - 1 &&
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#0f172a" viewBox="0 0 256 256" class="folder"><path d="M245,110.64A16,16,0,0,0,232,104H216V88a16,16,0,0,0-16-16H130.67L102.94,51.2a16.14,16.14,0,0,0-9.6-3.2H40A16,16,0,0,0,24,64V208h0a8,8,0,0,0,8,8H211.1a8,8,0,0,0,7.59-5.47l28.49-85.47A16.05,16.05,0,0,0,245,110.64ZM93.34,64,123.2,86.4A8,8,0,0,0,128,88h72v16H69.77a16,16,0,0,0-15.18,10.94L40,158.7V64Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#0f172a" viewBox="0 0 256 256" class="icon folder"><path d="M245,110.64A16,16,0,0,0,232,104H216V88a16,16,0,0,0-16-16H130.67L102.94,51.2a16.14,16.14,0,0,0-9.6-3.2H40A16,16,0,0,0,24,64V208h0a8,8,0,0,0,8,8H211.1a8,8,0,0,0,7.59-5.47l28.49-85.47A16.05,16.05,0,0,0,245,110.64ZM93.34,64,123.2,86.4A8,8,0,0,0,128,88h72v16H69.77a16,16,0,0,0-15.18,10.94L40,158.7V64Z"></path></svg>
<span class="breadcrumb" aria-current="page"> <span class="breadcrumb" aria-current="page">
<h1 class="label"> <h1 class="label">
@@ -23,7 +23,7 @@ const { breadcrumbs = [] } = Astro.props
</span> </span>
} }
{!(index === breadcrumbs.length - 1) && {!(index === breadcrumbs.length - 1) &&
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#0f172a" viewBox="0 0 256 256" class="folder"><path d="M216,72H131.31L104,44.69A15.86,15.86,0,0,0,92.69,40H40A16,16,0,0,0,24,56V200.62A15.4,15.4,0,0,0,39.38,216H216.89A15.13,15.13,0,0,0,232,200.89V88A16,16,0,0,0,216,72ZM40,56H92.69l16,16H40ZM216,200H40V88H216Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#0f172a" viewBox="0 0 256 256" class="icon folder"><path d="M216,72H131.31L104,44.69A15.86,15.86,0,0,0,92.69,40H40A16,16,0,0,0,24,56V200.62A15.4,15.4,0,0,0,39.38,216H216.89A15.13,15.13,0,0,0,232,200.89V88A16,16,0,0,0,216,72ZM40,56H92.69l16,16H40ZM216,200H40V88H216Z"></path></svg>
<a href={breadcrumb.url} class="breadcrumb" class:list={{ active: index === breadcrumbs.length - 1 }} data-astro-prefetch="hover"> <a href={breadcrumb.url} class="breadcrumb" class:list={{ active: index === breadcrumbs.length - 1 }} data-astro-prefetch="hover">
<span class="label"> <span class="label">
@@ -31,7 +31,7 @@ const { breadcrumbs = [] } = Astro.props
</span> </span>
</a> </a>
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="#0f172a" viewBox="0 0 256 256"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="#0f172a" viewBox="0 0 256 256" class="icon"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path></svg>
} }
</li> </li>
))} ))}
@@ -48,17 +48,25 @@ menu {
margin-top: .5rem; margin-top: .5rem;
padding-block: .25rem; padding-block: .25rem;
padding-inline: .8rem; padding-inline: .8rem;
border: 1px solid var(--slate-400); color: var(--foreground);
background: var(--white); border: 1px solid var(--border);
background: var(--background);
border-radius: 100vmax; border-radius: 100vmax;
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px; box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
pointer-events: all; pointer-events: all;
transition-property: color, background-color, border-color, outline-color;
transition-duration: .15s;
transition-timing-function: var(--timing-function);
li { li {
display: flex; display: flex;
align-items: center; align-items: center;
gap: .25ch; gap: .25ch;
svg {
fill: var(--foreground);
}
&:has(a:hover, a:focus-visible) { &:has(a:hover, a:focus-visible) {
svg.folder { svg.folder {
fill: var(--blue-500); fill: var(--blue-500);
@@ -83,7 +91,7 @@ menu {
} }
.icon { .icon {
width: 1.1em; fill: var(--foreground);
} }
.label { .label {

View File

@@ -49,7 +49,7 @@ a {
&:hover, &:hover,
&:focus-visible { &:focus-visible {
background-color: var(--slate-200); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
} }
&[aria-current="page"] { &[aria-current="page"] {

View File

@@ -275,10 +275,11 @@ menu {
padding-block: .25rem; padding-block: .25rem;
top: calc(var(--mouse-y) - .5rem); top: calc(var(--mouse-y) - .5rem);
left: calc(var(--mouse-x) + .75rem); left: calc(var(--mouse-x) + .75rem);
background-color: var(--white); color: var(--foreground);
border: 1px solid var(--slate-400); background-color: var(--background);
border: 1px solid var(--border);
border-radius: .3rem; border-radius: .3rem;
box-shadow: rgba(0, 0, 0, 0.3) 0px 4px 12px; box-shadow: var(--shadow);
z-index: 1000; z-index: 1000;
transition-property: top, left; transition-property: top, left;
transition-duration: .16s; transition-duration: .16s;
@@ -295,13 +296,17 @@ menu {
cursor: pointer; cursor: pointer;
width: 100%; width: 100%;
svg {
fill: var(--foreground);
}
&:hover, &:hover,
&:focus-within { &:focus-within {
color: var(--blue-700); color: color-mix(in srgb, var(--accent) 90%, var(--background));
background-color: var(--slate-100); background-color: color-mix(in srgb, var(--accent) 10%, var(--background));
svg { svg {
fill: var(--blue-700); fill: color-mix(in srgb, var(--accent) 75%, var(--background));
} }
} }
} }
@@ -313,10 +318,11 @@ dialog {
max-width: calc(100% - 6rem); max-width: calc(100% - 6rem);
padding: 1.5rem 2rem; padding: 1.5rem 2rem;
z-index: 9999; z-index: 9999;
background-color: var(--white); color: var(--foreground);
border: 1px solid var(--slate-400); background-color: var(--background);
border: 1px solid var(--border);
border-radius: .75rem; border-radius: .75rem;
box-shadow: rgba(0, 0, 0, 0.3) 0px 4px 12px; box-shadow: var(--shadow);
overflow: visible; overflow: visible;
transform: translateY(1rem); transform: translateY(1rem);
transition: visibility 0s ease-out .3s, opacity .3s ease-out, transform .3s ease-out; transition: visibility 0s ease-out .3s, opacity .3s ease-out, transform .3s ease-out;

View File

@@ -94,8 +94,7 @@ const menus: Menu[] = [
{ {
name: 'Mines Blanches', name: 'Mines Blanches',
img: '/images/aldys-cantane-mines-blanches-cover.png', img: '/images/aldys-cantane-mines-blanches-cover.png',
url: `/${$currentLang.value}/aldys/cantane/mines-blanches`, url: `/${$currentLang.value}/aldys/cantane/mines-blanches`
newItem: true
}, },
] ]
} }
@@ -213,6 +212,10 @@ const menus: Menu[] = [
} }
} }
.dark .legal::before {
content: url('/icon/question-mark-dark.svg');
}
.map-menu { .map-menu {
margin-top: .25rem; margin-top: .25rem;
margin-bottom: .5rem; margin-bottom: .5rem;
@@ -251,7 +254,7 @@ const menus: Menu[] = [
img { img {
display: block; display: block;
border-radius: .3rem; border-radius: .3rem;
border: .1rem solid var(--white); border: .1rem solid var(--background);
outline: .15rem solid transparent; outline: .15rem solid transparent;
} }
@@ -264,15 +267,15 @@ const menus: Menu[] = [
pointer-events: none; pointer-events: none;
.fill { fill: var(--orange-500); } .fill { fill: var(--orange-500); }
.stroke { fill: var(--white); } .stroke { fill: var(--background); }
} }
} }
figcaption { figcaption {
font-size: .75em; font-size: .75em;
text-align: center; text-align: center;
color: var(--slate-500); color: color-mix(in srgb, var(--foreground) 80%, var(--background));
} }
} }
} }
</style> </style>

View File

@@ -308,11 +308,15 @@ function resetAllFields(actionAfter?: "focusAfter") {
margin-left: calc(45px + .5rem); margin-left: calc(45px + .5rem);
padding: .5rem 1.2rem; padding: .5rem 1.2rem;
width: calc(100% - 3rem); width: calc(100% - 3rem);
background: var(--white); color: var(--foreground);
border: 1px solid var(--slate-400); background: var(--background);
border: 1px solid var(--border);
border-radius: 25px; border-radius: 25px;
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px; box-shadow: var(--shadow);
pointer-events: all; pointer-events: all;
transition-property: color, background-color, border-color, outline-color;
transition-duration: .15s;
transition-timing-function: var(--timing-function);
@media screen and (width >= 900px) { @media screen and (width >= 900px) {
width: clamp(25rem, 35dvw, 30rem); width: clamp(25rem, 35dvw, 30rem);
@@ -338,7 +342,7 @@ function resetAllFields(actionAfter?: "focusAfter") {
flex-grow: 1; flex-grow: 1;
&::placeholder { &::placeholder {
color: var(--slate-400); color: color-mix(in srgb, var(--foreground) 75%, var(--background));
} }
} }
@@ -348,7 +352,7 @@ function resetAllFields(actionAfter?: "focusAfter") {
transform: translateY(-50%); transform: translateY(-50%);
left: 0; left: 0;
width: $search-icon-size; width: $search-icon-size;
fill: var(--slate-400); fill: color-mix(in srgb, var(--foreground) 75%, var(--background));
pointer-events: none; pointer-events: none;
} }
@@ -375,16 +379,20 @@ function resetAllFields(actionAfter?: "focusAfter") {
} }
&:hover { &:hover {
.icon {
color: var(--foreground);
}
&::before { &::before {
background-color: var(--slate-300); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
} }
} }
&:focus-visible { &:focus-visible {
&::before { &::before {
background-color: var(--slate-200); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
outline: 1px dotted var(--slate-500); outline: 1px dotted color-mix(in srgb, var(--foreground) 50%, var(--background));
outline: 4px auto var(--slate-900); outline: 4px auto color-mix(in srgb, var(--foreground) 90%, var(--background));
} }
} }
} }
@@ -399,22 +407,22 @@ function resetAllFields(actionAfter?: "focusAfter") {
&:hover { &:hover {
&::before { &::before {
background-color: var(--slate-300); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
} }
} }
&:focus-visible { &:focus-visible {
&::before { &::before {
background-color: var(--slate-200); background-color: color-mix(in srgb, var(--foreground) 20%, var(--background));
outline: 1px dotted var(--slate-500); outline: 1px dotted color-mix(in srgb, var(--foreground) 50%, var(--background));
outline: 4px auto var(--slate-900); outline: 4px auto color-mix(in srgb, var(--foreground) 90%, var(--background));
} }
} }
} }
.close-btn { .close-btn {
font-size: 1.1em; font-size: 1.1em;
color: var(--slate-500); color: color-mix(in srgb, var(--foreground) 75%, var(--background));
} }
} }
@@ -436,7 +444,7 @@ function resetAllFields(actionAfter?: "focusAfter") {
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background-color: var(--slate-300); background-color: color-mix(in srgb, var(--foreground) 30%, var(--background));
} }
> * + * { > * + * {
@@ -453,7 +461,7 @@ function resetAllFields(actionAfter?: "focusAfter") {
} }
&:hover:not(:has(a:hover)) { &:hover:not(:has(a:hover)) {
background-color: var(--slate-100); background-color: color-mix(in srgb, var(--foreground) 10%, var(--background));
.title { .title {
text-decoration: underline; text-decoration: underline;
@@ -490,9 +498,14 @@ function resetAllFields(actionAfter?: "focusAfter") {
.title { .title {
font-weight: 500; font-weight: 500;
text-underline-offset: 2px; text-underline-offset: 2px;
& + .desc {
margin-top: .25rem;
}
} }
.desc { .desc {
color: var(--slate-500); color: color-mix(in srgb, var(--foreground) 50%, var(--background));
.map-link { .map-link {
margin-top: .5rem; margin-top: .5rem;
@@ -528,12 +541,12 @@ function resetAllFields(actionAfter?: "focusAfter") {
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
right: .75rem; right: .75rem;
fill: var(--slate-400); fill: color-mix(in srgb, var(--foreground) 70%, var(--background));
} }
&:focus-visible { &:focus-visible {
outline: 1px dotted var(--slate-500); outline: 1px dotted color-mix(in srgb, var(--foreground) 50%, var(--background));
outline: 4px auto var(--slate-900); outline: 4px auto color-mix(in srgb, var(--foreground) 90%, var(--background));
.title { .title {
text-decoration: underline; text-decoration: underline;
@@ -600,8 +613,9 @@ function resetAllFields(actionAfter?: "focusAfter") {
&[data-focused="true"] { &[data-focused="true"] {
margin-bottom: 1em; margin-bottom: 1em;
.input-w { .input-w {
border-bottom: 1px solid var(--slate-200); border-bottom: 1px solid color-mix(in srgb, var(--foreground) 20%, var(--background));
margin-bottom: .5rem; margin-bottom: .5rem;
padding-bottom: .5rem; padding-bottom: .5rem;

View File

@@ -125,10 +125,11 @@ function emitCategorySwitch(newCategory: MapMarkerGroup) {
padding-inline: .8rem; padding-inline: .8rem;
font-weight: 600; font-weight: 600;
font-size: .85em; font-size: .85em;
background: var(--white); color: var(--foreground);
border: 1px solid var(--slate-400); background: var(--background);
border: 1px solid var(--border);
border-radius: 100vmax; border-radius: 100vmax;
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px; box-shadow: var(--shadow);
white-space: nowrap; white-space: nowrap;
pointer-events: all; pointer-events: all;
cursor: pointer; cursor: pointer;
@@ -145,6 +146,10 @@ function emitCategorySwitch(newCategory: MapMarkerGroup) {
width: 1.1em; width: 1.1em;
} }
svg {
fill: var(--foreground);
}
.label { .label {
text-underline-offset: .15rem; text-underline-offset: .15rem;
} }
@@ -154,12 +159,12 @@ function emitCategorySwitch(newCategory: MapMarkerGroup) {
@each $c in $colors { @each $c in $colors {
&.#{$c} { &.#{$c} {
&.active { &.active {
color: var(--white); color: var(--background);
background-color: var(--#{$c}-500); background-color: var(--#{$c}-500);
border-color: var(--#{$c}-700); border-color: var(--#{$c}-700);
.icon { .icon {
fill: var(--white); fill: var(--background);
} }
} }

View File

@@ -21,9 +21,10 @@ export const translations: LanguageDict = {
'capitals': 'Capitales', 'capitals': 'Capitales',
'points-of-interest': 'Points d\'intérêt', 'points-of-interest': 'Points d\'intérêt',
'personals': 'Personnels', 'personals': 'Personnels',
'nav.aria-label': 'Navigation principale', 'nav.aria-label': 'Menu principal',
'nav.map.aria-label': 'Changer de carte', 'nav.map.aria-label': 'Changer de carte',
'nav.lang.aria-label': 'Changer de langue', 'nav.lang.aria-label': 'Changer de langue',
'nav.theme.aria-label': 'Changer de thème',
'maps.go-to-map': 'Voir la carte détaillée', 'maps.go-to-map': 'Voir la carte détaillée',
'maps.go-to-player': 'Aller à la position actuelle des joueurs', 'maps.go-to-player': 'Aller à la position actuelle des joueurs',
'maps.seeQuest': 'Voir la quête', 'maps.seeQuest': 'Voir la quête',
@@ -44,8 +45,8 @@ export const translations: LanguageDict = {
<h3>Données personnelles</h3> <h3>Données personnelles</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>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>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>J'utilise une instance Matomo pour mesurer l'audience du site, mais les données sont anonymisées et je ne construis aucun profil à partir de ces dernières.</p>
<p>Malgré cela, <strong>aucune de vos données n'est vendue ou transmise à un tiers quel qu'il soit</strong>.</p> <p><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> <p>Si vous avez des questions, vous pouvez me contacter à <a href="mailto:contact@alexcreates.fr">contact@alexcreates.fr</a>.</p>
` `
}, },
@@ -65,9 +66,10 @@ export const translations: LanguageDict = {
'capitals': 'Capitals', 'capitals': 'Capitals',
'points-of-interest': 'Points of interest', 'points-of-interest': 'Points of interest',
'personals': 'Personals', 'personals': 'Personals',
'nav.aria-label': 'Main navigation', 'nav.aria-label': 'Main menu',
'nav.map.aria-label': 'Switch map', 'nav.map.aria-label': 'Switch map',
'nav.lang.aria-label': 'Switch language', 'nav.lang.aria-label': 'Switch language',
'nav.theme.aria-label': 'Switch color theme',
'maps.go-to-map': 'See detailed map', 'maps.go-to-map': 'See detailed map',
'maps.go-to-player': 'Go to current players position', 'maps.go-to-player': 'Go to current players position',
'maps.seeQuest': 'See the quest', 'maps.seeQuest': 'See the quest',
@@ -88,9 +90,11 @@ export const translations: LanguageDict = {
<h3>Privacy</h3> <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>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>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>This website doesn'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>I do use a self-hosted Matomo Instance to measure website audience, but data is anonymised and I don't build profiles with it.</p>
<p><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> <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;

View File

@@ -16,6 +16,13 @@ const lang = getLangFromUrl(Astro.url) || defaultLang;
<!doctype html> <!doctype html>
<html lang={lang}> <html lang={lang}>
<head> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{title} — Leim Wiki</title>
<script is:inline src="/leaflet/leaflet.js" />
<script is:inline type="text/javascript" src="/js/leaflet-measure.min.js"></script>
<script is:inline type="text/javascript" src="/js/leaflet-zoomify.min.js"></script>
<script> <script>
import { setLang } from "@/i18n/store"; import { setLang } from "@/i18n/store";
import { defaultLang, type Language } from "@/i18n/ui"; import { defaultLang, type Language } from "@/i18n/ui";
@@ -25,12 +32,21 @@ const lang = getLangFromUrl(Astro.url) || defaultLang;
setLang(currentLang || defaultLang); setLang(currentLang || defaultLang);
</script> </script>
<meta charset="UTF-8" /> <link rel="stylesheet" href="/leaflet/leaflet.css" rel="preload" />
<link rel="stylesheet" href="/leaflet-measure/leaflet-measure.css" rel="preload" />
<meta name="author" content="Alexis Pelé" /> <meta name="author" content="Alexis Pelé" />
{head?.description && <meta name="description" content={head.description} /> } <meta property="og:author" content="Alexis Pelé" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta property="og:locale" content={lang}>
<meta name="application-name" content="leim-maps">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-config" content="none">
{head?.description && (
<meta name="description" content={head.description} />
<meta property="og:description" content={head.description} />
)}
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<title>{title} — Leim Wiki</title>
<link rel="canonical" href={Astro.url}> <link rel="canonical" href={Astro.url}>
@@ -41,24 +57,83 @@ const lang = getLangFromUrl(Astro.url) || defaultLang;
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#6595b4"> <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#6595b4">
<meta name="msapplication-TileColor" content="#00aba9"> <meta name="msapplication-TileColor" content="#00aba9">
<meta name="theme-color" content="#a9d1eb"> <meta name="theme-color" content="#a9d1eb">
<meta name="color-scheme" content="dark light">
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} /> <meta property="og:url" content={Astro.url} />
{head?.image && <meta property="og:image" content={head.image} />}
{head?.description && <meta name="twitter:description" content={head.description} /> } {head?.description && <meta name="twitter:description" content={head.description} /> }
{head?.image && <meta property="twitter:image" content={head.image} />} {head?.image && (
<meta property="og:image" content={`${Astro.site?.origin}${head.image}`} />
<link rel="stylesheet" href="/leaflet/leaflet.css" rel="preload" /> <meta name="twitter:image" content={`${Astro.site?.origin}${head.image}`} />
<script is:inline src="/leaflet/leaflet.js" /> <meta name="twitter:card" content="summary_large_image" />
)}
<script is:inline type="text/javascript" src="/js/leaflet-zoomify.min.js"></script> <!-- Matomo -->
<script is:inline>
<link rel="stylesheet" href="/leaflet-measure/leaflet-measure.css" rel="preload" /> var _paq = window._paq = window._paq || [];
<script is:inline type="text/javascript" src="/js/leaflet-measure.min.js"></script> /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//stats.alexcreates.fr/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '3']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head> </head>
<body> <body>
<script is:inline>
let initialTheme = localStorage.getItem("theme");
const darkModeMq = window.matchMedia("(prefers-color-scheme: dark)");
// Initial paint from localstorage
switch (initialTheme) {
case "light":
enableLightTheme();
break;
case "system":
resetTheme();
break;
case "dark":
default:
enableDarkTheme();
break;
}
// Enables dark theme and updates preferences
function enableDarkTheme() {
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('light');
localStorage.setItem("theme", "dark");
}
// Enables light theme and updates preferences
function enableLightTheme() {
document.documentElement.classList.add('light');
document.documentElement.classList.remove('dark');
localStorage.setItem("theme", "light");
}
// Reset theme to OS values
function resetTheme() {
const prefersDark = darkModeMq.matches;
if (prefersDark) {
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('light');
} else {
document.documentElement.classList.add('light');
document.documentElement.classList.remove('dark');
}
localStorage.setItem("theme", "system");
}
</script>
<slot /> <slot />
</body> </body>
</html> </html>

View File

@@ -4,7 +4,12 @@ import Map from '@/components/maps/Map.astro'
import MapOverlay from '@/components/maps/MapOverlay.astro' import MapOverlay from '@/components/maps/MapOverlay.astro'
--- ---
<Layout title="Borélis ~ Maps"> <Layout
title="Borélis ~ Maps"
head={{
description: "Map of Borélis, a harbour city on the northern shores of the Kaldelium Accord."
}}
>
<MapOverlay <MapOverlay
mapKey='aldys-borelis' mapKey='aldys-borelis'
searchConfig={{ searchConfig={{

View File

@@ -1,5 +1,5 @@
--- ---
import type { MapMarker, PlayerMarker } from '@/types/Leaflet'; import type { MapMarker } from '@/types/Leaflet';
import Layout from '@/layouts/Layout.astro'; import Layout from '@/layouts/Layout.astro';
import Map from '@/components/maps/Map.astro' import Map from '@/components/maps/Map.astro'
@@ -10,7 +10,12 @@ import markersData from '@/components/maps/data/en/aldys/cantane/markers.json'
const markers = markersData.data as MapMarker[] const markers = markersData.data as MapMarker[]
--- ---
<Layout title="Cantane ~ Maps"> <Layout
title="Cantane ~ Maps"
head={{
description: "Map of the old city of Cantane, south of the Kaldelium Accord."
}}
>
<MapOverlay <MapOverlay
mapKey='aldys-cantane' mapKey='aldys-cantane'
markers={markers} markers={markers}

View File

@@ -10,7 +10,12 @@ import markersData from '@/components/maps/data/en/aldys/cantane/les-mines-blanc
const markers = markersData.data as MapMarker[] const markers = markersData.data as MapMarker[]
--- ---
<Layout title="White Hollow ~ Maps"> <Layout
title="White Hollow ~ Maps"
head={{
description: "Map of the White Hollow mining complex, left abandonned east of Cantane."
}}
>
<MapOverlay <MapOverlay
mapKey='aldys-cantane-mines' mapKey='aldys-cantane-mines'
markers={markers} markers={markers}

View File

@@ -12,7 +12,12 @@ const markers = markersData.data as MapMarker[]
const players = playersData as PlayerMarker const players = playersData as PlayerMarker
--- ---
<Layout title="Bamast ~ Maps"> <Layout
title="Bamast ~ Maps"
head={{
description: "Map of the archipelago of Bamast and its many islands in the Balamian Ocean."
}}
>
<MapOverlay <MapOverlay
mapKey='bamast' mapKey='bamast'
markers={markers} markers={markers}

View File

@@ -16,8 +16,8 @@ const players = playersData as PlayerMarker
title="Aldys ~ Maps" title="Aldys ~ Maps"
head={ head={
{ {
description: "Carte de l'Alliance Kaldélienne sur la planète de Léim.", description: "Map of the Aldys continent on the planet of Léim, displaying the Kaldelium accord and the Common Lands of Syaltha.",
image: '/images/bailey-zindel-NRQV-hBF10M-unsplash.jpg' image: '/bailey-zindel-NRQV-hBF10M-unsplash.jpg'
} }
} }
> >

View File

@@ -4,7 +4,12 @@ import Map from '@/components/maps/Map.astro'
import MapOverlay from '@/components/maps/MapOverlay.astro' import MapOverlay from '@/components/maps/MapOverlay.astro'
--- ---
<Layout title="Borélis ~ Cartographie"> <Layout
title="Borélis ~ Cartographie"
head={{
description: "Carte de la ville côtière de Borélis, sur les côtes gelées au nord de l'Alliance Kaldélienne."
}}
>
<MapOverlay <MapOverlay
mapKey='aldys-borelis' mapKey='aldys-borelis'
searchConfig={{ searchConfig={{

View File

@@ -10,7 +10,12 @@ import markersData from '@/components/maps/data/fr/aldys/cantane/markers.json'
const markers = markersData.data as MapMarker[] const markers = markersData.data as MapMarker[]
--- ---
<Layout title="Cantane ~ Cartographie"> <Layout
title="Cantane ~ Cartographie"
head={{
description: "Carte de la ville de Cantane, au sud de l'Alliance Kaldélienne."
}}
>
<MapOverlay <MapOverlay
mapKey='aldys-cantane' mapKey='aldys-cantane'
markers={markers} markers={markers}

View File

@@ -10,7 +10,12 @@ import markersData from '@/components/maps/data/fr/aldys/cantane/les-mines-blanc
const markers = markersData.data as MapMarker[] const markers = markersData.data as MapMarker[]
--- ---
<Layout title="Les Mines Blanches ~ Cartographie"> <Layout
title="Les Mines Blanches ~ Cartographie"
head={{
description: "Cartographie du complexe des Mines Blanches, laissé à l'abandon à l'est de Cantane."
}}
>
<MapOverlay <MapOverlay
mapKey='aldys-cantane-mines' mapKey='aldys-cantane-mines'
markers={markers} markers={markers}

View File

@@ -12,7 +12,12 @@ const markers = markersData.data as MapMarker[]
const players = playersData as PlayerMarker const players = playersData as PlayerMarker
--- ---
<Layout title="Bamast ~ Cartographie"> <Layout
title="Bamast ~ Cartographie"
head={{
description: "Carte de l'Archipel de Bamast et ses nombreuses îles de l'Océan Balamien."
}}
>
<MapOverlay <MapOverlay
mapKey='bamast' mapKey='bamast'
markers={markers} markers={markers}

View File

@@ -16,8 +16,8 @@ const players = playersData as PlayerMarker
title="Aldys ~ Cartographie" title="Aldys ~ Cartographie"
head={ head={
{ {
description: "Carte de l'Alliance Kaldélienne sur la planète de Léim.", description: "Carte du continent Aldys sur la planète de Léim, comprenant l'Alliance Kaldélienne et les Terres de Syaltha.",
image: '/images/bailey-zindel-NRQV-hBF10M-unsplash.jpg' image: '/bailey-zindel-NRQV-hBF10M-unsplash.jpg'
} }
} }
> >