i spent 3 days on this oh my god
This commit is contained in:
parent
443c21c106
commit
ee2cfdcf9a
6
app.vue
6
app.vue
|
@ -4,10 +4,12 @@
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
|
import '@unocss/reset/tailwind.css'
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
bodyAttrs: {
|
bodyAttrs: {
|
||||||
class: 'bg-bg',
|
class: 'bg-base p-2',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
84
components/DropDown.vue
Normal file
84
components/DropDown.vue
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<template>
|
||||||
|
<div class='dropdown'>
|
||||||
|
<button
|
||||||
|
id='dropdown-button'
|
||||||
|
rounded-lg
|
||||||
|
bg-base2
|
||||||
|
c-text
|
||||||
|
p2
|
||||||
|
b-2
|
||||||
|
b-text
|
||||||
|
b-solid
|
||||||
|
class='dropdown-button'
|
||||||
|
aria-haspopup='true'
|
||||||
|
:aria-expanded='isOpen'
|
||||||
|
@click='() => isOpen = !isOpen'
|
||||||
|
>
|
||||||
|
{{ selectedOption || defaultOption }}
|
||||||
|
</button>
|
||||||
|
<ul
|
||||||
|
v-if='isOpen'
|
||||||
|
bg-base2
|
||||||
|
c-text
|
||||||
|
list-none
|
||||||
|
rounded-lg
|
||||||
|
p4
|
||||||
|
b-2
|
||||||
|
b-text
|
||||||
|
b-solid
|
||||||
|
class='dropdown-menu'
|
||||||
|
role='menu'
|
||||||
|
aria-labelledby='dropdown-button'
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-for='(option, key) in optionsRef'
|
||||||
|
:key='key'
|
||||||
|
role='menuitem'
|
||||||
|
tabindex='0'
|
||||||
|
@click='selectOption(key)'
|
||||||
|
@keyup.enter='selectOption(key)'
|
||||||
|
>
|
||||||
|
{{ option.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useCookie } from '#imports'
|
||||||
|
|
||||||
|
// Define props types
|
||||||
|
const props = defineProps<{
|
||||||
|
options: Record<string, { name: string }>
|
||||||
|
modelValue: string
|
||||||
|
defaultOption: string
|
||||||
|
cookieName: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { options, modelValue, defaultOption, cookieName } = props
|
||||||
|
|
||||||
|
const optionsRef = ref(options)
|
||||||
|
|
||||||
|
const cookie = useCookie(cookieName)
|
||||||
|
|
||||||
|
const isOpen = ref(false)
|
||||||
|
const selectedOption = ref(options[modelValue]?.name || defaultOption)
|
||||||
|
|
||||||
|
const selectOption = (key: string) => {
|
||||||
|
const option = options[key]
|
||||||
|
|
||||||
|
// Update classes to use the selected option
|
||||||
|
document.body.classList.remove(...Object.keys(options))
|
||||||
|
document.body.classList.add(key)
|
||||||
|
|
||||||
|
// Update cookie
|
||||||
|
cookie.value = key
|
||||||
|
|
||||||
|
// Update selected option
|
||||||
|
selectedOption.value = option.name
|
||||||
|
|
||||||
|
// Close dropdown
|
||||||
|
isOpen.value = false
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,26 +0,0 @@
|
||||||
<template>
|
|
||||||
<select
|
|
||||||
v-model='selectedFont'
|
|
||||||
:disabled='loading'
|
|
||||||
@change='setFont(selectedFont)'
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for='(value, key) in fonts'
|
|
||||||
:key='key'
|
|
||||||
:value='key'
|
|
||||||
>
|
|
||||||
{{ value.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const { font, setFont } = $(useFont())
|
|
||||||
let selectedFont = $ref('')
|
|
||||||
let loading = $ref(true)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
selectedFont = font
|
|
||||||
loading = false
|
|
||||||
})
|
|
||||||
</script>
|
|
|
@ -1,4 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<FontSwitcher />
|
<div
|
||||||
<ThemeSwitcher />
|
flex
|
||||||
|
gap-2
|
||||||
|
pb-2
|
||||||
|
>
|
||||||
|
<DropDown
|
||||||
|
v-model='fontCookie'
|
||||||
|
:options='fonts'
|
||||||
|
default-option='JetBrains Mono'
|
||||||
|
cookie-name='font'
|
||||||
|
/>
|
||||||
|
<DropDown
|
||||||
|
v-model='themeCookie'
|
||||||
|
:options='themes'
|
||||||
|
default-option='Catppuccin Mocha'
|
||||||
|
cookie-name='theme'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { fonts, themes } from '#imports'
|
||||||
|
|
||||||
|
const fontCookie = useCookie('font') as Ref<string>
|
||||||
|
const themeCookie = useCookie('theme') as Ref<string>
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<template>
|
|
||||||
<select
|
|
||||||
v-model='selectedTheme'
|
|
||||||
:disabled='loading'
|
|
||||||
@change='setTheme(selectedTheme)'
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for='(value, key) in themes'
|
|
||||||
:key='key'
|
|
||||||
:value='key'
|
|
||||||
>
|
|
||||||
{{ value.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const { theme, setTheme } = $(useTheme())
|
|
||||||
let selectedTheme = $ref('')
|
|
||||||
let loading = $ref(true)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
selectedTheme = theme
|
|
||||||
loading = false
|
|
||||||
})
|
|
||||||
</script>
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { ref, onMounted } from 'vue'
|
|
||||||
|
|
||||||
const fontNames = Object.keys(fonts)
|
|
||||||
|
|
||||||
export const useFont = () => {
|
|
||||||
const font = ref('jetbrains-mono')
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
const storedFont = localStorage.getItem('font')
|
|
||||||
if (storedFont) {
|
|
||||||
font.value = storedFont
|
|
||||||
document.body.classList.remove(...fontNames)
|
|
||||||
document.body.classList.add(storedFont)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const setFont = (newFont: string) => {
|
|
||||||
font.value = newFont
|
|
||||||
document.body.classList.remove(...fontNames)
|
|
||||||
document.body.classList.add(newFont)
|
|
||||||
localStorage.setItem('font', newFont)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
font,
|
|
||||||
setFont,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { ref, onMounted } from 'vue'
|
|
||||||
|
|
||||||
const themeNames = Object.keys(themes)
|
|
||||||
|
|
||||||
export const useTheme = () => {
|
|
||||||
const theme = ref('catppuccin-mocha')
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
const storedTheme = localStorage.getItem('theme')
|
|
||||||
if (storedTheme) {
|
|
||||||
theme.value = storedTheme
|
|
||||||
document.body.classList.remove(...themeNames)
|
|
||||||
document.body.classList.add(storedTheme)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const setTheme = (newTheme: string) => {
|
|
||||||
theme.value = newTheme
|
|
||||||
document.body.classList.remove(...themeNames)
|
|
||||||
document.body.classList.add(newTheme)
|
|
||||||
localStorage.setItem('theme', newTheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
theme,
|
|
||||||
setTheme,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ import { fonts } from './utils/fonts'
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-04-03',
|
compatibilityDate: '2024-04-03',
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
modules: ['@unocss/nuxt', '@vueuse/nuxt', '@nuxt/eslint', '@vue-macros/nuxt'],
|
modules: ['@unocss/nuxt', '@vueuse/nuxt', '@nuxt/eslint', '@vue-macros/nuxt', '@pinia/nuxt'],
|
||||||
eslint: {
|
eslint: {
|
||||||
config: {
|
config: {
|
||||||
stylistic: {
|
stylistic: {
|
||||||
|
@ -34,21 +34,49 @@ export default defineNuxtConfig({
|
||||||
{
|
{
|
||||||
type: 'text/javascript',
|
type: 'text/javascript',
|
||||||
innerHTML: /* js */ `
|
innerHTML: /* js */ `
|
||||||
const theme = localStorage.getItem('theme')
|
// Function to get a cookie value by name
|
||||||
|
function getCookie(name) {
|
||||||
|
const nameEQ = name + "=";
|
||||||
|
const ca = document.cookie.split(';');
|
||||||
|
for (let i = 0; i < ca.length; i++) {
|
||||||
|
let c = ca[i];
|
||||||
|
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
|
||||||
|
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (theme === 'system' || !theme)
|
// Function to set a cookie with a name, value, and optional expiration days
|
||||||
document.body.classList.add(
|
function setCookie(name, value, days) {
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
let expires = "";
|
||||||
? 'dark'
|
if (days) {
|
||||||
: 'light'
|
const date = new Date();
|
||||||
)
|
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||||
else
|
expires = "; expires=" + date.toUTCString();
|
||||||
document.body.classList.add(theme)
|
}
|
||||||
|
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||||
|
}
|
||||||
|
|
||||||
const font = localStorage.getItem('font')
|
const theme = getCookie('theme');
|
||||||
|
|
||||||
if (font)
|
// If no theme cookie exists, set it to 'catppuccin-mocha'
|
||||||
document.body.classList.add(font)
|
if (!theme) {
|
||||||
|
setCookie('theme', 'catppuccin-mocha');
|
||||||
|
document.body.classList.add('catppuccin-mocha');
|
||||||
|
} else {
|
||||||
|
document.body.classList.add(theme); // Apply the existing theme class
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the font value from cookies
|
||||||
|
const font = getCookie('font');
|
||||||
|
|
||||||
|
// If no font cookie exists, set it to 'jetbrains-mono'
|
||||||
|
if (!font) {
|
||||||
|
setCookie('font', 'jetbrains-mono');
|
||||||
|
document.body.classList.add('jetbrains-mono');
|
||||||
|
} else {
|
||||||
|
document.body.classList.add(font); // Apply the existing font class
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
tagPosition: 'bodyClose',
|
tagPosition: 'bodyClose',
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,12 +15,15 @@
|
||||||
"@fontsource/source-code-pro": "^5.0.19",
|
"@fontsource/source-code-pro": "^5.0.19",
|
||||||
"@fontsource/ubuntu-mono": "^5.0.21",
|
"@fontsource/ubuntu-mono": "^5.0.21",
|
||||||
"@nuxtjs/google-fonts": "^3.2.0",
|
"@nuxtjs/google-fonts": "^3.2.0",
|
||||||
|
"@unocss/reset": "^0.62.3",
|
||||||
"nuxt": "^3.13.0",
|
"nuxt": "^3.13.0",
|
||||||
|
"typescript-cookie": "^1.0.6",
|
||||||
"unocss-preset-theme": "^0.13.0",
|
"unocss-preset-theme": "^0.13.0",
|
||||||
"vue": "^3.4.38"
|
"vue": "^3.4.38"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/eslint": "^0.5.2",
|
"@nuxt/eslint": "^0.5.2",
|
||||||
|
"@pinia/nuxt": "^0.5.4",
|
||||||
"@unocss/nuxt": "^0.62.3",
|
"@unocss/nuxt": "^0.62.3",
|
||||||
"@vue-macros/nuxt": "^1.11.6",
|
"@vue-macros/nuxt": "^1.11.6",
|
||||||
"@vueuse/nuxt": "^11.0.3"
|
"@vueuse/nuxt": "^11.0.3"
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<h1
|
||||||
<h1 c-text>
|
c-text
|
||||||
hi im mard
|
text-3xl
|
||||||
</h1>
|
>
|
||||||
</div>
|
hi im mard
|
||||||
|
</h1>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -4,7 +4,8 @@ export const themes = {
|
||||||
colors: {
|
colors: {
|
||||||
text: '#3760bf',
|
text: '#3760bf',
|
||||||
subtext: '#5c5f77',
|
subtext: '#5c5f77',
|
||||||
bg: '#eff1f5',
|
base: '#eff1f5',
|
||||||
|
base2: '#e1e2e7',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'tokyonight-night': {
|
'tokyonight-night': {
|
||||||
|
@ -12,39 +13,44 @@ export const themes = {
|
||||||
colors: {
|
colors: {
|
||||||
text: '#c0caf5',
|
text: '#c0caf5',
|
||||||
subtext: '#a9b1d6',
|
subtext: '#a9b1d6',
|
||||||
bg: '#1a1b26',
|
base: '#1a1b26',
|
||||||
|
base2: '#24283b',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'catppuccin-latte': {
|
'catppuccin-latte': {
|
||||||
name: 'Catppuccin (Latte)',
|
name: 'Catppuccin Latte',
|
||||||
colors: {
|
colors: {
|
||||||
text: '#4c4f69',
|
text: '#4c4f69',
|
||||||
subtext: '#5c5f77',
|
subtext: '#5c5f77',
|
||||||
bg: '#eff1f5',
|
base: '#eff1f5',
|
||||||
|
base2: '#e6e9ef',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'catppuccin-frappe': {
|
'catppuccin-frappe': {
|
||||||
name: 'Catppuccin (Frappe)',
|
name: 'Catppuccin Frappe',
|
||||||
colors: {
|
colors: {
|
||||||
text: '#c6d0f5',
|
text: '#c6d0f5',
|
||||||
subtext: '#b5bfe2',
|
subtext: '#b5bfe2',
|
||||||
bg: '#303446',
|
base: '#303446',
|
||||||
|
base2: '#292c3c',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'catppuccin-macchiato': {
|
'catppuccin-macchiato': {
|
||||||
name: 'Catppuccin (Macchiato)',
|
name: 'Catppuccin Macchiato',
|
||||||
colors: {
|
colors: {
|
||||||
text: '#cad3f5',
|
text: '#cad3f5',
|
||||||
subtext: '#b8c0e0',
|
subtext: '#b8c0e0',
|
||||||
bg: '#24273a',
|
base: '#24273a',
|
||||||
|
base2: '#1e2030',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'catppuccin-mocha': {
|
'catppuccin-mocha': {
|
||||||
name: 'Catppuccin (Mocha)',
|
name: 'Catppuccin Mocha',
|
||||||
colors: {
|
colors: {
|
||||||
text: '#cdd6f4',
|
text: '#cdd6f4',
|
||||||
subtext: '#bac2de',
|
subtext: '#bac2de',
|
||||||
bg: '#1e1e2e',
|
base: '#1e1e2e',
|
||||||
|
base2: '#181825',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue