feat: add support for icons in tabs (#4277)

This commit is contained in:
Tomek
2026-05-27 15:22:25 +00:00
committed by GitHub
parent 16a54b6bb9
commit f405fffa06
8 changed files with 26 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add icon support in tab items
+2 -2
View File
@@ -359,7 +359,7 @@
"react-dom": "catalog:",
},
"catalog": {
"@gitbook/api": "0.181.0",
"@gitbook/api": "0.182.0",
"@scalar/api-client-react": "^1.3.46",
"@tsconfig/node20": "^20.1.6",
"@tsconfig/strictest": "^2.0.6",
@@ -755,7 +755,7 @@
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@7.2.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.2.0" } }, "sha512-6639htZMjEkwskf3J+e6/iar+4cTNM9qhoWuRfj9F3eJD6r7iCzV1SWnQr2Mdv0QT0suuqU8BoJCZUyCtP9R4Q=="],
"@gitbook/api": ["@gitbook/api@0.181.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-tj7bPzty9jlG3zKiZlmvvqalbTCtukmU/BlFB3HPRZM4jQrmLBc+Ya0rOyTpTaLJEH1BZy0U9HGsoCfbP5W8Fg=="],
"@gitbook/api": ["@gitbook/api@0.182.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-O5CgVzbRL2esrsQJ816UcHMqY22fsMFAeLRQ8Gapus4S+/teXk3nf5YU5T10o3112niSD3QeNp2uIcsyMGOweg=="],
"@gitbook/browser-types": ["@gitbook/browser-types@workspace:packages/browser-types"],
+1 -1
View File
@@ -43,7 +43,7 @@
"catalog": {
"@tsconfig/strictest": "^2.0.6",
"@tsconfig/node20": "^20.1.6",
"@gitbook/api": "0.181.0",
"@gitbook/api": "0.182.0",
"@scalar/api-client-react": "^1.3.46",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
@@ -15,7 +15,7 @@ import { useLanguage } from '@/intl/client';
import { tString } from '@/intl/translate';
import { getLocalStorageItem, setLocalStorageItem } from '@/lib/browser';
import { tcls } from '@/lib/tailwind';
import { Icon } from '@gitbook/icons';
import { Icon, type IconName } from '@gitbook/icons';
import { useRouter } from 'next/navigation';
interface TabsState {
@@ -56,6 +56,7 @@ const TITLES_MAX = 5;
export interface TabsItem {
id: string;
title: string;
icon?: IconName;
body: React.ReactNode;
}
@@ -319,6 +320,7 @@ function TabsDropdownMenu(props: {
key={tab.id}
onClick={() => onSelect(tab.id)}
active={tab.id === activeTabId}
leadingIcon={tab.icon}
>
{tab.title}
</DropdownMenuItem>
@@ -347,7 +349,8 @@ const TabItem = memo(function TabItem(props: {
id={getTabButtonId(tab.id)}
onClick={() => onSelect(tab.id)}
>
{tab.title}
{tab.icon && <Icon icon={tab.icon} className="size-4 shrink-0" />}
<span className="min-w-0 truncate">{tab.title}</span>
</TabButton>
);
});
@@ -411,7 +414,7 @@ function TabButton(
{...rest}
type="button"
className={tcls(
'relative inline-block max-w-full truncate px-3.5 py-2 font-medium text-sm transition-[color]',
'relative inline-flex max-w-full items-center gap-1.5 px-3.5 py-2 font-medium text-sm transition-[color]',
props.className
)}
/>
@@ -1,4 +1,6 @@
import type { DocumentBlockTabs } from '@gitbook/api';
import type { IconName } from '@gitbook/icons';
import { validateIconName } from '@gitbook/icons/icons';
import { tcls } from '@/lib/tailwind';
@@ -20,9 +22,13 @@ export function Tabs(props: BlockProps<DocumentBlockTabs>) {
throw new Error('Tab block is missing a key');
}
const icon: IconName | undefined =
tab.data.icon && validateIconName(tab.data.icon) ? tab.data.icon : undefined;
return {
id: tab.meta?.id ?? tab.key,
title: tab.data.title ?? '',
icon,
body: (
<Blocks
key={tab.key}
@@ -27,7 +27,6 @@ export async function PageHeader(props: {
const hasAncestors = ancestors.length > 0;
// @ts-expect-error available in next API update
const pageActionsEnabled = page.layout.actions !== false;
// Show page actions if *any* of the actions are enabled
+1 -1
View File
@@ -358,7 +358,7 @@ function collectDocumentIconSourceRequests(
const record = node as Record<string, unknown>;
if (record.type === 'icon' || record.type === 'button') {
if (record.type === 'icon' || record.type === 'button' || record.type === 'tabs-item') {
const data = record.data;
if (data && typeof data === 'object') {
addIconSourceRequest(requests, (data as Record<string, unknown>).icon, iconStyle);
+5
View File
@@ -85,6 +85,7 @@ describe('resolveFirstDocument', () => {
width: RevisionPageLayoutOptionsWidth.Default,
metadata: true,
tags: true,
actions: true,
},
},
],
@@ -137,6 +138,7 @@ describe('resolveFirstDocument', () => {
width: RevisionPageLayoutOptionsWidth.Default,
metadata: true,
tags: true,
actions: true,
},
},
];
@@ -182,6 +184,7 @@ describe('resolvePagePath', () => {
width: RevisionPageLayoutOptionsWidth.Default,
metadata: true,
tags: true,
actions: true,
},
},
];
@@ -257,6 +260,7 @@ describe('resolvePagePath', () => {
width: RevisionPageLayoutOptionsWidth.Default,
metadata: true,
tags: true,
actions: true,
},
},
],
@@ -374,6 +378,7 @@ function createDocumentPage(id: string, path: string, hidden = false): RevisionP
width: RevisionPageLayoutOptionsWidth.Default,
metadata: true,
tags: true,
actions: true,
},
};
}