mirror of
https://github.com/ArthurDanjou/website.git
synced 2026-01-28 19:00:31 +01:00
Working on dynamic theme
This commit is contained in:
@@ -5,6 +5,10 @@ export default defineNuxtConfig({
|
|||||||
transpile: ['trpc-nuxt'],
|
transpile: ['trpc-nuxt'],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
css: [
|
||||||
|
'@/assets/css/main.scss',
|
||||||
|
],
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
'@pinia/nuxt',
|
'@pinia/nuxt',
|
||||||
'@pinia-plugin-persistedstate/nuxt',
|
'@pinia-plugin-persistedstate/nuxt',
|
||||||
@@ -17,6 +21,13 @@ export default defineNuxtConfig({
|
|||||||
'nuxt-icon',
|
'nuxt-icon',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
colorMode: {
|
||||||
|
preference: 'system',
|
||||||
|
fallback: 'light',
|
||||||
|
classPrefix: '',
|
||||||
|
classSuffix: '',
|
||||||
|
},
|
||||||
|
|
||||||
devtools: {
|
devtools: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
vscode: {
|
vscode: {
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
"@types/node": "^18",
|
"@types/node": "^18",
|
||||||
"@unocss/eslint-config": "^0.51.8",
|
"@unocss/eslint-config": "^0.51.8",
|
||||||
"@unocss/nuxt": "^0.51.8",
|
"@unocss/nuxt": "^0.51.8",
|
||||||
|
"@unocss/transformer-directives": "^0.51.8",
|
||||||
|
"@unocss/transformer-variant-group": "^0.51.8",
|
||||||
"@vueuse/core": "^10.1.0",
|
"@vueuse/core": "^10.1.0",
|
||||||
"@vueuse/nuxt": "^10.1.0",
|
"@vueuse/nuxt": "^10.1.0",
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
|
|||||||
4
src/assets/css/main.scss
Normal file
4
src/assets/css/main.scss
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
body {
|
||||||
|
font-family: 'DM Sans', sans-serif;
|
||||||
|
@apply bg-gray-100 dark:bg-dark-900 dark:text-white duration-200
|
||||||
|
}
|
||||||
@@ -48,9 +48,9 @@ export const useTheme = () => {
|
|||||||
case ColorsTheme.YELLOW:
|
case ColorsTheme.YELLOW:
|
||||||
return 'bg-yellow-500'
|
return 'bg-yellow-500'
|
||||||
case ColorsTheme.BLACK:
|
case ColorsTheme.BLACK:
|
||||||
return 'bg-black dark:(bg-white text-black) text-white'
|
return 'bg-black dark:bg-white dark:text-black text-white'
|
||||||
case ColorsTheme.WHITE:
|
case ColorsTheme.WHITE:
|
||||||
return 'bg-black dark:(bg-white text-black) text-white'
|
return 'bg-black dark:bg-white dark:text-black text-white'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useThemeStore } from '~/store/theme'
|
import { useThemeStore } from '~/store/theme'
|
||||||
|
|
||||||
const { getColor, getTheme, nextColor, nextTheme } = useThemeStore()
|
const { getColor, getTheme, swapColor, nextTheme } = useThemeStore()
|
||||||
const { getThemeTextColor, getThemeBackgroundColor } = useTheme()
|
const { getThemeTextColor, getThemeBackgroundColor } = useTheme()
|
||||||
|
|
||||||
|
onMounted(() => swapColor())
|
||||||
|
|
||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
const { $trpc } = useNuxtApp()
|
const { $trpc } = useNuxtApp()
|
||||||
|
const color = useColorMode()
|
||||||
const user = await $trpc.hello.query({ name: query.name?.toString() })
|
const user = await $trpc.hello.query({ name: query.name?.toString() })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<h1 :class="`text-sm ${getThemeTextColor}`">
|
<h1 :class="`${getThemeTextColor}`" duration="1000">
|
||||||
Main page
|
Main page
|
||||||
</h1>
|
</h1>
|
||||||
<h1 :class="`${getThemeBackgroundColor}`">
|
<h1 :class="`${getThemeBackgroundColor}`" duration="1000">
|
||||||
Main Page
|
Main Page
|
||||||
</h1>
|
</h1>
|
||||||
<div>
|
<div>
|
||||||
@@ -26,12 +29,12 @@ const user = await $trpc.hello.query({ name: query.name?.toString() })
|
|||||||
<div>
|
<div>
|
||||||
Theme colors : {{ getTheme.colors.map((color) => color.charAt(0).toUpperCase() + color.slice(1)).join(', ') }}
|
Theme colors : {{ getTheme.colors.map((color) => color.charAt(0).toUpperCase() + color.slice(1)).join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
<div @click="nextColor()">
|
|
||||||
setNextColor()
|
|
||||||
</div>
|
|
||||||
<div @click="nextTheme()">
|
<div @click="nextTheme()">
|
||||||
setNextTheme()
|
setNextTheme()
|
||||||
</div>
|
</div>
|
||||||
|
<div @click="color.preference = color.value === 'dark' ? 'light' : 'dark'">
|
||||||
|
toggleDarkMode()
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{ user.greeting }}
|
{{ user.greeting }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const appRouter = router({
|
|||||||
}))
|
}))
|
||||||
.query(({ input }) => {
|
.query(({ input }) => {
|
||||||
return {
|
return {
|
||||||
greeting: `Hello ${input.name ?? 'world'}!`,
|
greeting: `Hello ${input.name ?? 'World'}!`,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,20 +7,47 @@ export const useThemeStore = defineStore(
|
|||||||
() => {
|
() => {
|
||||||
const currentTheme = ref<Theme>(Themes[THEMES.RainbowTheme])
|
const currentTheme = ref<Theme>(Themes[THEMES.RainbowTheme])
|
||||||
const currentColor = ref<ColorsTheme>(currentTheme.value.colors[0])
|
const currentColor = ref<ColorsTheme>(currentTheme.value.colors[0])
|
||||||
|
let intervalId: NodeJS.Timeout | null = null
|
||||||
|
|
||||||
|
const isAvailable = (next: Theme): boolean => {
|
||||||
|
if (!next.availability)
|
||||||
|
return true
|
||||||
|
|
||||||
|
const today = new Date()
|
||||||
|
const [startDay, startMonth] = next.availability.start.split('/')
|
||||||
|
const [endDay, endMonth] = next.availability.end.split('/')
|
||||||
|
const start = new Date(today.getFullYear(), Number(startMonth) - 1, Number(startDay))
|
||||||
|
const end = new Date(today.getFullYear(), Number(endMonth) - 1, Number(endDay))
|
||||||
|
|
||||||
|
return today >= start && today <= end
|
||||||
|
}
|
||||||
|
|
||||||
|
const swapColor = () => {
|
||||||
|
if (intervalId !== null)
|
||||||
|
clearInterval(intervalId)
|
||||||
|
|
||||||
|
intervalId = setInterval(() => {
|
||||||
|
const colors = currentTheme.value.colors
|
||||||
|
const currentIndex = colors.indexOf(currentColor.value)
|
||||||
|
const nextIndex = (currentIndex + 1) % colors.length
|
||||||
|
currentColor.value = colors[nextIndex]
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
const nextTheme = () => {
|
const nextTheme = () => {
|
||||||
const themes = Object.values(Themes)
|
const themes = Object.values(Themes)
|
||||||
const currentIndex = themes.findIndex(theme => theme.name === currentTheme.value.name)
|
const currentIndex = themes.findIndex(theme => theme.name === currentTheme.value.name)
|
||||||
const nextIndex = (currentIndex + 1) % themes.length
|
let nextIndex = (currentIndex + 1) % themes.length
|
||||||
|
|
||||||
|
while (!isAvailable(themes[nextIndex])) {
|
||||||
|
nextIndex = (nextIndex + 1) % themes.length
|
||||||
|
if (nextIndex === currentIndex)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
currentTheme.value = themes[nextIndex]
|
currentTheme.value = themes[nextIndex]
|
||||||
currentColor.value = currentTheme.value.colors[0]
|
currentColor.value = currentTheme.value.colors[0]
|
||||||
}
|
swapColor()
|
||||||
|
|
||||||
const nextColor = () => {
|
|
||||||
const colors = currentTheme.value.colors
|
|
||||||
const currentIndex = colors.indexOf(currentColor.value)
|
|
||||||
const nextIndex = (currentIndex + 1) % colors.length
|
|
||||||
currentColor.value = colors[nextIndex]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTheme = computed(() => currentTheme)
|
const getTheme = computed(() => currentTheme)
|
||||||
@@ -30,7 +57,7 @@ export const useThemeStore = defineStore(
|
|||||||
getTheme,
|
getTheme,
|
||||||
getColor,
|
getColor,
|
||||||
nextTheme,
|
nextTheme,
|
||||||
nextColor,
|
swapColor,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
45
types.ts
45
types.ts
@@ -1,3 +1,4 @@
|
|||||||
|
// Define a theme
|
||||||
export enum ColorsTheme {
|
export enum ColorsTheme {
|
||||||
ORANGE = 'orange',
|
ORANGE = 'orange',
|
||||||
YELLOW = 'yellow',
|
YELLOW = 'yellow',
|
||||||
@@ -14,8 +15,13 @@ export enum ColorsTheme {
|
|||||||
export interface Theme {
|
export interface Theme {
|
||||||
name: String
|
name: String
|
||||||
colors: ColorsTheme[]
|
colors: ColorsTheme[]
|
||||||
|
availability?: {
|
||||||
|
start: String
|
||||||
|
end: String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the themes
|
||||||
const RainbowTheme: Theme = {
|
const RainbowTheme: Theme = {
|
||||||
name: 'Rainbow',
|
name: 'Rainbow',
|
||||||
colors: [
|
colors: [
|
||||||
@@ -32,11 +38,19 @@ const RainbowTheme: Theme = {
|
|||||||
const XMasTheme: Theme = {
|
const XMasTheme: Theme = {
|
||||||
name: 'Xmas',
|
name: 'Xmas',
|
||||||
colors: [ColorsTheme.RED, ColorsTheme.GREEN],
|
colors: [ColorsTheme.RED, ColorsTheme.GREEN],
|
||||||
|
availability: {
|
||||||
|
start: '01/12',
|
||||||
|
end: '31/12',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const EasterTheme: Theme = {
|
const EasterTheme: Theme = {
|
||||||
name: 'Easter',
|
name: 'Easter',
|
||||||
colors: [ColorsTheme.ROSE, ColorsTheme.YELLOW, ColorsTheme.CYAN],
|
colors: [ColorsTheme.ROSE, ColorsTheme.YELLOW, ColorsTheme.CYAN],
|
||||||
|
availability: {
|
||||||
|
start: '01/04',
|
||||||
|
end: '12/04',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlackAndWhiteTheme: Theme = {
|
const BlackAndWhiteTheme: Theme = {
|
||||||
@@ -44,11 +58,40 @@ const BlackAndWhiteTheme: Theme = {
|
|||||||
colors: [ColorsTheme.BLACK, ColorsTheme.WHITE],
|
colors: [ColorsTheme.BLACK, ColorsTheme.WHITE],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HalloweenTheme: Theme = {
|
||||||
|
name: 'Halloween',
|
||||||
|
colors: [
|
||||||
|
ColorsTheme.ORANGE,
|
||||||
|
ColorsTheme.BLACK,
|
||||||
|
ColorsTheme.GREEN,
|
||||||
|
ColorsTheme.PURPLE,
|
||||||
|
],
|
||||||
|
availability: {
|
||||||
|
start: '28/10',
|
||||||
|
end: '01/11',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const ValentineTheme: Theme = {
|
||||||
|
name: 'Valentine',
|
||||||
|
colors: [
|
||||||
|
ColorsTheme.RED,
|
||||||
|
ColorsTheme.ROSE,
|
||||||
|
],
|
||||||
|
availability: {
|
||||||
|
start: '12/02',
|
||||||
|
end: '16/02',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// List the themes
|
||||||
export enum THEMES {
|
export enum THEMES {
|
||||||
RainbowTheme,
|
RainbowTheme,
|
||||||
EasterTheme,
|
EasterTheme,
|
||||||
XMasTheme,
|
XMasTheme,
|
||||||
BlackAndWhiteTheme,
|
BlackAndWhiteTheme,
|
||||||
|
ValentineTheme,
|
||||||
|
HalloweenTheme,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Themes = {
|
export const Themes = {
|
||||||
@@ -56,4 +99,6 @@ export const Themes = {
|
|||||||
[THEMES.EasterTheme]: EasterTheme,
|
[THEMES.EasterTheme]: EasterTheme,
|
||||||
[THEMES.XMasTheme]: XMasTheme,
|
[THEMES.XMasTheme]: XMasTheme,
|
||||||
[THEMES.BlackAndWhiteTheme]: BlackAndWhiteTheme,
|
[THEMES.BlackAndWhiteTheme]: BlackAndWhiteTheme,
|
||||||
|
[THEMES.ValentineTheme]: ValentineTheme,
|
||||||
|
[THEMES.HalloweenTheme]: HalloweenTheme,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
defineConfig, presetAttributify, presetIcons,
|
defineConfig, presetAttributify, presetIcons,
|
||||||
presetTypography, presetUno, presetWind,
|
presetTypography, presetUno, presetWind,
|
||||||
transformerDirectives, transformerVariantGroup,
|
|
||||||
} from 'unocss'
|
} from 'unocss'
|
||||||
|
import transformerVariantGroup from '@unocss/transformer-variant-group'
|
||||||
|
import transformerDirectives from '@unocss/transformer-directives'
|
||||||
import { presetScrollbar } from 'unocss-preset-scrollbar'
|
import { presetScrollbar } from 'unocss-preset-scrollbar'
|
||||||
import { ColorsTheme } from './types'
|
import { ColorsTheme } from './types'
|
||||||
|
|
||||||
@@ -13,16 +14,21 @@ export default defineConfig({
|
|||||||
presetIcons(),
|
presetIcons(),
|
||||||
presetTypography(),
|
presetTypography(),
|
||||||
presetScrollbar(),
|
presetScrollbar(),
|
||||||
presetWind(),
|
presetWind({
|
||||||
|
dark: 'class',
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
transformers: [
|
transformers: [
|
||||||
transformerDirectives(),
|
transformerDirectives(),
|
||||||
transformerVariantGroup(),
|
transformerVariantGroup(),
|
||||||
],
|
],
|
||||||
safelist: [
|
safelist: [
|
||||||
|
// Theme text colors
|
||||||
...Object.values(ColorsTheme).map(color => `text-${color}-500`),
|
...Object.values(ColorsTheme).map(color => `text-${color}-500`),
|
||||||
'text-white', 'text-black',
|
...'bg-black dark:bg-white dark:text-black text-white'.split(' '),
|
||||||
|
|
||||||
|
// Theme background colors
|
||||||
...Object.values(ColorsTheme).map(color => `bg-${color}-500`),
|
...Object.values(ColorsTheme).map(color => `bg-${color}-500`),
|
||||||
'bg-white', 'bg-black',
|
...'text-black dark:text-white'.split(' '),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1745,7 +1745,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@unocss/core" "0.51.8"
|
"@unocss/core" "0.51.8"
|
||||||
|
|
||||||
"@unocss/transformer-directives@0.51.8":
|
"@unocss/transformer-directives@0.51.8", "@unocss/transformer-directives@^0.51.8":
|
||||||
version "0.51.8"
|
version "0.51.8"
|
||||||
resolved "https://registry.yarnpkg.com/@unocss/transformer-directives/-/transformer-directives-0.51.8.tgz#4fee9fa3fb97dbacc744a21f88b45eff5e835698"
|
resolved "https://registry.yarnpkg.com/@unocss/transformer-directives/-/transformer-directives-0.51.8.tgz#4fee9fa3fb97dbacc744a21f88b45eff5e835698"
|
||||||
integrity sha512-Q1vG0dZYaxbdz0pVnvpuFreGoSqmrk7TgKUHNuJP/XzTi04sriQoDSpC2QMIAuOyU7FyGpSjUORiaBm0/VNURw==
|
integrity sha512-Q1vG0dZYaxbdz0pVnvpuFreGoSqmrk7TgKUHNuJP/XzTi04sriQoDSpC2QMIAuOyU7FyGpSjUORiaBm0/VNURw==
|
||||||
@@ -1753,7 +1753,7 @@
|
|||||||
"@unocss/core" "0.51.8"
|
"@unocss/core" "0.51.8"
|
||||||
css-tree "^2.3.1"
|
css-tree "^2.3.1"
|
||||||
|
|
||||||
"@unocss/transformer-variant-group@0.51.8":
|
"@unocss/transformer-variant-group@0.51.8", "@unocss/transformer-variant-group@^0.51.8":
|
||||||
version "0.51.8"
|
version "0.51.8"
|
||||||
resolved "https://registry.yarnpkg.com/@unocss/transformer-variant-group/-/transformer-variant-group-0.51.8.tgz#342fdade1ece77a0874fd6ff9903c111de1bdfe0"
|
resolved "https://registry.yarnpkg.com/@unocss/transformer-variant-group/-/transformer-variant-group-0.51.8.tgz#342fdade1ece77a0874fd6ff9903c111de1bdfe0"
|
||||||
integrity sha512-blFQtAntyijFOm+BiiQhroaPwFNX6zYi19wUjY6NdvMAl/g4JzOFTzo+KehQf+lCI3Dvhr8Z2dGtDcnwfqUcDg==
|
integrity sha512-blFQtAntyijFOm+BiiQhroaPwFNX6zYi19wUjY6NdvMAl/g4JzOFTzo+KehQf+lCI3Dvhr8Z2dGtDcnwfqUcDg==
|
||||||
|
|||||||
Reference in New Issue
Block a user