diff --git a/frontend/src/components/ChatReferencesDrawer.vue b/frontend/src/components/ChatReferencesDrawer.vue index b405e336..d3c881f8 100644 --- a/frontend/src/components/ChatReferencesDrawer.vue +++ b/frontend/src/components/ChatReferencesDrawer.vue @@ -10,8 +10,9 @@ >
-

{{ panelTitle }}

- {{ totalCount }} +

+ {{ panelTitle }} · {{ totalCount }} +

@@ -41,17 +42,17 @@ v-for="item in section.items" :key="item.key" :ref="(el) => setItemRef(item.key, el as HTMLElement | null)" - class="reference-card" + class="reference-item" :class="{ - 'reference-card--web': item.kind === 'web', - 'reference-card--document': item.kind === 'document', - 'reference-card--tool': item.kind === 'tool', + 'reference-item--web': item.kind === 'web', + 'reference-item--document': item.kind === 'document', + 'reference-item--tool': item.kind === 'tool', 'is-highlighted': item.key === activeHighlightKey, }" > -
- {{ item.index }} - - - - {{ item.domain }} - - {{ t('chat.referencesDrawerDocument') }} - - - {{ t('chat.referencesDrawerTool') }} - -
+ +
- -
- - - {{ t('chat.navigateToDocument') }} - -
@@ -140,6 +141,7 @@ import { useRouter } from 'vue-router' import { useChatReferencesDrawer } from '@/composables/useChatReferencesDrawer' import { buildReferenceSections, + formatReferenceSnippet, resolveReferenceHighlightKey, type ReferenceListItem, } from '@/utils/referenceSources' @@ -267,6 +269,13 @@ function getDocumentHref(item: ReferenceListItem) { }).href } +function shouldShowItemTitle(item: ReferenceListItem) { + if (item.kind !== 'web') return true + const title = item.title?.trim() + const domain = item.domain?.trim() + return Boolean(title && title !== domain) +} + async function scrollToHighlight() { if (!panelEntered.value) return const key = activeHighlightKey.value @@ -361,49 +370,45 @@ watch(visible, (open) => { .chat-references-panel__title { margin: 0; - font-size: 15px; - font-weight: 600; - color: var(--td-text-color-primary); + font-size: 14px; + font-weight: 500; + color: var(--td-text-color-secondary); line-height: 1.4; } .chat-references-panel__count { - flex-shrink: 0; - min-width: 22px; - height: 22px; - padding: 0 8px; - border-radius: 999px; - background: var(--td-bg-color-secondarycontainer); - color: var(--td-text-color-secondary); - font-size: 12px; - font-weight: 600; - display: inline-flex; - align-items: center; - justify-content: center; + color: var(--td-text-color-placeholder); + font-weight: 500; } .chat-references-panel__close { border: 0; - background: transparent; - color: var(--td-text-color-placeholder); - width: 32px; - height: 32px; - border-radius: 8px; + background: var(--td-bg-color-secondarycontainer); + color: var(--td-text-color-secondary); + width: 36px; + height: 36px; + border-radius: 10px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; + flex-shrink: 0; + transition: background 0.15s ease, color 0.15s ease; + + :deep(.t-icon) { + font-size: 20px; + } &:hover { - background: var(--td-bg-color-component-hover); - color: var(--td-text-color-secondary); + background: color-mix(in srgb, var(--td-text-color-primary) 8%, var(--td-bg-color-secondarycontainer)); + color: var(--td-text-color-primary); } } .chat-references-panel__body { flex: 1; overflow-y: auto; - padding: 12px 12px 20px; + padding: 4px 12px 24px; } .chat-references-panel__empty { @@ -413,6 +418,12 @@ watch(visible, (open) => { font-size: 13px; } +.chat-references-panel__section { + display: flex; + flex-direction: column; + gap: 6px; +} + .chat-references-panel__section + .chat-references-panel__section { margin-top: 16px; } @@ -427,162 +438,139 @@ watch(visible, (open) => { letter-spacing: 0.04em; } -.reference-card { - border: 1px solid var(--td-component-stroke); +.reference-item { border-radius: 12px; - background: var(--td-bg-color-container); - overflow: hidden; - transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; + transition: background-color 0.15s ease; - & + & { - margin-top: 10px; - } - - &:hover { - border-color: color-mix(in srgb, var(--td-text-color-placeholder) 42%, var(--td-component-stroke)); - box-shadow: 0 4px 14px rgba(0, 0, 0, 0.04); + &:hover:not(.is-highlighted) { + background: color-mix(in srgb, var(--td-text-color-primary) 4%, transparent); } &.is-highlighted { - border-color: var(--td-text-color-placeholder); - background: var(--td-bg-color-secondarycontainer); - box-shadow: none; - animation: reference-card-highlight 1s ease; - } -} - -@keyframes reference-card-highlight { - 0% { - background: var(--td-bg-color-component-hover); - } - 100% { background: var(--td-bg-color-secondarycontainer); } } -.reference-card__inner { +.reference-item__body { display: block; - padding: 12px 14px; + padding: 10px 12px; color: inherit; text-decoration: none; - transition: background-color 0.16s ease; &.is-expandable { cursor: pointer; } } -.reference-card--web .reference-card__inner:hover { - background: color-mix(in srgb, var(--td-text-color-primary) 3%, var(--td-bg-color-container)); -} - -.reference-card--document .reference-card__inner:hover, -.reference-card--tool .reference-card__inner:hover { - background: color-mix(in srgb, var(--td-text-color-primary) 3%, var(--td-bg-color-container)); -} - -.reference-card__meta { +.reference-item__document { display: flex; - align-items: center; - gap: 8px; - margin-bottom: 8px; + align-items: flex-start; + gap: 10px; min-width: 0; } -.reference-card__index { +.reference-item__doc-icon { flex-shrink: 0; - width: 20px; - height: 20px; - border-radius: 999px; - background: var(--td-bg-color-secondarycontainer); - color: var(--td-text-color-secondary); - font-size: 11px; - font-weight: 600; - display: inline-flex; - align-items: center; - justify-content: center; + width: 18px; + margin-top: 3px; + font-size: 16px; + color: var(--td-text-color-primary); } -.reference-card__favicon { +.reference-item__document-main { + flex: 1; + min-width: 0; +} + +.reference-item__source { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + margin-bottom: 6px; +} + +.reference-item__source-mark { + flex-shrink: 0; width: 16px; height: 16px; - border-radius: 4px; - flex-shrink: 0; -} - -.reference-card__doc-icon { + border-radius: 999px; + object-fit: cover; + font-size: 14px; color: var(--td-text-color-placeholder); - flex-shrink: 0; } -.reference-card__domain { - font-size: 12px; +.reference-item__domain { + font-size: 13px; + line-height: 1.35; color: var(--td-text-color-placeholder); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.reference-card__title { +.reference-item__title-row { + display: flex; + align-items: flex-start; + gap: 8px; + min-width: 0; +} + +.reference-item__title { + flex: 1; + min-width: 0; margin: 0; - font-size: 14px; + font-size: 15px; font-weight: 600; - line-height: 1.45; + line-height: 1.4; color: var(--td-text-color-primary); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; + word-break: break-word; +} + +.reference-item__open { + flex-shrink: 0; + margin-top: 3px; + color: var(--td-text-color-placeholder); + line-height: 1; + opacity: 0; + transition: opacity 0.15s ease, color 0.15s ease; +} + +.reference-item:hover .reference-item__open, +.reference-item.is-highlighted .reference-item__open { + opacity: 1; +} + +.reference-item__open:hover { + color: var(--td-text-color-primary); +} + +.reference-item__snippet { + margin: 4px 0 0; + font-size: 13px; + line-height: 1.5; + color: var(--td-text-color-secondary); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; } -.reference-card__snippet { - margin: 8px 0 0; +.reference-item__content { + margin: 4px 0 0; font-size: 13px; line-height: 1.55; color: var(--td-text-color-secondary); - display: -webkit-box; - -webkit-line-clamp: 4; - -webkit-box-orient: vertical; - overflow: hidden; -} - -.reference-card__content { - margin-top: 8px; - font-size: 13px; - line-height: 1.6; - color: var(--td-text-color-secondary); white-space: pre-wrap; word-break: break-word; max-height: 360px; overflow-y: auto; } -.reference-card__actions { - display: flex; - align-items: center; - gap: 10px; - flex-wrap: wrap; - padding: 0 14px 12px; -} - -.reference-card__action { - border: 0; - background: transparent; - color: var(--td-text-color-secondary); - font-size: 12px; - display: inline-flex; - align-items: center; - gap: 4px; - cursor: pointer; - padding: 0; - text-decoration: none; - - &:hover { - color: var(--td-text-color-primary); - text-decoration: underline; - } -} - .references-panel-enter-active { transition: transform 0.24s cubic-bezier(0.22, 0.61, 0.36, 1), diff --git a/frontend/src/components/chat/FollowUpSuggestions.vue b/frontend/src/components/chat/FollowUpSuggestions.vue index b2945d49..458d0843 100644 --- a/frontend/src/components/chat/FollowUpSuggestions.vue +++ b/frontend/src/components/chat/FollowUpSuggestions.vue @@ -63,6 +63,8 @@ const dismiss = () => {