diff --git a/webui/src/components/ab-container.vue b/webui/src/components/ab-container.vue index 9aadb95c..68c89c14 100644 --- a/webui/src/components/ab-container.vue +++ b/webui/src/components/ab-container.vue @@ -25,47 +25,35 @@ withDefaults( diff --git a/webui/src/components/ab-fold-panel.vue b/webui/src/components/ab-fold-panel.vue index bc4d8c30..17d7c3d4 100644 --- a/webui/src/components/ab-fold-panel.vue +++ b/webui/src/components/ab-fold-panel.vue @@ -5,28 +5,28 @@ import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue'; withDefaults( defineProps<{ title: string; + defaultOpen?: boolean; }>(), { title: 'title', + defaultOpen: true, } ); - + {{ title }} - + - - - - + + - - + + @@ -34,7 +34,6 @@ withDefaults( diff --git a/webui/src/components/ab-label.vue b/webui/src/components/ab-label.vue index b1405179..4b551da8 100644 --- a/webui/src/components/ab-label.vue +++ b/webui/src/components/ab-label.vue @@ -24,14 +24,14 @@ const abLabel = computed(() => { diff --git a/webui/src/components/ab-setting.vue b/webui/src/components/ab-setting.vue index 6cb85fcd..03a63122 100644 --- a/webui/src/components/ab-setting.vue +++ b/webui/src/components/ab-setting.vue @@ -40,6 +40,6 @@ const data = defineModel('data'); - + diff --git a/webui/src/components/setting/config-download.vue b/webui/src/components/setting/config-download.vue index 927d4968..0267cb44 100644 --- a/webui/src/components/setting/config-download.vue +++ b/webui/src/components/setting/config-download.vue @@ -65,7 +65,7 @@ const items: SettingItem[] = [ - + [] = [ - + = { - + [] = [ - + [] = [ {{ $t('config.experimental_openai_set.warning') }} - + [] = [ - + - + {{ $t('passkey.not_supported') }} diff --git a/webui/src/components/setting/config-player.vue b/webui/src/components/setting/config-player.vue index e73e8cf5..0a07e5ec 100644 --- a/webui/src/components/setting/config-player.vue +++ b/webui/src/components/setting/config-player.vue @@ -4,7 +4,7 @@ const { types, type, url } = storeToRefs(usePlayerStore()); - + [] = [ - + { .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); } diff --git a/webui/src/pages/index/downloader.vue b/webui/src/pages/index/downloader.vue index f0a6ad31..ce482a42 100644 --- a/webui/src/pages/index/downloader.vue +++ b/webui/src/pages/index/downloader.vue @@ -25,13 +25,42 @@ onActivated(() => { - - - - {{ $t('downloader.hit') }} - + + + {{ $t('downloader.empty.title') }} + {{ $t('downloader.empty.subtitle') }} - + + + + 1 + + {{ $t('downloader.empty.step1_title') }} + {{ $t('downloader.empty.step1_desc') }} + + + + + 2 + + {{ $t('downloader.empty.step2_title') }} + {{ $t('downloader.empty.step2_desc') }} + + + + + 3 + + {{ $t('downloader.empty.step3_title') }} + {{ $t('downloader.empty.step3_desc') }} + + + + + + {{ $t('sidebar.config') }} + + { 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); + } +} diff --git a/webui/src/pages/index/log.vue b/webui/src/pages/index/log.vue index a35fd547..f74603b3 100644 --- a/webui/src/pages/index/log.vue +++ b/webui/src/pages/index/log.vue @@ -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 { diff --git a/webui/src/pages/index/player.vue b/webui/src/pages/index/player.vue index 7faaaa07..8f03fa27 100644 --- a/webui/src/pages/index/player.vue +++ b/webui/src/pages/index/player.vue @@ -8,13 +8,43 @@ const { url } = storeToRefs(usePlayerStore()); - - - - {{ $t('player.hit') }} - + + + {{ $t('player.empty.title') }} + {{ $t('player.empty.subtitle') }} - + + + + 1 + + {{ $t('player.empty.step1_title') }} + {{ $t('player.empty.step1_desc') }} + + + + + 2 + + {{ $t('player.empty.step2_title') }} + {{ $t('player.empty.step2_desc') }} + + + + + 3 + + {{ $t('player.empty.step3_title') }} + {{ $t('player.empty.step3_desc') }} + + + + + + {{ $t('sidebar.config') }} + + +