mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-11-05 23:18:56 +08:00
feat(webui): update settings, downloader, player, and log page styles
Restyle config components (ab-container, ab-fold-panel, ab-label, ab-setting) and all config-* setting panels to use the new design system. Add empty state guides with setup steps for downloader and player pages. Simplify log page layout. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,47 +25,35 @@ withDefaults(
|
||||
<style lang="scss" scoped>
|
||||
.container-card {
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: border-color var(--transition-normal),
|
||||
box-shadow var(--transition-normal);
|
||||
transition: border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.container-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20px;
|
||||
height: 42px;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
padding: 0 14px;
|
||||
height: 34px;
|
||||
background: transparent;
|
||||
color: var(--color-text-secondary);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
user-select: none;
|
||||
|
||||
@include forPC {
|
||||
height: 48px;
|
||||
}
|
||||
transition: color var(--transition-normal),
|
||||
border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.container-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
||||
@include forPC {
|
||||
font-size: 18px;
|
||||
}
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.container-body {
|
||||
padding: 14px;
|
||||
padding: 12px 14px;
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
font-size: 14px;
|
||||
transition: background-color var(--transition-normal),
|
||||
color var(--transition-normal);
|
||||
|
||||
@include forPC {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,28 +5,28 @@ import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue';
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
title: string;
|
||||
defaultOpen?: boolean;
|
||||
}>(),
|
||||
{
|
||||
title: 'title',
|
||||
defaultOpen: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Disclosure v-slot="{ open }">
|
||||
<Disclosure v-slot="{ open }" :default-open="defaultOpen">
|
||||
<div class="fold-panel">
|
||||
<DisclosureButton class="fold-panel-header">
|
||||
<div class="fold-panel-title">{{ title }}</div>
|
||||
<Component :is="open ? Up : Down" :size="18" />
|
||||
<Component :is="open ? Up : Down" :size="14" />
|
||||
</DisclosureButton>
|
||||
|
||||
<div class="fold-panel-body" :class="[open && 'fold-panel-body--open']">
|
||||
<div v-show="!open" class="fold-panel-divider"></div>
|
||||
|
||||
<DisclosurePanel>
|
||||
<DisclosurePanel>
|
||||
<div class="fold-panel-body">
|
||||
<slot></slot>
|
||||
</DisclosurePanel>
|
||||
</div>
|
||||
</div>
|
||||
</DisclosurePanel>
|
||||
</div>
|
||||
</Disclosure>
|
||||
</template>
|
||||
@@ -34,7 +34,6 @@ withDefaults(
|
||||
<style lang="scss" scoped>
|
||||
.fold-panel {
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--color-border);
|
||||
transition: border-color var(--transition-normal);
|
||||
}
|
||||
@@ -44,50 +43,28 @@ withDefaults(
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0 20px;
|
||||
height: 42px;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
padding: 0 14px;
|
||||
height: 34px;
|
||||
background: transparent;
|
||||
color: var(--color-text-secondary);
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
cursor: pointer;
|
||||
|
||||
@include forPC {
|
||||
height: 48px;
|
||||
}
|
||||
transition: color var(--transition-normal),
|
||||
border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.fold-panel-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
||||
@include forPC {
|
||||
font-size: 18px;
|
||||
}
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fold-panel-body {
|
||||
background: var(--color-surface);
|
||||
padding: 10px 8px;
|
||||
padding: 12px 14px;
|
||||
font-size: 14px;
|
||||
color: var(--color-text);
|
||||
transition: background-color var(--transition-normal),
|
||||
color var(--transition-normal);
|
||||
|
||||
&--open {
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
@include forPC {
|
||||
&--open {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fold-panel-divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: var(--color-border);
|
||||
margin: 12px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -24,14 +24,14 @@ const abLabel = computed(() => {
|
||||
<style lang="scss" scoped>
|
||||
.label-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 14px;
|
||||
color: var(--color-text);
|
||||
padding-top: 4px;
|
||||
transition: color var(--transition-normal);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,6 +40,6 @@ const data = defineModel<any>('data');
|
||||
</div>
|
||||
</ab-label>
|
||||
|
||||
<div v-if="bottomLine" line my-12></div>
|
||||
<div v-if="bottomLine" line my-6></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -65,7 +65,7 @@ const items: SettingItem<Downloader>[] = [
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.downloader_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in items"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -43,7 +43,7 @@ const items: SettingItem<BangumiManage>[] = [
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.manage_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in items"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -51,7 +51,7 @@ const logItems: SettingItem<Log> = {
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.normal_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in programItems"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -52,7 +52,7 @@ const items: SettingItem<Notification>[] = [
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.notification_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in items"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -85,7 +85,7 @@ const azureItems: SettingItem<ExperimentalOpenAI>[] = [
|
||||
<span>{{ $t('config.experimental_openai_set.warning') }}</span>
|
||||
</div>
|
||||
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in openAI.api_type === 'azure' ? azureItems : openAIItems"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -33,7 +33,7 @@ const items: SettingItem<RssParser>[] = [
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.parser_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in items"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -64,7 +64,7 @@ function formatDate(dateString: string | null): string {
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('passkey.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<!-- 不支持提示 -->
|
||||
<div v-if="!isSupported" text-orange-500 text-14>
|
||||
{{ $t('passkey.not_supported') }}
|
||||
|
||||
@@ -4,7 +4,7 @@ const { types, type, url } = storeToRefs(usePlayerStore());
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.media_player_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-model:data="type"
|
||||
type="select"
|
||||
|
||||
@@ -64,7 +64,7 @@ const items: SettingItem<Proxy>[] = [
|
||||
|
||||
<template>
|
||||
<ab-fold-panel :title="$t('config.proxy_set.title')">
|
||||
<div space-y-12>
|
||||
<div space-y-8>
|
||||
<ab-setting
|
||||
v-for="i in items"
|
||||
:key="i.configKey"
|
||||
|
||||
@@ -58,7 +58,7 @@ onActivated(() => {
|
||||
.config-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
gap: 12px;
|
||||
margin-bottom: auto;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@@ -69,14 +69,19 @@ onActivated(() => {
|
||||
.config-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.config-actions {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
margin-top: 20px;
|
||||
margin-top: 16px;
|
||||
padding: 12px 0;
|
||||
backdrop-filter: blur(8px);
|
||||
background: color-mix(in srgb, var(--color-background) 80%, transparent);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,13 +25,42 @@ onActivated(() => {
|
||||
|
||||
<template>
|
||||
<div class="page-embed">
|
||||
<template v-if="isNull">
|
||||
<div class="embed-empty">
|
||||
<RouterLink to="/config" class="embed-link">
|
||||
{{ $t('downloader.hit') }}
|
||||
</RouterLink>
|
||||
<div v-if="isNull" class="empty-guide">
|
||||
<div class="empty-guide-header anim-fade-in">
|
||||
<div class="empty-guide-title">{{ $t('downloader.empty.title') }}</div>
|
||||
<div class="empty-guide-subtitle">{{ $t('downloader.empty.subtitle') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="empty-guide-steps">
|
||||
<div class="empty-guide-step anim-slide-up" style="--delay: 0.15s">
|
||||
<div class="empty-guide-step-number">1</div>
|
||||
<div class="empty-guide-step-content">
|
||||
<div class="empty-guide-step-title">{{ $t('downloader.empty.step1_title') }}</div>
|
||||
<div class="empty-guide-step-desc">{{ $t('downloader.empty.step1_desc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="empty-guide-step anim-slide-up" style="--delay: 0.3s">
|
||||
<div class="empty-guide-step-number">2</div>
|
||||
<div class="empty-guide-step-content">
|
||||
<div class="empty-guide-step-title">{{ $t('downloader.empty.step2_title') }}</div>
|
||||
<div class="empty-guide-step-desc">{{ $t('downloader.empty.step2_desc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="empty-guide-step anim-slide-up" style="--delay: 0.45s">
|
||||
<div class="empty-guide-step-number">3</div>
|
||||
<div class="empty-guide-step-content">
|
||||
<div class="empty-guide-step-title">{{ $t('downloader.empty.step3_title') }}</div>
|
||||
<div class="empty-guide-step-desc">{{ $t('downloader.empty.step3_desc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RouterLink to="/config" class="empty-guide-action anim-slide-up" style="--delay: 0.6s">
|
||||
{{ $t('sidebar.config') }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<iframe
|
||||
v-else
|
||||
@@ -51,26 +80,6 @@ onActivated(() => {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.embed-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.embed-link {
|
||||
font-size: 24px;
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
transition: color var(--transition-fast);
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: var(--color-primary-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.embed-frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -78,4 +87,129 @@ onActivated(() => {
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.empty-guide {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.empty-guide-header {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.empty-guide-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.empty-guide-subtitle {
|
||||
font-size: 14px;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.empty-guide-steps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.empty-guide-step {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
padding: 14px 16px;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
transition: background-color var(--transition-normal),
|
||||
border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.empty-guide-step-number {
|
||||
flex-shrink: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty-guide-step-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.empty-guide-step-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.empty-guide-step-desc {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.empty-guide-action {
|
||||
margin-top: 24px;
|
||||
padding: 8px 24px;
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
transition: background-color var(--transition-fast);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-primary-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.anim-fade-in {
|
||||
animation: fadeIn 0.5s ease both;
|
||||
}
|
||||
|
||||
.anim-slide-up {
|
||||
animation: slideUp 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
animation-delay: var(--delay, 0s);
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(16px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -182,18 +182,18 @@ onDeactivated(() => {
|
||||
}
|
||||
|
||||
.log-layout {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
grid-template-columns: 3fr 2fr;
|
||||
}
|
||||
}
|
||||
|
||||
.log-main {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
min-width: 660px;
|
||||
}
|
||||
}
|
||||
|
||||
.log-viewer {
|
||||
@@ -202,16 +202,11 @@ onDeactivated(() => {
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
max-height: 60vh;
|
||||
min-height: 20vh;
|
||||
transition: border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.log-content {
|
||||
min-width: 0;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
min-width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
@@ -265,15 +260,10 @@ onDeactivated(() => {
|
||||
}
|
||||
|
||||
.log-sidebar {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
min-width: 400px;
|
||||
}
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.contact-list {
|
||||
|
||||
@@ -8,13 +8,43 @@ const { url } = storeToRefs(usePlayerStore());
|
||||
|
||||
<template>
|
||||
<div class="page-embed">
|
||||
<template v-if="url === ''">
|
||||
<div class="embed-empty">
|
||||
<RouterLink to="/config" class="embed-link">
|
||||
{{ $t('player.hit') }}
|
||||
</RouterLink>
|
||||
<div v-if="url === ''" class="empty-guide">
|
||||
<div class="empty-guide-header anim-fade-in">
|
||||
<div class="empty-guide-title">{{ $t('player.empty.title') }}</div>
|
||||
<div class="empty-guide-subtitle">{{ $t('player.empty.subtitle') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="empty-guide-steps">
|
||||
<div class="empty-guide-step anim-slide-up" style="--delay: 0.15s">
|
||||
<div class="empty-guide-step-number">1</div>
|
||||
<div class="empty-guide-step-content">
|
||||
<div class="empty-guide-step-title">{{ $t('player.empty.step1_title') }}</div>
|
||||
<div class="empty-guide-step-desc">{{ $t('player.empty.step1_desc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="empty-guide-step anim-slide-up" style="--delay: 0.3s">
|
||||
<div class="empty-guide-step-number">2</div>
|
||||
<div class="empty-guide-step-content">
|
||||
<div class="empty-guide-step-title">{{ $t('player.empty.step2_title') }}</div>
|
||||
<div class="empty-guide-step-desc">{{ $t('player.empty.step2_desc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="empty-guide-step anim-slide-up" style="--delay: 0.45s">
|
||||
<div class="empty-guide-step-number">3</div>
|
||||
<div class="empty-guide-step-content">
|
||||
<div class="empty-guide-step-title">{{ $t('player.empty.step3_title') }}</div>
|
||||
<div class="empty-guide-step-desc">{{ $t('player.empty.step3_desc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RouterLink to="/config" class="empty-guide-action anim-slide-up" style="--delay: 0.6s">
|
||||
{{ $t('sidebar.config') }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<iframe
|
||||
v-else
|
||||
:src="url"
|
||||
@@ -33,26 +63,6 @@ const { url } = storeToRefs(usePlayerStore());
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.embed-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.embed-link {
|
||||
font-size: 24px;
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
transition: color var(--transition-fast);
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: var(--color-primary-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.embed-frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -60,4 +70,129 @@ const { url } = storeToRefs(usePlayerStore());
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.empty-guide {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.empty-guide-header {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.empty-guide-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.empty-guide-subtitle {
|
||||
font-size: 14px;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.empty-guide-steps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.empty-guide-step {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
padding: 14px 16px;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
transition: background-color var(--transition-normal),
|
||||
border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.empty-guide-step-number {
|
||||
flex-shrink: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty-guide-step-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.empty-guide-step-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.empty-guide-step-desc {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.empty-guide-action {
|
||||
margin-top: 24px;
|
||||
padding: 8px 24px;
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
transition: background-color var(--transition-fast);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-primary-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.anim-fade-in {
|
||||
animation: fadeIn 0.5s ease both;
|
||||
}
|
||||
|
||||
.anim-slide-up {
|
||||
animation: slideUp 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
animation-delay: var(--delay, 0s);
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(16px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user