Added more things
All checks were successful
Build and Deploy Nuxt / build (push) Successful in 34s

This commit is contained in:
2026-03-20 00:07:23 +01:00
parent b1c5535420
commit 2def9a207c
9 changed files with 425 additions and 27 deletions

View File

@@ -1,3 +1,5 @@
<template> <template>
<head> <head>
<title>Aran Central</title> <title>Aran Central</title>
@@ -11,17 +13,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue';
onMounted(() => { onMounted(() => {
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; setupTheme()
if (isDarkMode) {
document.documentElement.setAttribute("data-theme", "dark");
} else {
document.documentElement.setAttribute("data-theme", "light");
}
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -6,8 +6,8 @@ $themes: (
background-line: #202324, background-line: #202324,
background-fore: #10141f, background-fore: #10141f,
border-color: #819796, border-color: #819796,
border: #202324,
text: #ebede9, text: #ebede9,
link: #a4dddb,
container-shadow: #151d28 container-shadow: #151d28
), ),
light: ( light: (
@@ -15,22 +15,46 @@ $themes: (
background-line: #f0f0f0, background-line: #f0f0f0,
background-fore: #ffffff, background-fore: #ffffff,
border-color: #e0e0e0, border-color: #e0e0e0,
border: #f0f0f0,
text: #1e1e1e, text: #1e1e1e,
link: #6590b3,
container-shadow: #5f6774 container-shadow: #5f6774
) )
); );
$accents: (
alfdir: (
link: #a4dddb,
),
solus: (
link: #e6a556,
)
);
@mixin theme-vars($theme-map) { @mixin theme-vars($theme-map) {
@each $name, $value in $theme-map { @each $name, $value in $theme-map {
--color-#{$name}: #{$value}; --color-#{$name}: #{$value};
} }
} }
@mixin accent-vars($accent-map) {
@each $name, $value in $accent-map {
--color-#{$name}: #{$value};
}
}
:root { :root {
@include theme-vars(map.get($themes, dark)); @include theme-vars(map.get($themes, dark));
@include accent-vars(map.get($accents, alfdir));
} }
[data-theme="light"] { [data-theme="light"] {
@include theme-vars(map.get($themes, light)); @include theme-vars(map.get($themes, light));
} }
[data-accent="alfdir"] {
@include accent-vars(map.get($accents, alfdir));
}
[data-accent="solus"] {
@include accent-vars(map.get($accents, solus));
}

View File

@@ -1,18 +1,18 @@
<template> <template>
<div class="menus"> <div class="menus">
<NuxtLink href="/">About</NuxtLink> <NuxtLink href="/">About</NuxtLink>
<NuxtLink href="/blog">Blogs</NuxtLink> <NuxtLink href="/blog">Blog</NuxtLink>
<NuxtLink class="disabled">Drawings</NuxtLink> <NuxtLink class="disabled">Drawings</NuxtLink>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.menus {
margin-bottom: 10px;
}
.menus > a { .menus > a {
margin-right: 20px; margin-right: 10px;
margin-left: 10px;
text-decoration: none;
text-shadow: 0 0 1px var(--color-link);
} }
.disabled { .disabled {

View File

@@ -1,21 +1,40 @@
<script setup lang="ts"> <script setup lang="ts">
import HeaderLinks from './HeaderLinks.vue'; import HeaderLinks from './HeaderLinks.vue';
import SiteOptions from './site_options/SiteOptions.vue';
</script> </script>
<template> <template>
<div class="header"> <div class="header">
<Container> <div class="container">
<h1>ARANROIG.COM</h1> </div>
<div class="header-container">
<HeaderLinks></HeaderLinks> <HeaderLinks></HeaderLinks>
</Container> </div>
<div class="container">
<SiteOptions></SiteOptions>
</div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.header { .header {
position: relative; position: relative;
margin-top: 50px; margin-top: 30px;
user-select: none; user-select: none;
display: flex;
justify-content: space-between;
}
.header-container {
position: relative;
margin-left: 15px;
margin-right: 15px;
background: var(--color-background-fore);
padding: 8px 12px;
font-size: 1em;
color: white;
border: 1px solid var(--color-border-color);
border-radius: 8px;
box-shadow: 8px -8px 0px 0px var(--color-container-shadow);
} }
</style> </style>

View File

@@ -1,21 +1,41 @@
<script setup lang="ts"> <script setup lang="ts">
import HeaderLinks from './HeaderLinks.vue'; import HeaderLinks from './HeaderLinks.vue';
import SiteOptions from './site_options/SiteOptions.vue';
</script> </script>
<template> <template>
<div class="header">
<div class="header-container">
</div>
<div class="undertable"> <div class="undertable">
<h1>ARANROIG.COM</h1> <h1>ARANROIG.COM</h1>
<HeaderLinks></HeaderLinks> <HeaderLinks></HeaderLinks>
<Sprite path="/sprites/alfadir/" frames="13" fps="6" top="-258px" left="-65px" width="1300"></Sprite> <Sprite path="/sprites/alfadir/" frames="13" fps="6" top="-267px" left="-80px" width="1300"></Sprite>
</div>
<div class="header-container">
<SiteOptions></SiteOptions>
</div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.header-conainer {
position:relative;
}
.header {
position: relative;
margin-top: 30px;
user-select: none;
display: flex;
justify-content: space-between;
}
.undertable { .undertable {
position: relative; position: relative;
margin-top: 350px; left: 45px;
margin-left: 80px; margin-top: 300px;
margin-left: -500px;
margin-bottom: 25px; margin-bottom: 25px;
user-select: none; user-select: none;
} }

View File

@@ -0,0 +1,94 @@
<script setup>
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
const dropdownVisible = ref(false);
const toggleDropdown = () => {
dropdownVisible.value = !dropdownVisible.value;
}
const menuContainer = ref(null);
const handleClickOutside = (e) => {
if (menuContainer.value && !menuContainer.value.contains(e.target)) {
dropdownVisible.value = false
}
}
onMounted(() => {
document.addEventListener('click', handleClickOutside)
})
onUnmounted(() => {
document.removeEventListener('click', handleClickOutside)
})
// i18n
const { locale } = useI18n()
const setLocale = (lang) => {
locale.value = lang
dropdownVisible.value = false
}
</script>
<template>
<div class="menu-container" ref="menuContainer">
<button class="menu-button" @click="toggleDropdown">Language </button>
<div class="dropdown" v-show="dropdownVisible">
<div class="section">
<div class="menu-item" @click="setLocale('en')">
🇬🇧 English
</div>
<div class="menu-item" @click="setLocale('es')">
🇪🇸 Spanish
</div>
<div class="menu-item" @click="setLocale('ca')">
🇦🇩 Catalan
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.menu-button {
background: #161b22;
color: white;
font-size: 1em;
border: 1px solid #30363d;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
margin-right: 15px;
}
.dropdown {
z-index: 10;
position: absolute;
top: 50px;
right: 0;
margin-right: 10px;
background: #161b22;
border: 1px solid #30363d;
border-radius: 8px;
padding: 8px 0;
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
}
/* Items */
.menu-item {
padding: 8px 16px;
color: #c9d1d9;
cursor: pointer;
display: flex;
gap: 10px;
align-items: center;
&.active {
background: #30363d;
}
}
</style>

View File

@@ -0,0 +1,17 @@
<script setup lang="ts">
import LanguageSelector from './LanguageSelector.vue';
import ThemeSelector from './ThemeSelector.vue';
</script>
<template>
<div class="site-options">
<ThemeSelector></ThemeSelector>
<LanguageSelector></LanguageSelector>
</div>
</template>
<style lang="scss" scoped>
.site-options {
display: flex;
}
</style>

View File

@@ -0,0 +1,182 @@
<script setup>
import { ref } from 'vue'
import { theme, accent, setTheme, setAccent } from '~/composables/theme'
// ref for dropdown visibility
const dropdownVisible = ref(false)
// toggle function
const toggleDropdown = () => {
dropdownVisible.value = !dropdownVisible.value
}
// close dropdown if click outside
const menuContainer = ref(null)
const handleClickOutside = (e) => {
if (menuContainer.value && !menuContainer.value.contains(e.target)) {
dropdownVisible.value = false
}
}
onMounted(() => {
document.addEventListener('click', handleClickOutside)
})
onUnmounted(() => {
document.removeEventListener('click', handleClickOutside)
})
</script>
<template>
<div class="menu-container" ref="menuContainer">
<button class="menu-button" @click="toggleDropdown">Theme </button>
<div class="dropdown" v-show="dropdownVisible">
<div class="two-columns">
<div class="section">
<div class="menu-section">
<div class="menu-header">
Theme
</div>
</div>
<div class="divider"></div>
<div class="menu-section">
<div :class="{'menu-item': true, 'active': theme === 'dark' }" @click="setTheme('dark')">
<div class="circle dark"></div>Dark
</div>
<div :class="{'menu-item': true, 'active': theme === 'light' }" @click="setTheme('light')">
<div class="circle light"></div>Light
</div>
</div>
</div>
<div class="section">
<div class="menu-section">
<div class="menu-header">
Accent
</div>
</div>
<div class="divider"></div>
<div class="menu-section">
<div :class="{'menu-item': true, 'active': accent === 'alfdir' }" @click="setAccent('alfdir')">
<div class="circle alfdir"></div>Alfdir
</div>
<div :class="{'menu-item': true, 'active': accent === 'solus' }" @click="setAccent('solus')">
<div class="circle solus"></div>Solus
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.circle {
width: 12px;
height: 12px;
margin-top: -3px;
border-radius: 50%; /* makes it a circle */
z-index: 200;
justify-content: center;
border: 2px var(--color-border) solid;
&.dark {
background-color: rgb(28, 28, 28);
}
&.light {
background-color: rgb(232, 232, 232);
}
&.alfdir {
background-color: #4f8fba;
}
&.solus {
background-color: #e9a02b;
}
}
/* Container */
.menu-container {
position: relative;
display: inline-block;
}
.two-columns {
display: flex;
flex-grow: 1;
flex-direction: row;
}
.section {
flex-grow: 1;
}
/* Button */
.menu-button {
background: #161b22;
color: white;
font-size: 1em;
border: 1px solid #30363d;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
margin-right: 15px;
}
/* Dropdown */
.dropdown {
z-index: 10;
position: absolute;
top: 50px;
right: 0;
margin-right: 10px;
width: 320px;
background: #161b22;
border: 1px solid #30363d;
border-radius: 8px;
padding: 8px 0;
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
}
/* Sections */
.menu-section {
padding: 4px 0;
}
/* Items */
.menu-item {
padding: 8px 16px;
color: #c9d1d9;
cursor: pointer;
display: flex;
border-radius: 5px;
gap: 10px;
margin: 8px;
align-items: center;
&.active {
background: #30363d;
}
}
.menu-header {
padding: 8px 16px;
color: #c9d1d9;
display: flex;
gap: 10px;
align-items: center;
font-weight: bold;
justify-content: center;
}
.menu-item:hover {
background: #21262d;
}
/* Divider */
.divider {
height: 1px;
background: #30363d;
margin: 6px 0;
}
</style>

View File

@@ -0,0 +1,47 @@
import { ref, onMounted, watch } from 'vue'
type Theme = 'light' | 'dark'
type Accent = 'alfdir'
const theme = ref<Theme>('light')
const accent = ref<Accent>('alfdir')
const applyTheme = () => {
document.documentElement.setAttribute('data-theme', theme.value)
document.documentElement.setAttribute('data-accent', accent.value)
}
const setTheme = (value: Theme) => {
theme.value = value
localStorage.setItem('theme', value)
applyTheme();
}
const setAccent = (value: Accent) => {
accent.value = value
localStorage.setItem('accent', value)
applyTheme();
}
const setupTheme = () => {
const savedTheme = localStorage.getItem('theme') as Theme | null
const savedAccent = localStorage.getItem('accent') as Accent | null
const media = window.matchMedia('(prefers-color-scheme: dark)')
theme.value = savedTheme || (media.matches ? 'dark' : 'light')
accent.value = savedAccent || 'alfdir'
applyTheme()
media.addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
theme.value = e.matches ? 'dark' : 'light'
applyTheme()
}
})
};
watch([theme, accent], applyTheme)
export { theme, accent, setTheme, setAccent, setupTheme}