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 (
+
) {
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 {