feat(stage-web): dynamic stage-web theme color

Co-authored-by: Makito <5277268+sumimakito@users.noreply.github.com>
This commit is contained in:
Neko Ayaka
2025-07-07 20:38:17 +08:00
co-authored by Makito
parent 2d08434bdf
commit 8301ededa6
8 changed files with 54 additions and 3 deletions
+8
View File
@@ -39,6 +39,14 @@ apps/stage-web/public/assets/fonts/
*.ogg
*.mp3
# Credentials
cert*/
*.pem
*.crt
*.cer
*.key
*.p12
twitter-session.json
# Make it easy for devenv users to override their local environment.
+9
View File
@@ -8,7 +8,16 @@
<link rel="icon" type="image/svg+xml" href="/favicon.svg" sizes="any" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<meta name="theme-color" content="rgb(18,18,18)" id="themeColor" />
<meta name="apple-mobile-web-app-title" content="AIRI" />
<script>
;(function () {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (setting === 'light' || (prefersDark && setting !== 'dark'))
document.querySelector('#themeColor').setAttribute('content', 'rgb(255,255,255)')
})()
</script>
<script>
;(function () {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
+1
View File
@@ -50,6 +50,7 @@
"@xsai/shared-chat": "catalog:",
"@xsai/stream-text": "catalog:",
"@xsai/utils-chat": "catalog:",
"colorjs.io": "^0.5.2",
"culori": "^4.0.2",
"driver.js": "^1.3.6",
"drizzle-kit": "^0.31.4",
@@ -103,7 +103,7 @@ watch(
<slot />
<div absolute left-0 right-0 top-0 w-full overflow-hidden>
<div
class="wave"
class="colored-area wave"
:style="{
'background': waveFillColor,
'height': `${fullHeight}px`,
+18 -1
View File
@@ -1,7 +1,9 @@
<script setup lang="ts">
import Color from 'colorjs.io'
import { WidgetStage } from '@proj-airi/stage-ui/components/scenes'
import { breakpointsTailwind, useBreakpoints, useDark, useMouse } from '@vueuse/core'
import { ref } from 'vue'
import { onMounted, ref } from 'vue'
import Cross from '../components/Backgrounds/Cross.vue'
import Header from '../components/Layouts/Header.vue'
@@ -19,11 +21,26 @@ function handleSettingsOpen(open: boolean) {
const positionCursor = useMouse()
const breakpoints = useBreakpoints(breakpointsTailwind)
const isMobile = breakpoints.smaller('md')
onMounted(() => {
if (!('document' in globalThis && globalThis.document != null))
return
if (!('window' in globalThis && globalThis.window != null))
return
const widgets = document.querySelector('.widgets.top-widgets .colored-area') as HTMLDivElement | undefined
if (!widgets)
return
const backgroundColor = window.getComputedStyle(widgets).getPropertyValue('background-color')
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', new Color(backgroundColor).to('srgb').toString({ format: 'hex' }))
})
</script>
<template>
<Cross>
<AnimatedWave
class="widgets top-widgets"
:fill-color="dark
? 'oklch(35% calc(var(--chromatic-chroma) * 0.6) var(--chromatic-hue))'
: 'color-mix(in srgb, oklch(95% calc(var(--chromatic-chroma-50) * 0.5) var(--chromatic-hue)) 80%, oklch(100% 0 360))'"
+8 -1
View File
@@ -1,3 +1,4 @@
import { readFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { env } from 'node:process'
@@ -63,6 +64,13 @@ export default defineConfig({
},
},
server: {
https: {
key: readFileSync(resolve(join(import.meta.dirname, '..', '..', 'localhost.pem'))),
cert: readFileSync(resolve(join(import.meta.dirname, '..', '..', 'localhost.crt'))),
},
},
plugins: [
Yaml(),
@@ -100,7 +108,6 @@ export default defineConfig({
manifest: {
name: 'AIRI',
short_name: 'AIRI',
theme_color: '#ffc6cb',
icons: [
{
purpose: 'maskable',
+1
View File
@@ -34,6 +34,7 @@ words:
- cjkfonts
- clippy
- collectblock
- colorjs
- composables
- cooldown
- coreml
+8
View File
@@ -670,6 +670,9 @@ importers:
'@xsai/utils-chat':
specifier: 'catalog:'
version: 0.3.0-beta.8
colorjs.io:
specifier: ^0.5.2
version: 0.5.2
culori:
specifier: ^4.0.2
version: 4.0.2
@@ -6557,6 +6560,9 @@ packages:
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
colorjs.io@0.5.2:
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
@@ -18187,6 +18193,8 @@ snapshots:
colorette@2.0.20: {}
colorjs.io@0.5.2: {}
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0