diff --git a/.changeset/long-wombats-raise.md b/.changeset/long-wombats-raise.md new file mode 100644 index 0000000000..dc6c8725d0 --- /dev/null +++ b/.changeset/long-wombats-raise.md @@ -0,0 +1,5 @@ +--- +"gitbook": patch +--- + +Add icon support in tab items diff --git a/bun.lock b/bun.lock index cfde53b26a..c5756be0f6 100644 --- a/bun.lock +++ b/bun.lock @@ -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"], diff --git a/package.json b/package.json index 4cd67423ee..b5d4373667 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index c5a7a07a7c..6ba79f9510 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -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} @@ -347,7 +349,8 @@ const TabItem = memo(function TabItem(props: { id={getTabButtonId(tab.id)} onClick={() => onSelect(tab.id)} > - {tab.title} + {tab.icon && } + {tab.title} ); }); @@ -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 )} /> diff --git a/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx index a7b85e23be..4151d0e9e8 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx @@ -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) { 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: ( 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 diff --git a/packages/gitbook/src/lib/icons/inline.ts b/packages/gitbook/src/lib/icons/inline.ts index d8d000cddd..76e3d01144 100644 --- a/packages/gitbook/src/lib/icons/inline.ts +++ b/packages/gitbook/src/lib/icons/inline.ts @@ -358,7 +358,7 @@ function collectDocumentIconSourceRequests( const record = node as Record; - 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).icon, iconStyle); diff --git a/packages/gitbook/src/lib/pages.test.ts b/packages/gitbook/src/lib/pages.test.ts index 114d396585..e1be6faeeb 100644 --- a/packages/gitbook/src/lib/pages.test.ts +++ b/packages/gitbook/src/lib/pages.test.ts @@ -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, }, }; }