0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-01-24 04:15:35 +01:00

refactor: rename TOC to sidebar and update related functionality

- Change references from TOC to sidebar in the file view and README rendering functions.
- Update CSS classes and JavaScript functions to reflect the new sidebar implementation.
- Ensure proper visibility and positioning of the sidebar in the file view context.
This commit is contained in:
hamki 2026-01-01 08:28:16 +08:00
parent e7fb9af3cb
commit 7386cc0aba
5 changed files with 70 additions and 68 deletions

View File

@ -93,7 +93,7 @@ func handleFileViewRenderMarkup(ctx *context.Context, filename string, sniffedTy
return true
}
ctx.Data["FileTocHTML"] = renderSidebarTocHTML(rctx)
ctx.Data["FileSidebarHTML"] = renderSidebarTocHTML(rctx)
return true
}

View File

@ -207,7 +207,7 @@ func prepareToRenderReadmeFile(ctx *context.Context, subfolder string, readmeFil
delete(ctx.Data, "IsMarkup")
}
ctx.Data["ReadmeTocHTML"] = renderSidebarTocHTML(rctx)
ctx.Data["FileSidebarHTML"] = renderSidebarTocHTML(rctx)
}
if ctx.Data["IsMarkup"] != true {

View File

@ -35,11 +35,13 @@
{{end}}
</div>
<div class="file-header-right file-actions flex-text-block tw-flex-wrap">
{{if or .ReadmeTocHTML .FileTocHTML}}
<button class="btn-octicon" id="toggle-toc-btn" data-tooltip-content="{{ctx.Locale.Tr "toc"}}">
{{svg "octicon-list-unordered" 16}}
{{if .FileSidebarHTML}}
<div class="ui compact icon buttons">
<button class="ui mini basic button" id="toggle-sidebar-btn" data-tooltip-content="{{ctx.Locale.Tr "toc"}}">
{{svg "octicon-list-unordered" 15}}
</button>
{{end}}
</div>
{{end}}
{{/* this componment is also controlled by frontend plugin renders */}}
<div class="ui compact icon buttons file-view-toggle-buttons {{Iif .HasSourceRenderedToggle "" "tw-hidden"}}">
{{if .IsRepresentableAsText}}
@ -144,9 +146,9 @@
</div>
{{end}}
</div>
{{if or .ReadmeTocHTML .FileTocHTML}}
<div class="file-view-toc markup toc-panel-hidden">
{{or .ReadmeTocHTML .FileTocHTML}}
{{if .FileSidebarHTML}}
<div class="file-view-sidebar markup sidebar-panel-hidden">
{{.FileSidebarHTML}}
</div>
{{end}}

View File

@ -79,8 +79,8 @@
transition: margin-right 0.2s ease;
}
/* When TOC is visible, reserve space on the right (only for file view, not home page) */
.repo-view-content.toc-visible {
/* When sidebar is visible, reserve space on the right (only for file view, not home page) */
.repo-view-content.sidebar-visible {
margin-right: 270px;
}
@ -112,8 +112,8 @@
text-decoration: none;
}
/* TOC as a fixed sidebar panel */
.file-view-toc {
/* File view sidebar panel (e.g., TOC for markdown files) */
.file-view-sidebar {
position: fixed;
top: 120px; /* Will be adjusted by JS to align with file content */
right: 0.5rem;
@ -129,21 +129,21 @@
transition: opacity 0.15s ease;
}
/* Show TOC after JS has positioned it */
.file-view-toc.toc-positioned {
/* Show sidebar after JS has positioned it */
.file-view-sidebar.sidebar-positioned {
opacity: 1;
}
/* Hidden state - using custom class to avoid Tailwind conflicts */
.file-view-toc.toc-panel-hidden {
.file-view-sidebar.sidebar-panel-hidden {
display: none;
}
.file-view-toc details {
.file-view-sidebar details {
font-size: 13px;
}
.file-view-toc summary {
.file-view-sidebar summary {
font-weight: var(--font-weight-semibold);
cursor: pointer;
padding: 8px 0;
@ -152,17 +152,17 @@
margin-bottom: 8px;
}
.file-view-toc ul {
.file-view-sidebar ul {
margin: 0;
list-style: none;
padding: 5px 0 5px 1em;
}
.file-view-toc ul ul {
.file-view-sidebar ul ul {
border-left: 1px dashed var(--color-secondary);
}
.file-view-toc a {
.file-view-sidebar a {
display: block;
padding: 6px 10px;
color: var(--color-text);
@ -172,28 +172,28 @@
border-radius: var(--border-radius);
}
.file-view-toc a:hover {
.file-view-sidebar a:hover {
color: var(--color-primary);
background: var(--color-hover);
}
/* TOC toggle button active state - when TOC is visible */
#toggle-toc-btn.active {
/* Sidebar toggle button active state - when sidebar is visible */
#toggle-sidebar-btn.active {
color: var(--color-primary);
}
/* Hide TOC sidebar on small screens */
/* Hide sidebar on small screens */
@media (max-width: 1400px) {
.file-view-toc {
.file-view-sidebar {
display: none !important;
}
#toggle-toc-btn {
#toggle-sidebar-btn {
display: none;
}
/* Don't reserve space for TOC on small screens */
.repo-view-content.toc-visible {
/* Don't reserve space for sidebar on small screens */
.repo-view-content.sidebar-visible {
margin-right: 0;
}
}

View File

@ -59,32 +59,32 @@ async function renderRawFileToContainer(container: HTMLElement, rawFileLink: str
}
}
function updateTocPosition(elFileView: HTMLElement, tocSidebar: HTMLElement): void {
function updateSidebarPosition(elFileView: HTMLElement, sidebar: HTMLElement): void {
const fileHeader = elFileView.querySelector('.file-header');
if (!fileHeader) return;
const headerRect = fileHeader.getBoundingClientRect();
// Align TOC top with the file header top, with a minimum of 12px from viewport top
// Align sidebar top with the file header top, with a minimum of 12px from viewport top
const topPos = Math.max(12, headerRect.top);
tocSidebar.style.top = `${topPos}px`;
sidebar.style.top = `${topPos}px`;
// Position TOC right next to the content (works for both file view and home page)
// Position sidebar right next to the content (works for both file view and home page)
const segment = elFileView.querySelector('.ui.segment');
if (segment) {
const segmentRect = segment.getBoundingClientRect();
const leftPos = segmentRect.right + 8; // 8px gap from content
tocSidebar.style.left = `${leftPos}px`;
tocSidebar.style.right = 'auto';
sidebar.style.left = `${leftPos}px`;
sidebar.style.right = 'auto';
}
// Mark as positioned to show the TOC (prevents flicker)
tocSidebar.classList.add('toc-positioned');
// Mark as positioned to show the sidebar (prevents flicker)
sidebar.classList.add('sidebar-positioned');
}
function initTocToggle(elFileView: HTMLElement): void {
const toggleBtn = elFileView.querySelector('#toggle-toc-btn');
const tocSidebar = elFileView.querySelector<HTMLElement>('.file-view-toc');
if (!toggleBtn || !tocSidebar) return;
function initSidebarToggle(elFileView: HTMLElement): void {
const toggleBtn = elFileView.querySelector('#toggle-sidebar-btn');
const sidebar = elFileView.querySelector<HTMLElement>('.file-view-sidebar');
if (!toggleBtn || !sidebar) return;
// Check if we're in file view (not home page) - only file view needs margin adjustment
const repoViewContent = elFileView.closest('.repo-view-content');
@ -92,26 +92,26 @@ function initTocToggle(elFileView: HTMLElement): void {
// Helper to update position
const updatePosition = () => {
if (!tocSidebar.classList.contains('toc-panel-hidden')) {
updateTocPosition(elFileView, tocSidebar);
if (!sidebar.classList.contains('sidebar-panel-hidden')) {
updateSidebarPosition(elFileView, sidebar);
}
};
// Helper to show TOC with proper positioning
const showToc = () => {
// Helper to show sidebar with proper positioning
const showSidebar = () => {
toggleBtn.classList.add('active');
// Wait for margin to take effect before showing and positioning TOC
// Wait for margin to take effect before showing and positioning sidebar
const showAfterLayout = () => {
tocSidebar.classList.remove('toc-panel-hidden');
sidebar.classList.remove('sidebar-panel-hidden');
requestAnimationFrame(() => {
updateTocPosition(elFileView, tocSidebar);
updateSidebarPosition(elFileView, sidebar);
});
};
// For file view, first add margin, wait for layout, then show TOC
if (isFileView) {
repoViewContent.classList.add('toc-visible');
// For file view, first add margin, wait for layout, then show sidebar
if (isFileView && repoViewContent) {
repoViewContent.classList.add('sidebar-visible');
// Wait for CSS transition to complete (200ms) before calculating position
setTimeout(showAfterLayout, 220);
} else {
@ -120,28 +120,28 @@ function initTocToggle(elFileView: HTMLElement): void {
}
};
// Helper to hide TOC
const hideToc = () => {
tocSidebar.classList.add('toc-panel-hidden');
tocSidebar.classList.remove('toc-positioned');
// Helper to hide sidebar
const hideSidebar = () => {
sidebar.classList.add('sidebar-panel-hidden');
sidebar.classList.remove('sidebar-positioned');
toggleBtn.classList.remove('active');
if (isFileView) {
repoViewContent.classList.remove('toc-visible');
if (isFileView && repoViewContent) {
repoViewContent.classList.remove('sidebar-visible');
}
};
// Restore saved state from localStorage (default to hidden)
const savedState = localStorage.getItem('file-view-toc-visible');
const savedState = localStorage.getItem('file-view-sidebar-visible');
const isVisible = savedState === 'true'; // default to hidden
// Apply initial state
if (isVisible) {
showToc();
showSidebar();
} else {
hideToc();
hideSidebar();
}
// Update TOC position on resize/scroll to keep aligned with file content
// Update sidebar position on resize/scroll to keep aligned with file content
const resizeObserver = new ResizeObserver(() => {
updatePosition();
});
@ -160,13 +160,13 @@ function initTocToggle(elFileView: HTMLElement): void {
}
toggleBtn.addEventListener('click', () => {
const isCurrentlyVisible = !tocSidebar.classList.contains('toc-panel-hidden');
const isCurrentlyVisible = !sidebar.classList.contains('sidebar-panel-hidden');
if (isCurrentlyVisible) {
hideToc();
localStorage.setItem('file-view-toc-visible', 'false');
hideSidebar();
localStorage.setItem('file-view-sidebar-visible', 'false');
} else {
showToc();
localStorage.setItem('file-view-toc-visible', 'true');
showSidebar();
localStorage.setItem('file-view-sidebar-visible', 'true');
}
});
}
@ -175,8 +175,8 @@ export function initRepoFileView(): void {
registerGlobalInitFunc('initRepoFileView', async (elFileView: HTMLElement) => {
initPluginsOnce();
// Initialize TOC toggle functionality
initTocToggle(elFileView);
// Initialize sidebar toggle functionality (e.g., TOC for markdown files)
initSidebarToggle(elFileView);
const rawFileLink = elFileView.getAttribute('data-raw-file-link')!;
const mimeType = elFileView.getAttribute('data-mime-type') || ''; // not used yet