diff --git a/packages/gitbook/src/components/DocumentView/HashLinkButton.tsx b/packages/gitbook/src/components/DocumentView/HashLinkButton.tsx new file mode 100644 index 0000000000..02f528c459 --- /dev/null +++ b/packages/gitbook/src/components/DocumentView/HashLinkButton.tsx @@ -0,0 +1,58 @@ +import { type ClassValue, tcls } from '@/lib/tailwind'; +import type { DocumentBlockHeading, DocumentBlockTabs } from '@gitbook/api'; +import { Icon } from '@gitbook/icons'; +import { getBlockTextStyle } from './spacing'; + +/** + * A hash icon which adds the block or active block item's ID in the URL hash. + * The button needs to be wrapped in a container with `hashLinkButtonWrapperStyles`. + */ +export const hashLinkButtonWrapperStyles = tcls('relative', 'group/hash'); + +export function HashLinkButton(props: { + id: string; + block: DocumentBlockTabs | DocumentBlockHeading; + label?: string; + className?: ClassValue; + iconClassName?: ClassValue; +}) { + const { id, block, className, iconClassName, label = 'Direct link to block' } = props; + const textStyle = getBlockTextStyle(block); + return ( +
+ + + +
+ ); +} diff --git a/packages/gitbook/src/components/DocumentView/Heading.tsx b/packages/gitbook/src/components/DocumentView/Heading.tsx index cb11038321..0de49e623f 100644 --- a/packages/gitbook/src/components/DocumentView/Heading.tsx +++ b/packages/gitbook/src/components/DocumentView/Heading.tsx @@ -1,9 +1,9 @@ import type { DocumentBlockHeading } from '@gitbook/api'; -import { Icon } from '@gitbook/icons'; import { tcls } from '@/lib/tailwind'; import type { BlockProps } from './Block'; +import { HashLinkButton, hashLinkButtonWrapperStyles } from './HashLinkButton'; import { Inlines } from './Inlines'; import { getBlockTextStyle } from './spacing'; @@ -23,50 +23,20 @@ export function Heading(props: BlockProps) { className={tcls( textStyle.textSize, 'heading', - 'group', - 'relative', 'grid', 'scroll-m-12', + hashLinkButtonWrapperStyles, style )} > -
- - - -
+ +
@@ -165,16 +168,14 @@ export function DynamicTabs( )} > {tabs.map((tab) => ( - + + + +
))} {tabs.map((tab, index) => ( diff --git a/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx index 4d5a0d555a..d1ab244852 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/Tabs.tsx @@ -39,6 +39,7 @@ export function Tabs(props: BlockProps) { ) { ); } - return ; + return ( + + ); } diff --git a/packages/gitbook/src/components/DocumentView/spacing.ts b/packages/gitbook/src/components/DocumentView/spacing.ts index a11db3546c..1c21a8b17d 100644 --- a/packages/gitbook/src/components/DocumentView/spacing.ts +++ b/packages/gitbook/src/components/DocumentView/spacing.ts @@ -10,6 +10,8 @@ export function getBlockTextStyle(block: DocumentBlock): { lineHeight: string; /** Tailwind class for the margin top (mt-*) */ marginTop?: string; + /** Tailwind class for the margin top to apply on the anchor link button */ + anchorButtonMarginTop?: string; } { switch (block.type) { case 'paragraph': @@ -22,18 +24,21 @@ export function getBlockTextStyle(block: DocumentBlock): { textSize: 'text-3xl font-semibold', lineHeight: 'leading-tight', marginTop: 'mt-[1em]', + anchorButtonMarginTop: 'mt-[1.05em]', }; case 'heading-2': return { textSize: 'text-2xl font-semibold', lineHeight: 'leading-snug', marginTop: 'mt-[0.75em]', + anchorButtonMarginTop: 'mt-[0.9em]', }; case 'heading-3': return { textSize: 'text-xl font-semibold', lineHeight: 'leading-snug', marginTop: 'mt-[0.5em]', + anchorButtonMarginTop: 'mt-[0.65em]', }; case 'divider': return {