mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-12 05:48:57 +00:00
feat: add support for icons in tabs (#4277)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Add icon support in tab items
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user