i spent 3 days on this oh my god

This commit is contained in:
Mars 2024-08-27 22:58:38 -04:00
parent 443c21c106
commit ee2cfdcf9a
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
12 changed files with 181 additions and 142 deletions

View file

@ -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>

BIN
bun.lockb

Binary file not shown.

84
components/DropDown.vue Normal file
View 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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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,
}
}

View file

@ -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,
}
}

View file

@ -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;
}
// Function to set a cookie with a name, value, and optional expiration days
function setCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
const theme = getCookie('theme');
if (theme === 'system' || !theme) // If no theme cookie exists, set it to 'catppuccin-mocha'
document.body.classList.add( if (!theme) {
window.matchMedia('(prefers-color-scheme: dark)').matches setCookie('theme', 'catppuccin-mocha');
? 'dark' document.body.classList.add('catppuccin-mocha');
: 'light' } else {
) document.body.classList.add(theme); // Apply the existing theme class
else }
document.body.classList.add(theme)
// Retrieve the font value from cookies
const font = localStorage.getItem('font') const font = getCookie('font');
if (font) // If no font cookie exists, set it to 'jetbrains-mono'
document.body.classList.add(font) 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',
}, },

View file

@ -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"

View file

@ -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>

View file

@ -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',
}, },
}, },
} }