doc: improve link icons and structure

This commit is contained in:
Nicolò Boschi 2026-03-13 15:09:13 +01:00
parent 5de793eec7
commit 26472df166
6 changed files with 215 additions and 44 deletions

View file

@ -238,37 +238,56 @@ const config: Config = {
{
to: '/cookbook',
label: 'Cookbook',
customProps: { icon: 'lu-book' },
},
{
to: '/blog',
label: 'Blog',
customProps: { icon: 'lu-rss' },
},
{
to: '/api-reference',
label: 'API Reference',
customProps: { icon: 'lu-book-open' },
},
{
href: 'https://join.slack.com/t/hindsight-space/shared_invite/zt-3nhbm4w29-LeSJ5Ixi6j8PdiYOCPlOgg',
label: 'Community',
customProps: { icon: 'si-slack' },
},
{
href: 'https://benchmarks.hindsight.vectorize.io/',
label: 'Benchmarks',
customProps: { icon: 'lu-chart-bar' },
},
{
href: 'https://benchmarks.hindsight.vectorize.io/',
label: 'Which Model Should I Use?',
customProps: { icon: 'lu-cpu' },
},
{
href: 'https://arxiv.org/abs/2512.12818',
label: 'Paper',
customProps: { icon: 'lu-file-text' },
},
],
},
{
type: 'docsVersionDropdown',
position: 'right',
className: 'navbar-item-version',
},
{
href: 'https://ui.hindsight.vectorize.io/signup',
position: 'right',
label: 'Cloud',
className: 'navbar-item-cloud',
},
{
type: 'docsVersionDropdown',
position: 'right',
className: 'navbar-item-version',
},
{
href: 'https://github.com/vectorize-io/hindsight',
position: 'right',
label: 'GitHub',
className: 'header-github-link',
'aria-label': 'GitHub repository',
},
],
},

View file

@ -122,6 +122,12 @@ const sidebars: SidebarsConfig = {
label: 'Webhooks',
customProps: { icon: 'lu-webhook' },
},
{
type: 'link',
href: '/api-reference',
label: 'API Reference',
customProps: { icon: 'lu-book-open', iconAfter: 'lu-arrow-up-right' },
},
],
},
{
@ -221,6 +227,12 @@ const sidebars: SidebarsConfig = {
label: 'Hosting',
collapsible: false,
items: [
{
type: 'link',
href: 'https://ui.hindsight.vectorize.io/signup',
label: 'Cloud',
customProps: { icon: 'lu-cloud', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'doc',
id: 'developer/installation',
@ -271,6 +283,55 @@ const sidebars: SidebarsConfig = {
},
],
},
{
type: 'category',
label: 'More',
collapsible: false,
items: [
{
type: 'link',
href: '/cookbook',
label: 'Cookbook',
customProps: { icon: 'lu-book', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'link',
href: '/blog',
label: 'Blog',
customProps: { icon: 'lu-rss', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'link',
href: 'https://join.slack.com/t/hindsight-space/shared_invite/zt-3nhbm4w29-LeSJ5Ixi6j8PdiYOCPlOgg',
label: 'Community',
customProps: { icon: 'si-slack', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'link',
href: 'https://github.com/vectorize-io/hindsight',
label: 'GitHub',
customProps: { icon: 'si-github', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'link',
href: 'https://benchmarks.hindsight.vectorize.io/',
label: 'Benchmarks',
customProps: { icon: 'lu-chart-bar', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'link',
href: 'https://benchmarks.hindsight.vectorize.io/',
label: 'Which Model Should I Use?',
customProps: { icon: 'lu-cpu', iconAfter: 'lu-arrow-up-right' },
},
{
type: 'link',
href: 'https://arxiv.org/abs/2512.12818',
label: 'Paper',
customProps: { icon: 'lu-file-text', iconAfter: 'lu-arrow-up-right' },
},
],
},
],
};

View file

@ -95,23 +95,15 @@
}
/* GitHub icon link */
.header-github-link::before {
content: '';
width: 24px;
height: 24px;
display: flex;
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23666' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;
}
[data-theme='dark'] .header-github-link::before {
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;
}
.header-github-link:hover {
opacity: 0.7;
}
/* Hide Docusaurus's built-in external link SVG — we use LuExternalLink via iconAfter */
svg[aria-label="(opens in new tab)"] {
display: none;
}
.navbar__link:hover {
background-color: var(--ifm-background-surface-color);
}
@ -252,22 +244,6 @@
display: block !important;
}
/* GitHub icon - add text label in mobile */
.navbar-sidebar .header-github-link::before {
display: none;
}
.navbar-sidebar .header-github-link::after {
content: 'GitHub';
font-family: 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-weight: 600;
font-size: 1rem;
color: #1e293b;
}
[data-theme='dark'] .navbar-sidebar .header-github-link::after {
color: #e2e8f0;
}
}
/* Hero section */

View file

@ -9,9 +9,11 @@ import {
LuZap, LuDatabase, LuGitCompare, LuRocket, LuMemoryStick,
LuWebhook, LuFileText, LuServer, LuSettings, LuTerminal,
LuActivity, LuPlug, LuShield, LuPackage, LuBook,
LuNetwork, LuCode2, LuLayers, LuCpu,
LuNetwork, LuCode, LuLayers, LuCpu,
LuArrowUpRight, LuBookOpen, LuRss, LuCloud, LuMessageCircle,
LuChartBar, LuChartColumn,
} from 'react-icons/lu';
import {SiGo, SiPython} from 'react-icons/si';
import {SiGo, SiPython, SiGithub, SiSlack} from 'react-icons/si';
const ICON_MAP: Record<string, IconType> = {
'lu-brain': LuBrain,
@ -35,11 +37,20 @@ const ICON_MAP: Record<string, IconType> = {
'lu-package': LuPackage,
'lu-book': LuBook,
'lu-network': LuNetwork,
'lu-code': LuCode2,
'lu-code': LuCode,
'lu-layers': LuLayers,
'lu-cpu': LuCpu,
'si-go': SiGo,
'si-python': SiPython,
'si-github': SiGithub,
'si-slack': SiSlack,
'lu-chart-bar': LuChartBar,
'lu-chart-column': LuChartColumn,
'lu-arrow-up-right': LuArrowUpRight,
'lu-book-open': LuBookOpen,
'lu-rss': LuRss,
'lu-cloud': LuCloud,
'lu-message-circle': LuMessageCircle,
};
type Props = WrapperProps<typeof LinkType>;
@ -47,23 +58,32 @@ type Props = WrapperProps<typeof LinkType>;
export default function LinkWrapper(props: Props): JSX.Element {
const {item} = props;
const icon = item.customProps?.icon as string | undefined;
const iconAfter = item.customProps?.iconAfter as string | undefined;
if (!icon) {
if (!icon && !iconAfter) {
return <Link {...props} />;
}
const IconComponent = ICON_MAP[icon];
const IconComponent = icon ? ICON_MAP[icon] : undefined;
const IconAfterComponent = iconAfter ? ICON_MAP[iconAfter] : undefined;
const iconNode = IconComponent
? <IconComponent size={16} style={{flexShrink: 0, opacity: 0.65}} />
: <img src={icon} alt="" style={{width: '16px', height: '16px', flexShrink: 0, objectFit: 'contain'}} />;
const iconNode = icon
? IconComponent
? <IconComponent size={16} style={{flexShrink: 0, opacity: 0.65}} />
: <img src={icon} alt="" style={{width: '16px', height: '16px', flexShrink: 0, objectFit: 'contain'}} />
: null;
const iconAfterNode = IconAfterComponent
? <IconAfterComponent size={13} style={{flexShrink: 0, opacity: 0.45}} />
: null;
const modifiedItem = {
...item,
label: (
<span style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
{iconNode}
<span>{item.label}</span>
<span style={{flex: 1}}>{item.label}</span>
{iconAfterNode}
</span>
),
};

View file

@ -0,0 +1,57 @@
import React from 'react';
import DefaultNavbarItem from '@theme-original/NavbarItem/DefaultNavbarItem';
import type DefaultNavbarItemType from '@theme/NavbarItem/DefaultNavbarItem';
import type {WrapperProps} from '@docusaurus/types';
import type {IconType} from 'react-icons';
import {
LuArrowUpRight, LuCode, LuCircleHelp, LuScrollText,
LuLayoutGrid, LuCloud, LuBook, LuRss, LuBookOpen,
LuChartBar, LuCpu, LuFileText,
} from 'react-icons/lu';
import {SiGithub, SiSlack} from 'react-icons/si';
const ICON_MAP: Record<string, IconType> = {
'lu-code': LuCode,
'lu-circle-help': LuCircleHelp,
'lu-scroll-text': LuScrollText,
'lu-layout-grid': LuLayoutGrid,
'lu-cloud': LuCloud,
'lu-book': LuBook,
'lu-rss': LuRss,
'lu-book-open': LuBookOpen,
'lu-chart-bar': LuChartBar,
'lu-cpu': LuCpu,
'lu-file-text': LuFileText,
'si-github': SiGithub,
'si-slack': SiSlack,
};
type Props = WrapperProps<typeof DefaultNavbarItemType>;
export default function DefaultNavbarItemWrapper(props: Props): JSX.Element {
const isExternal = typeof props.href === 'string' && props.href.startsWith('http');
const isGithub = (props.className as string | undefined)?.includes('header-github-link');
const iconKey = props.customProps?.icon as string | undefined;
const IconComponent = iconKey ? ICON_MAP[iconKey] : undefined;
if (isGithub) {
return <DefaultNavbarItem {...props} label={<SiGithub size={18} style={{display: 'block'}} />} />;
}
if (!IconComponent && !isExternal) {
return <DefaultNavbarItem {...props} />;
}
const modifiedProps = {
...props,
label: (
<span style={{display: 'inline-flex', alignItems: 'center', gap: '5px'}}>
{IconComponent && <IconComponent size={14} style={{flexShrink: 0, opacity: 0.8}} />}
{props.label}
{isExternal && <LuArrowUpRight size={11} style={{flexShrink: 0, opacity: 0.45}} />}
</span>
),
};
return <DefaultNavbarItem {...modifiedProps} />;
}

View file

@ -0,0 +1,38 @@
import React from 'react';
import DropdownNavbarItem from '@theme-original/NavbarItem/DropdownNavbarItem';
import type DropdownNavbarItemType from '@theme/NavbarItem/DropdownNavbarItem';
import type {WrapperProps} from '@docusaurus/types';
import type {IconType} from 'react-icons';
import {LuLayoutGrid, LuBook, LuRss, LuBookOpen} from 'react-icons/lu';
import {SiSlack} from 'react-icons/si';
const ICON_MAP: Record<string, IconType> = {
'lu-layout-grid': LuLayoutGrid,
'lu-book': LuBook,
'lu-rss': LuRss,
'lu-book-open': LuBookOpen,
'si-slack': SiSlack,
};
type Props = WrapperProps<typeof DropdownNavbarItemType>;
export default function DropdownNavbarItemWrapper(props: Props): JSX.Element {
const iconKey = props.customProps?.icon as string | undefined;
const IconComponent = iconKey ? ICON_MAP[iconKey] : undefined;
if (!IconComponent) {
return <DropdownNavbarItem {...props} />;
}
const modifiedProps = {
...props,
label: (
<span style={{display: 'inline-flex', alignItems: 'center', gap: '5px'}}>
<IconComponent size={14} style={{flexShrink: 0, opacity: 0.8}} />
{props.label}
</span>
),
};
return <DropdownNavbarItem {...modifiedProps} />;
}