refactor(stage-ui): remove decorative borders (#3255)

This commit is contained in:
Neko
2026-10-30 08:38:19 +08:00
committed by GitHub
parent aea0d8a461
commit 3a425f50d1
10 changed files with 66 additions and 57 deletions
@@ -1,9 +1,9 @@
<template>
<div
flex="~ col"
border="solid 4 primary-200/20 dark:primary-400/20"
h-full w-full rounded-xl
bg="primary-50/50 dark:primary-950/70" backdrop-blur-md
:class="[
'flex flex-col h-full w-full rounded-xl',
'bg-primary-50/50 dark:bg-primary-950/70 backdrop-blur-md',
]"
>
<slot />
</div>
@@ -136,11 +136,12 @@ async function updateTopPEnabled(value: boolean) {
</RadioCardSimple>
<RouterLink
to="/settings/providers"
border="2px solid"
class="border-neutral-100 bg-white dark:border-neutral-900 hover:border-primary-500/30 dark:bg-neutral-900/20 dark:hover:border-primary-400/30"
flex="~ col items-center justify-center"
transition="all duration-200 ease-in-out"
relative min-w-50 w-fit rounded-xl p-4
:class="[
'relative min-w-50 w-fit flex flex-col items-center justify-center rounded-xl p-4',
'border-2 border-solid border-neutral-100 bg-white dark:border-neutral-900 dark:bg-neutral-900/20',
'hover:bg-neutral-50 dark:hover:bg-neutral-900/50',
'transition-all duration-200 ease-in-out',
]"
>
<div i-solar:add-circle-line-duotone class="text-2xl text-neutral-500 dark:text-neutral-500" />
<div
@@ -153,7 +154,6 @@ async function updateTopPEnabled(value: boolean) {
<div v-else>
<RouterLink
class="flex items-center gap-3 rounded-lg p-4"
border="2 dashed neutral-200 dark:neutral-800"
bg="neutral-50 dark:neutral-800"
transition="colors duration-200 ease-in-out"
to="/settings/providers"
@@ -419,7 +419,7 @@ onUnmounted(() => {
:class="[
'relative min-w-50 w-fit flex flex-col items-center justify-center rounded-xl p-4',
'border-2 border-solid border-neutral-100 bg-white dark:border-neutral-900 dark:bg-neutral-900/20',
'hover:border-primary-500/30 dark:hover:border-primary-400/30',
'hover:bg-neutral-50 dark:hover:bg-neutral-900/50',
'transition-all duration-200 ease-in-out',
]"
>
@@ -435,7 +435,6 @@ onUnmounted(() => {
to="/settings/providers"
:class="[
'flex items-center gap-3 rounded-lg p-4',
'border-2 border-dashed border-neutral-200 dark:border-neutral-800',
'bg-neutral-50 dark:bg-neutral-800',
'transition-colors duration-200 ease-in-out',
]"
@@ -681,11 +681,12 @@ async function handleDeleteProvider(providerId: string) {
</RadioCardSimple>
<RouterLink
to="/settings/providers#speech"
border="2px solid"
class="border-neutral-100 bg-white dark:border-neutral-900 hover:border-primary-500/30 dark:bg-neutral-900/20 dark:hover:border-primary-400/30"
flex="~ col items-center justify-center"
transition="all duration-200 ease-in-out"
relative min-w-50 w-fit rounded-xl p-4
:class="[
'relative min-w-50 w-fit flex flex-col items-center justify-center rounded-xl p-4',
'border-2 border-solid border-neutral-100 bg-white dark:border-neutral-900 dark:bg-neutral-900/20',
'hover:bg-neutral-50 dark:hover:bg-neutral-900/50',
'transition-all duration-200 ease-in-out',
]"
>
<div i-solar:add-circle-line-duotone class="text-2xl text-neutral-500 dark:text-neutral-500" />
<div
@@ -697,7 +698,7 @@ async function handleDeleteProvider(providerId: string) {
</fieldset>
<div v-else>
<RouterLink
class="flex items-center gap-3 rounded-lg p-4" border="2 dashed neutral-200 dark:neutral-800"
class="flex items-center gap-3 rounded-lg p-4"
bg="neutral-50 dark:neutral-800" transition="colors duration-200 ease-in-out" to="/settings/providers"
>
<div i-solar:warning-circle-line-duotone class="text-2xl text-amber-500 dark:text-amber-400" />
@@ -983,23 +984,26 @@ async function handleDeleteProvider(providerId: string) {
<div flex="~ row" gap-4>
<button
border="neutral-800 dark:neutral-200 solid 2" transition="border duration-250 ease-in-out"
rounded-lg px-4 text="neutral-100 dark:neutral-900" py-2 text-sm
:disabled="!speechStore.enabled || isGenerating || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !activeSpeechVoice"
:class="{ 'opacity-50 cursor-not-allowed': !speechStore.enabled || isGenerating || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !activeSpeechVoice }"
bg="neutral-700 dark:neutral-300" @click="generateTestSpeech"
:class="[
'rounded-lg px-4 py-2 text-sm transition-colors duration-250 ease-in-out',
'bg-neutral-700 text-neutral-100 dark:bg-neutral-300 dark:text-neutral-900',
{ 'opacity-50 cursor-not-allowed': !speechStore.enabled || isGenerating || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !activeSpeechVoice },
]"
@click="generateTestSpeech"
>
<div flex="~ row" items-center gap-2>
<div i-solar:play-circle-bold-duotone />
<div :class="['flex flex-row items-center gap-2']">
<div :class="['i-solar:play-circle-bold-duotone']" />
<span>{{ isGenerating ? t('settings.pages.providers.provider.elevenlabs.playground.buttons.button.test-voice.generating') : t('settings.pages.providers.provider.elevenlabs.playground.buttons.button.test-voice.label') }}</span>
</div>
</button>
<button
v-if="audioUrl" border="primary-300 dark:primary-800 solid 2"
transition="border duration-250 ease-in-out" rounded-lg px-4 py-2 text-sm @click="stopTestAudio"
v-if="audioUrl"
:class="['rounded-lg px-4 py-2 text-sm transition-colors duration-250 ease-in-out', 'bg-primary-100 dark:bg-primary-900/50']"
@click="stopTestAudio"
>
<div flex="~ row" items-center gap-2>
<div i-solar:stop-circle-bold-duotone />
<div :class="['flex flex-row items-center gap-2']">
<div :class="['i-solar:stop-circle-bold-duotone']" />
<span>Stop</span>
</div>
</button>
@@ -213,10 +213,10 @@ function formatRelativeTime(timestamp: number | null) {
'transition',
'duration-200',
'ease-in-out',
'hover:border-primary-500/30',
'hover:bg-neutral-50',
'dark:border-neutral-900',
'dark:bg-neutral-900/20',
'dark:hover:border-primary-400/30',
'dark:hover:bg-neutral-900/50',
'flex',
'items-center',
'justify-center',
@@ -237,15 +237,11 @@ function formatRelativeTime(timestamp: number | null) {
'items-center',
'gap-3',
'rounded-lg',
'border-2',
'border-dashed',
'border-neutral-200',
'bg-neutral-50',
'p-4',
'transition',
'duration-200',
'ease-in-out',
'dark:border-neutral-800',
'dark:bg-neutral-800',
]"
>
@@ -383,7 +379,7 @@ function formatRelativeTime(timestamp: number | null) {
/>
<div :class="['grid', 'gap-4', 'md:grid-cols-3']">
<div :class="['rounded-lg', 'border', 'border-neutral-200', 'bg-white', 'p-3', 'dark:border-neutral-800', 'dark:bg-neutral-900']">
<div :class="['rounded-lg p-3', 'bg-neutral-100/70 dark:bg-neutral-800/50']">
<div :class="['text-xs', 'uppercase', 'tracking-wide', 'text-neutral-400']">
{{ t('settings.pages.modules.vision.stats.captures') }}
</div>
@@ -395,7 +391,7 @@ function formatRelativeTime(timestamp: number | null) {
</div>
</div>
<div :class="['rounded-lg', 'border', 'border-neutral-200', 'bg-white', 'p-3', 'dark:border-neutral-800', 'dark:bg-neutral-900']">
<div :class="['rounded-lg p-3', 'bg-neutral-100/70 dark:bg-neutral-800/50']">
<div :class="['text-xs', 'uppercase', 'tracking-wide', 'text-neutral-400']">
{{ t('settings.pages.modules.vision.stats.context-updates') }}
</div>
@@ -407,7 +403,7 @@ function formatRelativeTime(timestamp: number | null) {
</div>
</div>
<div :class="['rounded-lg', 'border', 'border-neutral-200', 'bg-white', 'p-3', 'dark:border-neutral-800', 'dark:bg-neutral-900']">
<div :class="['rounded-lg p-3', 'bg-neutral-100/70 dark:bg-neutral-800/50']">
<div :class="['text-xs', 'uppercase', 'tracking-wide', 'text-neutral-400']">
{{ t('settings.pages.modules.vision.stats.inferences') }}
</div>
@@ -419,7 +415,7 @@ function formatRelativeTime(timestamp: number | null) {
</div>
</div>
<div :class="['rounded-lg', 'border', 'border-neutral-200', 'bg-white', 'p-3', 'dark:border-neutral-800', 'dark:bg-neutral-900']">
<div :class="['rounded-lg p-3', 'bg-neutral-100/70 dark:bg-neutral-800/50']">
<div :class="['text-xs', 'uppercase', 'tracking-wide', 'text-neutral-400']">
{{ t('settings.pages.modules.vision.stats.failed-inferences') }}
</div>
@@ -431,7 +427,7 @@ function formatRelativeTime(timestamp: number | null) {
</div>
</div>
<div :class="['rounded-lg', 'border', 'border-neutral-200', 'bg-white', 'p-3', 'dark:border-neutral-800', 'dark:bg-neutral-900']">
<div :class="['rounded-lg p-3', 'bg-neutral-100/70 dark:bg-neutral-800/50']">
<div :class="['text-xs', 'uppercase', 'tracking-wide', 'text-neutral-400']">
{{ t('settings.pages.modules.vision.stats.last-inference') }}
</div>
@@ -78,13 +78,19 @@ const syncIcon = computed(() => props.syncState ? syncIcons[props.syncState] : u
</div>
<div
v-if="props.pricing"
text="[10px] neutral-600 dark:neutral-300" border="1 neutral-200 dark:neutral-700" rounded-md px-1.5 py-0.5 font-bold tracking-wider uppercase
:class="[
'rounded-md px-1.5 py-0.5 text-[10px] font-bold tracking-wider uppercase',
'bg-neutral-500/10 text-neutral-600 dark:bg-neutral-400/15 dark:text-neutral-300',
]"
>
{{ $t(`settings.pages.providers.filters.${props.pricing}`) }}
</div>
<div
v-if="props.deployment"
text="[10px] neutral-600 dark:neutral-300" border="1 neutral-200 dark:neutral-700" rounded-md px-1.5 py-0.5 font-bold tracking-wider uppercase
:class="[
'rounded-md px-1.5 py-0.5 text-[10px] font-bold tracking-wider uppercase',
'bg-neutral-500/10 text-neutral-600 dark:bg-neutral-400/15 dark:text-neutral-300',
]"
>
{{ $t(`settings.pages.providers.filters.${props.deployment}`) }}
</div>
@@ -357,7 +357,7 @@ function toggleOpen() {
'border-neutral-200 bg-white/95 dark:border-neutral-800 dark:bg-neutral-900/95',
]"
>
<div ref="createContentRef" :class="['flex flex-wrap items-center justify-end gap-2 border-2 rounded-xl p-2']">
<div ref="createContentRef" :class="['flex flex-wrap items-center justify-end gap-2 rounded-xl p-2']">
<input
ref="nameInputRef"
v-model="newProfileName"
@@ -9,15 +9,15 @@ const { t } = useI18n()
</script>
<template>
<div :class="['relative shrink-0 rounded-xl border border-primary-200/50 p-1 dark:border-primary-800/50']">
<img v-if="previewUrl" :src="previewUrl" :alt="file.name" :class="['h-20 w-20 rounded-lg object-cover']">
<div :class="['relative shrink-0']">
<img v-if="previewUrl" :src="previewUrl" :alt="file.name" :class="['h-20 w-20 rounded-xl object-cover', 'bg-neutral-100 dark:bg-neutral-800']">
<button
type="button"
:aria-label="t('stage.chat.images.remove', { name: file.name })"
:class="['absolute right-1 top-1 h-6 w-6 flex items-center justify-center rounded-full bg-neutral-900/70 text-white shadow-sm', 'transition-colors duration-200 hover:bg-red-600 focus-visible:outline-2 focus-visible:outline-primary-500 motion-reduce:transition-none']"
@click.stop="emit('remove')"
>
<span :class="['i-solar:close-circle-bold size-4']" />
<span :class="['i-mingcute:close-line size-3.5']" />
</button>
</div>
</template>
@@ -160,14 +160,16 @@ defineExpose({
<!-- Playground actions -->
<button
border="neutral-800 dark:neutral-200 solid 2" transition="border duration-250 ease-in-out"
rounded-lg px-3 text="neutral-100 dark:neutral-900" py-1.5 text-sm
:disabled="isGenerating || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !apiKeyConfigured"
:class="{ 'opacity-50 cursor-not-allowed': isGenerating || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !apiKeyConfigured }"
bg="neutral-700 dark:neutral-300" @click="handleGenerateTestSpeech"
:class="[
'rounded-lg px-3 py-1.5 text-sm transition-colors duration-250 ease-in-out',
'bg-neutral-700 text-neutral-100 dark:bg-neutral-300 dark:text-neutral-900',
{ 'opacity-50 cursor-not-allowed': isGenerating || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !apiKeyConfigured },
]"
@click="handleGenerateTestSpeech"
>
<div flex="~ row" items-center gap-2>
<div i-solar:play-circle-bold-duotone />
<div :class="['flex flex-row items-center gap-2']">
<div :class="['i-solar:play-circle-bold-duotone']" />
<span>{{ isGenerating ? t('settings.pages.providers.provider.elevenlabs.playground.buttons.button.test-voice.generating') : t('settings.pages.providers.provider.elevenlabs.playground.buttons.button.test-voice.label') }}</span>
</div>
</button>
@@ -222,14 +222,16 @@ defineExpose({
<!-- Playground actions -->
<button
border="neutral-800 dark:neutral-200 solid 2" transition="border duration-250 ease-in-out"
rounded-lg px-3 text="neutral-100 dark:neutral-900" py-1.5 text-sm
:disabled="isGenerating || voicesLoading || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !selectedVoice || !apiKeyConfigured"
:class="{ 'opacity-50 cursor-not-allowed': isGenerating || voicesLoading || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !selectedVoice || !apiKeyConfigured }"
bg="neutral-700 dark:neutral-300" @click="handleGenerateTestSpeech"
:class="[
'rounded-lg px-3 py-1.5 text-sm transition-colors duration-250 ease-in-out',
'bg-neutral-700 text-neutral-100 dark:bg-neutral-300 dark:text-neutral-900',
{ 'opacity-50 cursor-not-allowed': isGenerating || voicesLoading || (!testText.trim() && !useSSML) || (useSSML && !ssmlText.trim()) || !selectedVoice || !apiKeyConfigured },
]"
@click="handleGenerateTestSpeech"
>
<div flex="~ row" items-center gap-2>
<div i-solar:play-circle-bold-duotone />
<div :class="['flex flex-row items-center gap-2']">
<div :class="['i-solar:play-circle-bold-duotone']" />
<span>{{ isGenerating ? t('settings.pages.providers.provider.elevenlabs.playground.buttons.button.test-voice.generating') : t('settings.pages.providers.provider.elevenlabs.playground.buttons.button.test-voice.label') }}</span>
</div>
</button>