feat: improve chunk viewer with fixed navigation and markdown rendering
This commit implements three UI improvements for the chunk viewer: 1. Fixed modal footer with navigation controls - Moved PDF navigation buttons to a fixed footer - Footer remains visible while scrolling content - Three-section layout: fixed header, scrollable body, fixed footer 2. Removed duplicate navigation controls - Removed previous/next buttons from PDFViewer component - Controls now only in App.vue modal footer - Cleaned up unused imports and CSS 3. Markdown rendering for chunk content - Created MarkdownViewer component using markdown-it - Renders markdown content aligned with Nextcloud design system - Removed problematic markdown-it-task-checkbox dependency - Combines before/chunk/after context with visual separators 4. Cleaned up search results display - Removed excerpt snippets from results list - Kept only chunk/page metadata for cleaner UI The modal structure now has: - Fixed header (title + close button) - Scrollable body (PDF canvas or markdown content) - Fixed footer (page navigation - always visible) Fixes markdown rendering "require is not defined" error by using only markdown-it without CommonJS plugins.
This commit is contained in:
+49
-4
@@ -13,6 +13,7 @@
|
||||
"@nextcloud/l10n": "^3.1.0",
|
||||
"@nextcloud/router": "^3.0.1",
|
||||
"@nextcloud/vue": "^8.29.2",
|
||||
"markdown-it": "^14.1.0",
|
||||
"pdfjs-dist": "^4.0.379",
|
||||
"plotly.js-dist-min": "^2.35.3",
|
||||
"vue": "^2.7.16",
|
||||
@@ -4113,9 +4114,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0",
|
||||
"peer": true
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/array-buffer-byte-length": {
|
||||
"version": "1.0.2",
|
||||
@@ -5722,7 +5721,6 @@
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
@@ -8622,6 +8620,15 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/linkify-it": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uc.micro": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/linkify-string": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/linkify-string/-/linkify-string-4.3.2.tgz",
|
||||
@@ -8737,6 +8744,23 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-it": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "^4.4.0",
|
||||
"linkify-it": "^5.0.0",
|
||||
"mdurl": "^2.0.0",
|
||||
"punycode.js": "^2.3.1",
|
||||
"uc.micro": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"markdown-it": "bin/markdown-it.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/material-colors": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz",
|
||||
@@ -8909,6 +8933,12 @@
|
||||
"license": "CC0-1.0",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/mdurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/meow": {
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
|
||||
@@ -10414,6 +10444,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode.js": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qified": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qified/-/qified-0.5.3.tgz",
|
||||
@@ -12669,6 +12708,12 @@
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/uc.micro": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ufo": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
|
||||
|
||||
Vendored
+1
@@ -22,6 +22,7 @@
|
||||
"@nextcloud/l10n": "^3.1.0",
|
||||
"@nextcloud/router": "^3.0.1",
|
||||
"@nextcloud/vue": "^8.29.2",
|
||||
"markdown-it": "^14.1.0",
|
||||
"plotly.js-dist-min": "^2.35.3",
|
||||
"pdfjs-dist": "^4.0.379",
|
||||
"vue": "^2.7.16",
|
||||
|
||||
Vendored
+84
-36
@@ -199,10 +199,6 @@
|
||||
· {{ t('astroglobe', 'Page {page}/{total}', { page: result.page_number, total: result.page_count }) }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mcp-result-excerpt">
|
||||
{{ result.excerpt }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -296,6 +292,7 @@
|
||||
<!-- PDF/Chunk Viewer Modal -->
|
||||
<div v-if="showViewer" class="mcp-modal-overlay" @click.self="closeViewer">
|
||||
<div class="mcp-modal">
|
||||
<!-- Fixed Header -->
|
||||
<div class="mcp-modal-header">
|
||||
<h3>{{ viewerTitle }}</h3>
|
||||
<NcButton type="tertiary" @click="closeViewer">
|
||||
@@ -304,6 +301,8 @@
|
||||
</template>
|
||||
</NcButton>
|
||||
</div>
|
||||
|
||||
<!-- Scrollable Content -->
|
||||
<div class="mcp-modal-body">
|
||||
<!-- Loading State -->
|
||||
<div v-if="viewerLoading" class="mcp-viewer-loading">
|
||||
@@ -311,27 +310,43 @@
|
||||
<span>{{ t('astroglobe', 'Loading content...') }}</span>
|
||||
</div>
|
||||
|
||||
<!-- PDF Viewer -->
|
||||
<!-- PDF Viewer (canvas only, controls in footer) -->
|
||||
<PDFViewer
|
||||
v-else-if="viewerType === 'pdf'"
|
||||
:file-path="currentPdfPath"
|
||||
:page-number="viewerPage"
|
||||
@prev-page="viewerPage--"
|
||||
@next-page="viewerPage++"
|
||||
@loaded="handlePdfLoaded"
|
||||
@error="handlePdfError" />
|
||||
|
||||
<!-- Text Viewer (for non-PDFs) -->
|
||||
<div v-else class="mcp-text-viewer">
|
||||
<div v-if="viewerContext.before" class="mcp-context-text">
|
||||
{{ viewerContext.before }}
|
||||
</div>
|
||||
<div class="mcp-highlighted-chunk">
|
||||
{{ viewerContext.chunk }}
|
||||
</div>
|
||||
<div v-if="viewerContext.after" class="mcp-context-text">
|
||||
{{ viewerContext.after }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Markdown Viewer (for non-PDFs) -->
|
||||
<MarkdownViewer
|
||||
v-else
|
||||
:content="getMarkdownContent()" />
|
||||
</div>
|
||||
|
||||
<!-- Fixed Footer (navigation controls) -->
|
||||
<div v-if="!viewerLoading && viewerType === 'pdf' && pdfTotalPages > 0" class="mcp-modal-footer">
|
||||
<NcButton
|
||||
:disabled="viewerPage <= 1"
|
||||
@click="viewerPage--">
|
||||
<template #icon>
|
||||
<ChevronLeft :size="20" />
|
||||
</template>
|
||||
{{ t('astroglobe', 'Previous') }}
|
||||
</NcButton>
|
||||
<span class="mcp-page-info">
|
||||
{{ t('astroglobe', 'Page {current} of {total}', { current: viewerPage, total: pdfTotalPages }) }}
|
||||
</span>
|
||||
<NcButton
|
||||
:disabled="viewerPage >= pdfTotalPages"
|
||||
@click="viewerPage++">
|
||||
<template #icon>
|
||||
<ChevronRight :size="20" />
|
||||
</template>
|
||||
{{ t('astroglobe', 'Next') }}
|
||||
</NcButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -356,12 +371,15 @@ import ChartBox from 'vue-material-design-icons/ChartBox.vue'
|
||||
import Cog from 'vue-material-design-icons/Cog.vue'
|
||||
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
||||
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
||||
import ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'
|
||||
import ChevronRight from 'vue-material-design-icons/ChevronRight.vue'
|
||||
import Refresh from 'vue-material-design-icons/Refresh.vue'
|
||||
import OpenInNew from 'vue-material-design-icons/OpenInNew.vue'
|
||||
import Eye from 'vue-material-design-icons/Eye.vue'
|
||||
import Close from 'vue-material-design-icons/Close.vue'
|
||||
|
||||
import PDFViewer from './components/PDFViewer.vue'
|
||||
import MarkdownViewer from './components/MarkdownViewer.vue'
|
||||
|
||||
import axios from '@nextcloud/axios'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
@@ -394,11 +412,14 @@ export default {
|
||||
NcEmptyContent,
|
||||
NcCheckboxRadioSwitch,
|
||||
PDFViewer,
|
||||
MarkdownViewer,
|
||||
Magnify,
|
||||
ChartBox,
|
||||
Cog,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Refresh,
|
||||
OpenInNew,
|
||||
Eye,
|
||||
@@ -434,6 +455,7 @@ export default {
|
||||
viewerTitle: '',
|
||||
viewerType: 'text',
|
||||
viewerPage: 1,
|
||||
pdfTotalPages: 0,
|
||||
currentPdfPath: '',
|
||||
viewerContext: {
|
||||
chunk: '',
|
||||
@@ -776,8 +798,35 @@ export default {
|
||||
this.viewerType = 'text'
|
||||
},
|
||||
|
||||
handlePdfLoaded(event) {
|
||||
this.pdfTotalPages = event.totalPages || 0
|
||||
},
|
||||
|
||||
getMarkdownContent() {
|
||||
// Combine before/chunk/after context into single markdown string
|
||||
let content = ''
|
||||
|
||||
if (this.viewerContext.before) {
|
||||
content += this.viewerContext.before + '\n\n'
|
||||
}
|
||||
|
||||
if (this.viewerContext.chunk) {
|
||||
// Highlight the main chunk with a separator
|
||||
content += '---\n\n'
|
||||
content += this.viewerContext.chunk
|
||||
content += '\n\n---'
|
||||
}
|
||||
|
||||
if (this.viewerContext.after) {
|
||||
content += '\n\n' + this.viewerContext.after
|
||||
}
|
||||
|
||||
return content
|
||||
},
|
||||
|
||||
closeViewer() {
|
||||
this.showViewer = false
|
||||
this.pdfTotalPages = 0
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1031,25 +1080,6 @@ a.mcp-result-title {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.mcp-result-excerpt {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-maxcontrast);
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
|
||||
&--expanded {
|
||||
display: block;
|
||||
-webkit-line-clamp: unset;
|
||||
background: var(--color-background-dark);
|
||||
padding: 12px;
|
||||
border-radius: var(--border-radius);
|
||||
margin-top: 8px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
.mcp-result-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1159,6 +1189,24 @@ a.mcp-result-title {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mcp-modal-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
padding: 16px 20px;
|
||||
border-top: 1px solid var(--color-border);
|
||||
background: var(--color-main-background);
|
||||
flex-shrink: 0;
|
||||
|
||||
.mcp-page-info {
|
||||
font-size: 14px;
|
||||
color: var(--color-text-maxcontrast);
|
||||
min-width: 150px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.mcp-viewer-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div class="markdown-viewer" v-html="html" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
name: 'MarkdownViewer',
|
||||
|
||||
props: {
|
||||
content: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
const md = new MarkdownIt({
|
||||
html: false, // Disable HTML for security
|
||||
linkify: true,
|
||||
breaks: true,
|
||||
typographer: true,
|
||||
})
|
||||
|
||||
return {
|
||||
html: '',
|
||||
md,
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
content: {
|
||||
immediate: true,
|
||||
handler(newContent) {
|
||||
this.renderMarkdown(newContent)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
renderMarkdown(text) {
|
||||
if (!text) {
|
||||
this.html = ''
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
this.html = this.md.render(text)
|
||||
} catch (error) {
|
||||
console.error('Markdown rendering error:', error)
|
||||
// Fallback to escaped plain text
|
||||
this.html = `<pre>${this.escapeHtml(text)}</pre>`
|
||||
}
|
||||
},
|
||||
|
||||
escapeHtml(text) {
|
||||
const div = document.createElement('div')
|
||||
div.textContent = text
|
||||
return div.innerHTML
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.markdown-viewer {
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: var(--color-main-text);
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
// Typography
|
||||
:deep(h1), :deep(h2), :deep(h3), :deep(h4), :deep(h5), :deep(h6) {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
:deep(h1) { font-size: 2em; border-bottom: 1px solid var(--color-border); padding-bottom: 8px; }
|
||||
:deep(h2) { font-size: 1.5em; border-bottom: 1px solid var(--color-border); padding-bottom: 8px; }
|
||||
:deep(h3) { font-size: 1.25em; }
|
||||
:deep(h4) { font-size: 1em; }
|
||||
:deep(h5) { font-size: 0.875em; }
|
||||
:deep(h6) { font-size: 0.85em; color: var(--color-text-maxcontrast); }
|
||||
|
||||
// Paragraphs and spacing
|
||||
:deep(p) {
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
// Lists
|
||||
:deep(ul), :deep(ol) {
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
:deep(li) {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
// Code blocks
|
||||
:deep(code) {
|
||||
padding: 2px 6px;
|
||||
background: var(--color-background-dark);
|
||||
border-radius: var(--border-radius);
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
:deep(pre) {
|
||||
background: var(--color-background-dark);
|
||||
padding: 16px;
|
||||
border-radius: var(--border-radius);
|
||||
overflow-x: auto;
|
||||
margin-bottom: 16px;
|
||||
|
||||
code {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// Blockquotes
|
||||
:deep(blockquote) {
|
||||
margin: 0 0 16px 0;
|
||||
padding: 0 16px;
|
||||
border-left: 4px solid var(--color-primary-element);
|
||||
color: var(--color-text-maxcontrast);
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Links
|
||||
:deep(a) {
|
||||
color: var(--color-primary-element);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
// Tables
|
||||
:deep(table) {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
:deep(th), :deep(td) {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--color-border);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
:deep(th) {
|
||||
background: var(--color-background-dark);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// Horizontal rule
|
||||
:deep(hr) {
|
||||
border: none;
|
||||
border-top: 1px solid var(--color-border);
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
// Images
|
||||
:deep(img) {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -11,27 +11,6 @@
|
||||
<div v-else ref="container" class="pdf-canvas-container">
|
||||
<canvas ref="canvas" />
|
||||
</div>
|
||||
<div v-if="!loading && !error && totalPages > 0" class="pdf-controls">
|
||||
<NcButton
|
||||
:disabled="pageNumber <= 1"
|
||||
@click="$emit('prev-page')">
|
||||
<template #icon>
|
||||
<ChevronLeft :size="20" />
|
||||
</template>
|
||||
{{ t('astroglobe', 'Previous') }}
|
||||
</NcButton>
|
||||
<span class="page-info">
|
||||
{{ t('astroglobe', 'Page {current} of {total}', { current: pageNumber, total: totalPages }) }}
|
||||
</span>
|
||||
<NcButton
|
||||
:disabled="pageNumber >= totalPages"
|
||||
@click="$emit('next-page')">
|
||||
<template #icon>
|
||||
<ChevronRight :size="20" />
|
||||
</template>
|
||||
{{ t('astroglobe', 'Next') }}
|
||||
</NcButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -40,19 +19,13 @@ import * as pdfjsLib from 'pdfjs-dist'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
import AlertCircle from 'vue-material-design-icons/AlertCircle.vue'
|
||||
import ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'
|
||||
import ChevronRight from 'vue-material-design-icons/ChevronRight.vue'
|
||||
|
||||
export default {
|
||||
name: 'PDFViewer',
|
||||
components: {
|
||||
NcLoadingIcon,
|
||||
NcButton,
|
||||
AlertCircle,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
},
|
||||
props: {
|
||||
filePath: {
|
||||
@@ -247,34 +220,9 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.pdf-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 8px;
|
||||
background: var(--color-background-dark);
|
||||
border-radius: var(--border-radius-large);
|
||||
|
||||
.page-info {
|
||||
font-size: 14px;
|
||||
color: var(--color-text-maxcontrast);
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pdf-viewer {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.pdf-controls {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.page-info {
|
||||
order: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user