diff --git a/.changeset/tender-carrots-film.md b/.changeset/tender-carrots-film.md
new file mode 100644
index 0000000000..a807d74542
--- /dev/null
+++ b/.changeset/tender-carrots-film.md
@@ -0,0 +1,5 @@
+---
+'gitbook': patch
+---
+
+Add icons to sections
diff --git a/bun.lockb b/bun.lockb
index c08095915f..c571339241 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/packages/gitbook/package.json b/packages/gitbook/package.json
index 7ec5c1f862..6fd0ce6f39 100644
--- a/packages/gitbook/package.json
+++ b/packages/gitbook/package.json
@@ -16,7 +16,7 @@
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static"
},
"dependencies": {
- "@gitbook/api": "^0.77.0",
+ "@gitbook/api": "^0.78.0",
"@gitbook/cache-do": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/icons": "workspace:*",
diff --git a/packages/gitbook/src/components/SiteSectionTabs/SectionIcon.tsx b/packages/gitbook/src/components/SiteSectionTabs/SectionIcon.tsx
new file mode 100644
index 0000000000..66f810b9f7
--- /dev/null
+++ b/packages/gitbook/src/components/SiteSectionTabs/SectionIcon.tsx
@@ -0,0 +1,21 @@
+import type { SiteSection } from '@gitbook/api';
+import { Icon, type IconName } from '@gitbook/icons';
+
+import { type ClassValue, tcls } from '@/lib/tailwind';
+
+/**
+ * Icon shown beside a section in the site section tabs.
+ */
+export function SectionIcon(props: { icon: IconName; isActive: boolean }) {
+ const { icon, isActive } = props;
+
+ return (
+
+ );
+}
diff --git a/packages/gitbook/src/components/SiteSectionTabs/SiteSectionTabs.tsx b/packages/gitbook/src/components/SiteSectionTabs/SiteSectionTabs.tsx
index 31bfd0c568..a194c8dc2f 100644
--- a/packages/gitbook/src/components/SiteSectionTabs/SiteSectionTabs.tsx
+++ b/packages/gitbook/src/components/SiteSectionTabs/SiteSectionTabs.tsx
@@ -1,10 +1,13 @@
'use client';
-import { SiteSection } from '@gitbook/api';
+
+import type { SiteSection } from '@gitbook/api';
+import type { IconName } from '@gitbook/icons';
import React from 'react';
import { tcls } from '@/lib/tailwind';
import { Link } from '../primitives';
+import { SectionIcon } from './SectionIcon';
/**
* A set of navigational tabs representing site sections for multi-section sites
@@ -14,13 +17,7 @@ export function SiteSectionTabs(props: {
section: SiteSection;
index: number;
}) {
- const { list: sections, section: currentSection, index: currentIndex } = props;
-
- const tabs = sections.map((section) => ({
- id: section.id,
- label: section.title,
- path: section.urls.published ?? '',
- }));
+ const { list: sections, index: currentIndex } = props;
const currentTabRef = React.useRef(null);
const navRef = React.useRef(null);
@@ -43,7 +40,9 @@ export function SiteSectionTabs(props: {
}, []);
React.useEffect(() => {
- updateTabDimensions();
+ if (currentIndex >= 0) {
+ updateTabDimensions();
+ }
}, [currentIndex, updateTabDimensions]);
React.useLayoutEffect(() => {
@@ -55,11 +54,11 @@ export function SiteSectionTabs(props: {
};
}, [updateTabDimensions]);
- const opacity = Boolean(tabDimensions) ? 1 : 0.0;
+ const opacity = tabDimensions ? 1 : 0.0;
const scale = (tabDimensions?.width ?? 0) * 0.01;
const startPos = `${tabDimensions?.left ?? 0}px`;
- return tabs.length > 0 ? (
+ return sections.length > 0 ? (
) : null;
@@ -126,24 +134,26 @@ export function SiteSectionTabs(props: {
/**
* The tab item - a link to a site section
*/
-const Tab = React.forwardRef(
- function Tab(props, ref) {
- const { active, href, label } = props;
- return (
-
-
- {label}
-
-
- );
- },
-);
+const Tab = React.forwardRef<
+ HTMLSpanElement,
+ { active: boolean; href: string; icon?: React.ReactNode; label: string }
+>(function Tab(props, ref) {
+ const { active, href, icon, label } = props;
+ return (
+
+
+ {icon}
+ {label}
+
+
+ );
+});